From da3faa00946396a57c9e78f4314d0a114916a811 Mon Sep 17 00:00:00 2001 From: Julian Rueth Date: Fri, 27 Jun 2014 07:12:59 +0200 Subject: [PATCH 001/452] Added derivations for non-rational separable function fields --- .../rings/function_field/function_field.py | 73 +++++++++++- src/sage/rings/function_field/maps.py | 111 +++++++++++++++++- 2 files changed, 181 insertions(+), 3 deletions(-) diff --git a/src/sage/rings/function_field/function_field.py b/src/sage/rings/function_field/function_field.py index ac2706fc46b..87d88faa9fa 100644 --- a/src/sage/rings/function_field/function_field.py +++ b/src/sage/rings/function_field/function_field.py @@ -155,7 +155,7 @@ def characteristic(self): sage: K.characteristic() 7 sage: R. = K[] - sage: L. = K.extension(y^2-x) + sage: L. = K.extension(y^2 - x) sage: L.characteristic() 7 """ @@ -438,7 +438,7 @@ def __reduce__(self): EXAMPLES:: sage: K. = FunctionField(QQ); R. = K[] - sage: L = K.extension(y^2-x) + sage: L = K.extension(y^2 - x) sage: clazz,args = L.__reduce__() sage: clazz(*args) Function field in y defined by y^2 - x @@ -981,6 +981,75 @@ def genus(self): else: raise NotImplementedError("Computation of genus over this rational function field not implemented yet") + @cached_method + def derivation(self): + r""" + Return a generator of the space of derivations over the constant base + ring of this function field. + + A derivation on `R` is map `R\to R` with + `D(\alpha+\beta)=D(\alpha)+D(\beta)` and `D(\alpha\beta)=\beta + D(\alpha)+\alpha D(\beta)` for all `\alpha,\beta\in R`. For a function + field which is a finite extension of `K(x)` with `K` perfect, the + derivations form a one-dimensional `K`-vector space generated by the + derivation returned by this method. + + ALGORITHM: + + If this field is a separable extension of another function field `F`, + then Proposition 11 of [GT1996]_ describes how to compute the unique + extension of a derivation on `F` to this field; we apply this algorithm + to the generator of the space of derivations on `F`. + If this field has not been generated as a separable extension, then we + find an isomorphic field which is a separable extension of a rational + function field, see :meth:`separable_model`. + + OUTPUT: + + An endofunction on this function field. + + REFERENCES:: + + .. [GT1996] Gianni, P., & Trager, B. (1996). Square-free algorithms in + positive characteristic. Applicable Algebra in Engineering, + Communication and Computing, 7(1), 1-14. + + EXAMPLES:: + + sage: K. = FunctionField(GF(3)) + sage: R. = K[] + sage: L. = K.extension(y^2 - x) + sage: d = L.derivation(); d + Derivation map: + From: Function field in y defined by y^2 + 2*x + To: Function field in y defined by y^2 + 2*x + Defn: y |--> 2/x*y + sage: d(x) + 1 + sage: d(x^3) + 0 + sage: d(x*y) + 0 + sage: d(y) + 2/x*y + + Currently the functionality for finding a separable model is not + implemented (see :trac:`16562`, :trac:`16564`) + + sage: R. = K[] + sage: L. = K.extension(y^3 - x) + sage: L.derivation() + Traceback (most recent call last): + ... + NotImplementedError: construction of separable models not implemented + + """ + from maps import FunctionFieldDerivation_separable + if self.polynomial().gcd(self.polynomial().derivative()).is_one(): + return FunctionFieldDerivation_separable(self, self.base_ring().derivation()) + else: + raise NotImplementedError("construction of separable models not implemented") + def is_RationalFunctionField(x): """ Return True if ``x`` is of rational function field type. diff --git a/src/sage/rings/function_field/maps.py b/src/sage/rings/function_field/maps.py index d66f3363a2c..a7e870b5ac8 100644 --- a/src/sage/rings/function_field/maps.py +++ b/src/sage/rings/function_field/maps.py @@ -13,7 +13,7 @@ sage: K. = FunctionField(QQ); R. = K[] sage: K.hom(1/x) Morphism of function fields defined by x |--> 1/x - sage: L. = K.extension(y^2-x) + sage: L. = K.extension(y^2 - x) sage: K.hom(y) Morphism of function fields defined by x |--> y sage: L.hom([y,x]) @@ -131,6 +131,8 @@ def __init__(self, K, u): sage: K. = FunctionField(QQ) sage: d = K.derivation() # indirect doctest + sage: type(d) + """ from function_field import is_RationalFunctionField @@ -172,6 +174,113 @@ def _call_(self, x): else: return self._u * self.codomain()( numerator / g**2 ) +class FunctionFieldDerivation_separable(FunctionFieldDerivation): + r""" + The unique extension of the derivation ``d`` to ``L``. + + INPUT: + + - ``L`` -- a function field which is a separable extension of the domain of + ``d`` + + - ``d`` -- a derivation on a function field + + EXAMPLES:: + + sage: K. = FunctionField(QQ) + sage: R. = K[] + sage: L. = K.extension(y^2 - x) + sage: d = L.derivation() + + """ + def __init__(self, L, d): + r""" + Initialization. + + EXAMPLES:: + + sage: K. = FunctionField(GF(3)) + sage: R. = K[] + sage: L. = K.extension(y^2 - x) + sage: d = L.derivation() # indirect doctest + sage: type(d) + + + """ + if not isinstance(d, FunctionFieldDerivation): + raise TypeError("d must be a derivation on a function field") + from function_field import is_FunctionField + if not is_FunctionField(L): + raise TypeError("L must be a function field") + if d.domain() is not L.base_ring(): + raise ValueError("L must be an extension of the domain of d") + FunctionFieldDerivation.__init__(self, L) + + self._d = d + f = self.domain().polynomial() + if not f.gcd(f.derivative()).is_one(): + raise ValueError("L must be a separable extension of its base field.") + x = self.domain().gen() + self._gen_image = - f.map_coefficients(lambda c:d(c))(x) / f.derivative()(x) + + def _call_(self, x): + r""" + Evaluate the derivation on ``x``. + + INPUT: + + - ``x`` -- an element of the function field + + EXAMPLES:: + + sage: K. = FunctionField(QQ) + sage: R. = K[] + sage: L. = K.extension(y^2 - x) + sage: d = L.derivation() + sage: d(x) # indirect doctest + 1 + sage: d(y) + (-1/2/-x)*y + sage: d(y^2) + 1 + + """ + if x.is_zero(): + return self.codomain().zero() + return x._x.map_coefficients(self._d) \ + + x._x.derivative()(self.domain().gen()) * self._gen_image + + def _repr_defn(self): + r""" + Helper method to print this map. + + TESTS:: + + sage: K. = FunctionField(QQ) + sage: R. = K[] + sage: L. = K.extension(y^2 - x) + sage: L.derivation() # indirect doctest + Derivation map: + From: Function field in y defined by y^2 - x + To: Function field in y defined by y^2 - x + Defn: y |--> (-1/2/-x)*y + sage: R. = L[] + sage: M. = L.extension(z^2 - y) + sage: M.derivation() + Derivation map: + From: Function field in z defined by z^2 - y + To: Function field in z defined by z^2 - y + Defn: y |--> (-1/2/-x)*y + z |--> 1/4/x*z + + """ + base = self._d._repr_defn() + ret = "%s |--> %s"%(self.domain().gen(),self._gen_image) + if base: + return base + "\n" + ret + else: + return ret + class FunctionFieldIsomorphism(Morphism): r""" A base class for isomorphisms between function fields and From acf7a815a41916caf9a08c0c533470e7bb940c9b Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 12 Mar 2015 23:13:40 -0700 Subject: [PATCH 002/452] Added PBW basis for Lie algebras. --- .../en/reference/algebras/lie_algebras.rst | 1 + .../lie_algebras/poincare_birkhoff_witt.py | 363 ++++++++++++++++++ .../categories/lie_algebras_with_basis.py | 15 + 3 files changed, 379 insertions(+) create mode 100644 src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py diff --git a/src/doc/en/reference/algebras/lie_algebras.rst b/src/doc/en/reference/algebras/lie_algebras.rst index 23a49b8f498..d83f30cdb38 100644 --- a/src/doc/en/reference/algebras/lie_algebras.rst +++ b/src/doc/en/reference/algebras/lie_algebras.rst @@ -8,6 +8,7 @@ Lie Algebras sage/algebras/lie_algebras/heisenberg.py sage/algebras/lie_algebras/lie_algebra.py sage/algebras/lie_algebras/lie_algebra_element.py + sage/algebras/lie_algebras/poincare_birkhoff_witt.py sage/algebras/lie_algebras/structure_coefficients.py sage/algebras/lie_algebras/virasoro.py diff --git a/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py b/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py new file mode 100644 index 00000000000..0729dfbda1b --- /dev/null +++ b/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py @@ -0,0 +1,363 @@ +""" +The Poincare-Birkhoff-Witt Basis For A Universal Enveloping Algebra + +AUTHORS: + +- Travis Scrimshaw (2013-11-03): Initial version +""" + +#***************************************************************************** +# Copyright (C) 2013 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 +# is available at: +# +# http://www.gnu.org/licenses/ +#***************************************************************************** + +from sage.misc.cachefunc import cached_method +from sage.misc.misc_c import prod +from sage.categories.algebras import Algebras +from sage.monoids.indexed_free_monoid import IndexedFreeAbelianMonoid +from sage.combinat.free_module import CombinatorialFreeModule +from sage.sets.family import Family +from sage.rings.all import ZZ + +class PoincareBirkhoffWittBasis(CombinatorialFreeModule): + r""" + The Poincare-Birkhoff-Witt (PBW) basis of the universal enveloping + algebra of a Lie algebra. + + Consider a Lie algebra `\mathfrak{g}` with basis `(b_i)_{i=1}^n`, + so the universal enveloping algebra `U(\mathfrak{g})` is generated + by `b_i` and subject to the relations + + .. MATH:: + + [b_i, b_j] = \sum_{k \in I} c_{ij}^k b_k + + where `c_{ij}^k` are the structure coefficients of `\mathfrak{g}`. The + Poincare-Birkhoff-Witt (PBW) basis is given by picking a particular + ordering of `(b_i)_{i \in I}` and is given by the monomials + `b_1^{e_1} b_2^{e_2} \cdots b_n^{e_n}`. Specifically, we can rewrite + `b_j b_i = b_i b_j + [b_j, b_i]` where `j > i`, and we can repeat + this to sort any monmoial into + + .. MATH:: + + b_{i_1} \cdots b_{i_k} = b_1^{e_1} \cdots b_n^{e_n} + LOT + + where `LOT` are lower order terms. Thus the PBW is a filtered basis + for `U(\mathfrak{g})`. + + EXAMPLES: + + We construct the PBW basis of `\mathfrak{sl}_2`:: + + sage: L = lie_algebras.sl(QQ, 2) + sage: PBW = L.pbw_basis() + + We then do some computations, in particular, we check that `[E, F] = H`:: + + sage: E,F,H = PBW.algebra_generators() + sage: E*F + PBW['E']*PBW['F'] + sage: F*E + PBW['E']*PBW['F'] - PBW['H'] + sage: E*F - F*E + PBW['H'] + + Next we construct another instance of the PBW basis, but sorted in the + reverse order:: + + sage: PBW2 = L.pbw_basis(prefix='PBW2', basis_cmp=lambda x,y: -cmp(x,y)) + + We then check the multiplication is preserved:: + + sage: PBW2(E) * PBW2(F) + PBW2['F']*PBW2['E'] + PBW2['H'] + sage: PBW2(E*F) + PBW2['F']*PBW2['E'] + PBW2['H'] + sage: F * E + H + PBW['E']*PBW['F'] + + We now construct the PBW basis for Lie algebra of regular + vector fields on `\CC^{\times}`:: + + sage: L = lie_algebras.regular_vector_fields(QQ) + sage: PBW = L.pbw_basis() + sage: G = PBW.algebra_generators() + sage: G[2] * G[3] + PBW[2]*PBW[3] + sage: G[3] * G[2] + PBW[2]*PBW[3] - PBW[5] + sage: G[-2] * G[3] * G[2] + PBW[-2]*PBW[2]*PBW[3] - PBW[-2]*PBW[5] + """ + @staticmethod + def __classcall_private__(cls, g, basis_cmp=None, prefix='PBW', **kwds): + """ + Normalize input to ensure a unique representation. + + TESTS:: + + sage: from sage.algebras.lie_algebras.poincare_birkhoff_witt import PoincareBirkhoffWittBasis + sage: L = lie_algebras.sl(QQ, 2) + sage: P1 = PoincareBirkhoffWittBasis(L) + sage: P2 = PoincareBirkhoffWittBasis(L, prefix='PBW') + sage: P1 is P2 + True + """ + return super(PoincareBirkhoffWittBasis, cls).__classcall__(cls, + g, basis_cmp, prefix, **kwds) + + def __init__(self, g, basis_cmp, prefix, **kwds): + """ + Initialize ``self``. + + TESTS:: + + sage: L = lie_algebras.sl(QQ, 2) + sage: PBW = L.pbw_basis() + sage: E,F,H = PBW.algebra_generators() + sage: TestSuite(PBW).run(elements=[E, F, H]) + sage: TestSuite(PBW).run(elements=[E, F, H, E*F + H]) # long time + """ + if basis_cmp is not None: + self._basis_cmp = basis_cmp + + R = g.base_ring() + self._g = g + monomials = IndexedFreeAbelianMonoid(g.basis().keys(), prefix, + generator_cmp=self._monoid_cmp, **kwds) + CombinatorialFreeModule.__init__(self, R, monomials, + prefix='', bracket=False, latex_bracket=False, + generator_cmp=self._monomial_cmp, + category=Algebras(R).WithBasis()) + + def _basis_cmp(self, x, y): + """ + Compare the indices of ``x`` and ``y``. + + TESTS:: + + sage: L = lie_algebras.sl(QQ, 2) + sage: PBW = L.pbw_basis() + sage: PBW._basis_cmp('E', 'H') + -1 + + :: + + sage: L = lie_algebras.sl(QQ, 2) + sage: PBW = L.pbw_basis(basis_cmp=lambda x,y: -cmp(x,y)) + sage: prod(PBW.gens()) + PBW['H']*PBW['F']*PBW['E'] + PBW['H']^2 + """ + K = self._g.basis().keys() + if K.cardinality() == float('inf'): + return cmp(x, y) + lst = list(K) + return cmp(lst.index(x), lst.index(y)) + + def _monoid_cmp(self, x, y): + """ + Comparison function for the underlying monoid. + + EXAMPLES:: + + sage: L = lie_algebras.sl(QQ, 2) + sage: PBW = L.pbw_basis(basis_cmp=lambda x,y: -cmp(x,y)) + sage: M = PBW.basis().keys() + sage: prod(M.gens()) # indirect doctest + PBW['H']*PBW['F']*PBW['E'] + """ + return self._basis_cmp(x[0], y[0]) + + def _monomial_cmp(self, x, y): + """ + Compare the monomials ``x`` and ``y`` of ``self`` by reverse + degree lexicographic order. + + EXAMPLES:: + + sage: L = lie_algebras.sl(QQ, 2) + sage: PBW = L.pbw_basis() + sage: E,F,H = sorted(PBW.algebra_generators(), key=str) + sage: H*F*F*E # indirect doctest + PBW['E']*PBW['F']^2*PBW['H'] - 2*PBW['E']*PBW['F']^2 + - 2*PBW['F']*PBW['H']^2 + 6*PBW['F']*PBW['H'] - 4*PBW['F'] + + sage: PBW = L.pbw_basis(basis_cmp=lambda x,y: -cmp(x,y)) + sage: E,F,H = sorted(PBW.algebra_generators(), key=str) + sage: E*F*F*H # indirect doctest + PBW['H']*PBW['F']^2*PBW['E'] + 2*PBW['H']^2*PBW['F'] + + 2*PBW['F']^2*PBW['E'] + 6*PBW['H']*PBW['F'] + 4*PBW['F'] + """ + c = cmp(len(y), len(x)) + if c: + return c + w = y.to_word_list() + for i,a in enumerate(x.to_word_list()): + c = self._basis_cmp(a, w[i]) + if c: + return c + return 0 + + def _repr_(self): + """ + Return a string representation of ``self``. + + EXAMPLES:: + + sage: L = lie_algebras.sl(QQ, 2) + sage: L.pbw_basis() + Universal enveloping algebra of sl2 over Rational Field + in the Poincare-Birkhoff-Witt basis + """ + return "Universal enveloping algebra of {} in the Poincare-Birkhoff-Witt basis".format(self._g) + + def _coerce_map_from_(self, R): + """ + Return ``True`` if there is a coercion map from ``R`` to ``self``. + + EXAMPLES: + + We lift from the Lie algebra:: + + sage: L = lie_algebras.sl(QQ, 2) + sage: PBW = L.pbw_basis() + sage: PBW.has_coerce_map_from(L) + True + sage: [PBW(g) for g in L.gens()] + [PBW['E'], PBW['F'], PBW['H']] + + We can go between PBW bases under different sorting orders:: + + sage: PBW2 = L.pbw_basis(basis_cmp=lambda x,y: -cmp(x,y)) + sage: E,F,H = sorted(PBW.algebra_generators(), key=str) + sage: PBW2(E*F*H) + PBW['H']*PBW['F']*PBW['E'] + PBW['H']^2 + """ + if R == self._g: + # Make this into the lift map + I = self._indices + basis_function = lambda x: self.monomial(I.gen(x)) + # TODO: this diagonal, but with a smaller indexing set... + return self._g.module_morphism(basis_function, codomain=self, + triangular='upper', unitriangular=True) + + if isinstance(R, PoincareBirkhoffWittBasis) and self._g == R._g: + I = self._indices + def basis_function(x): + return self.prod(self.monomial(I.gen(g)**e) for g,e in x._sorted_items()) + # TODO: this diagonal, but with a smaller indexing set... + return R.module_morphism(basis_function, codomain=self) + + return super(PoincareBirkhoffWittBasis, self)._coerce_map_from_(R) + + def lie_algebra(self): + """ + Return the underlying Lie algebra of ``self``. + + EXAMPLES:: + + sage: L = lie_algebras.sl(QQ, 2) + sage: PBW = L.pbw_basis() + sage: PBW.lie_algebra() is L + True + """ + return self._g + + def algebra_generators(self): + """ + Return the algebra generators of ``self``. + + EXAMPLES:: + + sage: L = lie_algebras.sl(QQ, 2) + sage: PBW = L.pbw_basis() + sage: PBW.algebra_generators() + Finite family {'H': PBW['H'], 'E': PBW['E'], 'F': PBW['F']} + """ + G = self._indices.gens() + return Family(self._indices._indices, lambda x: self.monomial(G[x]), + name="generator map") + + gens = algebra_generators + + @cached_method + def one_basis(self): + """ + Return the basis element indexing `1`. + + EXAMPLES:: + + sage: L = lie_algebras.sl(QQ, 2) + sage: PBW = L.pbw_basis() + sage: ob = PBW.one_basis(); ob + 1 + sage: ob.parent() + Free abelian monoid indexed by {'E', 'F', 'H'} + """ + return self._indices.one() + + def product_on_basis(self, lhs, rhs): + """ + Return the product of the two basis elements ``lhs`` and ``rhs``. + + EXAMPLES:: + + sage: L = lie_algebras.sl(QQ, 2) + sage: PBW = L.pbw_basis() + sage: I = PBW.indices() + sage: PBW.product_on_basis(I.gen('E'), I.gen('F')) + PBW['E']*PBW['F'] + sage: PBW.product_on_basis(I.gen('E'), I.gen('H')) + PBW['E']*PBW['H'] + sage: PBW.product_on_basis(I.gen('H'), I.gen('E')) + PBW['E']*PBW['H'] + 2*PBW['E'] + sage: PBW.product_on_basis(I.gen('F'), I.gen('E')) + PBW['E']*PBW['F'] - PBW['H'] + sage: PBW.product_on_basis(I.gen('F'), I.gen('H')) + PBW['F']*PBW['H'] + sage: PBW.product_on_basis(I.gen('H'), I.gen('F')) + PBW['F']*PBW['H'] - 2*PBW['F'] + sage: PBW.product_on_basis(I.gen('H')**2, I.gen('F')**2) + PBW['F']^2*PBW['H']^2 - 8*PBW['F']^2*PBW['H'] + 16*PBW['F']^2 + + sage: E,F,H = sorted(PBW.algebra_generators(), key=str) + sage: E*F - F*E + PBW['H'] + sage: H * F * E + PBW['E']*PBW['F']*PBW['H'] - PBW['H']^2 + sage: E * F * H * E + PBW['E']^2*PBW['F']*PBW['H'] + 2*PBW['E']^2*PBW['F'] + - PBW['E']*PBW['H']^2 - 2*PBW['E']*PBW['H'] + """ + # Some trivial base cases + if lhs == self.one_basis(): + return self.monomial(rhs) + if rhs == self.one_basis(): + return self.monomial(lhs) + + I = self._indices + trail = lhs.trailing_support() + lead = rhs.leading_support() + if self._basis_cmp(trail, lead) <= 0: + return self.monomial(lhs * rhs) + + # Create the commutator + # We have xy - yx = [x, y] -> xy = yx + [x, y] and we have x > y + terms = self._g.monomial(trail).bracket(self._g.monomial(lead)) + lead = I.gen(lead) + trail = I.gen(trail) + terms = self.sum_of_terms((I.gen(t), c) for t,c in terms) + terms += self.monomial(lead * trail) + return self.monomial(lhs // trail) * terms * self.monomial(rhs // lead) + diff --git a/src/sage/categories/lie_algebras_with_basis.py b/src/sage/categories/lie_algebras_with_basis.py index 51856eefe2d..445b13a6ae4 100644 --- a/src/sage/categories/lie_algebras_with_basis.py +++ b/src/sage/categories/lie_algebras_with_basis.py @@ -92,6 +92,21 @@ def free_module(self): # Otherwise just index by the basis of ``self`` as a fallback return CombinatorialFreeModule(self.base_ring(), self.basis()) + def pbw_basis(self, basis_cmp=None, **kwds): + """ + Return the Poincare-Birkhoff-Witt basis of the universal + enveloping algebra corresponding to ``self``. + + EXAMPLES:: + """ + from sage.algebras.lie_algebras.poincare_birkhoff_witt \ + import PoincareBirkhoffWittBasis + return PoincareBirkhoffWittBasis(self, basis_cmp, **kwds) + + poincare_birkhoff_witt_basis = pbw_basis + + _construct_UEA = pbw_basis + class ElementMethods: def _bracket_(self, y): """ From 4c38c0154869dd9cbe8bf0ca647dec891f60fee1 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 12 Mar 2015 23:16:47 -0700 Subject: [PATCH 003/452] Added example for pbw_basis() method. --- src/sage/categories/lie_algebras_with_basis.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sage/categories/lie_algebras_with_basis.py b/src/sage/categories/lie_algebras_with_basis.py index 445b13a6ae4..202868bdacd 100644 --- a/src/sage/categories/lie_algebras_with_basis.py +++ b/src/sage/categories/lie_algebras_with_basis.py @@ -98,6 +98,9 @@ def pbw_basis(self, basis_cmp=None, **kwds): enveloping algebra corresponding to ``self``. EXAMPLES:: + + sage: L = lie_algebras.sl(QQ, 2) + sage: PBW = L.pbw_basis() """ from sage.algebras.lie_algebras.poincare_birkhoff_witt \ import PoincareBirkhoffWittBasis From 1b5e93620d3ac86ea9601db270c0f87548ae36e0 Mon Sep 17 00:00:00 2001 From: Buck Evan Date: Wed, 15 Apr 2015 16:30:38 -0400 Subject: [PATCH 004/452] fix NameError in mathematica_free integration --- src/sage/symbolic/integration/external.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/symbolic/integration/external.py b/src/sage/symbolic/integration/external.py index c090982bfcb..c79281bdabd 100644 --- a/src/sage/symbolic/integration/external.py +++ b/src/sage/symbolic/integration/external.py @@ -55,7 +55,7 @@ def mma_free_integrator(expression, v, a=None, b=None): if chr(i) not in vars: shadow_x = SR.var(chr(i)) break - expression = expression.subs({x:shadow_x}).subs({dvar: x}) + expression = expression.subs({x:shadow_x}).subs({v: x}) params = urllib.urlencode({'expr': expression._mathematica_init_(), 'random': 'false'}) page = urllib.urlopen("http://integrals.wolfram.com/index.jsp", params).read() page = page[page.index('"inputForm"'):page.index('"outputForm"')] From 5078cf84761975ad3539bef966655ef328f1e0f5 Mon Sep 17 00:00:00 2001 From: Karl-Dieter Crisman Date: Fri, 29 May 2015 00:51:19 -0400 Subject: [PATCH 005/452] Doctest Trac 18212 for mma_free integration fix --- src/sage/symbolic/integration/external.py | 28 +++++++++++++++++++++-- src/sage/symbolic/integration/integral.py | 4 ++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/sage/symbolic/integration/external.py b/src/sage/symbolic/integration/external.py index 560fdacdff0..aceb024d7c0 100644 --- a/src/sage/symbolic/integration/external.py +++ b/src/sage/symbolic/integration/external.py @@ -1,4 +1,14 @@ -"Symbolic integration via external software" +"""Symbolic integration via external software + +TESTS: + +Test a few imports, without internet:: + + sage: from sage.symbolic.integration.external import mma_free_integrator + sage: from sage.symbolic.integration.external import sympy_integrator + sage: sympy_integrator(sin(x), x) + -cos(x) +""" from sage.symbolic.expression import Expression from sage.symbolic.ring import SR @@ -42,9 +52,23 @@ def sympy_integrator(expression, v, a=None, b=None): def mma_free_integrator(expression, v, a=None, b=None): """ - sage: from sage.symbolic.integration.external import mma_free_integrator + Function for using integrals.wolfram.com to compute + symbolic integration. + + EXAMPLE:: + + sage: from sage.symbolic.integration.external import mma_free_integrator # optional - internet sage: mma_free_integrator(sin(x), x) # optional - internet -cos(x) + + TESTS: + + Check that :trac:`18212` is resolved:: + + sage: var('y') # optional - internet + y + sage: integral(sin(y)^2, y, algorithm='mathematica_free') # optional - internet + -1/2*cos(y)*sin(y) + 1/2*y """ import urllib, re # We need to integrate against x diff --git a/src/sage/symbolic/integration/integral.py b/src/sage/symbolic/integration/integral.py index b8514d7e5be..6c6bcb1c580 100644 --- a/src/sage/symbolic/integration/integral.py +++ b/src/sage/symbolic/integration/integral.py @@ -478,8 +478,8 @@ def integrate(expression, v=None, a=None, b=None, algorithm=None, hold=False): Alternatively, just use algorithm='mathematica_free' to integrate via Mathematica over the internet (does NOT require a Mathematica license!):: - sage: _ = var('x, y, z') - sage: f = sin(x^2) + y^z + sage: _ = var('x, y, z') # optional - internet + sage: f = sin(x^2) + y^z # optional - internet sage: f.integrate(x, algorithm="mathematica_free") # optional - internet x*y^z + sqrt(1/2)*sqrt(pi)*fresnels(sqrt(2)*x/sqrt(pi)) From ac8427a78a3db9f82f83b1fd2f0c5d75d3035c12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20R=C3=BCth?= Date: Sat, 15 Aug 2015 02:31:25 -0500 Subject: [PATCH 006/452] Fixed format errors in docstrings --- src/sage/rings/function_field/function_field.py | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/sage/rings/function_field/function_field.py b/src/sage/rings/function_field/function_field.py index 31259b8f3de..4793d709ae4 100644 --- a/src/sage/rings/function_field/function_field.py +++ b/src/sage/rings/function_field/function_field.py @@ -1049,11 +1049,11 @@ def derivation(self): An endofunction on this function field. - REFERENCES:: + REFERENCES: .. [GT1996] Gianni, P., & Trager, B. (1996). Square-free algorithms in - positive characteristic. Applicable Algebra in Engineering, - Communication and Computing, 7(1), 1-14. + positive characteristic. Applicable Algebra in Engineering, + Communication and Computing, 7(1), 1-14. EXAMPLES:: @@ -1075,7 +1075,7 @@ def derivation(self): 2/x*y Currently the functionality for finding a separable model is not - implemented (see :trac:`16562`, :trac:`16564`) + implemented (see :trac:`16562`, :trac:`16564`):: sage: R. = K[] sage: L. = K.extension(y^3 - x) @@ -1619,13 +1619,6 @@ def derivation(self): An endofunction on this function field. - REFERENCES: - - .. [GT1996] - Gianni, P., & Trager, B. (1996). Square-free algorithms in - positive characteristic. Applicable Algebra in Engineering, - Communication and Computing, 7(1), 1-14. - EXAMPLES:: sage: K. = FunctionField(GF(3)) From f967e4f4a6aef7dfb039c3690eb7f039356f46da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20R=C3=BCth?= Date: Sun, 16 Aug 2015 17:09:24 -0500 Subject: [PATCH 007/452] test Leibniz's law for function field derivations --- .../rings/function_field/function_field.py | 37 +++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/src/sage/rings/function_field/function_field.py b/src/sage/rings/function_field/function_field.py index 4793d709ae4..4676e545532 100644 --- a/src/sage/rings/function_field/function_field.py +++ b/src/sage/rings/function_field/function_field.py @@ -324,6 +324,36 @@ def _coerce_map_from_(self, R): return True return False + def _test_derivation(self, **options): + r""" + Test the correctness of the derivations of this function field. + + EXAMPLES:: + + sage: K. = FunctionField(QQ) + sage: TestSuite(K).run() # indirect doctest + + """ + tester = self._tester(**options) + S = tester.some_elements() + K = self.constant_base_field().some_elements() + try: + d = self.derivation() + except NotImplementedError: + return # some function fields no not implement derivation() yet + from sage.combinat.cartesian_product import CartesianProduct + # Leibniz's law + for x,y in tester.some_elements(CartesianProduct(S, S)): + tester.assert_(d(x*y) == x*d(y) + d(x)*y) + # Linearity + for x,y in tester.some_elements(CartesianProduct(S, S)): + tester.assert_(d(x+y) == d(x) + d(y)) + for c,x in tester.some_elements(CartesianProduct(K, S)): + tester.assert_(d(c*x) == c*d(x)) + # Constants map to zero + for c in tester.some_elements(K): + tester.assert_(d(c) == 0) + class FunctionField_polymod(FunctionField): """ A function field defined by a univariate polynomial, as an @@ -1074,6 +1104,13 @@ def derivation(self): sage: d(y) 2/x*y + Derivations are linear and satisfy Leibniz's law:: + + sage: d(x+y) == d(x) + d(y) + True + sage: d(x*y) == x*d(y) + y*d(x) + True + Currently the functionality for finding a separable model is not implemented (see :trac:`16562`, :trac:`16564`):: From d11261cb69a349d68c696561a560460465e11c91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20R=C3=BCth?= Date: Sun, 16 Aug 2015 17:09:58 -0500 Subject: [PATCH 008/452] TestSuite for inseparable and non-perfect base function fields --- src/sage/rings/function_field/function_field.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/sage/rings/function_field/function_field.py b/src/sage/rings/function_field/function_field.py index 4676e545532..0c1ae543641 100644 --- a/src/sage/rings/function_field/function_field.py +++ b/src/sage/rings/function_field/function_field.py @@ -52,11 +52,22 @@ sage: M.base_field().base_field() Rational function field in x over Finite Field in a of size 5^2 +It is also possible to work with function fields over an imperfect base field:: + + sage: N. = FunctionField(K) + +Function field extensions can be inseparable:: + + sage: R. = K[] + sage: O. = K.extension(v^5 - x) + TESTS:: sage: TestSuite(K).run() sage: TestSuite(L).run() # long time (8s on sage.math, 2012) sage: TestSuite(M).run() # long time (52s on sage.math, 2012) + sage: TestSuite(N).run() # long time + sage: TestSuite(O).run() # long time The following two test suites do not pass ``_test_elements`` yet since ``R.an_element()`` has a ``_test_category`` method wich it should not have. From 06770a3da7ce7ba7771f44e5233925922903761b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20R=C3=BCth?= Date: Sun, 16 Aug 2015 17:10:40 -0500 Subject: [PATCH 009/452] Fixed wording of function field derivation docstring --- src/sage/rings/function_field/function_field.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/sage/rings/function_field/function_field.py b/src/sage/rings/function_field/function_field.py index 0c1ae543641..749f3b7f213 100644 --- a/src/sage/rings/function_field/function_field.py +++ b/src/sage/rings/function_field/function_field.py @@ -1080,11 +1080,10 @@ def derivation(self): If this field is a separable extension of another function field `F`, then Proposition 11 of [GT1996]_ describes how to compute the unique - extension of a derivation on `F` to this field; we apply this algorithm - to the generator of the space of derivations on `F`. - If this field has not been generated as a separable extension, then we - find an isomorphic field which is a separable extension of a rational - function field, see :meth:`separable_model`. + extension of a derivation on `F` to this field; we apply the formula + described there to the generator of the space of derivations on `F`. + The general inseparable case is not implemented yet (see :trac:`16562`, + :trac:`16564`.)` OUTPUT: From da8a277f9d027c44aac61cdb32eb0145ea612f4e Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 26 Aug 2015 21:04:13 -0500 Subject: [PATCH 010/452] Initial creation of KR crystals category. --- .../categories/affine_derived_crystals.py | 168 ++++++++++++++++++ src/sage/categories/crystals.py | 20 +-- src/sage/combinat/crystals/affine.py | 11 +- .../combinat/crystals/kirillov_reshetikhin.py | 18 +- .../rigged_configurations/kr_tableaux.py | 5 +- .../rigged_configurations.py | 7 +- .../tensor_product_kr_tableaux.py | 11 +- 7 files changed, 205 insertions(+), 35 deletions(-) create mode 100644 src/sage/categories/affine_derived_crystals.py diff --git a/src/sage/categories/affine_derived_crystals.py b/src/sage/categories/affine_derived_crystals.py new file mode 100644 index 00000000000..0c57189f1b4 --- /dev/null +++ b/src/sage/categories/affine_derived_crystals.py @@ -0,0 +1,168 @@ +r""" +Affine Derived Subalgebra Crystals +""" +#***************************************************************************** +# Copyright (C) 2015 Travis Scrimshaw +# +# Distributed under the terms of the GNU General Public License (GPL) +# http://www.gnu.org/licenses/ +#****************************************************************************** + +from sage.misc.abstract_method import abstract_method +from sage.misc.cachefunc import cached_method +#from sage.categories.category_with_axiom import CategoryWithAxiom +from sage.categories.category_singleton import Category_singleton +from sage.categories.crystals import Crystals +from sage.categories.regular_crystals import RegularCrystals +from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets +from sage.categories.tensor import TensorProductsCategory +from sage.graphs.dot2tex_utils import have_dot2tex + +class AffineDerivedSubalgebraCrystals(Category_singleton): + r""" + The category of `U_q'(\mathfrak{g})`-crystals, where `\mathfrak{g}` + is of affine type. + + EXAMPLES:: + + sage: C = FiniteCrystals() + sage: C + Category of finite crystals + sage: C.super_categories() + [Category of crystals, Category of finite enumerated sets] + sage: C.example() + Highest weight crystal of type A_3 of highest weight omega_1 + + TESTS:: + + sage: TestSuite(C).run() + sage: B = FiniteCrystals().example() + sage: TestSuite(B).run(verbose = True) + running ._test_an_element() . . . pass + running ._test_cardinality() . . . pass + running ._test_category() . . . pass + running ._test_elements() . . . + Running the test suite of self.an_element() + running ._test_category() . . . pass + running ._test_eq() . . . pass + running ._test_not_implemented_methods() . . . pass + running ._test_pickling() . . . pass + running ._test_stembridge_local_axioms() . . . pass + pass + running ._test_elements_eq_reflexive() . . . pass + running ._test_elements_eq_symmetric() . . . pass + running ._test_elements_eq_transitive() . . . pass + running ._test_elements_neq() . . . pass + running ._test_enumerated_set_contains() . . . pass + running ._test_enumerated_set_iter_cardinality() . . . pass + running ._test_enumerated_set_iter_list() . . . pass + running ._test_eq() . . . pass + running ._test_fast_iter() . . . pass + running ._test_not_implemented_methods() . . . pass + running ._test_pickling() . . . pass + running ._test_some_elements() . . . pass + running ._test_stembridge_local_axioms() . . . pass + """ + @cached_method + def super_categories(self): + r""" + EXAMPLES:: + + sage: FiniteCrystals().extra_super_categories() + [Category of finite enumerated sets] + """ + return [RegularCrystals().Finite()] + + def example(self, n = 3): + """ + Returns an example of Kirillov-Reshetikhin crystals, as per + :meth:`Category.example`. + + EXAMPLES:: + + sage: B = KirillovReshetikhinCrystals().example(); B + Highest weight crystal of type A_3 of highest weight omega_1 + """ + from sage.combinat.crystals.kirillov_reshetikhin import KirillovReshetikhinCrystal + return KirillovReshetkhinCrystal(['A', n, 1], 1, 1) + + class ParentMethods: + def weight_lattice_realization(self): + """ + Return the weight lattice realization used to express weights + of elements in ``self``. + + The default is to use the non-extended affine weight lattice. + + EXAMPLES:: + + sage: C = crystals.Letters(['A', 5]) + sage: C.weight_lattice_realization() + Ambient space of the Root system of type ['A', 5] + sage: K = crystals.KirillovReshetikhin(['A',2,1], 1, 1) + sage: K.weight_lattice_realization() + Weight lattice of the Root system of type ['A', 2, 1] + """ + F = self.cartan_type().root_system() + return F.weight_lattice(extended=False) + + def digraph(self, subset=None, index_set=None): + r""" + Return the :class:`DiGraph` associated to ``self``. + + INPUT: + + - ``subset`` -- (optional) a subset of vertices for + which the digraph should be constructed + + - ``index_set`` -- (optional) the index set to draw arrows + + .. SEEALSO:: + + :meth:`sage.categories.crystals.Crystals.ParentMethods.digraph` + + EXAMPLES:: + + sage: C = crystals.KirillovReshetikhin(['D',4,1], 2, 1) + sage: G = C.digraph() + sage: G.latex_options() # optional - dot2tex + sage: view(G, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window) + """ + G = Crystals().parent_class.digraph(self, subset, index_set) + if have_dot2tex(): + f = lambda u_v_label: ({"backward": u_v_label[2] == 0}) + G.set_latex_options(edge_options=f) + return G + +class KirillovReshetikhinCrystals(Category_singleton): + """ + Category of Kirillov-Reshetikhin crystals. + """ + @cached_method + def super_categories(self): + r""" + EXAMPLES:: + + sage: RegularCrystals().super_categories() + [Category of crystals] + """ + return [AffineDerivedSubalgebraCrystals()] + + class ParentMethods: + @abstract_method + def r(self): + """ + Return the value `r` in ``self`` written as `B^{r,s}`. + """ + + @abstract_method + def s(self): + """ + Return the value `s` in ``self`` written as `B^{r,s}`. + """ + + class TensorProducts(TensorProductsCategory): + """ + The category of tensor products of Kirillov-Reshetikhin crystals. + """ + diff --git a/src/sage/categories/crystals.py b/src/sage/categories/crystals.py index 252f2e7bf84..af49b244f87 100644 --- a/src/sage/categories/crystals.py +++ b/src/sage/categories/crystals.py @@ -233,7 +233,8 @@ def an_element(self): def weight_lattice_realization(self): """ - Returns the weight lattice realization used to express weights. + Return the weight lattice realization used to express weights + in ``self``. This default implementation uses the ambient space of the root system for (non relabelled) finite types and the @@ -241,6 +242,9 @@ def weight_lattice_realization(self): ambient spaces were partially implemented, and may be changed in the future. + For affine types, this returns the extended weight lattice + by default. + EXAMPLES:: sage: C = crystals.Letters(['A', 5]) @@ -253,6 +257,8 @@ def weight_lattice_realization(self): F = self.cartan_type().root_system() if self.cartan_type().is_finite() and F.ambient_space() is not None: return F.ambient_space() + if self.cartan_type().is_affine(): + return F.weight_lattice(extended=True) return F.weight_lattice() def cartan_type(self): @@ -734,7 +740,7 @@ def crystal_morphism(self, on_gens, codomain=None, def digraph(self, subset=None, index_set=None): """ - Returns the DiGraph associated to ``self``. + Return the :class:`DiGraph` associated to ``self``. INPUT: @@ -809,12 +815,7 @@ def digraph(self, subset=None, index_set=None): .. TODO:: Add more tests. """ from sage.graphs.all import DiGraph - from sage.categories.highest_weight_crystals import HighestWeightCrystals d = {} - if self in HighestWeightCrystals: - f = lambda u_v_label: ({}) - else: - f = lambda u_v_label: ({"backward": u_v_label[2] == 0}) # Parse optional arguments if subset is None: @@ -832,9 +833,8 @@ def digraph(self, subset=None, index_set=None): G = DiGraph(d) if have_dot2tex(): G.set_latex_options(format="dot2tex", - edge_labels = True, - color_by_label = self.cartan_type()._index_set_coloring, - edge_options = f) + edge_labels=True, + color_by_label=self.cartan_type()._index_set_coloring) return G def latex_file(self, filename): diff --git a/src/sage/combinat/crystals/affine.py b/src/sage/combinat/crystals/affine.py index 136a1873c32..3ffaaac9847 100644 --- a/src/sage/combinat/crystals/affine.py +++ b/src/sage/combinat/crystals/affine.py @@ -13,8 +13,7 @@ #**************************************************************************** from sage.misc.abstract_method import abstract_method -from sage.categories.regular_crystals import RegularCrystals -from sage.categories.finite_crystals import FiniteCrystals +from sage.categories.affine_derived_crystals import AffineDerivedSubalgebraCrystals from sage.structure.parent import Parent from sage.structure.unique_representation import UniqueRepresentation from sage.structure.element_wrapper import ElementWrapper @@ -79,7 +78,7 @@ def __classcall__(cls, cartan_type, *args, **options): ct = CartanType(cartan_type) return super(AffineCrystalFromClassical, cls).__classcall__(cls, ct, *args, **options) - def __init__(self, cartan_type, classical_crystal, category = None): + def __init__(self, cartan_type, classical_crystal, category=None): """ Input is an affine Cartan type ``cartan_type``, a classical crystal ``classical_crystal``, and automorphism and its inverse @@ -110,7 +109,7 @@ def __init__(self, cartan_type, classical_crystal, category = None): sage: TestSuite(A).run() """ if category is None: - category = (RegularCrystals(), FiniteCrystals()) + category = AffineDerivedSubalgebraCrystals() self._cartan_type = cartan_type Parent.__init__(self, category = category) self.classical_crystal = classical_crystal; @@ -531,7 +530,7 @@ class AffineCrystalFromClassicalAndPromotion(AffineCrystalFromClassical): [[[2]], [[1]], [[3]]] """ - def __init__(self, cartan_type, classical_crystal, p_automorphism, p_inverse_automorphism, dynkin_node): + def __init__(self, cartan_type, classical_crystal, p_automorphism, p_inverse_automorphism, dynkin_node, category=None): """ Input is an affine Cartan type ``cartan_type``, a classical crystal ``classical_crystal``, and promotion automorphism and its inverse @@ -556,7 +555,7 @@ def __init__(self, cartan_type, classical_crystal, p_automorphism, p_inverse_aut sage: TestSuite(A).run() """ - AffineCrystalFromClassical.__init__(self, cartan_type, classical_crystal) + AffineCrystalFromClassical.__init__(self, cartan_type, classical_crystal, category) self.p_automorphism = p_automorphism self.p_inverse_automorphism = p_inverse_automorphism self.dynkin_node = dynkin_node diff --git a/src/sage/combinat/crystals/kirillov_reshetikhin.py b/src/sage/combinat/crystals/kirillov_reshetikhin.py index 474a8a82f2e..426d816fb19 100644 --- a/src/sage/combinat/crystals/kirillov_reshetikhin.py +++ b/src/sage/combinat/crystals/kirillov_reshetikhin.py @@ -29,8 +29,7 @@ from sage.combinat.combinat import CombinatorialObject from sage.structure.parent import Parent from sage.categories.crystals import CrystalMorphism -from sage.categories.regular_crystals import RegularCrystals -from sage.categories.finite_crystals import FiniteCrystals +from sage.categories.affine_derived_crystals import KirillovReshetikhinCrystals from sage.categories.homset import Hom from sage.categories.map import Map from sage.rings.integer import Integer @@ -457,8 +456,8 @@ def __init__(self, cartan_type, r, s, dual = None): sage: K.s() 1 """ - # We need this here for the classical_decomposition() call - Parent.__init__(self, category = (RegularCrystals(), FiniteCrystals())) + # We need this here for the classic al_decomposition() call + Parent.__init__(self, category=KirillovReshetikhinCrystals()) if dual is None: self._cartan_type = cartan_type else: @@ -466,7 +465,8 @@ def __init__(self, cartan_type, r, s, dual = None): self._r = r self._s = s self._dual = dual - AffineCrystalFromClassical.__init__(self, cartan_type, self.classical_decomposition()) + AffineCrystalFromClassical.__init__(self, cartan_type, self.classical_decomposition(), + KirillovReshetikhinCrystals()) def _repr_(self): """ @@ -493,7 +493,7 @@ def _element_constructor_(self, *args, **options): # Check to make sure it can be converted if elt.cartan_type() != self.cartan_type() \ or elt.parent().r() != self._r or elt.parent().s() != self._s: - raise ValueError("The Kirillov-Reshetikhin tableau must have the same Cartan type and shape") + raise ValueError("the Kirillov-Reshetikhin tableau must have the same Cartan type and shape") to_hw = elt.to_classical_highest_weight() rows = [] @@ -860,7 +860,8 @@ def __init__(self, cartan_type, r, s): KirillovReshetikhinGenericCrystal.__init__(self, cartan_type, r, s) AffineCrystalFromClassicalAndPromotion.__init__(self, cartan_type, self.classical_decomposition(), self.promotion(), self.promotion_inverse(), - self.dynkin_diagram_automorphism(0)) + self.dynkin_diagram_automorphism(0), + KirillovReshetikhinCrystals()) class KirillovReshetikhinCrystalFromPromotionElement(AffineCrystalFromClassicalAndPromotionElement, KirillovReshetikhinGenericCrystalElement): @@ -1974,7 +1975,8 @@ def __init__(self, cartan_type, r, s): sage: TestSuite(K).run() """ KirillovReshetikhinGenericCrystal.__init__(self, cartan_type, r ,s) - AffineCrystalFromClassical.__init__(self, cartan_type, self.classical_decomposition()) + AffineCrystalFromClassical.__init__(self, cartan_type, self.classical_decomposition(), + KirillovReshetikhinCrystals()) def classical_decomposition(self): r""" diff --git a/src/sage/combinat/rigged_configurations/kr_tableaux.py b/src/sage/combinat/rigged_configurations/kr_tableaux.py index 1637d297003..861a7e7c893 100644 --- a/src/sage/combinat/rigged_configurations/kr_tableaux.py +++ b/src/sage/combinat/rigged_configurations/kr_tableaux.py @@ -49,8 +49,7 @@ from sage.structure.parent import Parent from sage.structure.element_wrapper import ElementWrapper -from sage.categories.finite_crystals import FiniteCrystals -from sage.categories.regular_crystals import RegularCrystals +from sage.categories.affine_derived_crystals import KirillovReshetikhinCrystals from sage.combinat.crystals.letters import CrystalOfLetters, EmptyLetter from sage.combinat.root_system.cartan_type import CartanType @@ -285,7 +284,7 @@ def __init__(self, cartan_type, r, s): self._s = s self._cartan_type = cartan_type - Parent.__init__(self, category=(RegularCrystals(), FiniteCrystals())) + Parent.__init__(self, category=KirillovReshetikhinCrystals()) self.letters = CrystalOfLetters(cartan_type.classical()) self.module_generators = self._build_module_generators() diff --git a/src/sage/combinat/rigged_configurations/rigged_configurations.py b/src/sage/combinat/rigged_configurations/rigged_configurations.py index 3078d3b9e97..b48e90b35bf 100644 --- a/src/sage/combinat/rigged_configurations/rigged_configurations.py +++ b/src/sage/combinat/rigged_configurations/rigged_configurations.py @@ -29,8 +29,7 @@ from sage.combinat.misc import IterableFunctionCall import sage.combinat.tableau as tableau from sage.rings.all import QQ -from sage.categories.finite_crystals import FiniteCrystals -from sage.categories.regular_crystals import RegularCrystals +from sage.categories.affine_derived_crystals import KirillovReshetikhinCrystals from sage.combinat.root_system.cartan_type import CartanType from sage.combinat.cartesian_product import CartesianProduct from sage.combinat.rigged_configurations.kleber_tree import KleberTree, VirtualKleberTree @@ -405,6 +404,8 @@ def __classcall_private__(cls, cartan_type, B): # Standardize B input into a tuple of tuples B = tuple(tuple(factor) for factor in B) + if not B: + raise ValueError("must contain at least one factor") if cartan_type.type() == 'BC': # Type `A_{2n}^{(2)}` return RCTypeA2Even(cartan_type, B) @@ -442,7 +443,7 @@ def __init__(self, cartan_type, B): self._rc_index = cl.index_set() # We store the Cartan matrix for the vacancy number calculations for speed self._cartan_matrix = cl.cartan_matrix() - Parent.__init__(self, category=(RegularCrystals(), FiniteCrystals())) + Parent.__init__(self, category=KirillovReshetikhinCrystals().TensorProducts()) def _repr_(self): """ diff --git a/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py b/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py index 440d06e8c6d..f071e9add28 100644 --- a/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py +++ b/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py @@ -112,8 +112,8 @@ def __getitem__(self, i): [[1], [2], [3]] (X) [[1], [2]] """ if self._cache is None: - self._cache = [x.to_tensor_product_of_kirillov_reshetikhin_tableaux() - for x in self.tp_krt.rigged_configurations().module_generators] + self._cache = tuple([x.to_tensor_product_of_kirillov_reshetikhin_tableaux() + for x in self.tp_krt.rigged_configurations().module_generators]) return self._cache[i] def __iter__(self): @@ -130,8 +130,8 @@ def __iter__(self): [[1], [-1]] """ if self._cache is None: - self._cache = [x.to_tensor_product_of_kirillov_reshetikhin_tableaux() - for x in self.tp_krt.rigged_configurations().module_generators] + self._cache = tuple([x.to_tensor_product_of_kirillov_reshetikhin_tableaux() + for x in self.tp_krt.rigged_configurations().module_generators]) for x in self._cache: yield x @@ -151,7 +151,8 @@ def __repr__(self): @cached_method def cardinality(self): """ - Return the cardinality of ``self`` which is the number of highest weight elements. + Return the cardinality of ``self``, which is the number of + highest weight elements. EXAMPLES:: From 7b4ae6be548aee7a87ca79dc0aee34dffe1ab202 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 26 Aug 2015 21:59:56 -0500 Subject: [PATCH 011/452] Moving methods to KR crystals category and simplifying weight_lattice_realization. --- .../categories/affine_derived_crystals.py | 299 +++++++++++++++++- src/sage/categories/crystals.py | 31 ++ src/sage/combinat/crystals/affinization.py | 12 - src/sage/combinat/crystals/alcove_path.py | 21 -- .../crystals/generalized_young_walls.py | 12 - .../combinat/crystals/kirillov_reshetikhin.py | 125 +------- .../combinat/crystals/monomial_crystals.py | 26 +- .../rigged_configurations/kr_tableaux.py | 35 -- .../rigged_configurations.py | 32 +- 9 files changed, 337 insertions(+), 256 deletions(-) diff --git a/src/sage/categories/affine_derived_crystals.py b/src/sage/categories/affine_derived_crystals.py index 0c57189f1b4..9d80325d434 100644 --- a/src/sage/categories/affine_derived_crystals.py +++ b/src/sage/categories/affine_derived_crystals.py @@ -25,13 +25,14 @@ class AffineDerivedSubalgebraCrystals(Category_singleton): EXAMPLES:: - sage: C = FiniteCrystals() + sage: from sage.categories.affine_derived_crystals import AffineDerivedSubalgebraCrystals + sage: C = AffineDerivedSubalgebraCrystals() sage: C - Category of finite crystals + Category of affine derived subalgebra crystals sage: C.super_categories() - [Category of crystals, Category of finite enumerated sets] + [Category of finite regular crystals] sage: C.example() - Highest weight crystal of type A_3 of highest weight omega_1 + Kirillov-Reshetikhin crystal of type ['A', 3, 1] with (r,s)=(1,1) TESTS:: @@ -68,8 +69,9 @@ def super_categories(self): r""" EXAMPLES:: - sage: FiniteCrystals().extra_super_categories() - [Category of finite enumerated sets] + sage: from sage.categories.affine_derived_crystals import AffineDerivedSubalgebraCrystals + sage: AffineDerivedSubalgebraCrystals().super_categories() + [Category of finite regular crystals] """ return [RegularCrystals().Finite()] @@ -80,11 +82,12 @@ def example(self, n = 3): EXAMPLES:: - sage: B = KirillovReshetikhinCrystals().example(); B - Highest weight crystal of type A_3 of highest weight omega_1 + sage: from sage.categories.affine_derived_crystals import AffineDerivedSubalgebraCrystals + sage: B = AffineDerivedSubalgebraCrystals().example(); B + Kirillov-Reshetikhin crystal of type ['A', 3, 1] with (r,s)=(1,1) """ from sage.combinat.crystals.kirillov_reshetikhin import KirillovReshetikhinCrystal - return KirillovReshetkhinCrystal(['A', n, 1], 1, 1) + return KirillovReshetikhinCrystal(['A', n, 1], 1, 1) class ParentMethods: def weight_lattice_realization(self): @@ -126,6 +129,8 @@ def digraph(self, subset=None, index_set=None): sage: C = crystals.KirillovReshetikhin(['D',4,1], 2, 1) sage: G = C.digraph() sage: G.latex_options() # optional - dot2tex + LaTeX options for Digraph on 29 vertices: + {...'edge_options': at 0x...>,...} sage: view(G, tightpage=True) # optional - dot2tex graphviz, not tested (opens external window) """ G = Crystals().parent_class.digraph(self, subset, index_set) @@ -143,26 +148,292 @@ def super_categories(self): r""" EXAMPLES:: - sage: RegularCrystals().super_categories() - [Category of crystals] + sage: from sage.categories.affine_derived_crystals import KirillovReshetikhinCrystals + sage: KirillovReshetikhinCrystals().super_categories() + [Category of affine derived subalgebra crystals] """ - return [AffineDerivedSubalgebraCrystals()] + return [AffineDerivedSubalgebraCrystals().Finite()] class ParentMethods: @abstract_method def r(self): - """ + r""" Return the value `r` in ``self`` written as `B^{r,s}`. + + EXAMPLES:: + + sage: K = crystals.KirillovReshetikhin(['A',3,1], 2,4) + sage: K.r() + 2 """ @abstract_method def s(self): - """ + r""" Return the value `s` in ``self`` written as `B^{r,s}`. + + EXAMPLES:: + + sage: K = crystals.KirillovReshetikhin(['A',3,1], 2,4) + sage: K.s() + 4 + """ + + @abstract_method + def classical_decomposition(self): + """ + Return the classical decomposition of ``self``. + + EXAMPLES:: + + sage: K = crystals.KirillovReshetikhin(['A',3,1], 2,2) + sage: K.classical_decomposition() + The crystal of tableaux of type ['A', 3] and shape(s) [[2, 2]] + """ + + @cached_method + def classically_highest_weight_vectors(self): + """ + Return the classically highest weight elements of ``self``. + """ + I0 = self.cartan_type().classical().index_set() + return tuple([x for x in self if x.is_highest_weight(I0)]) + + @cached_method + def maximal_vector(self): + r""" + Return the unique element of classical weight `s \Lambda_r` + in ``self``. + + EXAMPLES:: + + sage: K = crystals.KirillovReshetikhin(['C',2,1],1,2) + sage: K.module_generator() + [[1, 1]] + sage: K = crystals.KirillovReshetikhin(['E',6,1],1,1) + sage: K.module_generator() + [(1,)] + + sage: K = crystals.KirillovReshetikhin(['D',4,1],2,1) + sage: K.module_generator() + [[1], [2]] """ + R = self.weight_lattice_realization() + Lambda = R.fundamental_weights() + r = self.r() + s = self.s() + weight = s*Lambda[r] - s*Lambda[0] * Lambda[r].level() / Lambda[0].level() + + # First check the module generators as it is likely to be in here + for b in self.module_generators: + if b.weight() == weight: + return b + + # Otherwise check all of the elements + for b in self: + if b not in self.module_generators and b.weight() == weight: + return b + + assert False, "BUG: invalid Kirillov-Reshetikhin crystal" + + # TODO: Should this be in one of the super categories? + def affinization(self): + """ + Return the corresponding affinization crystal of ``self``. + + EXAMPLES:: + + sage: K = crystals.KirillovReshetikhin(['A',2,1], 1, 1) + sage: K.affinization() + Affinization of Kirillov-Reshetikhin crystal of type ['A', 2, 1] with (r,s)=(1,1) + + sage: K = crystals.KirillovReshetikhin(['A',2,1], 1, 1, model='KR') + sage: K.affinization() + Affinization of Kirillov-Reshetikhin tableaux of type ['A', 2, 1] and shape (1, 1) + """ + from sage.combinat.crystals.affinization import AffinizationOfCrystal + return AffinizationOfCrystal(self) + + @cached_method + def R_matrix(self, K): + r""" + Return the combinatorial `R`-matrix of ``self`` to ``K``. + + The *combinatorial* `R`-*matrix* is the affine crystal + isomorphism `R : L \otimes K \to K \otimes L` which maps + `u_{L} \otimes u_K` to `u_K \otimes u_{L}`, where `u_K` + is the unique element in `K = B^{r,s}` of weight + `s\Lambda_r - s c \Lambda_0` (see :meth:`module_generator`). + + INPUT: + + - ``self`` -- a crystal `L` + - ``K`` -- a Kirillov-Reshetikhin crystal of the same type as `L` + + EXAMPLES:: + + sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) + sage: L = crystals.KirillovReshetikhin(['A',2,1],1,2) + sage: f = K.R_matrix(L) + sage: [[b,f(b)] for b in crystals.TensorProduct(K,L)] + [[[[[1]], [[1, 1]]], [[[1, 1]], [[1]]]], + [[[[1]], [[1, 2]]], [[[1, 1]], [[2]]]], + [[[[1]], [[2, 2]]], [[[1, 2]], [[2]]]], + [[[[1]], [[1, 3]]], [[[1, 1]], [[3]]]], + [[[[1]], [[2, 3]]], [[[1, 2]], [[3]]]], + [[[[1]], [[3, 3]]], [[[1, 3]], [[3]]]], + [[[[2]], [[1, 1]]], [[[1, 2]], [[1]]]], + [[[[2]], [[1, 2]]], [[[2, 2]], [[1]]]], + [[[[2]], [[2, 2]]], [[[2, 2]], [[2]]]], + [[[[2]], [[1, 3]]], [[[2, 3]], [[1]]]], + [[[[2]], [[2, 3]]], [[[2, 2]], [[3]]]], + [[[[2]], [[3, 3]]], [[[2, 3]], [[3]]]], + [[[[3]], [[1, 1]]], [[[1, 3]], [[1]]]], + [[[[3]], [[1, 2]]], [[[1, 3]], [[2]]]], + [[[[3]], [[2, 2]]], [[[2, 3]], [[2]]]], + [[[[3]], [[1, 3]]], [[[3, 3]], [[1]]]], + [[[[3]], [[2, 3]]], [[[3, 3]], [[2]]]], + [[[[3]], [[3, 3]]], [[[3, 3]], [[3]]]]] + + sage: K = crystals.KirillovReshetikhin(['D',4,1],1,1) + sage: L = crystals.KirillovReshetikhin(['D',4,1],2,1) + sage: f = K.R_matrix(L) + sage: T = crystals.TensorProduct(K,L) + sage: b = T( K(rows=[[1]]), L(rows=[]) ) + sage: f(b) + [[[2], [-2]], [[1]]] + + Alternatively, one can compute the combinatorial `R`-matrix + using the isomorphism method of digraphs:: + + sage: K1 = crystals.KirillovReshetikhin(['A',2,1],1,1) + sage: K2 = crystals.KirillovReshetikhin(['A',2,1],2,1) + sage: T1 = crystals.TensorProduct(K1,K2) + sage: T2 = crystals.TensorProduct(K2,K1) + sage: T1.digraph().is_isomorphic(T2.digraph(), edge_labels = True, certify = True) #todo: not implemented (see #10904 and #10549) + (True, {[[[1]], [[2], [3]]]: [[[1], [3]], [[2]]], [[[3]], [[2], [3]]]: [[[2], [3]], [[3]]], + [[[3]], [[1], [3]]]: [[[1], [3]], [[3]]], [[[1]], [[1], [3]]]: [[[1], [3]], [[1]]], [[[1]], + [[1], [2]]]: [[[1], [2]], [[1]]], [[[2]], [[1], [2]]]: [[[1], [2]], [[2]]], [[[3]], + [[1], [2]]]: [[[2], [3]], [[1]]], [[[2]], [[1], [3]]]: [[[1], [2]], [[3]]], [[[2]], [[2], [3]]]: [[[2], [3]], [[2]]]}) + """ + from sage.combinat.crystals.tensor_product import TensorProductOfCrystals + T1 = TensorProductOfCrystals(self, K) + T2 = TensorProductOfCrystals(K, self) + gen1 = T1( self.maximal_vector(), K.maximal_vector() ) + gen2 = T2( K.maximal_vector(), self.maximal_vector() ) + g = { gen1 : gen2 } + return T1.crystal_morphism(g, check=False) + + def q_dimension(self, q=None, prec=None, use_product=False): + """ + Return the `q`-dimension of ``self``. + + The `q`-dimension of a KR crystal is defined as the `q`-dimension of + the underlying classical crystal. + + EXAMPLES:: + + sage: KRC = crystals.KirillovReshetikhin(['A',2,1], 2,2) + sage: KRC.q_dimension() + q^4 + q^3 + 2*q^2 + q + 1 + sage: KRC = crystals.KirillovReshetikhin(['D',4,1], 2,1) + sage: KRC.q_dimension() + q^10 + q^9 + 3*q^8 + 3*q^7 + 4*q^6 + 4*q^5 + 4*q^4 + 3*q^3 + 3*q^2 + q + 2 + """ + return self.classical_decomposition().q_dimension(q, prec, use_product) + + class ElementMethods: + def lusztig_involution(self): + r""" + Return the result of the classical Lusztig involution on ``self``. + + EXAMPLES:: + + sage: KRT = crystals.KirillovReshetikhin(['D',4,1], 2, 3, model='KR') + sage: mg = KRT.module_generators[1] + sage: mg.lusztig_involution() + [[-2, -2, 1], [-1, -1, 2]] + sage: elt = mg.f_string([2,1,3,2]); elt + [[3, -2, 1], [4, -1, 2]] + sage: elt.lusztig_involution() + [[-4, -2, 1], [-3, -1, 2]] + """ + Cl = self.parent().cartan_type().classical() + I = Cl.index_set() + aut = Cl.opposition_automorphism() + hw = self.to_highest_weight(I)[1] + hw.reverse() + return self.to_lowest_weight(I)[0].e_string(aut[i] for i in hw) class TensorProducts(TensorProductsCategory): """ The category of tensor products of Kirillov-Reshetikhin crystals. """ + class ParentMethods: + @cached_method + def classically_highest_weight_vectors(self): + """ + Return the classically highest weight elements of ``self``. + + This works by using a backtracking algorithm since if + `b_2 \otimes b_1` is classically highest weight then `b_1` + is classically highest weight. + + EXAMPLES:: + + sage: C = crystals.Tableaux(['D',4], shape=[2,2]) + sage: D = crystals.Tableaux(['D',4], shape=[1]) + sage: T = crystals.TensorProduct(D, C) + sage: T.highest_weight_vectors() + ([[[1]], [[1, 1], [2, 2]]], + [[[3]], [[1, 1], [2, 2]]], + [[[-2]], [[1, 1], [2, 2]]]) + sage: L = filter(lambda x: x.is_highest_weight(), T) + sage: tuple(L) == T.highest_weight_vectors() + True + """ + n = len(self.crystals) + I0 = self.cartan_type().classical().index_set() + it = [ iter(self.crystals[-1].classically_highest_weight_vectors()) ] + path = [] + ret = [] + while it: + try: + x = next(it[-1]) + except StopIteration: + it.pop() + if path: + path.pop(0) + continue + + b = self.element_class(self, [x] + path) + if not b.is_highest_weight(): + continue + path.insert(0, x) + if len(path) == n: + ret.append(b) + path.pop(0) + else: + it.append( iter(self.crystals[-len(path)-1]) ) + return tuple(ret) + + def cardinality(self): + """ + Return the cardinality of ``self``. + + EXAMPLES:: + + sage: RC = RiggedConfigurations(['A', 3, 1], [[3, 2], [1, 2]]) + sage: RC.cardinality() + 100 + sage: RC = RiggedConfigurations(['B', 3, 1], [[2,2],[1,2]]) + sage: RC.cardinality() + 5130 + sage: RC = RiggedConfigurations(['E', 7, 1], [[1,1]]) + sage: RC.cardinality() + 134 + """ + CWLR = self.cartan_type().classical().root_system().ambient_space() + return sum(CWLR.weyl_dimension(mg.classical_weight()) + for mg in self.classically_highest_weight_vectors()) diff --git a/src/sage/categories/crystals.py b/src/sage/categories/crystals.py index af49b244f87..936c8e6ff13 100644 --- a/src/sage/categories/crystals.py +++ b/src/sage/categories/crystals.py @@ -253,6 +253,37 @@ def weight_lattice_realization(self): sage: K = crystals.KirillovReshetikhin(['A',2,1], 1, 1) sage: K.weight_lattice_realization() Weight lattice of the Root system of type ['A', 2, 1] + + TESTS: + + Check that crystals have the correct weight lattice realization:: + + sage: A = crystals.KirillovReshetikhin(['A',2,1], 1, 1).affinization() + sage: A.weight_lattice_realization() + Extended weight lattice of the Root system of type ['A', 2, 1] + + sage: B = crystals.AlcovePaths(['A',2,1],[1,0,0]) + sage: B.weight_lattice_realization() + Extended weight lattice of the Root system of type ['A', 2, 1] + + sage: C = crystals.AlcovePaths("B3",[1,0,0]) + sage: C.weight_lattice_realization() + Ambient space of the Root system of type ['B', 3] + + sage: M = crystals.infinity.NakajimaMonomials(['A',3,2]) + sage: M.weight_lattice_realization() + Extended weight lattice of the Root system of type ['B', 2, 1]^* + sage: M = crystals.infinity.NakajimaMonomials(['A',2]) + sage: M.weight_lattice_realization() + Ambient space of the Root system of type ['A', 2] + sage: A = CartanMatrix([[2,-3],[-3,2]]) + sage: M = crystals.infinity.NakajimaMonomials(A) + sage: M.weight_lattice_realization() + Weight lattice of the Root system of type Dynkin diagram of rank 2 + + sage: Y = crystals.infinity.GeneralizedYoungWalls(3) + sage: Y.weight_lattice_realization() + Extended weight lattice of the Root system of type ['A', 3, 1] """ F = self.cartan_type().root_system() if self.cartan_type().is_finite() and F.ambient_space() is not None: diff --git a/src/sage/combinat/crystals/affinization.py b/src/sage/combinat/crystals/affinization.py index 8bd5d7bf212..16062b6fba3 100644 --- a/src/sage/combinat/crystals/affinization.py +++ b/src/sage/combinat/crystals/affinization.py @@ -104,18 +104,6 @@ def _repr_(self): """ return "Affinization of {}".format(self._B) - def weight_lattice_realization(self): - """ - Return the weight lattice realization of ``self``. - - EXAMPLES:: - - sage: A = crystals.KirillovReshetikhin(['A',2,1], 1, 1).affinization() - sage: A.weight_lattice_realization() - Extended weight lattice of the Root system of type ['A', 2, 1] - """ - return self.cartan_type().root_system().weight_lattice(extended=True) - # TODO: This should become unnecessary once we have a proper category for KR crystals def digraph(self, subset=None, index_set=None): """ diff --git a/src/sage/combinat/crystals/alcove_path.py b/src/sage/combinat/crystals/alcove_path.py index b8cacdf58c2..d1a73ae4d2b 100644 --- a/src/sage/combinat/crystals/alcove_path.py +++ b/src/sage/combinat/crystals/alcove_path.py @@ -502,27 +502,6 @@ def digraph_fast(self, depth=None): return DiGraph(G) - def weight_lattice_realization(self): - r""" - Return the weight lattice realization of ``self``. - - EXAMPLES:: - - sage: B = crystals.AlcovePaths(['A',2,1],[1,0,0]) - sage: B.weight_lattice_realization() - Extended weight lattice of the Root system of type ['A', 2, 1] - - sage: C = crystals.AlcovePaths("B3",[1,0,0]) - sage: C.weight_lattice_realization() - Ambient space of the Root system of type ['B', 3] - """ - F = self.cartan_type().root_system() - if self.cartan_type().is_affine(): - return F.weight_lattice(extended=True) - if self.cartan_type().is_finite() and F.ambient_space() is not None: - return F.ambient_space() - return F.weight_lattice() - class CrystalOfAlcovePathsElement(ElementWrapper): """ Crystal of alcove paths element. diff --git a/src/sage/combinat/crystals/generalized_young_walls.py b/src/sage/combinat/crystals/generalized_young_walls.py index 14bd73956ec..bfa60933f6f 100644 --- a/src/sage/combinat/crystals/generalized_young_walls.py +++ b/src/sage/combinat/crystals/generalized_young_walls.py @@ -786,18 +786,6 @@ def _repr_(self): """ return "Crystal of generalized Young walls of type {}".format(self._cartan_type) - def weight_lattice_realization(self): - r""" - Return the extended affine weight lattice of ``self``. - - EXAMPLES:: - - sage: Y = crystals.infinity.GeneralizedYoungWalls(3) - sage: Y.weight_lattice_realization() - Extended weight lattice of the Root system of type ['A', 3, 1] - """ - return RootSystem(self._cartan_type).weight_lattice(extended=True) - ######################## ## Highest weight GYW ## diff --git a/src/sage/combinat/crystals/kirillov_reshetikhin.py b/src/sage/combinat/crystals/kirillov_reshetikhin.py index 426d816fb19..99d50bb7a41 100644 --- a/src/sage/combinat/crystals/kirillov_reshetikhin.py +++ b/src/sage/combinat/crystals/kirillov_reshetikhin.py @@ -506,21 +506,10 @@ def _element_constructor_(self, *args, **options): return hw_elt.f_string(f_str) return AffineCrystalFromClassical._element_constructor_(self, *args, **options) - @abstract_method - def classical_decomposition(self): - """ - Return the classical decomposition of ``self``. - - EXAMPLES:: - - sage: K = crystals.KirillovReshetikhin(['A',3,1], 2,2) - sage: K.classical_decomposition() - The crystal of tableaux of type ['A', 3] and shape(s) [[2, 2]] - """ - def module_generator(self): r""" - Returns the unique module generator of classical weight `s \Lambda_r` of a Kirillov-Reshetikhin crystal `B^{r,s}` + Return the unique module generator of classical weight + `s \Lambda_r` of a Kirillov-Reshetikhin crystal `B^{r,s}` EXAMPLES:: @@ -576,9 +565,9 @@ def is_perfect(self): REFERENCES: - .. [FOS2010] G. Fourier, M. Okado, A. Schilling. - Perfectness of Kirillov-Reshetikhin crystals for nonexceptional types - Contemp. Math. 506 (2010) 127-143 ( arXiv:0811.1604 [math.RT] ) + .. [FOS2010] G. Fourier, M. Okado, A. Schilling. + Perfectness of Kirillov-Reshetikhin crystals for nonexceptional types + Contemp. Math. 506 (2010) 127-143 ( :arxiv:`0811.1604` ) EXAMPLES:: @@ -627,75 +616,6 @@ def level(self): raise ValueError("this crystal is not perfect") return self.s()/self.cartan_type().c()[self.r()] - @cached_method - def R_matrix(self, K): - r""" - INPUT: - - - ``self`` -- a crystal `L` - - ``K`` -- a Kirillov-Reshetikhin crystal of the same type as `L` - - Returns the *combinatorial `R`-matrix* from `L \otimes K \to K - \otimes L`, where the combinatorial `R`-matrix is the affine - crystal isomorphism which maps `u_{L} \otimes u_K` to `u_K - \otimes u_{L}`, where `u_K` is the unique element in `K = - B^{r,s}` of weight `s\Lambda_r - s c \Lambda_0` (see - module_generator). - - EXAMPLES:: - - sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) - sage: L = crystals.KirillovReshetikhin(['A',2,1],1,2) - sage: f = K.R_matrix(L) - sage: [[b,f(b)] for b in crystals.TensorProduct(K,L)] - [[[[[1]], [[1, 1]]], [[[1, 1]], [[1]]]], - [[[[1]], [[1, 2]]], [[[1, 1]], [[2]]]], - [[[[1]], [[2, 2]]], [[[1, 2]], [[2]]]], - [[[[1]], [[1, 3]]], [[[1, 1]], [[3]]]], - [[[[1]], [[2, 3]]], [[[1, 2]], [[3]]]], - [[[[1]], [[3, 3]]], [[[1, 3]], [[3]]]], - [[[[2]], [[1, 1]]], [[[1, 2]], [[1]]]], - [[[[2]], [[1, 2]]], [[[2, 2]], [[1]]]], - [[[[2]], [[2, 2]]], [[[2, 2]], [[2]]]], - [[[[2]], [[1, 3]]], [[[2, 3]], [[1]]]], - [[[[2]], [[2, 3]]], [[[2, 2]], [[3]]]], - [[[[2]], [[3, 3]]], [[[2, 3]], [[3]]]], - [[[[3]], [[1, 1]]], [[[1, 3]], [[1]]]], - [[[[3]], [[1, 2]]], [[[1, 3]], [[2]]]], - [[[[3]], [[2, 2]]], [[[2, 3]], [[2]]]], - [[[[3]], [[1, 3]]], [[[3, 3]], [[1]]]], - [[[[3]], [[2, 3]]], [[[3, 3]], [[2]]]], - [[[[3]], [[3, 3]]], [[[3, 3]], [[3]]]]] - - sage: K = crystals.KirillovReshetikhin(['D',4,1],1,1) - sage: L = crystals.KirillovReshetikhin(['D',4,1],2,1) - sage: f = K.R_matrix(L) - sage: T = crystals.TensorProduct(K,L) - sage: b = T( K(rows=[[1]]), L(rows=[]) ) - sage: f(b) - [[[2], [-2]], [[1]]] - - Alternatively, one can compute the combinatorial `R`-matrix using the isomorphism method - of digraphs:: - - sage: K1 = crystals.KirillovReshetikhin(['A',2,1],1,1) - sage: K2 = crystals.KirillovReshetikhin(['A',2,1],2,1) - sage: T1 = crystals.TensorProduct(K1,K2) - sage: T2 = crystals.TensorProduct(K2,K1) - sage: T1.digraph().is_isomorphic(T2.digraph(), edge_labels = True, certify = True) #todo: not implemented (see #10904 and #10549) - (True, {[[[1]], [[2], [3]]]: [[[1], [3]], [[2]]], [[[3]], [[2], [3]]]: [[[2], [3]], [[3]]], - [[[3]], [[1], [3]]]: [[[1], [3]], [[3]]], [[[1]], [[1], [3]]]: [[[1], [3]], [[1]]], [[[1]], - [[1], [2]]]: [[[1], [2]], [[1]]], [[[2]], [[1], [2]]]: [[[1], [2]], [[2]]], [[[3]], - [[1], [2]]]: [[[2], [3]], [[1]]], [[[2]], [[1], [3]]]: [[[1], [2]], [[3]]], [[[2]], [[2], [3]]]: [[[2], [3]], [[2]]]}) - """ - T1 = TensorProductOfCrystals(self, K) - T2 = TensorProductOfCrystals(K, self) - gen1 = T1( self.module_generator(), K.module_generator() ) - gen2 = T2( K.module_generator(), self.module_generator() ) - g = { gen1 : gen2 } - return T1.crystal_morphism(g, check=False) - - @cached_method def kirillov_reshetikhin_tableaux(self): """ Return the corresponding set of @@ -710,37 +630,6 @@ def kirillov_reshetikhin_tableaux(self): from sage.combinat.rigged_configurations.kr_tableaux import KirillovReshetikhinTableaux return KirillovReshetikhinTableaux(self.cartan_type(), self._r, self._s) - def affinization(self): - """ - Return the corresponding affinization crystal of ``self``. - - EXAMPLES:: - - sage: K = crystals.KirillovReshetikhin(['A',2,1], 1, 1) - sage: K.affinization() - Affinization of Kirillov-Reshetikhin crystal of type ['A', 2, 1] with (r,s)=(1,1) - """ - from sage.combinat.crystals.affinization import AffinizationOfCrystal - return AffinizationOfCrystal(self) - - def q_dimension(self, q=None, prec=None, use_product=False): - """ - Return the `q`-dimension of ``self``. - - The `q`-dimension of a KR crystal is defined as the `q`-dimension of - the underlying classical crystal. - - EXAMPLES:: - - sage: KRC = crystals.KirillovReshetikhin(['A',2,1], 2,2) - sage: KRC.q_dimension() - q^4 + q^3 + 2*q^2 + q + 1 - sage: KRC = crystals.KirillovReshetikhin(['D',4,1], 2,1) - sage: KRC.q_dimension() - q^10 + q^9 + 3*q^8 + 3*q^7 + 4*q^6 + 4*q^5 + 4*q^4 + 3*q^3 + 3*q^2 + q + 2 - """ - return self.classical_decomposition().q_dimension(q, prec, use_product) - class KirillovReshetikhinGenericCrystalElement(AffineCrystalFromClassicalElement): """ Abstract class for all Kirillov-Reshetikhin crystal elements. @@ -3019,11 +2908,11 @@ def _element_constructor_(self, *args, **options): # Check to make sure it can be converted if elt.cartan_type() != self.cartan_type() \ or elt.parent().r() != self._r or elt.parent().s() != self._s: - raise ValueError("The Kirillov-Reshetikhin tableau must have the same Cartan type and shape") + raise ValueError("the Kirillov-Reshetikhin tableau must have the same Cartan type and shape") to_hw = elt.to_classical_highest_weight() f_str = reversed(to_hw[1]) - return self.module_generator().f_string(f_str) + return self.maximal_vector().f_string(f_str) return KirillovReshetikhinCrystalFromPromotion._element_constructor_(self, *args, **options) def classical_decomposition(self): diff --git a/src/sage/combinat/crystals/monomial_crystals.py b/src/sage/combinat/crystals/monomial_crystals.py index a1c2afa155a..2f4ac01c582 100644 --- a/src/sage/combinat/crystals/monomial_crystals.py +++ b/src/sage/combinat/crystals/monomial_crystals.py @@ -916,7 +916,7 @@ def _repr_(self): def cardinality(self): r""" - Return the cardinality of ``self``, which is always `\infty`. + Return the cardinality of ``self``, which is always `\infty`.i EXAMPLES:: @@ -926,30 +926,6 @@ def cardinality(self): """ return Infinity - def weight_lattice_realization(self): - r""" - Return the weight lattice realization of ``self``. - - EXAMPLES:: - - sage: M = crystals.infinity.NakajimaMonomials(['A',3,2]) - sage: M.weight_lattice_realization() - Extended weight lattice of the Root system of type ['B', 2, 1]^* - sage: M = crystals.infinity.NakajimaMonomials(['A',2]) - sage: M.weight_lattice_realization() - Ambient space of the Root system of type ['A', 2] - sage: A = CartanMatrix([[2,-3],[-3,2]]) - sage: M = crystals.infinity.NakajimaMonomials(A) - sage: M.weight_lattice_realization() - Weight lattice of the Root system of type Dynkin diagram of rank 2 - """ - F = self.cartan_type().root_system() - if self.cartan_type().is_finite() and F.ambient_space() is not None: - return F.ambient_space() - if self.cartan_type().is_affine(): - return F.weight_lattice(extended=True) - return F.weight_lattice() - class CrystalOfNakajimaMonomialsElement(NakajimaYMonomial): r""" Element class for diff --git a/src/sage/combinat/rigged_configurations/kr_tableaux.py b/src/sage/combinat/rigged_configurations/kr_tableaux.py index 861a7e7c893..9ec8846368e 100644 --- a/src/sage/combinat/rigged_configurations/kr_tableaux.py +++ b/src/sage/combinat/rigged_configurations/kr_tableaux.py @@ -502,19 +502,6 @@ def kirillov_reshetikhin_crystal(self): """ return KashiwaraNakashimaTableaux(self._cartan_type, self._r, self._s) - def affinization(self): - """ - Return the corresponding affinization crystal of ``self``. - - EXAMPLES:: - - sage: K = crystals.KirillovReshetikhin(['A',2,1], 1, 1, model='KR') - sage: K.affinization() - Affinization of Kirillov-Reshetikhin tableaux of type ['A', 2, 1] and shape (1, 1) - """ - from sage.combinat.crystals.affinization import AffinizationOfCrystal - return AffinizationOfCrystal(self) - def classical_decomposition(self): """ Return the classical crystal decomposition of ``self``. @@ -1386,28 +1373,6 @@ def phi(self, i): return self.to_kirillov_reshetikhin_crystal().phi0() return TensorProductOfRegularCrystalsElement.phi(self, i) - def lusztig_involution(self): - r""" - Return the result of the classical Lusztig involution on ``self``. - - EXAMPLES:: - - sage: KRT = crystals.KirillovReshetikhin(['D',4,1], 2, 3, model='KR') - sage: mg = KRT.module_generators[1] - sage: mg.lusztig_involution() - [[-2, -2, 1], [-1, -1, 2]] - sage: elt = mg.f_string([2,1,3,2]); elt - [[3, -2, 1], [4, -1, 2]] - sage: elt.lusztig_involution() - [[-4, -2, 1], [-3, -1, 2]] - """ - Cl = self.parent().cartan_type().classical() - I = Cl.index_set() - aut = Cl.opposition_automorphism() - hw = self.to_highest_weight(I)[1] - hw.reverse() - return self.to_lowest_weight(I)[0].e_string(aut[i] for i in hw) - def left_split(self): r""" Return the image of ``self`` under the left column splitting map. diff --git a/src/sage/combinat/rigged_configurations/rigged_configurations.py b/src/sage/combinat/rigged_configurations/rigged_configurations.py index b48e90b35bf..f7aec5ed40c 100644 --- a/src/sage/combinat/rigged_configurations/rigged_configurations.py +++ b/src/sage/combinat/rigged_configurations/rigged_configurations.py @@ -682,6 +682,19 @@ def _blocks_to_values(self, blocks): values[-1].extend(block) return values + def classically_highest_weight_vectors(self): + """ + Return the classically highest weight elements of ``self``. + + TESTS:: + + sage: RC = RiggedConfigurations(['A', 4, 1], [[2, 2]]) + sage: ascii_art(RC.classically_highest_weight_vectors()) + ( ) + ( (/) (/) (/) (/) ) + """ + return self.module_generators + def _element_constructor_(self, *lst, **options): """ Construct a ``RiggedConfigurationElement``. @@ -850,25 +863,6 @@ def tensor_product_of_kirillov_reshetikhin_tableaux(self): from sage.combinat.rigged_configurations.tensor_product_kr_tableaux import TensorProductOfKirillovReshetikhinTableaux return TensorProductOfKirillovReshetikhinTableaux(self._cartan_type, self.dims) - def cardinality(self): - """ - Return the cardinality of ``self``. - - EXAMPLES:: - - sage: RC = RiggedConfigurations(['A', 3, 1], [[3, 2], [1, 2]]) - sage: RC.cardinality() - 100 - sage: RC = RiggedConfigurations(['B', 3, 1], [[2,2],[1,2]]) - sage: RC.cardinality() - 5130 - sage: RC = RiggedConfigurations(['E', 7, 1], [[1,1]]) - sage: RC.cardinality() - 134 - """ - CWLR = self.cartan_type().classical().root_system().ambient_space() - return sum(CWLR.weyl_dimension(mg.classical_weight()) for mg in self.module_generators) - @cached_method def tensor_product_of_kirillov_reshetikhin_crystals(self): """ From 4c64e074ee0982569d73f4122cb2ff2acb0b9347 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sun, 30 Aug 2015 17:18:01 -0500 Subject: [PATCH 012/452] Moved 1-dim sum and relate functions to the category. --- .../categories/affine_derived_crystals.py | 215 +++++++++++++++++ src/sage/combinat/crystals/littelmann_path.py | 139 ++++++----- src/sage/combinat/crystals/tensor_product.py | 220 ------------------ 3 files changed, 300 insertions(+), 274 deletions(-) diff --git a/src/sage/categories/affine_derived_crystals.py b/src/sage/categories/affine_derived_crystals.py index 9d80325d434..242abb07f1d 100644 --- a/src/sage/categories/affine_derived_crystals.py +++ b/src/sage/categories/affine_derived_crystals.py @@ -17,6 +17,8 @@ from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets from sage.categories.tensor import TensorProductsCategory from sage.graphs.dot2tex_utils import have_dot2tex +from sage.functions.other import ceil + class AffineDerivedSubalgebraCrystals(Category_singleton): r""" @@ -437,3 +439,216 @@ def cardinality(self): return sum(CWLR.weyl_dimension(mg.classical_weight()) for mg in self.classically_highest_weight_vectors()) + def one_dimensional_configuration_sum(self, q=None, group_components=True): + r""" + Compute the one-dimensional configuration sum of ``self``. + + INPUT: + + - ``q`` -- (default: ``None``) a variable or ``None``; + if ``None``, a variable `q` is set in the code + - ``group_components`` -- (default: ``True``) boolean; if + ``True``, then the terms are grouped by classical component + + The one-dimensional configuration sum is the sum of the + weights of all elements in the crystal weighted by the + energy function. + + EXAMPLES:: + + sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) + sage: T = crystals.TensorProduct(K,K) + sage: T.one_dimensional_configuration_sum() + B[-2*Lambda[1] + 2*Lambda[2]] + (q+1)*B[-Lambda[1]] + + (q+1)*B[Lambda[1] - Lambda[2]] + B[2*Lambda[1]] + + B[-2*Lambda[2]] + (q+1)*B[Lambda[2]] + sage: R. = ZZ[] + sage: T.one_dimensional_configuration_sum(t, False) + B[-2*Lambda[1] + 2*Lambda[2]] + (t+1)*B[-Lambda[1]] + + (t+1)*B[Lambda[1] - Lambda[2]] + B[2*Lambda[1]] + + B[-2*Lambda[2]] + (t+1)*B[Lambda[2]] + + sage: R = RootSystem(['A',2,1]) + sage: La = R.weight_space().basis() + sage: LS = crystals.ProjectedLevelZeroLSPaths(2*La[1]) + sage: LS.one_dimensional_configuration_sum() == T.one_dimensional_configuration_sum() # long time + True + + TESTS:: + + sage: K1 = crystals.KirillovReshetikhin(['A',2,1],1,1) + sage: K2 = crystals.KirillovReshetikhin(['A',2,1],2,1) + sage: T = crystals.TensorProduct(K1,K2) + sage: T.one_dimensional_configuration_sum() == T.one_dimensional_configuration_sum(group_components=False) + True + """ + if q is None: + from sage.rings.all import QQ + q = QQ['q'].gens()[0] + P0 = self.weight_lattice_realization().classical() + B = P0.algebra(q.parent()) + if group_components: + G = self.digraph(index_set=self.cartan_type().classical().index_set()) + C = G.connected_components() + return B.sum(q**(c[0].energy_function())*B.sum(B(P0(b.weight())) for b in c) + for c in C) + return B.sum(q**(b.energy_function())*B(P0(b.weight())) for b in self) + + class ElementMethods: + def energy_function(self): + r""" + Return the energy function of ``self``. + + The energy is only defined when ``self`` is an element of a + tensor product of affine Kirillov-Reshetikhin crystals. In this + implementation, it is assumed that ``self`` is an element of a + tensor product of perfect crystals of the same level, see + Theorem 7.5 in [SchillingTingley2011]_. + + INPUT: + + - ``self`` -- an element of a tensor product of perfect + Kirillov-Reshetkhin crystals of the same level + + OUTPUT: an integer + + REFERENCES: + + .. [SchillingTingley2011] A. Schilling, P. Tingley. + *Demazure crystals, Kirillov-Reshetikhin crystals, and + the energy function*. + Electronic Journal of Combinatorics. **19(2)**. 2012. + :arXiv:`1104.2359` + + EXAMPLES:: + + sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) + sage: T = crystals.TensorProduct(K,K,K) + sage: hw = [b for b in T if all(b.epsilon(i)==0 for i in [1,2])] + sage: for b in hw: + ....: print b, b.energy_function() + [[[1]], [[1]], [[1]]] 0 + [[[1]], [[2]], [[1]]] 2 + [[[2]], [[1]], [[1]]] 1 + [[[3]], [[2]], [[1]]] 3 + + sage: K = crystals.KirillovReshetikhin(['C',2,1],1,2) + sage: T = crystals.TensorProduct(K,K) + sage: hw = [b for b in T if all(b.epsilon(i)==0 for i in [1,2])] + sage: for b in hw: # long time (5s on sage.math, 2011) + ....: print b, b.energy_function() + [[], []] 4 + [[], [[1, 1]]] 1 + [[[1, 1]], []] 3 + [[[1, 1]], [[1, 1]]] 0 + [[[1, 2]], [[1, 1]]] 1 + [[[2, 2]], [[1, 1]]] 2 + [[[-1, -1]], [[1, 1]]] 2 + [[[1, -1]], [[1, 1]]] 2 + [[[2, -1]], [[1, 1]]] 2 + + sage: K = crystals.KirillovReshetikhin(['C',2,1],1,1) + sage: T = crystals.TensorProduct(K) + sage: t = T.module_generators[0] + sage: t.energy_function() + Traceback (most recent call last): + ... + NotImplementedError: all crystals in the tensor product need to be perfect of the same level + """ + C = self.parent().crystals[0] + ell = ceil(C.s()/C.cartan_type().c()[C.r()]) + if any(ell != K.s()/K.cartan_type().c()[K.r()] for K in self.parent().crystals): + raise NotImplementedError("all crystals in the tensor product need to be perfect of the same level") + t = self.parent()(*[K.module_generator() for K in self.parent().crystals]) + d = t.affine_grading() + return d - self.affine_grading() + + def affine_grading(self): + r""" + Return the affine grading of ``self``. + + The affine grading is only defined when ``self`` is an + element of a tensor product of Kirillov-Reshetikhin + crystals. It is calculated by finding a path from ``self`` + to a ground state path using the helper method + :meth:`e_string_to_ground_state` and counting the number + of affine Kashiwara operators `e_0` applied on the way. + + OUTPUT: an integer + + EXAMPLES:: + + sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) + sage: T = crystals.TensorProduct(K,K) + sage: t = T.module_generators[0] + sage: t.affine_grading() + 1 + + sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) + sage: T = crystals.TensorProduct(K,K,K) + sage: hw = [b for b in T if all(b.epsilon(i)==0 for i in [1,2])] + sage: for b in hw: + ....: print b, b.affine_grading() + [[[1]], [[1]], [[1]]] 3 + [[[1]], [[2]], [[1]]] 1 + [[[2]], [[1]], [[1]]] 2 + [[[3]], [[2]], [[1]]] 0 + + sage: K = crystals.KirillovReshetikhin(['C',2,1],1,1) + sage: T = crystals.TensorProduct(K,K,K) + sage: hw = [b for b in T if all(b.epsilon(i)==0 for i in [1,2])] + sage: for b in hw: + ....: print b, b.affine_grading() + [[[1]], [[1]], [[1]]] 2 + [[[1]], [[2]], [[1]]] 1 + [[[1]], [[-1]], [[1]]] 0 + [[[2]], [[1]], [[1]]] 1 + [[[-2]], [[2]], [[1]]] 0 + [[[-1]], [[1]], [[1]]] 1 + """ + return self.e_string_to_ground_state().count(0) + + @cached_method + def e_string_to_ground_state(self): + r""" + Return a string of integers in the index set + `(i_1, \ldots, i_k)` such that `e_{i_k} \cdots e_{i_1}` + of ``self`` is the ground state. + + This method calculates a path from ``self`` to a ground + state path using Demazure arrows as defined in Lemma 7.3 + in [SchillingTingley2011]_. + + OUTPUT: a tuple of integers `(i_1, \ldots, i_k)` + + EXAMPLES:: + + sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) + sage: T = crystals.TensorProduct(K,K) + sage: t = T.module_generators[0] + sage: t.e_string_to_ground_state() + (0, 2) + + sage: K = crystals.KirillovReshetikhin(['C',2,1],1,1) + sage: T = crystals.TensorProduct(K,K) + sage: t = T.module_generators[0]; t + [[[1]], [[1]]] + sage: t.e_string_to_ground_state() + (0,) + sage: x=t.e(0) + sage: x.e_string_to_ground_state() + () + sage: y=t.f_string([1,2,1,1,0]); y + [[[2]], [[1]]] + sage: y.e_string_to_ground_state() + () + """ + I = self.cartan_type().classical().index_set() + ell = max(ceil(K.s()/K.cartan_type().c()[K.r()]) for K in self.parent().crystals) + for i in I: + if self.epsilon(i) > 0: + return (i,) + (self.e(i)).e_string_to_ground_state() + if self.epsilon(0) > ell: + return (0,) + (self.e(0)).e_string_to_ground_state() + return () + diff --git a/src/sage/combinat/crystals/littelmann_path.py b/src/sage/combinat/crystals/littelmann_path.py index a2f68709eb2..ca154ddaf32 100644 --- a/src/sage/combinat/crystals/littelmann_path.py +++ b/src/sage/combinat/crystals/littelmann_path.py @@ -23,15 +23,15 @@ # http://www.gnu.org/licenses/ #**************************************************************************** -from sage.misc.cachefunc import cached_in_parent_method +from sage.misc.cachefunc import cached_in_parent_method, cached_method from sage.structure.unique_representation import UniqueRepresentation from sage.structure.element_wrapper import ElementWrapper from sage.structure.parent import Parent from sage.categories.highest_weight_crystals import HighestWeightCrystals from sage.categories.regular_crystals import RegularCrystals -from sage.categories.finite_crystals import FiniteCrystals from sage.categories.classical_crystals import ClassicalCrystals from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets +from sage.categories.affine_derived_crystals import KirillovReshetikhinCrystals from sage.combinat.root_system.cartan_type import CartanType from sage.combinat.root_system.weyl_group import WeylGroup from sage.rings.integer import Integer @@ -208,15 +208,15 @@ def __init__(self, starting_weight, starting_weight_parent): self._name = "The crystal of LS paths of type %s and weight %s"%(cartan_type,starting_weight) if cartan_type.is_affine(): if all(i>=0 for i in starting_weight.coefficients()): - Parent.__init__( self, category = (RegularCrystals(), - HighestWeightCrystals(), - InfiniteEnumeratedSets()) ) + Parent.__init__( self, category=(RegularCrystals(), + HighestWeightCrystals(), + InfiniteEnumeratedSets()) ) elif starting_weight.parent().is_extended(): - Parent.__init__(self, category = (RegularCrystals(), InfiniteEnumeratedSets())) + Parent.__init__(self, category=(RegularCrystals(), InfiniteEnumeratedSets())) else: - Parent.__init__(self, category = (RegularCrystals(), FiniteCrystals())) + Parent.__init__(self, category=KirillovReshetikhinCrystals().TensorProducts()) else: - Parent.__init__(self, category = ClassicalCrystals()) + Parent.__init__(self, category=ClassicalCrystals()) if starting_weight == starting_weight.parent().zero(): initial_element = self(tuple([])) @@ -632,12 +632,14 @@ class CrystalOfProjectedLevelZeroLSPaths(CrystalOfLSPaths): INPUT: - - ``weight`` -- a dominant weight of the weight space of an affine Kac-Moody root system + - ``weight`` -- a dominant weight of the weight space of an affine + Kac-Moody root system - When ``weight`` is just a single fundamental weight `\Lambda_r`, this crystal is - isomorphic to a Kirillov-Reshetikhin (KR) crystal, see also + When ``weight`` is just a single fundamental weight `\Lambda_r`, this + crystal is isomorphic to a Kirillov-Reshetikhin (KR) crystal, see also :meth:`sage.combinat.crystals.kirillov_reshetikhin.crystals.KirillovReshetikhinFromLSPaths`. - For general weights, it is isomorphic to a tensor product of single-column KR crystals. + For general weights, it is isomorphic to a tensor product of + single-column KR crystals. EXAMPLES:: @@ -701,10 +703,18 @@ def __classcall_private__(cls, weight): if weight.parent().is_extended(): raise ValueError("The weight should be in the non-extended weight lattice!") La = weight.parent().basis() - weight = weight - (weight.level())*La[0]/(La[0].level()) + weight = weight - weight.level() * La[0] / La[0].level() return super(CrystalOfLSPaths, cls).__classcall__(cls, weight, starting_weight_parent = weight.parent()) - def one_dimensional_configuration_sum(self, q = None, group_components = True): + @cached_method + def classically_highest_weight_vectors(self): + r""" + Return the classically highest weight vectors of ``self``. + """ + I0 = self.cartan_type().classical().index_set() + return tuple([x for x in self.list() if x.is_highest_weight(I0)]) + + def one_dimensional_configuration_sum(self, q=None, group_components=True): r""" Compute the one-dimensional configuration sum. @@ -715,10 +725,12 @@ def one_dimensional_configuration_sum(self, q = None, group_components = True): - ``group_components`` -- (default: ``True``) boolean; if ``True``, then the terms are grouped by classical component - The one-dimensional configuration sum is the sum of the weights of all elements in the crystal - weighted by the energy function. For untwisted types it uses the parabolic quantum Bruhat graph, see [LNSSS2013]_. - In the dual-of-untwisted case, the parabolic quantum Bruhat graph is defined by - exchanging the roles of roots and coroots (which is still conjectural at this point). + The one-dimensional configuration sum is the sum of the weights + of all elements in the crystal weighted by the energy function. + For untwisted types it uses the parabolic quantum Bruhat graph, + see [LNSSS2013]_. In the dual-of-untwisted case, the parabolic + quantum Bruhat graph is defined by exchanging the roles of roots + and coroots (which is still conjectural at this point). EXAMPLES:: @@ -727,11 +739,13 @@ def one_dimensional_configuration_sum(self, q = None, group_components = True): sage: LS = crystals.ProjectedLevelZeroLSPaths(2*La[1]) sage: LS.one_dimensional_configuration_sum() # long time B[-2*Lambda[1] + 2*Lambda[2]] + (q+1)*B[-Lambda[1]] - + (q+1)*B[Lambda[1] - Lambda[2]] + B[2*Lambda[1]] + B[-2*Lambda[2]] + (q+1)*B[Lambda[2]] + + (q+1)*B[Lambda[1] - Lambda[2]] + B[2*Lambda[1]] + + B[-2*Lambda[2]] + (q+1)*B[Lambda[2]] sage: R. = ZZ[] sage: LS.one_dimensional_configuration_sum(t, False) # long time - B[-2*Lambda[1] + 2*Lambda[2]] + (t+1)*B[-Lambda[1]] + (t+1)*B[Lambda[1] - Lambda[2]] - + B[2*Lambda[1]] + B[-2*Lambda[2]] + (t+1)*B[Lambda[2]] + B[-2*Lambda[1] + 2*Lambda[2]] + (t+1)*B[-Lambda[1]] + + (t+1)*B[Lambda[1] - Lambda[2]] + B[2*Lambda[1]] + + B[-2*Lambda[2]] + (t+1)*B[Lambda[2]] TESTS:: @@ -780,7 +794,7 @@ def weight(x): def is_perfect(self, level=1): r""" - Checks whether the crystal ``self`` is perfect (of level ``level``). + Check whether the crystal ``self`` is perfect (of level ``level``). INPUT: @@ -788,15 +802,18 @@ def is_perfect(self, level=1): A crystal `\mathcal{B}` is perfect of level `\ell` if: - #. `\mathcal{B}` is isomorphic to the crystal graph of a finite-dimensional `U_q^{'}(\mathfrak{g})`-module. + #. `\mathcal{B}` is isomorphic to the crystal graph of a + finite-dimensional `U_q^{'}(\mathfrak{g})`-module. #. `\mathcal{B}\otimes \mathcal{B}` is connected. - #. There exists a `\lambda\in X`, such that `\mathrm{wt}(\mathcal{B}) \subset \lambda - + \sum_{i\in I} \mathbb{Z}_{\le 0} \alpha_i` and there is a unique element in `\mathcal{B}` of classical - weight `\lambda`. - #. `\forall b \in \mathcal{B}, \mathrm{level}(\varepsilon (b)) \geq \ell`. - #. `\forall \Lambda` dominant weights of level `\ell`, there exist unique elements - `b_{\Lambda}, b^{\Lambda} \in \mathcal{B}`, - such that `\varepsilon ( b_{\Lambda}) = \Lambda = \varphi( b^{\Lambda})`. + #. There exists a `\lambda\in X`, such that + `\mathrm{wt}(\mathcal{B}) \subset \lambda + \sum_{i\in I} + \ZZ_{\le 0} \alpha_i` and there is a unique element in + `\mathcal{B}` of classical weight `\lambda`. + #. For all `b \in \mathcal{B}`, + `\mathrm{level}(\varepsilon (b)) \geq \ell`. + #. For all `\Lambda` dominant weights of level `\ell`, there exist + unique elements `b_{\Lambda}, b^{\Lambda} \in \mathcal{B}`, such + that `\varepsilon ( b_{\Lambda}) = \Lambda = \varphi( b^{\Lambda})`. Points (1)-(3) are known to hold. This method checks points (4) and (5). @@ -937,58 +954,70 @@ def energy_function(self): r""" Return the energy function of ``self``. - The energy function `D(\pi)` of the level zero LS path `\pi \in \mathbb{B}_\mathrm{cl}(\lambda)` - requires a series of definitions; for simplicity the root system is assumed to be untwisted affine. + The energy function `D(\pi)` of the level zero LS path + `\pi \in \mathbb{B}_\mathrm{cl}(\lambda)` requires a series + of definitions; for simplicity the root system is assumed to + be untwisted affine. - The LS path `\pi` is a piecewise linear map from the unit interval `[0,1]` to the weight lattice. - It is specified by "times" `0=\sigma_0<\sigma_1<\dotsm<\sigma_s=1` and "direction vectors" - `x_u \lambda` where `x_u \in W/W_J` for `1\le u\le s`, and `W_J` is the - stabilizer of `\lambda` in the finite Weyl group `W`. Precisely, + The LS path `\pi` is a piecewise linear map from the unit + interval `[0,1]` to the weight lattice. It is specified by + "times" `0 = \sigma_0 < \sigma_1 < \dotsm < \sigma_s = 1` and + "direction vectors" `x_u \lambda` where `x_u \in W / W_J` for + `1 \le u \le s`, and `W_J` is the stabilizer of `\lambda` in + the finite Weyl group `W`. Precisely, .. MATH:: - \pi(t)=\sum_{u'=1}^{u-1} (\sigma_{u'}-\sigma_{u'-1})x_{u'}\lambda+(t-\sigma_{u-1})x_{u}\lambda + \pi(t) = \sum_{u'=1}^{u-1} (\sigma_{u'}-\sigma_{u'-1}) + x_{u'} \lambda + (t-\sigma_{u-1}) x_{u} \lambda - for `1\le u\le s` and `\sigma_{u-1} \le t \le \sigma_{u}`. + for `1 \le u \le s` and `\sigma_{u-1} \le t \le \sigma_{u}`. - For any `x,y\in W/W_J` let + For any `x,y \in W / W_J`, let .. MATH:: - d: x= w_{0} \stackrel{\beta_{1}}{\leftarrow} + d: x = w_{0} \stackrel{\beta_{1}}{\leftarrow} w_{1} \stackrel{\beta_{2}}{\leftarrow} \cdots \stackrel{\beta_{n}}{\leftarrow} w_{n}=y - be a shortest directed path in the parabolic quantum Bruhat graph. Define + be a shortest directed path in the parabolic quantum + Bruhat graph. Define .. MATH:: - \mathrm{wt}(d):=\sum_{\substack{1\le k\le n \\ \ell(w_{k-1})<\ell(w_k)}} - \beta_{k}^{\vee} + \mathrm{wt}(d) := \sum_{\substack{1 \le k \le n + \\ \ell(w_{k-1}) < \ell(w_k)}} + \beta_{k}^{\vee}. It can be shown that `\mathrm{wt}(d)` depends only on `x,y`; - call its value `\mathrm{wt}(x,y)`. The energy function `D(\pi)` is defined by + call its value `\mathrm{wt}(x,y)`. The energy function `D(\pi)` + is defined by .. MATH:: - D(\pi)=-\sum_{u=1}^{s-1} (1-\sigma_{u}) \langle \lambda,\mathrm{wt}(x_u,x_{u+1}) \rangle + D(\pi) = -\sum_{u=1}^{s-1} (1-\sigma_{u}) \langle \lambda, + \mathrm{wt}(x_u,x_{u+1}) \rangle. For more information, see [LNSSS2013]_. REFERENCES: .. [LNSSS2013] C. Lenart, S. Naito, D. Sagaki, A. Schilling, M. Shimozono, - A uniform model for Kirillov-Reshetikhin crystals. Extended abstract. - DMTCS proc, to appear ( {{{:arXiv:`1211.6019`}}} ) + *A uniform model for Kirillov-Reshetikhin crystals. Extended abstract.* + DMTCS proc, to appear ( :arXiv:`1211.6019` ) .. NOTE:: - In the dual-of-untwisted case the parabolic quantum Bruhat graph that is used is obtained by - exchanging the roles of roots and coroots. Moreover, in the computation of the - pairing the short roots must be doubled (or tripled for type `G`). This factor - is determined by the translation factor of the corresponding root. - Type `BC` is viewed as untwisted type, whereas the dual of `BC` is viewed as twisted. - Except for the untwisted cases, these formulas are currently still conjectural. + In the dual-of-untwisted case the parabolic quantum + Bruhat graph that is used is obtained by exchanging the + roles of roots and coroots. Moreover, in the computation + of the pairing the short roots must be doubled (or tripled + for type `G`). This factor is determined by the translation + factor of the corresponding root. Type `BC` is viewed as + untwisted type, whereas the dual of `BC` is viewed as twisted. + Except for the untwisted cases, these formulas are + currently still conjectural. EXAMPLES:: @@ -1021,7 +1050,8 @@ def energy_function(self): (Lambda[0] - Lambda[2], -Lambda[0] + Lambda[1]) 0 (Lambda[0] - Lambda[2], -Lambda[1] + Lambda[2]) 0 - The next test checks that the energy function is constant on classically connected components:: + The next test checks that the energy function is constant + on classically connected components:: sage: R = RootSystem(['A',2,1]) sage: La = R.weight_space().basis() @@ -1116,3 +1146,4 @@ def stretch_short_root(a): return s/2 else: return s + diff --git a/src/sage/combinat/crystals/tensor_product.py b/src/sage/combinat/crystals/tensor_product.py index 8c746d07ebc..c7fbdb4f1b7 100644 --- a/src/sage/combinat/crystals/tensor_product.py +++ b/src/sage/combinat/crystals/tensor_product.py @@ -319,57 +319,6 @@ def _element_constructor_(self, *crystalElements): """ return self.element_class(self, list(crystalElements)) - def one_dimensional_configuration_sum(self, q=None, group_components=True): - r""" - Computes the one-dimensional configuration sum. - - INPUT: - - - ``q`` -- (default: ``None``) a variable or ``None``; if ``None``, - a variable `q` is set in the code - - ``group_components`` -- (default: ``True``) boolean; if ``True``, - then the terms are grouped by classical component - - The one-dimensional configuration sum is the sum of the weights of all - elements in the crystal weighted by the energy function. - - EXAMPLES:: - - sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) - sage: T = crystals.TensorProduct(K,K) - sage: T.one_dimensional_configuration_sum() - B[-2*Lambda[1] + 2*Lambda[2]] + (q+1)*B[-Lambda[1]] + (q+1)*B[Lambda[1] - Lambda[2]] - + B[2*Lambda[1]] + B[-2*Lambda[2]] + (q+1)*B[Lambda[2]] - sage: R. = ZZ[] - sage: T.one_dimensional_configuration_sum(t, False) - B[-2*Lambda[1] + 2*Lambda[2]] + (t+1)*B[-Lambda[1]] + (t+1)*B[Lambda[1] - Lambda[2]] - + B[2*Lambda[1]] + B[-2*Lambda[2]] + (t+1)*B[Lambda[2]] - - sage: R = RootSystem(['A',2,1]) - sage: La = R.weight_space().basis() - sage: LS = crystals.ProjectedLevelZeroLSPaths(2*La[1]) - sage: LS.one_dimensional_configuration_sum() == T.one_dimensional_configuration_sum() # long time - True - - TESTS:: - - sage: K1 = crystals.KirillovReshetikhin(['A',2,1],1,1) - sage: K2 = crystals.KirillovReshetikhin(['A',2,1],2,1) - sage: T = crystals.TensorProduct(K1,K2) - sage: T.one_dimensional_configuration_sum() == T.one_dimensional_configuration_sum(group_components=False) - True - """ - if q is None: - from sage.rings.all import QQ - q = QQ['q'].gens()[0] - P0 = self.weight_lattice_realization().classical() - B = P0.algebra(q.parent()) - if group_components: - G = self.digraph(index_set = self.cartan_type().classical().index_set()) - C = G.connected_components() - return sum(q**(c[0].energy_function())*B.sum(B(P0(b.weight())) for b in c) for c in C) - return B.sum(q**(b.energy_function())*B(P0(b.weight())) for b in self) - TensorProductOfCrystalsOptions=GlobalOptions(name='tensor_product_of_crystals', doc=r""" Sets the global options for tensor products of crystals. The default is to @@ -1401,175 +1350,6 @@ def positions_of_unmatched_plus(self, i): l.reverse() return [len(self)-1-l[j] for j in range(len(l))] - def energy_function(self): - r""" - Return the energy function of ``self``. - - The energy is only defined when ``self`` is an element of a tensor - product of affine Kirillov-Reshetikhin crystals. In this - implementation, it is assumed that ``self`` is an element of a - tensor product of perfect crystals of the same level, see - Theorem 7.5 in [SchillingTingley2011]_. - - INPUT: - - - ``self`` -- an element of a tensor product of perfect - Kirillov-Reshetkhin crystals of the same level - - OUTPUT: an integer - - REFERENCES: - - .. [SchillingTingley2011] A. Schilling, P. Tingley. - Demazure crystals, Kirillov-Reshetikhin crystals, and the energy - function. Electronic Journal of Combinatorics. **19(2)**. 2012. - :arXiv:`1104.2359` - - EXAMPLES:: - - sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) - sage: T = crystals.TensorProduct(K,K,K) - sage: hw = [b for b in T if all(b.epsilon(i)==0 for i in [1,2])] - sage: for b in hw: - ....: print b, b.energy_function() - [[[1]], [[1]], [[1]]] 0 - [[[1]], [[2]], [[1]]] 2 - [[[2]], [[1]], [[1]]] 1 - [[[3]], [[2]], [[1]]] 3 - - sage: K = crystals.KirillovReshetikhin(['C',2,1],1,2) - sage: T = crystals.TensorProduct(K,K) - sage: hw = [b for b in T if all(b.epsilon(i)==0 for i in [1,2])] - sage: for b in hw: # long time (5s on sage.math, 2011) - ....: print b, b.energy_function() - [[], []] 4 - [[], [[1, 1]]] 1 - [[[1, 1]], []] 3 - [[[1, 1]], [[1, 1]]] 0 - [[[1, 2]], [[1, 1]]] 1 - [[[2, 2]], [[1, 1]]] 2 - [[[-1, -1]], [[1, 1]]] 2 - [[[1, -1]], [[1, 1]]] 2 - [[[2, -1]], [[1, 1]]] 2 - - sage: K = crystals.KirillovReshetikhin(['C',2,1],1,1) - sage: T = crystals.TensorProduct(K) - sage: t = T.module_generators[0] - sage: t.energy_function() - Traceback (most recent call last): - ... - ValueError: All crystals in the tensor product need to be perfect of the same level - """ - C = self.parent().crystals[0] - ell = ceil(C.s()/C.cartan_type().c()[C.r()]) - if any(ell != K.s()/K.cartan_type().c()[K.r()] for K in self.parent().crystals): - raise ValueError("All crystals in the tensor product need to be perfect of the same level") - t = self.parent()(*[K.module_generator() for K in self.parent().crystals]) - d = t.affine_grading() - return d - self.affine_grading() - - def affine_grading(self): - r""" - Returns the affine grading of `self`. - - The affine grading is only defined when ``self`` is an element of a - tensor product of affine Kirillov-Reshetikhin crystals. It is - calculated by finding a path from ``self`` to a ground state path - using the helper method :meth:`e_string_to_ground_state` and counting - the number of affine Kashiwara operators `e_0` applied on the way. - - INPUT: - - - ``self`` -- an element of a tensor product of Kirillov-Reshetikhin - crystals - - OUTPUT: an integer - - EXAMPLES:: - - sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) - sage: T = crystals.TensorProduct(K,K) - sage: t = T.module_generators[0] - sage: t.affine_grading() - 1 - - sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) - sage: T = crystals.TensorProduct(K,K,K) - sage: hw = [b for b in T if all(b.epsilon(i)==0 for i in [1,2])] - sage: for b in hw: - ....: print b, b.affine_grading() - [[[1]], [[1]], [[1]]] 3 - [[[1]], [[2]], [[1]]] 1 - [[[2]], [[1]], [[1]]] 2 - [[[3]], [[2]], [[1]]] 0 - - sage: K = crystals.KirillovReshetikhin(['C',2,1],1,1) - sage: T = crystals.TensorProduct(K,K,K) - sage: hw = [b for b in T if all(b.epsilon(i)==0 for i in [1,2])] - sage: for b in hw: - ....: print b, b.affine_grading() - [[[1]], [[1]], [[1]]] 2 - [[[1]], [[2]], [[1]]] 1 - [[[1]], [[-1]], [[1]]] 0 - [[[2]], [[1]], [[1]]] 1 - [[[-2]], [[2]], [[1]]] 0 - [[[-1]], [[1]], [[1]]] 1 - """ - return self.e_string_to_ground_state().count(0) - - @cached_method - def e_string_to_ground_state(self): - r""" - Returns a string of integers in the index set `(i_1,\ldots,i_k)` such - that `e_{i_k} \cdots e_{i_1}` of ``self`` is the ground state. - - This method is only defined when ``self`` is an element of a tensor - product of affine Kirillov-Reshetikhin crystals. It calculates a path - from ``self`` to a ground state path using Demazure arrows as defined - in Lemma 7.3 in [SchillingTingley2011]_. - - INPUT: - - - ``self`` -- an element of a tensor product of Kirillov-Reshetikhin - crystals - - OUTPUT: a tuple of integers `(i_1,\ldots,i_k)` - - EXAMPLES:: - - sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) - sage: T = crystals.TensorProduct(K,K) - sage: t = T.module_generators[0] - sage: t.e_string_to_ground_state() - (0, 2) - - sage: K = crystals.KirillovReshetikhin(['C',2,1],1,1) - sage: T = crystals.TensorProduct(K,K) - sage: t = T.module_generators[0]; t - [[[1]], [[1]]] - sage: t.e_string_to_ground_state() - (0,) - sage: x=t.e(0) - sage: x.e_string_to_ground_state() - () - sage: y=t.f_string([1,2,1,1,0]); y - [[[2]], [[1]]] - sage: y.e_string_to_ground_state() - () - """ - from sage.combinat.rigged_configurations.kr_tableaux import KirillovReshetikhinTableaux - if self.parent().crystals[0].__module__ != 'sage.combinat.crystals.kirillov_reshetikhin' and \ - not isinstance(self.parent().crystals[0], KirillovReshetikhinTableaux): - raise ValueError("All crystals in the tensor product need to be Kirillov-Reshetikhin crystals") - I = self.cartan_type().classical().index_set() - ell = max(ceil(K.s()/K.cartan_type().c()[K.r()]) for K in self.parent().crystals) - for i in I: - if self.epsilon(i) > 0: - return (i,) + (self.e(i)).e_string_to_ground_state() - if self.epsilon(0) > ell: - return (0,) + (self.e(0)).e_string_to_ground_state() - return () - CrystalOfWords.Element = TensorProductOfCrystalsElement class FullTensorProductOfRegularCrystals(FullTensorProductOfCrystals): From c92a80f8e9607f068b58595e9bb1764f54d1a95b Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Mon, 31 Aug 2015 19:17:34 -0500 Subject: [PATCH 013/452] Fixing bug in classically HW vectors. --- .../categories/affine_derived_crystals.py | 31 ++++++++++--------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/src/sage/categories/affine_derived_crystals.py b/src/sage/categories/affine_derived_crystals.py index 242abb07f1d..4c6b12a847d 100644 --- a/src/sage/categories/affine_derived_crystals.py +++ b/src/sage/categories/affine_derived_crystals.py @@ -197,6 +197,12 @@ def classical_decomposition(self): def classically_highest_weight_vectors(self): """ Return the classically highest weight elements of ``self``. + + EXAMPLES:: + + sage: K = crystals.KirillovReshetikhin(['E',6,1],1,1) + sage: K.classically_highest_weight_vectors() + ([(1,)],) """ I0 = self.cartan_type().classical().index_set() return tuple([x for x in self if x.is_highest_weight(I0)]) @@ -210,14 +216,14 @@ def maximal_vector(self): EXAMPLES:: sage: K = crystals.KirillovReshetikhin(['C',2,1],1,2) - sage: K.module_generator() + sage: K.maximal_vector() [[1, 1]] sage: K = crystals.KirillovReshetikhin(['E',6,1],1,1) - sage: K.module_generator() + sage: K.maximal_vector() [(1,)] sage: K = crystals.KirillovReshetikhin(['D',4,1],2,1) - sage: K.module_generator() + sage: K.maximal_vector() [[1], [2]] """ R = self.weight_lattice_realization() @@ -383,16 +389,13 @@ def classically_highest_weight_vectors(self): EXAMPLES:: - sage: C = crystals.Tableaux(['D',4], shape=[2,2]) - sage: D = crystals.Tableaux(['D',4], shape=[1]) - sage: T = crystals.TensorProduct(D, C) - sage: T.highest_weight_vectors() - ([[[1]], [[1, 1], [2, 2]]], - [[[3]], [[1, 1], [2, 2]]], - [[[-2]], [[1, 1], [2, 2]]]) - sage: L = filter(lambda x: x.is_highest_weight(), T) - sage: tuple(L) == T.highest_weight_vectors() - True + sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) + sage: T = crystals.TensorProduct(K,K,K) + sage: T.classically_highest_weight_vectors() + ([[[1]], [[1]], [[1]]], + [[[2]], [[1]], [[1]]], + [[[1]], [[2]], [[1]]], + [[[3]], [[2]], [[1]]]) """ n = len(self.crystals) I0 = self.cartan_type().classical().index_set() @@ -409,7 +412,7 @@ def classically_highest_weight_vectors(self): continue b = self.element_class(self, [x] + path) - if not b.is_highest_weight(): + if not b.is_highest_weight(index_set=I0): continue path.insert(0, x) if len(path) == n: From af87ee807a31918ec7b1f2cb5c8b3ad45c56a006 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 1 Sep 2015 09:54:12 -0500 Subject: [PATCH 014/452] Fixing category hierarchy for (tensor products of) KR crystals. --- .../categories/affine_derived_crystals.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/sage/categories/affine_derived_crystals.py b/src/sage/categories/affine_derived_crystals.py index 4c6b12a847d..2fb0dad6329 100644 --- a/src/sage/categories/affine_derived_crystals.py +++ b/src/sage/categories/affine_derived_crystals.py @@ -32,7 +32,7 @@ class AffineDerivedSubalgebraCrystals(Category_singleton): sage: C Category of affine derived subalgebra crystals sage: C.super_categories() - [Category of finite regular crystals] + [Category of regular crystals] sage: C.example() Kirillov-Reshetikhin crystal of type ['A', 3, 1] with (r,s)=(1,1) @@ -73,9 +73,9 @@ def super_categories(self): sage: from sage.categories.affine_derived_crystals import AffineDerivedSubalgebraCrystals sage: AffineDerivedSubalgebraCrystals().super_categories() - [Category of finite regular crystals] + [Category of regular crystals] """ - return [RegularCrystals().Finite()] + return [RegularCrystals()] def example(self, n = 3): """ @@ -152,7 +152,7 @@ def super_categories(self): sage: from sage.categories.affine_derived_crystals import KirillovReshetikhinCrystals sage: KirillovReshetikhinCrystals().super_categories() - [Category of affine derived subalgebra crystals] + [Category of finite affine derived subalgebra crystals] """ return [AffineDerivedSubalgebraCrystals().Finite()] @@ -377,6 +377,17 @@ class TensorProducts(TensorProductsCategory): """ The category of tensor products of Kirillov-Reshetikhin crystals. """ + @cached_method + def extra_super_categories(self): + """ + EXAMPLES:: + + sage: from sage.categories.affine_derived_crystals import KirillovReshetikhinCrystals + sage: KirillovReshetikhinCrystals().TensorProducts().extra_super_categories() + [Category of finite affine derived subalgebra crystals] + """ + return [AffineDerivedSubalgebraCrystals().Finite()] + class ParentMethods: @cached_method def classically_highest_weight_vectors(self): From f8114a7d61e056b2b1c3c08108d191ba41824c4d Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 1 Sep 2015 09:56:06 -0500 Subject: [PATCH 015/452] Added maximal_vector() for tensor product of KR crystals. --- .../categories/affine_derived_crystals.py | 14 +++++++++++ src/sage/combinat/crystals/littelmann_path.py | 24 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/sage/categories/affine_derived_crystals.py b/src/sage/categories/affine_derived_crystals.py index 2fb0dad6329..371a9810323 100644 --- a/src/sage/categories/affine_derived_crystals.py +++ b/src/sage/categories/affine_derived_crystals.py @@ -389,6 +389,20 @@ def extra_super_categories(self): return [AffineDerivedSubalgebraCrystals().Finite()] class ParentMethods: + @cached_method + def maximal_vector(self): + """ + Return the maximal vector of ``self``. + + EXAMPLES:: + + sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) + sage: T = crystals.TensorProduct(K,K,K) + sage: T.maximal_vector() + [[[1]], [[1]], [[1]]] + """ + return self(*[K.maximal_vector() for K in self.crystals]) + @cached_method def classically_highest_weight_vectors(self): """ diff --git a/src/sage/combinat/crystals/littelmann_path.py b/src/sage/combinat/crystals/littelmann_path.py index ca154ddaf32..d1742618931 100644 --- a/src/sage/combinat/crystals/littelmann_path.py +++ b/src/sage/combinat/crystals/littelmann_path.py @@ -706,10 +706,34 @@ def __classcall_private__(cls, weight): weight = weight - weight.level() * La[0] / La[0].level() return super(CrystalOfLSPaths, cls).__classcall__(cls, weight, starting_weight_parent = weight.parent()) + @cached_method + def maximal_vector(self): + """ + Return the maximal vector of ``self``. + + EXAMPLES:: + + sage: R = RootSystem(['A',2,1]) + sage: La = R.weight_space().basis() + sage: LS = crystals.ProjectedLevelZeroLSPaths(2*La[1]+La[2]) + sage: LS.maximal_vector() + (-3*Lambda[0] + 2*Lambda[1] + Lambda[2],) + """ + return self.module_generators[0] + @cached_method def classically_highest_weight_vectors(self): r""" Return the classically highest weight vectors of ``self``. + + EXAMPLES:: + + sage: R = RootSystem(['A',2,1]) + sage: La = R.weight_space().basis() + sage: LS = crystals.ProjectedLevelZeroLSPaths(2*La[1]) + sage: LS.classically_highest_weight_vectors() + ((-2*Lambda[0] + 2*Lambda[1],), + (-Lambda[0] + Lambda[1], -Lambda[1] + Lambda[2])) """ I0 = self.cartan_type().classical().index_set() return tuple([x for x in self.list() if x.is_highest_weight(I0)]) From f2058a8aec1a941a469a2c07692d8e80119f1929 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 1 Sep 2015 10:24:41 -0500 Subject: [PATCH 016/452] More changes to the category structure and added a generic classical_weight(). --- .../categories/affine_derived_crystals.py | 55 ++++++++++++++++--- 1 file changed, 46 insertions(+), 9 deletions(-) diff --git a/src/sage/categories/affine_derived_crystals.py b/src/sage/categories/affine_derived_crystals.py index 371a9810323..e13059b4a89 100644 --- a/src/sage/categories/affine_derived_crystals.py +++ b/src/sage/categories/affine_derived_crystals.py @@ -10,7 +10,6 @@ from sage.misc.abstract_method import abstract_method from sage.misc.cachefunc import cached_method -#from sage.categories.category_with_axiom import CategoryWithAxiom from sage.categories.category_singleton import Category_singleton from sage.categories.crystals import Crystals from sage.categories.regular_crystals import RegularCrystals @@ -32,7 +31,7 @@ class AffineDerivedSubalgebraCrystals(Category_singleton): sage: C Category of affine derived subalgebra crystals sage: C.super_categories() - [Category of regular crystals] + [Category of crystals] sage: C.example() Kirillov-Reshetikhin crystal of type ['A', 3, 1] with (r,s)=(1,1) @@ -73,9 +72,9 @@ def super_categories(self): sage: from sage.categories.affine_derived_crystals import AffineDerivedSubalgebraCrystals sage: AffineDerivedSubalgebraCrystals().super_categories() - [Category of regular crystals] + [Category of crystals] """ - return [RegularCrystals()] + return [Crystals()] def example(self, n = 3): """ @@ -121,7 +120,7 @@ def digraph(self, subset=None, index_set=None): which the digraph should be constructed - ``index_set`` -- (optional) the index set to draw arrows - + .. SEEALSO:: :meth:`sage.categories.crystals.Crystals.ParentMethods.digraph` @@ -141,6 +140,44 @@ def digraph(self, subset=None, index_set=None): G.set_latex_options(edge_options=f) return G +# TODO: Should we make "regular" an axiom? +class RegularAffineDerivedSubalgebraCrystals(Category_singleton): + r""" + The category of regular `U_q'(\mathfrak{g})`-crystals, where + `\mathfrak{g}` is of affine type. + """ + @cached_method + def super_categories(self): + """ + EXAMPLES:: + + sage: from sage.categories.affine_derived_crystals import RegularAffineDerivedSubalgebraCrystals + sage: RegularAffineDerivedSubalgebraCrystals().super_categories() + [Category of regular crystals, + Category of affine derived subalgebra crystals] + """ + return [RegularCrystals(), AffineDerivedSubalgebraCrystals()] + + class ElementMethods: + def classical_weight(self): + """ + Return the classical weight of ``self``. + + EXAMPLES:: + + sage: R = RootSystem(['A',2,1]) + sage: La = R.weight_space().basis() + sage: LS = crystals.ProjectedLevelZeroLSPaths(2*La[1]) + sage: hw = LS.classically_highest_weight_vectors() + sage: [(v.weight(), v.classical_weight()) for v in hw] + [(-2*Lambda[0] + 2*Lambda[1], (2, 0, 0)), + (-Lambda[0] + Lambda[2], (1, 1, 0))] + """ + CT = self.cartan_type().classical() + I0 = CT.index_set() + La = CT.root_system().ambient_space().fundamental_weights() + return sum(La[i] * (self.phi(i) - self.epsilon(i)) for i in I0) + class KirillovReshetikhinCrystals(Category_singleton): """ Category of Kirillov-Reshetikhin crystals. @@ -152,9 +189,9 @@ def super_categories(self): sage: from sage.categories.affine_derived_crystals import KirillovReshetikhinCrystals sage: KirillovReshetikhinCrystals().super_categories() - [Category of finite affine derived subalgebra crystals] + [Category of finite regular affine derived subalgebra crystals] """ - return [AffineDerivedSubalgebraCrystals().Finite()] + return [RegularAffineDerivedSubalgebraCrystals().Finite()] class ParentMethods: @abstract_method @@ -384,9 +421,9 @@ def extra_super_categories(self): sage: from sage.categories.affine_derived_crystals import KirillovReshetikhinCrystals sage: KirillovReshetikhinCrystals().TensorProducts().extra_super_categories() - [Category of finite affine derived subalgebra crystals] + [Category of finite regular affine derived subalgebra crystals] """ - return [AffineDerivedSubalgebraCrystals().Finite()] + return [RegularAffineDerivedSubalgebraCrystals().Finite()] class ParentMethods: @cached_method From fe54e813594400303e6611ee0279f9fafc5595f4 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 1 Sep 2015 14:53:36 -0500 Subject: [PATCH 017/452] Added classically HW vecs for KR crystals in KN tableaux. Made general is_perfect(). --- .../categories/affine_derived_crystals.py | 125 ++++++++++++++++++ .../combinat/crystals/kirillov_reshetikhin.py | 65 ++------- 2 files changed, 134 insertions(+), 56 deletions(-) diff --git a/src/sage/categories/affine_derived_crystals.py b/src/sage/categories/affine_derived_crystals.py index e13059b4a89..37c64994bb7 100644 --- a/src/sage/categories/affine_derived_crystals.py +++ b/src/sage/categories/affine_derived_crystals.py @@ -17,6 +17,7 @@ from sage.categories.tensor import TensorProductsCategory from sage.graphs.dot2tex_utils import have_dot2tex from sage.functions.other import ceil +from sage.rings.all import ZZ class AffineDerivedSubalgebraCrystals(Category_singleton): @@ -369,6 +370,130 @@ def R_matrix(self, K): g = { gen1 : gen2 } return T1.crystal_morphism(g, check=False) + def is_perfect(self, ell=None): + r""" + Check if ``self`` is a perfect crystal of level ``ell``. + + A crystal `\mathcal{B}` is perfect of level `\ell` if: + + #. `\mathcal{B}` is isomorphic to the crystal graph of a + finite-dimensional `U_q^{'}(\mathfrak{g})`-module. + #. `\mathcal{B}\otimes \mathcal{B}` is connected. + #. There exists a `\lambda\in X`, such that + `\mathrm{wt}(\mathcal{B}) \subset \lambda + \sum_{i\in I} + \ZZ_{\le 0} \alpha_i` and there is a unique element in + `\mathcal{B}` of classical weight `\lambda`. + #. For all `b \in \mathcal{B}`, + `\mathrm{level}(\varepsilon (b)) \geq \ell`. + #. For all `\Lambda` dominant weights of level `\ell`, there + exist unique elements `b_{\Lambda}, b^{\Lambda} \in + \mathcal{B}`, such that `\varepsilon ( b_{\Lambda}) = + \Lambda = \varphi( b^{\Lambda})`. + + Points (1)-(3) are known to hold. This method checks + points (4) and (5). + + If ``self`` is the Kirillov-Reshetikhin crystal `B^{r,s}`, + then it was proven for non-exceptional types in [FOS2010]_ + that it is perfect if and only if `s/c_r` is an integer + (where `c_r` is a constant related to the type of the crystal). + + It is conjectured this is true for all affine types. + + INPUT: + + - ``ell`` -- (default: `s / c_r`) integer; the level + + REFERENCES: + + .. [FOS2010] G. Fourier, M. Okado, A. Schilling. *Perfectness of + Kirillov-Reshetikhin crystals for nonexceptional types*. + Contemp. Math. 506 (2010) 127-143 ( :arxiv:`0811.1604` ) + + EXAMPLES:: + + sage: K = crystals.KirillovReshetikhin(['A',2,1], 1, 1) + sage: K.is_perfect() + True + + sage: K = crystals.KirillovReshetikhin(['C',2,1], 1, 1) + sage: K.is_perfect() + False + + sage: K = crystals.KirillovReshetikhin(['C',2,1], 1, 2) + sage: K.is_perfect() + True + + .. TODO:: + + Implement a version for tensor products of KR crystals. + """ + if ell is None: + ell = self.s() / self.cartan_type().c()[self.r()] + if ell not in ZZ: + return False + + if ell not in ZZ: + raise ValueError("perfectness not defined for non-integral levels") + + # [FOS2010]_ check + if self.cartan_type().classical().type() not in ['E','F','G']: + return ell == self.s() / self.cartan_type().c()[self.r()] + + # Check by definition + # TODO: This is duplicated from ProjectedLevelZeroLSPaths, combine the two methods. + # TODO: Similarly, don't duplicate in the tensor product category, maybe + # move this to the derived affine category? + MPhi = [] + for b in self: + p = b.Phi().level() + assert p == b.Epsilon().level() + if p < level: + return False + if p == level: + MPhi += [b] + weights = [] + I = self.index_set() + rank = len(I) + La = self.weight_lattice_realization().basis() + from sage.combinat.integer_vector import IntegerVectors + for n in range(1,level+1): + for c in IntegerVectors(n, rank): + w = sum(c[i]*La[i] for i in I) + if w.level() == level: + weights.append(w) + return sorted(b.Phi() for b in MPhi) == sorted(weights) + + def level(self): + r""" + Return the level of ``self`` when ``self`` is a perfect crystal. + + .. SEEALSO:: + + :meth:`~sage.categories.affine_derived_crystals.KirillovReshetikhinCrystals.ParentMethods.is_perfect` + + EXAMPLES:: + + sage: K = crystals.KirillovReshetikhin(['A',2,1], 1, 1) + sage: K.level() + 1 + sage: K = crystals.KirillovReshetikhin(['C',2,1], 1, 2) + sage: K.level() + 1 + sage: K = crystals.KirillovReshetikhin(['D',4,1], 1, 3) + sage: K.level() + 3 + + sage: K = crystals.KirillovReshetikhin(['C',2,1], 1, 1) + sage: K.level() + Traceback (most recent call last): + ... + ValueError: this crystal is not perfect + """ + if not self.is_perfect(): + raise ValueError("this crystal is not perfect") + return self.s() / self.cartan_type().c()[self.r()] + def q_dimension(self, q=None, prec=None, use_product=False): """ Return the `q`-dimension of ``self``. diff --git a/src/sage/combinat/crystals/kirillov_reshetikhin.py b/src/sage/combinat/crystals/kirillov_reshetikhin.py index 99d50bb7a41..32a9d3b2f7e 100644 --- a/src/sage/combinat/crystals/kirillov_reshetikhin.py +++ b/src/sage/combinat/crystals/kirillov_reshetikhin.py @@ -555,66 +555,19 @@ def s(self): """ return self._s - def is_perfect(self): - r""" - Returns True or False depending on whether ``self`` is a perfect crystal or not, respectively. - - If ``self`` is the Kirillov-Reshetikhin crystal `B^{r,s}`, then it was proven in [FOS2010]_ - that it is perfect if and only if `s/c_r` is an integer (where `c_r` is a constant related to the - type of the crystal). - - REFERENCES: - - .. [FOS2010] G. Fourier, M. Okado, A. Schilling. - Perfectness of Kirillov-Reshetikhin crystals for nonexceptional types - Contemp. Math. 506 (2010) 127-143 ( :arxiv:`0811.1604` ) - - EXAMPLES:: - - sage: K = crystals.KirillovReshetikhin(['A',2,1], 1, 1) - sage: K.is_perfect() - True - - sage: K = crystals.KirillovReshetikhin(['C',2,1], 1, 1) - sage: K.is_perfect() - False - - sage: K = crystals.KirillovReshetikhin(['C',2,1], 1, 2) - sage: K.is_perfect() - True + @cached_method + def classically_highest_weight_vectors(self): """ - x = self.s()/self.cartan_type().c()[self.r()] - return x - ceil(x) == 0 - - def level(self): - r""" - Returns the level of ``self`` assuming that it is a perfect crystal. - - If ``self`` is the Kirillov-Reshetikhin crystal `B^{r,s}`, then it was proven in [FOS2010]_ - that its level is `s/c_r` which is an integer if ``self`` is perfect - (here `c_r` is a constant related to the type of the crystal). + Return the classically highest weight vectors of ``self``. EXAMPLES:: - sage: K = crystals.KirillovReshetikhin(['A',2,1], 1, 1) - sage: K.level() - 1 - sage: K = crystals.KirillovReshetikhin(['C',2,1], 1, 2) - sage: K.level() - 1 - sage: K = crystals.KirillovReshetikhin(['D',4,1], 1, 3) - sage: K.level() - 3 - - sage: K = crystals.KirillovReshetikhin(['C',2,1], 1, 1) - sage: K.level() - Traceback (most recent call last): - ... - ValueError: this crystal is not perfect - """ - if not self.is_perfect(): - raise ValueError("this crystal is not perfect") - return self.s()/self.cartan_type().c()[self.r()] + sage: K = crystals.KirillovReshetikhin(['D', 4, 1], 2, 2) + sage: K.classically_highest_weight_vectors() + ([], [[1], [2]], [[1, 1], [2, 2]]) + """ + return tuple([self.retract(mg) + for mg in self.classical_decomposition().module_generators]) def kirillov_reshetikhin_tableaux(self): """ From 25ae4ceafb4b0d66fe3e491fd8f3ac03c34c59f3 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 1 Sep 2015 15:10:53 -0500 Subject: [PATCH 018/452] Added cardinality() for KR crystals. --- .../categories/affine_derived_crystals.py | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/sage/categories/affine_derived_crystals.py b/src/sage/categories/affine_derived_crystals.py index 37c64994bb7..548a1752518 100644 --- a/src/sage/categories/affine_derived_crystals.py +++ b/src/sage/categories/affine_derived_crystals.py @@ -219,7 +219,7 @@ def s(self): 4 """ - @abstract_method + @abstract_method(optional=True) def classical_decomposition(self): """ Return the classical decomposition of ``self``. @@ -245,6 +245,24 @@ def classically_highest_weight_vectors(self): I0 = self.cartan_type().classical().index_set() return tuple([x for x in self if x.is_highest_weight(I0)]) + # TODO: This is duplicated in tensor product category + def cardinality(self): + """ + Return the cardinality of ``self``. + + EXAMPLES:: + + sage: K = crystals.KirillovReshetikhin(['E',6,1], 1,1) + sage: K.cardinality() + 27 + sage: K = crystals.KirillovReshetikhin(['C',6,1], 4,3) + sage: K.cardinality() + 4736732 + """ + CWLR = self.cartan_type().classical().root_system().ambient_space() + return sum(CWLR.weyl_dimension(mg.classical_weight()) + for mg in self.classically_highest_weight_vectors()) + @cached_method def maximal_vector(self): r""" @@ -609,6 +627,7 @@ def classically_highest_weight_vectors(self): it.append( iter(self.crystals[-len(path)-1]) ) return tuple(ret) + # TODO: This is duplicated in KR crystals category def cardinality(self): """ Return the cardinality of ``self``. From 6a57ce259f30676cf7bd144542c76d2f2169fcd7 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sat, 5 Sep 2015 07:45:44 -0500 Subject: [PATCH 019/452] Removing a little trailing whitespace. --- src/sage/categories/affine_derived_crystals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/categories/affine_derived_crystals.py b/src/sage/categories/affine_derived_crystals.py index 548a1752518..e270a9977d4 100644 --- a/src/sage/categories/affine_derived_crystals.py +++ b/src/sage/categories/affine_derived_crystals.py @@ -121,7 +121,7 @@ def digraph(self, subset=None, index_set=None): which the digraph should be constructed - ``index_set`` -- (optional) the index set to draw arrows - + .. SEEALSO:: :meth:`sage.categories.crystals.Crystals.ParentMethods.digraph` From e6b5d62eeeb071aa74c5f4d2f7dd84499e727983 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 20 Oct 2015 14:48:20 -0500 Subject: [PATCH 020/452] Fixing some issues with spin cases and affine crystals. --- src/sage/combinat/crystals/affine.py | 18 +++++++++-- .../combinat/crystals/kirillov_reshetikhin.py | 8 ++--- .../rigged_configurations/kr_tableaux.py | 31 +++++++++++++++---- 3 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/sage/combinat/crystals/affine.py b/src/sage/combinat/crystals/affine.py index 3ffaaac9847..8b044d7fc17 100644 --- a/src/sage/combinat/crystals/affine.py +++ b/src/sage/combinat/crystals/affine.py @@ -13,7 +13,7 @@ #**************************************************************************** from sage.misc.abstract_method import abstract_method -from sage.categories.affine_derived_crystals import AffineDerivedSubalgebraCrystals +from sage.categories.affine_derived_crystals import RegularAffineDerivedSubalgebraCrystals from sage.structure.parent import Parent from sage.structure.unique_representation import UniqueRepresentation from sage.structure.element_wrapper import ElementWrapper @@ -109,7 +109,7 @@ def __init__(self, cartan_type, classical_crystal, category=None): sage: TestSuite(A).run() """ if category is None: - category = AffineDerivedSubalgebraCrystals() + category = RegularAffineDerivedSubalgebraCrystals() self._cartan_type = cartan_type Parent.__init__(self, category = category) self.classical_crystal = classical_crystal; @@ -129,6 +129,20 @@ def _repr_(self): """ return "An affine crystal for type {}".format(self.cartan_type()) + def cardinality(self): + """ + Return the cardinality of ``self``. + + EXAMPLES:: + + sage: C = crystals.Tableaux(['A',3],shape=[1]) + sage: pr = attrcall("promotion") + sage: pr_inverse = attrcall("promotion_inverse") + sage: A = crystals.AffineFromClassicalAndPromotion(['A',3,1],C,pr,pr_inverse,1) + sage: A.cardinality() == C.cardinality() + True + """ + return self.classical_crystal.cardinality() def __iter__(self): r""" diff --git a/src/sage/combinat/crystals/kirillov_reshetikhin.py b/src/sage/combinat/crystals/kirillov_reshetikhin.py index 8613b151ec1..d3a63f5c005 100644 --- a/src/sage/combinat/crystals/kirillov_reshetikhin.py +++ b/src/sage/combinat/crystals/kirillov_reshetikhin.py @@ -2085,15 +2085,15 @@ def _element_constructor_(self, *args, **options): # Check to make sure it can be converted if elt.cartan_type() != self.cartan_type() \ or elt.parent().r() != self._r or elt.parent().s() != self._s: - raise ValueError("The Kirillov-Reshetikhin tableau must have the same Cartan type and shape") + raise ValueError("the Kirillov-Reshetikhin tableau must have the same Cartan type and shape") to_hw = elt.to_classical_highest_weight() - wt = to_hw[0].classical_weight() / 2 + wt = to_hw[0].classical_weight() f_str = reversed(to_hw[1]) for x in self.module_generators: if x.classical_weight() == wt: return x.f_string(f_str) - raise ValueError("No matching highest weight element found") + raise ValueError("no matching highest weight element found") return KirillovReshetikhinGenericCrystal._element_constructor_(self, *args, **options) def classical_decomposition(self): @@ -2534,7 +2534,7 @@ def _element_constructor_(self, *args, **options): raise ValueError("the Kirillov-Reshetikhin tableau must have the same Cartan type and shape") to_hw = elt.to_classical_highest_weight() - wt = to_hw[0].classical_weight() / 2 + wt = to_hw[0].classical_weight() f_str = reversed(to_hw[1]) for x in self.module_generators: if x.classical_weight() == wt: diff --git a/src/sage/combinat/rigged_configurations/kr_tableaux.py b/src/sage/combinat/rigged_configurations/kr_tableaux.py index b9b025897cb..f42420b7009 100644 --- a/src/sage/combinat/rigged_configurations/kr_tableaux.py +++ b/src/sage/combinat/rigged_configurations/kr_tableaux.py @@ -273,7 +273,7 @@ def __init__(self, cartan_type, r, s): EXAMPLES:: sage: KRT = crystals.KirillovReshetikhin(['A', 4, 1], 2, 2, model='KR') - sage: TestSuite(KRT).run() # long time + sage: TestSuite(KRT).run() sage: KRT = crystals.KirillovReshetikhin(['D', 4, 1], 2, 2, model='KR') sage: TestSuite(KRT).run() # long time sage: KRT = crystals.KirillovReshetikhin(['D', 4, 1], 4, 1, model='KR'); KRT @@ -453,7 +453,7 @@ def _element_constructor_(self, *lst, **options): # Check to make sure it can be converted if lst[0].cartan_type() != self.cartan_type() \ or lst[0].parent().r() != self._r or lst[0].parent().s() != self._s: - raise ValueError("The Kirillov-Reshetikhin crystal must have the same Cartan type and (r,s)") + raise ValueError("the Kirillov-Reshetikhin crystal must have the same Cartan type and (r,s)") return self.from_kirillov_reshetikhin_crystal(lst[0]) return self.element_class(self, list(lst), **options) @@ -1011,9 +1011,9 @@ def from_kirillov_reshetikhin_crystal(self, krc): f_str = reversed(to_hw[1]) wt = to_hw[0].weight() for x in self.module_generators: - if x.classical_weight() / 2 == wt: + if x.classical_weight() == wt: return x.f_string(f_str) - raise ValueError("No matching highest weight element found") + raise ValueError("no matching highest weight element found") class KirillovReshetikhinTableauxElement(TensorProductOfRegularCrystalsElement): r""" @@ -1287,8 +1287,7 @@ def classical_weight(self): WLR = F.weight_lattice() else: WLR = F.ambient_space() - weight = lambda x: x.weight() - return sum((weight(self[j]) for j in range(len(self))), WLR.zero()) + return sum((self[j].weight() for j in range(len(self))), WLR.zero()) def e(self, i): """ @@ -1586,6 +1585,26 @@ def left_split(self): rf = TP.crystals[1](*(self[h:])) return TP(lf, rf) + # FIXME: This is a copy of the above classical weight, and cached_method + # overwrites this method if it is called via super. + @cached_method + def classical_weight(self): + r""" + Return the classical weight of ``self``. + + EXAMPLES:: + + sage: KRT = crystals.KirillovReshetikhin(['D', 4, 1], 4, 1, model='KR') + sage: KRT.module_generators[0].classical_weight() + (1/2, 1/2, 1/2, 1/2) + """ + F = self.cartan_type().classical().root_system() + if F.ambient_space() is None: + WLR = F.weight_lattice() + else: + WLR = F.ambient_space() + return sum((self[j].weight() for j in range(len(self))), WLR.zero()) / 2 + KRTableauxBn.Element = KRTableauxSpinElement KRTableauxSpin.Element = KRTableauxSpinElement From a1fc17caa3cd1232a75392ed34eb89e8564c4324 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 20 Oct 2015 22:08:31 +0200 Subject: [PATCH 021/452] trac #19139 little doc problem --- src/sage/combinat/crystals/littelmann_path.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/combinat/crystals/littelmann_path.py b/src/sage/combinat/crystals/littelmann_path.py index d1742618931..089513588b9 100644 --- a/src/sage/combinat/crystals/littelmann_path.py +++ b/src/sage/combinat/crystals/littelmann_path.py @@ -830,14 +830,14 @@ def is_perfect(self, level=1): finite-dimensional `U_q^{'}(\mathfrak{g})`-module. #. `\mathcal{B}\otimes \mathcal{B}` is connected. #. There exists a `\lambda\in X`, such that - `\mathrm{wt}(\mathcal{B}) \subset \lambda + \sum_{i\in I} - \ZZ_{\le 0} \alpha_i` and there is a unique element in + `\mathrm{wt}(\mathcal{B}) \subset \lambda + \sum_{i\in I} \ZZ_{\le 0} \alpha_i` + and there is a unique element in `\mathcal{B}` of classical weight `\lambda`. #. For all `b \in \mathcal{B}`, `\mathrm{level}(\varepsilon (b)) \geq \ell`. #. For all `\Lambda` dominant weights of level `\ell`, there exist unique elements `b_{\Lambda}, b^{\Lambda} \in \mathcal{B}`, such - that `\varepsilon ( b_{\Lambda}) = \Lambda = \varphi( b^{\Lambda})`. + that `\varepsilon (b_{\Lambda}) = \Lambda = \varphi(b^{\Lambda})`. Points (1)-(3) are known to hold. This method checks points (4) and (5). From 7de002b3f7026fefca92a48cfc32c963a8ec38f7 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sun, 23 Aug 2015 21:58:58 +0000 Subject: [PATCH 022/452] Generate the Kleber tree by using integral points in a polytope. Conflicts: src/sage/combinat/rigged_configurations/kleber_tree.py --- .../rigged_configurations/kleber_tree.py | 151 +++++++----------- 1 file changed, 56 insertions(+), 95 deletions(-) diff --git a/src/sage/combinat/rigged_configurations/kleber_tree.py b/src/sage/combinat/rigged_configurations/kleber_tree.py index 031c85902b3..c914d5b3d80 100644 --- a/src/sage/combinat/rigged_configurations/kleber_tree.py +++ b/src/sage/combinat/rigged_configurations/kleber_tree.py @@ -114,11 +114,11 @@ def _draw_tree(tree_node, node_label=True, style_point=None, style_node='fill=wh \end{tikzpicture} """ draw_point = lambda point: '(%.3f, %.3f)'%(point[0],point[1]) - if len(tree_node.children) == 0: + if not tree_node.children: r = '' node_name = node_prefix + str(node_id) r = "\\node (%s) at %s"%(node_name, draw_point(start)) - if(node_label): + if node_label: r += "{$%s$};\n"%tree_node._latex_() else: r += "{};\n" @@ -176,7 +176,7 @@ def _draw_tree(tree_node, node_label=True, style_point=None, style_node='fill=wh rpos[1] = pos[1] point_str = '' node_str = "\\node%s (%s) at %s"%(style_node, node_name, draw_point(pos)) - if(node_label): + if node_label: node_str += "{$%s$};\n"%tree_node._latex_() else: node_str += "{};\n" @@ -301,11 +301,11 @@ def multiplicity(self): sage: KT = KleberTree(['A',3,1], [[3,2],[2,1],[1,1],[1,1]]) sage: for x in KT: x, x.multiplicity() (Kleber tree node with weight [2, 1, 2] and upwards edge root [0, 0, 0], 1) + (Kleber tree node with weight [3, 0, 1] and upwards edge root [0, 1, 1], 1) (Kleber tree node with weight [0, 2, 2] and upwards edge root [1, 0, 0], 1) (Kleber tree node with weight [1, 0, 3] and upwards edge root [1, 1, 0], 2) (Kleber tree node with weight [1, 1, 1] and upwards edge root [1, 1, 1], 4) (Kleber tree node with weight [0, 0, 2] and upwards edge root [2, 2, 1], 2) - (Kleber tree node with weight [3, 0, 1] and upwards edge root [0, 1, 1], 1) (Kleber tree node with weight [2, 0, 0] and upwards edge root [0, 1, 1], 2) (Kleber tree node with weight [0, 0, 2] and upwards edge root [1, 1, 0], 1) (Kleber tree node with weight [0, 1, 0] and upwards edge root [1, 1, 1], 2) @@ -589,7 +589,7 @@ def __classcall_private__(cls, cartan_type, B, classical=None): raise ValueError("use VirtualKleberTree for non-simply-laced types") # Standardize B input into a tuple of tuples - B = tuple(map(tuple, B)) + B = tuple([tuple(rs) for rs in B]) if classical is None: classical = cartan_type.classical() @@ -616,7 +616,7 @@ def __init__(self, cartan_type, B, classical_ct): self._cartan_type = cartan_type self.B = B self._classical_ct = classical_ct - self._build_tree(B) + self._build_tree() self._latex_options = dict(edge_labels=True, use_vector_notation=False, hspace=2.5, vspace=min(-2.5, -0.75*self._classical_ct.rank())) @@ -644,7 +644,7 @@ def latex_options(self, **options): sage: sorted(KT.latex_options().items()) [('edge_labels', True), ('hspace', 2.5), ('use_vector_notation', True), ('vspace', -4)] """ - if len(options) == 0: + if not options: from copy import copy return copy(self._latex_options) for k in options: @@ -672,7 +672,7 @@ def _latex_(self): _draw_tree(self.root, **self._latex_options) \ + "\\end{tikzpicture}" - def _build_tree(self, B): + def _build_tree(self): """ Build the Kleber tree. @@ -696,7 +696,7 @@ def _build_tree(self, B): for i in range(n): L.append([0]) - for r,s in B: + for r,s in self.B: while len(L[0]) < s: # Add more columns if needed for row in L: row.append(0) @@ -707,7 +707,7 @@ def _build_tree(self, B): for a in range(n): self.root.weight += sum(L[a]) * weight_basis[I[a]] new_children = [] - for new_child in self._children_root_iter(): + for new_child in self._children_iter(self.root): if not self._prune(new_child, 1): new_children.append(new_child) self.root.children.append(new_child) @@ -740,7 +740,7 @@ def _build_tree(self, B): new_children.append(new_child) # Connect the new children into the tree - if len(new_children) > 0: + if new_children: growth = True for new_child in new_children: new_child.parent_node.children.append(new_child) @@ -748,16 +748,23 @@ def _build_tree(self, B): self._set = full_list - def _children_root_iter(self): - """ - Iterate over the children of the root node. + def _children_iter(self, node): + r""" + Iterate over the children of ``node``. Helper iterator to iterate over all children, by generating and/or - computing them, of the Kleber tree root. + computing them, of the Kleber tree node. - Right now we are just assuming that if a linear combination of positive - roots keeps us in the Weyl chamber, then a shorter linear combination - does as well. + We compute the children by computing integral points (expressed as + simple roots) in the polytope given by the intersection of the + negative root cone and shifted positive weight cone. More precisely, + we rewrite the condition `\lambda - \mu \in Q^+`, for `\mu \in P^+`, + as `\lambda - Q^+ = \mu \in P^+`. + + INPUT: + + - ``node`` -- the current node in the tree whose children we want + to generate TESTS:: @@ -767,70 +774,7 @@ def _children_root_iter(self): Kleber tree node with weight [2, 0, 0] and upwards edge root [0, 0, 0] Kleber tree node with weight [0, 1, 1] and upwards edge root [1, 0, 0] Kleber tree node with weight [0, 0, 0] and upwards edge root [2, 1, 1] - """ - pos_roots = list(self._classical_ct.root_system().root_space().positive_roots()) - WS = self._classical_ct.root_system().weight_space() - num_pos_roots = len(pos_roots) - roots_visited = [] - - for root in pos_roots: - # If we've already tried this root - if root in roots_visited: - continue - - # If not, then try it - - roots_visited.append(root) - - new_weight = self.root.weight - WS(root) - - if new_weight.is_dominant(): - yield KleberTreeNode(self, new_weight, root, self.root) - root_stack = [root] - index_stack = [0] - - # Now try all of its children - while len(root_stack) > 0: - # If we've tried all of the roots, then back up - if index_stack[-1] == num_pos_roots: - root_stack.pop() - index_stack.pop() - continue - - new_root = root_stack[-1] + pos_roots[index_stack[-1]] - index_stack[-1] += 1 - - # If we've already tried this root, move on to the next one - if new_root in roots_visited: - continue - roots_visited.append(new_root) - - new_weight = self.root.weight - WS(new_root) - - if new_weight.is_dominant(): - yield KleberTreeNode(self, new_weight, new_root, self.root) - root_stack.append(new_root) - index_stack.append(0) - - def _children_iter(self, node): - """ - Iterate over all children nodes. - - This is a helper iterator to iterate over all children, by generating - and/or computing them, of a given Kleber tree node this isn't the root. - - We perform the dominance iteration by using the condition that that - new root must be smaller than the previous root. - - INPUT: - - - ``node`` -- The current node in the tree whose children we want - to generate - - TESTS:: - - sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree sage: KT = KleberTree(['D', 4, 1], [[2,2]]) sage: KT[1] Kleber tree node with weight [0, 1, 0, 0] and upwards edge root [1, 2, 1, 1] @@ -841,21 +785,38 @@ def _children_iter(self, node): sage: for x in KT._children_iter(KT[1]): x Kleber tree node with weight [0, 0, 0, 0] and upwards edge root [1, 2, 1, 1] """ - RS = self._classical_ct.root_system().root_space() - WS = self._classical_ct.root_system().weight_space() + n = self._classical_ct.rank() I = self._classical_ct.index_set() - - L = [range(val + 1) for val in node.up_root.to_vector()] - - it = itertools.product(*L) - it.next() # First element is the zero element - for root in it: - # Convert the list to an honest root in the root space - converted_root = RS.sum_of_terms([[I[i], val] for i, val in enumerate(root)]) - - new_weight = node.weight - WS(converted_root) - if new_weight.is_dominant(): - yield KleberTreeNode(self, new_weight, converted_root, node) + Q = self._classical_ct.root_system().root_space() + P = self._classical_ct.root_system().weight_space() + + # Construct the polytope by inequalities + from sage.geometry.polyhedron.constructor import Polyhedron + # Construct the shifted weight cone + root_weight = node.weight.to_vector() + ieqs = [[root_weight[i]] + list(col) + for i,col in enumerate(self._classical_ct.cartan_matrix())] + # Construct the negative weight cone + for i in range(n): + v = [0] * (n+1) + v[i+1] = -1 + ieqs.append(v) + ieqs.append([-1]*(n+1)) # For avoiding the origin + # Construct the bounds for the non-root nodes + if node != self.root: + for i,c in enumerate(node.up_root.to_vector()): + v = [0] * (n+1) + v[0] = c + v[i+1] = 1 + ieqs.append(v) + poly = Polyhedron(ieqs=ieqs) + + # Build the nodes from the polytope + # Sort for a consistent ordering (it is typically a small list) + for pt in sorted(poly.integral_points(), reverse=True): + up_root = Q._from_dict({I[i]: -val for i,val in enumerate(pt) if val != 0}, remove_zeros=False, ) + wt = node.weight + sum(val*P.simple_root(I[i]) for i,val in enumerate(pt)) + yield KleberTreeNode(self, wt, up_root, node) def _prune(self, new_child, depth): r""" From 7d3174bbcf58ed435593b71e0261554f8584db9e Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 25 Nov 2015 17:35:10 -0600 Subject: [PATCH 023/452] Changing the category for the new KR tableaux class. --- src/sage/combinat/rigged_configurations/kr_tableaux.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/rigged_configurations/kr_tableaux.py b/src/sage/combinat/rigged_configurations/kr_tableaux.py index 0551fab488c..4e026b76178 100644 --- a/src/sage/combinat/rigged_configurations/kr_tableaux.py +++ b/src/sage/combinat/rigged_configurations/kr_tableaux.py @@ -1764,7 +1764,7 @@ def __init__(self, cartan_type, r, s): self._r = r self._s = s self._cartan_type = cartan_type - Parent.__init__(self, category=(RegularCrystals(), FiniteCrystals())) + Parent.__init__(self, category=KirillovReshetikhinCrystals()) self.letters = CrystalOfLetters(cartan_type.classical()) @lazy_attribute From 38dc0c29e2119c48ffe4a719364e1dcc8193322b Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 25 Nov 2015 21:05:54 -0600 Subject: [PATCH 024/452] Tweaking the category for projected LS paths since they aren't realized as a tensor product. --- src/sage/combinat/crystals/littelmann_path.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/crystals/littelmann_path.py b/src/sage/combinat/crystals/littelmann_path.py index 089513588b9..24017249950 100644 --- a/src/sage/combinat/crystals/littelmann_path.py +++ b/src/sage/combinat/crystals/littelmann_path.py @@ -31,7 +31,8 @@ from sage.categories.regular_crystals import RegularCrystals from sage.categories.classical_crystals import ClassicalCrystals from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets -from sage.categories.affine_derived_crystals import KirillovReshetikhinCrystals +from sage.categories.affine_derived_crystals import (RegularAffineDerivedSubalgebraCrystals, + KirillovReshetikhinCrystals) from sage.combinat.root_system.cartan_type import CartanType from sage.combinat.root_system.weyl_group import WeylGroup from sage.rings.integer import Integer @@ -214,7 +215,12 @@ def __init__(self, starting_weight, starting_weight_parent): elif starting_weight.parent().is_extended(): Parent.__init__(self, category=(RegularCrystals(), InfiniteEnumeratedSets())) else: - Parent.__init__(self, category=KirillovReshetikhinCrystals().TensorProducts()) + cl = self._cartan_type.classical().index_set() + if sum(self.weight[i] for i in cl) == 1: + cat = KirillovReshetikhinCrystals() + else: + cat = RegularAffineDerivedSubalgebraCrystals().Finite() + Parent.__init__(self, category=cat) else: Parent.__init__(self, category=ClassicalCrystals()) From 98a04064d53d4bacf209b8d7380f7e9bb2e539f1 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sun, 20 Dec 2015 21:07:53 -0600 Subject: [PATCH 025/452] Converting to weight/root lattice and using the old method for types A and D. --- .../rigged_configurations/kleber_tree.py | 105 +++++++++++++----- 1 file changed, 80 insertions(+), 25 deletions(-) diff --git a/src/sage/combinat/rigged_configurations/kleber_tree.py b/src/sage/combinat/rigged_configurations/kleber_tree.py index c914d5b3d80..5b16b21446d 100644 --- a/src/sage/combinat/rigged_configurations/kleber_tree.py +++ b/src/sage/combinat/rigged_configurations/kleber_tree.py @@ -72,11 +72,13 @@ from sage.misc.latex import latex from sage.rings.arith import binomial from sage.rings.integer import Integer +from sage.rings.all import ZZ from sage.structure.parent import Parent from sage.structure.element import Element from sage.structure.unique_representation import UniqueRepresentation from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets +from sage.modules.free_module import FreeModule from sage.combinat.root_system.cartan_type import CartanType @@ -219,8 +221,8 @@ def __init__(self, parent_obj, node_weight, dominant_root, parent_node=None): sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree sage: RS = RootSystem(['A', 2]) - sage: WS = RS.weight_space() - sage: R = RS.root_space() + sage: WS = RS.weight_lattice() + sage: R = RS.root_lattice() sage: KT = KleberTree(['A', 2, 1], [[1,1]]) sage: parent = KT(WS.sum_of_terms([(1,5), (2,2)]), R.zero()) sage: parent @@ -248,8 +250,8 @@ def depth(self): sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree sage: RS = RootSystem(['A', 2]) - sage: WS = RS.weight_space() - sage: R = RS.root_space() + sage: WS = RS.weight_lattice() + sage: R = RS.root_lattice() sage: KT = KleberTree(['A', 2, 1], [[1,1]]) sage: n = KT(WS.sum_of_terms([(1,5), (2,2)]), R.zero()) sage: n.depth @@ -354,8 +356,8 @@ def __hash__(self): sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree sage: RS = RootSystem(['A', 2]) - sage: WS = RS.weight_space() - sage: R = RS.root_space() + sage: WS = RS.weight_lattice() + sage: R = RS.root_lattice() sage: KT = KleberTree(['A', 2, 1], [[1,1]]) sage: n = KT(WS.sum_of_terms([(1,5), (2,2)]), R.zero()) sage: hash(n) @@ -372,8 +374,8 @@ def __cmp__(self, rhs): sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree sage: RS = RootSystem(['A', 2]) - sage: WS = RS.weight_space() - sage: R = RS.root_space() + sage: WS = RS.weight_lattice() + sage: R = RS.root_lattice() sage: KT = KleberTree(['A', 2, 1], [[1,1]]) sage: n = KT(WS.sum_of_terms([(1,5), (2,2)]), R.zero()) sage: n2 = KT(WS.sum_of_terms([(1,5), (2,2)]), R.zero(), n) @@ -404,8 +406,8 @@ def _repr_(self): sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree sage: RS = RootSystem(['A', 3]) - sage: WS = RS.weight_space() - sage: R = RS.root_space() + sage: WS = RS.weight_lattice() + sage: R = RS.root_lattice() sage: KT = KleberTree(['A', 2, 1], [[1,1]]) sage: node = KT(WS.sum_of_terms([(1,2), (2,1), (3,1)]), R.sum_of_terms([(1,3), (3,3)])); node Kleber tree node with weight [2, 1, 1] and upwards edge root [3, 0, 3] @@ -428,8 +430,8 @@ def _latex_(self): sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree sage: RS = RootSystem(['A', 3]) - sage: WS = RS.weight_space() - sage: R = RS.root_space() + sage: WS = RS.weight_lattice() + sage: R = RS.root_lattice() sage: KT = KleberTree(['A', 3, 1], [[3,2], [1,1]]) sage: node = KT(WS.sum_of_terms([(1,4), (3,1)]), R.zero()) sage: latex(node) @@ -613,6 +615,11 @@ def __init__(self, cartan_type, B, classical_ct): """ Parent.__init__(self, category=FiniteEnumeratedSets()) + if classical_ct.type() == 'E' and classical_ct.rank() >= 7: + self._child_itr = self._children_iter + else: + self._child_itr = self._children_iter_vector + self._cartan_type = cartan_type self.B = B self._classical_ct = classical_ct @@ -683,9 +690,10 @@ def _build_tree(self): sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree sage: KT = KleberTree(['A',3,1], [[2,2]]) # indirect doctest """ + P = self._classical_ct.root_system().weight_lattice() # Create an empty node at first step - self.root = KleberTreeNode(self, self._classical_ct.root_system().weight_space().zero(), - self._classical_ct.root_system().root_space().zero()) + self.root = KleberTreeNode(self, P.zero(), + self._classical_ct.root_system().root_lattice().zero()) full_list = [self.root] # The list of tree nodes n = self._classical_ct.rank() @@ -703,7 +711,7 @@ def _build_tree(self): L[I.index(r)][s - 1] += 1 # The -1 is for indexing # Perform a special case of the algorithm for the root node - weight_basis = self._classical_ct.root_system().weight_space().basis() + weight_basis = P.basis() for a in range(n): self.root.weight += sum(L[a]) * weight_basis[I[a]] new_children = [] @@ -730,12 +738,12 @@ def _build_tree(self): x.weight += L[a][i] * weight_basis[I[a]] if x in leaves: - for new_child in self._children_iter(x): + for new_child in self._child_itr(x): if not self._prune(new_child, depth): new_children.append(new_child) else: for x in leaves: - for new_child in self._children_iter(x): + for new_child in self._child_itr(x): if not self._prune(new_child, depth): new_children.append(new_child) @@ -787,8 +795,8 @@ def _children_iter(self, node): """ n = self._classical_ct.rank() I = self._classical_ct.index_set() - Q = self._classical_ct.root_system().root_space() - P = self._classical_ct.root_system().weight_space() + Q = self._classical_ct.root_system().root_lattice() + P = self._classical_ct.root_system().weight_lattice() # Construct the polytope by inequalities from sage.geometry.polyhedron.constructor import Polyhedron @@ -818,6 +826,53 @@ def _children_iter(self, node): wt = node.weight + sum(val*P.simple_root(I[i]) for i,val in enumerate(pt)) yield KleberTreeNode(self, wt, up_root, node) + def _children_iter_vector(self, node): + r""" + Iterate over the children of ``node``. + + Helper iterator to iterate over all children, by generating and/or + computing them, of the Kleber tree node. This implementation + iterates over all possible uproot vectors. + + .. SEEALSO:: + + :meth:`_children_iter` + + INPUT: + + - ``node`` -- the current node in the tree whose children we want + to generate + + TESTS:: + + sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree + sage: KT = KleberTree(['D', 4, 1], [[2,2]]) + sage: KT[1] + Kleber tree node with weight [0, 1, 0, 0] and upwards edge root [1, 2, 1, 1] + sage: for x in KT._children_iter(KT[1]): x + Kleber tree node with weight [0, 0, 0, 0] and upwards edge root [1, 2, 1, 1] + """ + Q = self._classical_ct.root_system().root_lattice() + P = self._classical_ct.root_system().weight_lattice() + I = self._classical_ct.index_set() + wt = node.weight.to_vector() + # Everything is dense at this point; moreover, ranks are relatively small + CM = self._classical_ct.cartan_matrix().dense_matrix() + F = FreeModule(ZZ, self._classical_ct.rank()) + + L = [range(val + 1) for val in node.up_root.to_vector()] + + it = itertools.product(*L) + it.next() # First element is the zero element + for root in it: + # Convert the list to the weight lattice + converted_root = CM * F(root) + + if all(wt[i] >= val for i,val in enumerate(converted_root)): + wd = {I[i]: wt[i] - val for i, val in enumerate(converted_root)} + rd = {I[i]: val for i, val in enumerate(root)} + yield KleberTreeNode(self, P._from_dict(wd), Q._from_dict(rd), node) + def _prune(self, new_child, depth): r""" Return ``True`` if we are to prune the tree at ``new_child``. @@ -974,8 +1029,8 @@ def _element_constructor_(self, node_weight, dominant_root, parent_node=None): sage: from sage.combinat.rigged_configurations.kleber_tree import KleberTree sage: RS = RootSystem(['A', 2]) - sage: WS = RS.weight_space() - sage: R = RS.root_space() + sage: WS = RS.weight_lattice() + sage: R = RS.root_lattice() sage: KT = KleberTree(['A', 2, 1], [[1,1]]) sage: root = KT(WS.sum_of_terms([(1,5), (2,2)]), R.zero()); root # indirect doctest Kleber tree node with weight [5, 2] and upwards edge root [0, 0] @@ -1131,8 +1186,8 @@ def _prune(self, new_child, depth): sage: from sage.combinat.rigged_configurations.kleber_tree import VirtualKleberTree sage: RS = RootSystem(['A', 3]) - sage: WS = RS.weight_space() - sage: R = RS.root_space() + sage: WS = RS.weight_lattice() + sage: R = RS.root_lattice() sage: KT = VirtualKleberTree(['C',2,1], [[1,2],[1,1],[2,1]]) sage: x = KT(WS.sum_of_terms([(1,1), (2,1), (3,3)]), R.sum_of_terms([(1,2),(2,2),(3,1)]), KT.root) sage: KT._prune(x, 1) @@ -1327,8 +1382,8 @@ def _prune(self, new_child, depth): sage: from sage.combinat.rigged_configurations.kleber_tree import VirtualKleberTree sage: RS = RootSystem(['A', 5]) - sage: WS = RS.weight_space() - sage: R = RS.root_space() + sage: WS = RS.weight_lattice() + sage: R = RS.root_lattice() sage: KT = VirtualKleberTree(['A',6,2], [[2,2]]) sage: x = KT(WS.sum_of_terms([(2,1), (4,1)]), R.sum_of_terms([(1,1),(2,2),(3,2),(4,2),(5,1)]), KT.root) sage: KT._prune(x, 1) From 33af86e92c739daf4adfce96c3bb3752974bb1e6 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sun, 20 Dec 2015 21:21:03 -0600 Subject: [PATCH 026/452] Tweak the conditions for switching between algorithms just in terms of the rank. --- src/sage/combinat/rigged_configurations/kleber_tree.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/rigged_configurations/kleber_tree.py b/src/sage/combinat/rigged_configurations/kleber_tree.py index 5b16b21446d..6e3416e8c38 100644 --- a/src/sage/combinat/rigged_configurations/kleber_tree.py +++ b/src/sage/combinat/rigged_configurations/kleber_tree.py @@ -615,7 +615,7 @@ def __init__(self, cartan_type, B, classical_ct): """ Parent.__init__(self, category=FiniteEnumeratedSets()) - if classical_ct.type() == 'E' and classical_ct.rank() >= 7: + if classical_ct.rank() >= 7: self._child_itr = self._children_iter else: self._child_itr = self._children_iter_vector From 91cfa334d4ae936f8c5724996e3ccda598e0d618 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 1 Sep 2015 10:30:43 -0500 Subject: [PATCH 027/452] Initial creating of energy function by definition. --- .../categories/affine_derived_crystals.py | 152 +++++++++++++++--- 1 file changed, 126 insertions(+), 26 deletions(-) diff --git a/src/sage/categories/affine_derived_crystals.py b/src/sage/categories/affine_derived_crystals.py index dde4a05908b..a999e77bb1d 100644 --- a/src/sage/categories/affine_derived_crystals.py +++ b/src/sage/categories/affine_derived_crystals.py @@ -553,6 +553,65 @@ def lusztig_involution(self): hw.reverse() return self.to_lowest_weight(I)[0].e_string(aut[i] for i in hw) + @cached_method + def energy_function(self): + r""" + Return the energy function of ``self``. + + Let `B` be a KR crystal. Let `b^{\sharp}` denote the unique + element such that `\varphi(b^{\sharp}) = \ell \Lambda_0` with + `\ell = \min \{ \langle c, \varphi(b) \mid b \in B \}`. Let + `u_B` denote the maximal element of `B`. The *energy* of + `b \in B` is given by + + .. MATH:: + + D(b) = H(b \otimes b^{\sharp}) - H(u_B \otimes b^{\sharp}). + """ + ell = float('inf') + bsharp = None + for b in self.parent(): + phi = b.Phi() + if phi.support() == [0] and phi[0] < ell: + bsharp = b + ell = phi[0] + return self.local_energy_function(bsharp) - self.parent().maximal_vector().local_energy_function(bsharp) + + @cached_method + def local_energy_function(self, b): + r""" + Return the local energy function of ``self`` and ``b``. + + .. TODO:: + + Return a function `H: B \otimes B' \to \ZZ` + """ + K = self.parent() + T = K.tensor(b.parent()) + x = T(self, b) + if x == T.maximal_vector(): + from sage.rings.all import ZZ + return ZZ.zero() + + ell = ceil(K.s()/K.cartan_type().c()[K.r()]) + for i in T.cartan_type().classical().index_set(): + y = x.e(i) + if y is not None: + return y[0].local_energy_function(y[1]) + + y = x.e(0) + if y is not None: + H = y[0].local_energy_function(y[1]) + + xp = K.R_matrix(b.parent())(x) + yp = xp.e(0) + if b == y[1] and xp[1] == yp[1]: # LL case + return H - 1 + if self == y[0] and xp[0] == yp[0]: # RR case + return H + 1 + + assert False + class TensorProducts(TensorProductsCategory): """ The category of tensor products of Kirillov-Reshetikhin crystals. @@ -710,20 +769,37 @@ def one_dimensional_configuration_sum(self, q=None, group_components=True): return B.sum(q**(b.energy_function())*B(P0(b.weight())) for b in self) class ElementMethods: - def energy_function(self): + def energy_function(self, algorithm=None): r""" Return the energy function of ``self``. - The energy is only defined when ``self`` is an element of a - tensor product of affine Kirillov-Reshetikhin crystals. In this - implementation, it is assumed that ``self`` is an element of a - tensor product of perfect crystals of the same level, see - Theorem 7.5 in [SchillingTingley2011]_. + ALGORITHM: + + .. RUBRIC:: definition + + .. RUBRIC:: grading + + If ``self`` is an element of `T`, a tensor product of perfect + crystals of the same level, then use the affine grading + to determine the energy. Specifically, let `g` denote + the affine grading of ``self`` and `d` the affine grading + of the maximal vector in `T`. Then the energy of ``self`` + is given by `d - g`. + + For more details, see Theorem 7.5 in [SchillingTingley2011]_. INPUT: - - ``self`` -- an element of a tensor product of perfect - Kirillov-Reshetkhin crystals of the same level + - ``algorithm`` -- (default: ``None``) use one of the + following algorithms to determine the energy function: + + * ``'definition'`` - use the definition of the energy + function; + * ``'grading'`` - use the affine grading; + + if not specified, then this uses ``'grading'`` if all + factors are perfect of the same level and otherwise + this uses ``'definition'`` OUTPUT: an integer @@ -739,9 +815,9 @@ def energy_function(self): sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) sage: T = crystals.TensorProduct(K,K,K) - sage: hw = [b for b in T if all(b.epsilon(i)==0 for i in [1,2])] + sage: hw = T.classically_highest_weight_vectors() sage: for b in hw: - ....: print b, b.energy_function() + ....: print b, b.energy_function() [[[1]], [[1]], [[1]]] 0 [[[1]], [[2]], [[1]]] 2 [[[2]], [[1]], [[1]]] 1 @@ -749,7 +825,7 @@ def energy_function(self): sage: K = crystals.KirillovReshetikhin(['C',2,1],1,2) sage: T = crystals.TensorProduct(K,K) - sage: hw = [b for b in T if all(b.epsilon(i)==0 for i in [1,2])] + sage: hw = T.classically_highest_weight_vectors() sage: for b in hw: # long time (5s on sage.math, 2011) ....: print b, b.energy_function() [[], []] 4 @@ -765,28 +841,52 @@ def energy_function(self): sage: K = crystals.KirillovReshetikhin(['C',2,1],1,1) sage: T = crystals.TensorProduct(K) sage: t = T.module_generators[0] - sage: t.energy_function() + sage: t.energy_function('grading') Traceback (most recent call last): ... NotImplementedError: all crystals in the tensor product need to be perfect of the same level """ C = self.parent().crystals[0] ell = ceil(C.s()/C.cartan_type().c()[C.r()]) - if any(ell != K.s()/K.cartan_type().c()[K.r()] for K in self.parent().crystals): - raise NotImplementedError("all crystals in the tensor product need to be perfect of the same level") - t = self.parent()(*[K.module_generator() for K in self.parent().crystals]) - d = t.affine_grading() - return d - self.affine_grading() + is_perfect = all(ell == K.s()/K.cartan_type().c()[K.r()] + for K in self.parent().crystals) + if algorithm is None: + if is_perfect: + algorithm = 'grading' + else: + algorithm = 'definition' + + if algorithm == 'grading': + if not is_perfect: + raise NotImplementedError("all crystals in the tensor product need to be perfect of the same level") + d = self.parent().maximal_vector().affine_grading() + return d - self.affine_grading() + + if algorithm == 'definition': + # Setup + from sage.rings.all import ZZ + energy = ZZ.zero() + R_mats = [[K.R_matrix(Kp) for Kp in self.parent().crystals[i+1:]] + for i,K in enumerate(self.parent().crystals)] + + for j,b in enumerate(self): + for k,R in enumerate(R_mats[j]): + bp = self[j+k+1] + energy += b.local_energy_function(bp) # H contribution + T = R.domain() + b = R(T(b, bp))[1] + energy += b.energy_function() # D contribution + return energy + else: + raise ValueError("invalid algorithm") def affine_grading(self): r""" Return the affine grading of ``self``. - The affine grading is only defined when ``self`` is an - element of a tensor product of Kirillov-Reshetikhin - crystals. It is calculated by finding a path from ``self`` - to a ground state path using the helper method - :meth:`e_string_to_ground_state` and counting the number + The affine grading is calculated by finding a path + from ``self`` to a ground state path (using the helper method + :meth:`e_string_to_ground_state`) and counting the number of affine Kashiwara operators `e_0` applied on the way. OUTPUT: an integer @@ -801,7 +901,7 @@ def affine_grading(self): sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) sage: T = crystals.TensorProduct(K,K,K) - sage: hw = [b for b in T if all(b.epsilon(i)==0 for i in [1,2])] + sage: hw = T.classically_highest_weight_vectors() sage: for b in hw: ....: print b, b.affine_grading() [[[1]], [[1]], [[1]]] 3 @@ -811,7 +911,7 @@ def affine_grading(self): sage: K = crystals.KirillovReshetikhin(['C',2,1],1,1) sage: T = crystals.TensorProduct(K,K,K) - sage: hw = [b for b in T if all(b.epsilon(i)==0 for i in [1,2])] + sage: hw = T.classically_highest_weight_vectors() sage: for b in hw: ....: print b, b.affine_grading() [[[1]], [[1]], [[1]]] 2 @@ -850,10 +950,10 @@ def e_string_to_ground_state(self): [[[1]], [[1]]] sage: t.e_string_to_ground_state() (0,) - sage: x=t.e(0) + sage: x = t.e(0) sage: x.e_string_to_ground_state() () - sage: y=t.f_string([1,2,1,1,0]); y + sage: y = t.f_string([1,2,1,1,0]); y [[[2]], [[1]]] sage: y.e_string_to_ground_state() () From 021e1712f6726e48822c139bb5c3ed6a22fa295d Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 1 Sep 2015 23:33:22 -0500 Subject: [PATCH 028/452] Moving local_energy_function to a subclass of Map. --- .../categories/affine_derived_crystals.py | 202 ++++++++++++++---- 1 file changed, 158 insertions(+), 44 deletions(-) diff --git a/src/sage/categories/affine_derived_crystals.py b/src/sage/categories/affine_derived_crystals.py index a999e77bb1d..18a44f94302 100644 --- a/src/sage/categories/affine_derived_crystals.py +++ b/src/sage/categories/affine_derived_crystals.py @@ -15,6 +15,8 @@ from sage.categories.regular_crystals import RegularCrystals from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets from sage.categories.tensor import TensorProductsCategory +from sage.categories.map import Map +from sage.categories.homset import Hom from sage.graphs.dot2tex_utils import have_dot2tex from sage.functions.other import ceil from sage.rings.all import ZZ @@ -388,6 +390,61 @@ def R_matrix(self, K): g = { gen1 : gen2 } return T1.crystal_morphism(g, check=False) + @cached_method + def local_energy_function(self, B): + r""" + Return the local energy function of ``self`` and ``B``. + + EXAMPLES:: + + sage: K = crystals.KirillovReshetikhin(['A',6,2], 2,1) + sage: Kp = crystals.KirillovReshetikhin(['A',6,2], 1,1) + sage: H = K.local_energy_function(Kp); H + Local energy function of + Kirillov-Reshetikhin crystal of type ['BC', 3, 2] with (r,s)=(2,1) + tensor + Kirillov-Reshetikhin crystal of type ['BC', 3, 2] with (r,s)=(1,1) + """ + return LocalEnergyFunction(self, B) + + @cached_method + def b_sharp(self): + r""" + Return the element `b^{\sharp}` of ``self``. + + Let `B` be a KR crystal. The element `b^{\sharp}` is the unique + element such that `\varphi(b^{\sharp}) = \ell \Lambda_0` with + `\ell = \min \{ \langle c, \varphi(b) \mid b \in B \}`. + + EXAMPLES:: + + sage: K = crystals.KirillovReshetikhin(['A',6,2], 2,1) + sage: K.b_sharp() + [] + sage: K.b_sharp().Phi() + Lambda[0] + + sage: K = crystals.KirillovReshetikhin(['C',3,1], 1,3) + sage: K.b_sharp() + [[-1]] + sage: K.b_sharp().Phi() + 2*Lambda[0] + + sage: K = crystals.KirillovReshetikhin(['D',6,2], 2,2) + sage: K.b_sharp() # long time + [] + sage: K.b_sharp().Phi() + 2*Lambda[0] + """ + ell = float('inf') + bsharp = None + for b in self: + phi = b.Phi() + if phi.support() == [0] and phi[0] < ell: + bsharp = b + ell = phi[0] + return bsharp + def is_perfect(self, ell=None): r""" Check if ``self`` is a perfect crystal of level ``ell``. @@ -567,50 +624,26 @@ def energy_function(self): .. MATH:: D(b) = H(b \otimes b^{\sharp}) - H(u_B \otimes b^{\sharp}). - """ - ell = float('inf') - bsharp = None - for b in self.parent(): - phi = b.Phi() - if phi.support() == [0] and phi[0] < ell: - bsharp = b - ell = phi[0] - return self.local_energy_function(bsharp) - self.parent().maximal_vector().local_energy_function(bsharp) - @cached_method - def local_energy_function(self, b): - r""" - Return the local energy function of ``self`` and ``b``. - - .. TODO:: + EXAMPLES:: - Return a function `H: B \otimes B' \to \ZZ` + sage: for x in K.classically_highest_weight_vectors(): + ....: x, x.energy_function() + ([], 1) + ([[1], [2]], 0) + + sage: K = crystals.KirillovReshetikhin(['D',4,3], 1,2) + sage: for x in K.classically_highest_weight_vectors(): + ....: x, x.energy_function() + ([], 2) + ([[1]], 1) + ([[1, 1]], 0) """ - K = self.parent() - T = K.tensor(b.parent()) - x = T(self, b) - if x == T.maximal_vector(): - from sage.rings.all import ZZ - return ZZ.zero() - - ell = ceil(K.s()/K.cartan_type().c()[K.r()]) - for i in T.cartan_type().classical().index_set(): - y = x.e(i) - if y is not None: - return y[0].local_energy_function(y[1]) - - y = x.e(0) - if y is not None: - H = y[0].local_energy_function(y[1]) - - xp = K.R_matrix(b.parent())(x) - yp = xp.e(0) - if b == y[1] and xp[1] == yp[1]: # LL case - return H - 1 - if self == y[0] and xp[0] == yp[0]: # RR case - return H + 1 - - assert False + B = self.parent() + bsharp = B.b_sharp() + T = B.tensor(B) + H = B.local_energy_function(B) + return H(T(self, bsharp)) - H(T(B.maximal_vector(), bsharp)) class TensorProducts(TensorProductsCategory): """ @@ -864,17 +897,20 @@ def energy_function(self, algorithm=None): if algorithm == 'definition': # Setup - from sage.rings.all import ZZ energy = ZZ.zero() R_mats = [[K.R_matrix(Kp) for Kp in self.parent().crystals[i+1:]] for i,K in enumerate(self.parent().crystals)] + H_funcs = [[K.local_energy_function(Kp) for Kp in self.parent().crystals[i+1:]] + for i,K in enumerate(self.parent().crystals)] for j,b in enumerate(self): for k,R in enumerate(R_mats[j]): + H = H_funcs[j][k] bp = self[j+k+1] - energy += b.local_energy_function(bp) # H contribution T = R.domain() - b = R(T(b, bp))[1] + t = T(b, bp) + energy += H(t) + b = R(t)[1] energy += b.energy_function() # D contribution return energy else: @@ -967,3 +1003,81 @@ def e_string_to_ground_state(self): return (0,) + (self.e(0)).e_string_to_ground_state() return () + +##################################################################### +## Local energy function + +class LocalEnergyFunction(Map): + r""" + The local energy function. + + The *local energy function* `H : B \otimes B' \to \ZZ` is... + """ + def __init__(self, B, Bp, normalization=0): + """ + Initialize ``self``. + """ + self._B = B + self._Bp = Bp + T = B.tensor(Bp) + self._known_values = {T.maximal_vector(): ZZ(normalization)} + self._I0 = T.cartan_type().classical().index_set() + Map.__init__(self, Hom(T, ZZ)) + + def _repr_(self): + """ + Return a string representation of ``self``. + """ + return "Local energy function of {} tensor {}".format(self._B, self._Bp) + + def _call_(self, x): + """ + Return the local energy of ``x``. + """ + # Setup variables + visited = {x: 0} + check0 = [x] + + # Helper functions + def classical_hw(cur): + for i in self._I0: + y = cur.e(i) + if y is not None and y not in visited: + visited[y] = visited[cur] # No change + return y + return None # is classically HW or all have been visited + + cur = x + baseline = 0 + while cur not in self._known_values: + # We first go to the classically highest weight since the + # maximal vector is classically highest weight + y = classical_hw(cur) + + # If classically HW, then try some 0 arrows + while y is None: + y = check0.pop().e(0) + if y in visited: + y = None + continue + + if y is not None: + xp = self._B.R_matrix(self._Bp)(x) + yp = xp.e(0) + if x[1] == y[1] and xp[1] == yp[1]: # LL case + visited[y] = visited[cur] + 1 + elif x[0] == y[0] and xp[0] == yp[0]: # RR case + visited[y] = visited[cur] - 1 + else: + visited[y] = visited[cur] # Otherwise no change + + cur = y + check0.append(y) + baseline = visited[cur] + + baseline = self._known_values[cur] - baseline + for y in visited: + self._known_values[y] = baseline + visited[y] + + return self._known_values[x] + From 50a92d9070988e3f6894fc283b0f1a13b9f67a49 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 28 Jan 2016 17:11:13 -0600 Subject: [PATCH 029/452] Fixing bugs and adding more documentation. --- .../categories/affine_derived_crystals.py | 217 +++++++++++++----- 1 file changed, 160 insertions(+), 57 deletions(-) diff --git a/src/sage/categories/affine_derived_crystals.py b/src/sage/categories/affine_derived_crystals.py index 18a44f94302..8b2e1438ca1 100644 --- a/src/sage/categories/affine_derived_crystals.py +++ b/src/sage/categories/affine_derived_crystals.py @@ -385,16 +385,19 @@ def R_matrix(self, K): from sage.combinat.crystals.tensor_product import TensorProductOfCrystals T1 = TensorProductOfCrystals(self, K) T2 = TensorProductOfCrystals(K, self) - gen1 = T1( self.maximal_vector(), K.maximal_vector() ) - gen2 = T2( K.maximal_vector(), self.maximal_vector() ) - g = { gen1 : gen2 } - return T1.crystal_morphism(g, check=False) + gen1 = T1(self.maximal_vector(), K.maximal_vector()) + gen2 = T2(K.maximal_vector(), self.maximal_vector()) + return T1.crystal_morphism({gen1: gen2}, check=False) @cached_method def local_energy_function(self, B): r""" Return the local energy function of ``self`` and ``B``. + See + :class:`~sage.categories.affine_derived_crystals.LocalEnergyFunction` + for a definition. + EXAMPLES:: sage: K = crystals.KirillovReshetikhin(['A',6,2], 2,1) @@ -433,7 +436,7 @@ def b_sharp(self): sage: K = crystals.KirillovReshetikhin(['D',6,2], 2,2) sage: K.b_sharp() # long time [] - sage: K.b_sharp().Phi() + sage: K.b_sharp().Phi() # long time 2*Lambda[0] """ ell = float('inf') @@ -623,10 +626,14 @@ def energy_function(self): .. MATH:: - D(b) = H(b \otimes b^{\sharp}) - H(u_B \otimes b^{\sharp}). + D(b) = H(b \otimes b^{\sharp}) - H(u_B \otimes b^{\sharp}), + + where `H` is the :meth:`local energy function + `. EXAMPLES:: + sage: K = crystals.KirillovReshetikhin(['D',4,1], 2,1) sage: for x in K.classically_highest_weight_vectors(): ....: x, x.energy_function() ([], 1) @@ -810,14 +817,28 @@ def energy_function(self, algorithm=None): .. RUBRIC:: definition + Let `T` be a tensor product of Kirillov-Reshetikhin + crystals. Let `R_i` and `H_i` be the combinatorial + `R`-matrix and local energy functions, respectively, acting + on the `i` and `i+1` factors. Let `D_B` be the energy + function of a single Kirillov-Reshetikhin crystal. The + *energy function* is given by + + .. MATH:: + + D = \sum_{j > i} H_i R_{i+1} R_{i+2} \cdots R_{j-1} + + \sum_j D_B R_1 R_2 \cdots R_{j-1}, + + where `D_B` acts on the rightmost factor. + .. RUBRIC:: grading - If ``self`` is an element of `T`, a tensor product of perfect - crystals of the same level, then use the affine grading - to determine the energy. Specifically, let `g` denote - the affine grading of ``self`` and `d` the affine grading - of the maximal vector in `T`. Then the energy of ``self`` - is given by `d - g`. + If ``self`` is an element of `T`, a tensor product of + perfect crystals of the same level, then use the affine + grading to determine the energy. Specifically, let `g` + denote the affine grading of ``self`` and `d` the affine + grading of the maximal vector in `T`. Then the energy + of ``self`` is given by `d - g`. For more details, see Theorem 7.5 in [SchillingTingley2011]_. @@ -846,24 +867,24 @@ def energy_function(self, algorithm=None): EXAMPLES:: - sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) + sage: K = crystals.KirillovReshetikhin(['A',2,1], 1, 1) sage: T = crystals.TensorProduct(K,K,K) sage: hw = T.classically_highest_weight_vectors() sage: for b in hw: ....: print b, b.energy_function() [[[1]], [[1]], [[1]]] 0 - [[[1]], [[2]], [[1]]] 2 [[[2]], [[1]], [[1]]] 1 + [[[1]], [[2]], [[1]]] 2 [[[3]], [[2]], [[1]]] 3 - sage: K = crystals.KirillovReshetikhin(['C',2,1],1,2) + sage: K = crystals.KirillovReshetikhin(['C',2,1], 1, 2) sage: T = crystals.TensorProduct(K,K) sage: hw = T.classically_highest_weight_vectors() - sage: for b in hw: # long time (5s on sage.math, 2011) + sage: for b in hw: ....: print b, b.energy_function() [[], []] 4 - [[], [[1, 1]]] 1 [[[1, 1]], []] 3 + [[], [[1, 1]]] 1 [[[1, 1]], [[1, 1]]] 0 [[[1, 2]], [[1, 1]]] 1 [[[2, 2]], [[1, 1]]] 2 @@ -871,13 +892,23 @@ def energy_function(self, algorithm=None): [[[1, -1]], [[1, 1]]] 2 [[[2, -1]], [[1, 1]]] 2 - sage: K = crystals.KirillovReshetikhin(['C',2,1],1,1) + sage: K = crystals.KirillovReshetikhin(['C',2,1], 1, 1) sage: T = crystals.TensorProduct(K) sage: t = T.module_generators[0] sage: t.energy_function('grading') Traceback (most recent call last): ... NotImplementedError: all crystals in the tensor product need to be perfect of the same level + + TESTS:: + + sage: K = crystals.KirillovReshetikhin(['C',2,1], 1, 2) + sage: K2 = crystals.KirillovReshetikhin(['C',2,1], 2, 2) + sage: T = tensor([K, K2]) + sage: hw = T.classically_highest_weight_vectors() + sage: all(b.energy_function() == b.energy_function(algorithm='definition') + ....: for b in hw) + True """ C = self.parent().crystals[0] ell = ceil(C.s()/C.cartan_type().c()[C.r()]) @@ -901,12 +932,12 @@ def energy_function(self, algorithm=None): R_mats = [[K.R_matrix(Kp) for Kp in self.parent().crystals[i+1:]] for i,K in enumerate(self.parent().crystals)] H_funcs = [[K.local_energy_function(Kp) for Kp in self.parent().crystals[i+1:]] - for i,K in enumerate(self.parent().crystals)] + for i,K in enumerate(self.parent().crystals)] - for j,b in enumerate(self): - for k,R in enumerate(R_mats[j]): - H = H_funcs[j][k] - bp = self[j+k+1] + for i,b in enumerate(self): + for j,R in enumerate(R_mats[i]): + H = H_funcs[i][j] + bp = self[i+j+1] T = R.domain() t = T(b, bp) energy += H(t) @@ -941,8 +972,8 @@ def affine_grading(self): sage: for b in hw: ....: print b, b.affine_grading() [[[1]], [[1]], [[1]]] 3 - [[[1]], [[2]], [[1]]] 1 [[[2]], [[1]], [[1]]] 2 + [[[1]], [[2]], [[1]]] 1 [[[3]], [[2]], [[1]]] 0 sage: K = crystals.KirillovReshetikhin(['C',2,1],1,1) @@ -951,11 +982,11 @@ def affine_grading(self): sage: for b in hw: ....: print b, b.affine_grading() [[[1]], [[1]], [[1]]] 2 - [[[1]], [[2]], [[1]]] 1 - [[[1]], [[-1]], [[1]]] 0 [[[2]], [[1]], [[1]]] 1 - [[[-2]], [[2]], [[1]]] 0 [[[-1]], [[1]], [[1]]] 1 + [[[1]], [[2]], [[1]]] 1 + [[[-2]], [[2]], [[1]]] 0 + [[[1]], [[-1]], [[1]]] 0 """ return self.e_string_to_ground_state().count(0) @@ -1011,14 +1042,63 @@ class LocalEnergyFunction(Map): r""" The local energy function. - The *local energy function* `H : B \otimes B' \to \ZZ` is... + Let `B` and `B'` be Kirillov-Reshetikhin crystals with maximal + vectors `u_B` and `u_{B'}` respectively. The *local energy function* + `H : B \otimes B' \to \ZZ` is the function which satisfies + + .. MATH:: + + H(e_0(b \otimes b')) = H(b \otimes b') + \begin{cases} + 1 & \text{if } i = 0 \text{ and LL}, \\ + -1 & \text{if } i = 0 \text{ and RR}, \\ + 0 & \text{otherwise,} + \end{cases} + + where LL (resp. RR) denote `e_0` acts on the left (resp. right) + on both `b \otimes b'` and `R(b \otimes b')`, and + normalized by `H(u_B \otimes u_{B'}) = 0`. + + INPUT: + + - ``B`` -- a Kirillov-Reshetikhin crystal + - ``Bp`` -- a Kirillov-Reshetikhin crystal + - ``normalization`` -- (default: 0) the normalization value + + EXAMPLES:: + + sage: K = crystals.KirillovReshetikhin(['C',2,1], 1,2) + sage: K2 = crystals.KirillovReshetikhin(['C',2,1], 2,1) + sage: H = K.local_energy_function(K2) + sage: T = tensor([K, K2]) + sage: hw = T.classically_highest_weight_vectors() + sage: for b in hw: + ....: b, H(b) + ([[], [[1], [2]]], 1) + ([[[1, 1]], [[1], [2]]], 0) + ([[[2, -2]], [[1], [2]]], 1) + ([[[1, -2]], [[1], [2]]], 1) + + REFERENCES: + + .. [KKMMNN92] S-J. Kang, M. Kashiwara, K. C. Misra, T. Miwa, + T. Nakashima, and A. Nakayashiki. + *Affine crystals and vertex models*. + Int. J. Mod. Phys. A, **7** (suppl. 1A), (1992) pp. 449-484. """ def __init__(self, B, Bp, normalization=0): """ Initialize ``self``. + + EXAMPLES:: + + sage: K = crystals.KirillovReshetikhin(['A',7,2], 1,2) + sage: K2 = crystals.KirillovReshetikhin(['A',7,2], 2,1) + sage: H = K.local_energy_function(K2) + sage: TestSuite(H).run(skip=['_test_category', '_test_pickling']) """ self._B = B self._Bp = Bp + self._R_matrix = self._B.R_matrix(self._Bp) T = B.tensor(Bp) self._known_values = {T.maximal_vector(): ZZ(normalization)} self._I0 = T.cartan_type().classical().index_set() @@ -1027,55 +1107,78 @@ def __init__(self, B, Bp, normalization=0): def _repr_(self): """ Return a string representation of ``self``. + + EXAMPLES:: + + sage: K = crystals.KirillovReshetikhin(['A', 6, 2], 2, 1) + sage: Kp = crystals.KirillovReshetikhin(['A', 6, 2], 1, 1) + sage: H = K.local_energy_function(Kp); H + Local energy function of + Kirillov-Reshetikhin crystal of type ['BC', 3, 2] with (r,s)=(2,1) + tensor + Kirillov-Reshetikhin crystal of type ['BC', 3, 2] with (r,s)=(1,1) """ return "Local energy function of {} tensor {}".format(self._B, self._Bp) def _call_(self, x): """ Return the local energy of ``x``. + + EXAMPLES:: + + sage: K = crystals.KirillovReshetikhin(['B',4,1], 1,2) + sage: K2 = crystals.KirillovReshetikhin(['B',4,1], 2,1) + sage: H = K.local_energy_function(K2) + sage: T = tensor([K, K2]) + sage: hw = T.classically_highest_weight_vectors() + sage: H(hw[0]) + 1 """ # Setup variables visited = {x: 0} check0 = [x] - # Helper functions - def classical_hw(cur): + # Helper function + def to_classical_hw(cur): for i in self._I0: - y = cur.e(i) - if y is not None and y not in visited: - visited[y] = visited[cur] # No change - return y + b = cur.e(i) + if b is not None and b not in visited: + visited[b] = visited[cur] # No change + return b return None # is classically HW or all have been visited cur = x - baseline = 0 + # Get the affine node (it might not be 0 if the type + # has been relabeled) + i0 = x.parent().cartan_type().special_node() while cur not in self._known_values: - # We first go to the classically highest weight since the - # maximal vector is classically highest weight - y = classical_hw(cur) - - # If classically HW, then try some 0 arrows - while y is None: - y = check0.pop().e(0) - if y in visited: - y = None + # We first go towards the classically highest weight since + # the maximal vector is classically highest weight + b = to_classical_hw(cur) + + # If classically HW, then try 0 arrows + while b is None: + b = check0.pop() + c = b.e(i0) + # If there is no 0 arrow or we have already seen c, move along + if c is None or c in visited: + b = None continue - if y is not None: - xp = self._B.R_matrix(self._Bp)(x) - yp = xp.e(0) - if x[1] == y[1] and xp[1] == yp[1]: # LL case - visited[y] = visited[cur] + 1 - elif x[0] == y[0] and xp[0] == yp[0]: # RR case - visited[y] = visited[cur] - 1 - else: - visited[y] = visited[cur] # Otherwise no change + bp = self._R_matrix(b) + cp = bp.e(i0) + if b[1] == c[1] and bp[1] == cp[1]: # LL case + visited[c] = visited[b] + 1 + elif b[0] == c[0] and bp[0] == cp[0]: # RR case + visited[c] = visited[b] - 1 + else: + visited[c] = visited[b] # Otherwise no change + b = c - cur = y - check0.append(y) - baseline = visited[cur] + cur = b + check0.append(b) - baseline = self._known_values[cur] - baseline + baseline = self._known_values[cur] - visited[cur] for y in visited: self._known_values[y] = baseline + visited[y] From ded9cf4bb48a05b14674ba98d277820003f92261 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 12 Nov 2015 22:08:48 -0600 Subject: [PATCH 030/452] Initial version from code provided by Dinakar and Peter. --- .../crystals/braid_move_calculator.py | 200 ++++++++++++++ .../crystals/catalog_infinity_crystals.py | 2 + src/sage/combinat/crystals/mv_polytope.py | 25 ++ src/sage/combinat/crystals/pbw_crystal.py | 224 +++++++++++++++ src/sage/combinat/crystals/pbw_datum.py | 258 ++++++++++++++++++ 5 files changed, 709 insertions(+) create mode 100644 src/sage/combinat/crystals/braid_move_calculator.py create mode 100644 src/sage/combinat/crystals/mv_polytope.py create mode 100644 src/sage/combinat/crystals/pbw_crystal.py create mode 100644 src/sage/combinat/crystals/pbw_datum.py diff --git a/src/sage/combinat/crystals/braid_move_calculator.py b/src/sage/combinat/crystals/braid_move_calculator.py new file mode 100644 index 00000000000..24937814209 --- /dev/null +++ b/src/sage/combinat/crystals/braid_move_calculator.py @@ -0,0 +1,200 @@ + +## Dinakar Muthiah June 3, 2014 + +""" Sample usage +W = CoxeterGroup(['A',5]) +load('BraidMoveCalculator.sage'); B = BraidMoveCalculator(W) +view(B.chain_of_reduced_words((1,2,1,3,2,1,4,3,2,1,5,4,3,2,1),(5,4,5,3,4,5,2,3,4,5,1,2,3,4,5))) + +""" +from sage.combinat.root_system.cartan_type import CartanType + + +class BraidMoveCalculator(object): + def __init__(self,coxeter_group): + self.coxeter_group = coxeter_group + self.simple_reflections = self.coxeter_group.simple_reflections() + + def multiply_word(self,word): + return self.coxeter_group.from_reduced_word(word) + #return prod([self.s[i] for i in word]) + + def is_reduced(self,word): + return (len(word) == self.multiply_word(word).length()) + + def braid_word(self,i,j): + s = self.simple_reflections + # m_ij = (s[i]*s[j]).order() #For some reason this is no longer implemented + m_ij = self.coxeter_group.coxeter_matrix()[i-1,j-1] + num_pairs = int(m_ij)/int(2) + extra_term = int(m_ij)%2 + return (i,j)*num_pairs + (i,)*extra_term + + def _apply_put_in_front_recur_step(self, k, input_word, coxeter_matrix_entry): + #print "k:", k + #print "input_word:", input_word + #print "coxeter_matrix_entry:", coxeter_matrix_entry + i = input_word[0] + def partial_braid_word(length,swap=False,i=i,k=k): + if swap: + i,k = k,i + running_braid_word = [] + for counter in xrange(length): + if counter % 2 == 0: + running_braid_word.append(i) + else: + running_braid_word.append(k) + return tuple(running_braid_word) + + current_last_word = input_word + current_first_letter = k + output_word_list = [current_last_word] + for counter in xrange(1, coxeter_matrix_entry): + current_word_list = self.put_in_front(current_first_letter, current_last_word[1:]) + output_word_list += [partial_braid_word(counter) + word + for word in current_word_list[1:]] + if current_first_letter == k: + current_first_letter = i + else: + current_first_letter = k + current_last_word = current_word_list[-1] + #print "counter:", counter + #print "current_last_word", current_last_word + #print "current_first_letter", current_first_letter + if i != k: + output_word_list += [partial_braid_word(coxeter_matrix_entry,swap=True) + + current_last_word[1:]] + return output_word_list + + def put_in_front(self, k, input_word): + """ + Return a list of reduced words beginning with + ``input_word`` and ending with a reduced word whose first letter + is ``k``. There still remains an issue with 0 indices. + """ + i = input_word[0] + if i == 0 or k == 0: + raise NotImplementedError + entry = self.coxeter_group.coxeter_matrix()[i, k] + return self._apply_put_in_front_recur_step(k, input_word, entry) + + def chain_of_reduced_words(self, start_word, end_word): + if start_word == end_word: + return [start_word] + k = end_word[0] + first_word_list = self.put_in_front(k, start_word) + first_last_word = first_word_list[-1] + return (first_word_list[:-1] + + [ (k,) + word for word in + self.chain_of_reduced_words(first_last_word[1:], + end_word[1:])]) + + +# Maybe we need to be more specific, and pass not the Cartan type, but the root lattice? +# TODO: Move to PBW_data? +def enhance_braid_move_chain(braid_move_chain, cartan_type): + r""" + Return a list of tuples that records the data of the long words in + ``braid_move_chain`` plus the data of the intervals where the braid moves + occur and the data of the off-diagonal entries of the `2 \times 2` Cartan + submatrices of each braid move. + + INPUT: + + - ``braid_move_chain`` -- a chain of reduced words in the Weyl group + of ``cartan_type`` + - ``cartan_type`` -- a finite-type CartanType + + OUTPUT: + A list of 3-tuples ``(reduced_word,interval_of_change,cartan_sub_matrix)`` + where + - ``reduced_word`` agrees with the elements of ``braid_move_chain`` + - ``interval_of_change`` is the (half-open) interval of indices where the + braid move occurs. This is `None` for the first tuple. + - ``cartan_sub_matrix`` is the off-diagonal entries of the `2 \times 2` + submatrix of the cartan matrix corresponding to the braid move. + This is `None` for the first tuple. + + For a matrix:: + + [2 a] + [b 2] + + the ``cartan_sub_matrix`` is the pair ``(a, b)``. + """ + cartan_type = CartanType(cartan_type) + if not cartan_type.is_finite(): + raise ValueError("cartan_type must be finite type") + cartan_matrix = cartan_type.cartan_matrix() + output_list = [] + output_list.append( (braid_move_chain[0],None,None) ) + for k,current_word in enumerate(braid_move_chain[1:]): + previous_word = braid_move_chain[k] + interval_of_change = diff_interval(previous_word,current_word) + i = previous_word[interval_of_change[0]] - 1 # -1 for indexing + j = current_word[interval_of_change[0]] - 1 # -1 for indexing + cartan_sub_matrix = (cartan_matrix[i,j], cartan_matrix[j,i]) + output_list.append( (current_word,interval_of_change,cartan_sub_matrix) ) + return output_list + + +def enhanced_braid_chain_test(): + braid_chain = [(1, 2, 1, 3, 2, 1), + (1, 2, 3, 1, 2, 1), + (1, 2, 3, 2, 1, 2), + (1, 3, 2, 3, 1, 2), + (3, 1, 2, 3, 1, 2), + (3, 1, 2, 1, 3, 2), + (3, 2, 1, 2, 3, 2), + (3, 2, 1, 3, 2, 3)] + + enhanced_chain = enhance_braid_move_chain(braid_chain,CartanType(["A",5])) + assert enhanced_chain[0][1] == None + assert enhanced_chain[0][2] == None + assert enhanced_chain[7][1] == (3, 6) + assert enhanced_chain[7][2] == (-1, -1) + + +def diff_interval(list1,list2): + """ + Return the smallest contiguous half-open interval [a,b) + that contains the indices where ``list1`` and ``list2`` differ. + Return ``None`` if the lists don't differ. + + INPUT: + + - ``list1``, ``list2`` -- two lists of the same length (no length checking) + """ + min_diff = None + max_diff = None + for i,elem1 in enumerate(list1): + if elem1 != list2[i]: + min_diff = i + break + if min_diff is None: + if len(list1) == len(list2): + return None + else: + raise IndexError + for j in xrange(len(list2), min_diff, -1): + if list1[j-1] != list2[j-1]: + max_diff = j + break + return (min_diff, max_diff) + + +def diff_interval_test(): + assert diff_interval([1,2,3,4],[1,2,3,4]) == None + assert diff_interval([1,2,3,4],[1,3,2,4]) == (1,3) + assert diff_interval([1,2,4,4,5],[1,3,45,6,3]) == (1,5) + try: + diff_interval([1],[2,3]) + raise AssertionError, "IndexError not raised" + except IndexError: + pass + try: + diff_interval([],[2,3]) + raise AssertionError, "IndexError not raised" + except IndexError: + pass + diff --git a/src/sage/combinat/crystals/catalog_infinity_crystals.py b/src/sage/combinat/crystals/catalog_infinity_crystals.py index 680921a4677..03657d139ab 100644 --- a/src/sage/combinat/crystals/catalog_infinity_crystals.py +++ b/src/sage/combinat/crystals/catalog_infinity_crystals.py @@ -7,6 +7,7 @@ ` * :class:`LSPaths ` * :class:`NakajimaMonomials ` +* :class:`PBW ` * :class:`PolyhedralRealization ` * :class:`RiggedConfigurations ` @@ -18,6 +19,7 @@ from sage.combinat.rigged_configurations.rc_infinity import InfinityCrystalOfRiggedConfigurations as RiggedConfigurations from infinity_crystals import InfinityCrystalOfTableaux as Tableaux from sage.combinat.crystals.polyhedral_realization import InfinityCrystalAsPolyhedralRealization as PolyhedralRealization +from sage.combinat.crystals.pbw_crystal import PBWCrystal as PBW from sage.combinat.crystals.star_crystal import StarCrystal as Star from sage.combinat.crystals.littelmann_path import InfinityCrystalOfLSPaths as LSPaths diff --git a/src/sage/combinat/crystals/mv_polytope.py b/src/sage/combinat/crystals/mv_polytope.py new file mode 100644 index 00000000000..09ff0417f0f --- /dev/null +++ b/src/sage/combinat/crystals/mv_polytope.py @@ -0,0 +1,25 @@ +r""" +A module for implementing ``MVPolytopes``. +""" + +from sage.structure.parent import Parent +from sage.structure.element import Element + + +class MVPolytope(Element): + def __init__(self, parent, long_word, lusztig_datum): + Element.__init__(self, parent) + self._initial_long_word = tuple(long_word) + self._lusztig_datum = tuple(lusztig_datum) + self._lusztig_data_dict = {self._initial_long_word: self._lusztig_datum} + +class MVPolytopes(Parent): + def __init__(self, root_system): + Parent.__init__(self) + if not root_system.is_finite(): + raise ValueError("{} is not a finite root system".format(root_system)) + self.root_system = root_system + + def _element_constructor_(self, *args): + return self.element_class(self, *args) + diff --git a/src/sage/combinat/crystals/pbw_crystal.py b/src/sage/combinat/crystals/pbw_crystal.py new file mode 100644 index 00000000000..8d16a4897db --- /dev/null +++ b/src/sage/combinat/crystals/pbw_crystal.py @@ -0,0 +1,224 @@ +r""" +The crystal of PBWData up to equivalence. A model of the crystal +`B(\infty)` whose elements are PBWDatum up to equivalence by the +tropical Plucker relations. +""" +# Date: May 11, 2015 +# Author: Dinakar Muthiah +# This borrows some interface ideas +# from a file written Peter Tingley and Adam Schultz + +from sage.misc.cachefunc import cached_method +from sage.structure.element import Element +from sage.structure.parent import Parent +from sage.structure.unique_representation import UniqueRepresentation +from sage.categories.highest_weight_crystals import HighestWeightCrystals +from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets +from sage.combinat.root_system.cartan_type import CartanType +from sage.combinat.crystals.pbw_datum import PBWData, PBWDatum + +class PBWCrystalElement(Element): + def __init__(self, parent, long_word, lusztig_datum): + Element.__init__(self, parent) + self.pbw_datum = PBWDatum(parent.pbw_datum_parent, long_word, lusztig_datum) + + def _repr_(self): + """ + Return a string representation of ``self``. + """ + pbw_datum = self.pbw_datum.convert_to_new_long_word(self.parent()._default_word) + return "PBW monomial with Lusztig datum {}".format(pbw_datum.lusztig_datum) + + def _latex_(self): + """ + Return a latex representation of ``self``. + """ + pbw_datum = self.pbw_datum.convert_to_new_long_word(self.parent()._default_word) + lusztig_datum = list(pbw_datum.lusztig_datum) + al = self.parent().pbw_datum_parent._root_list_from(self.parent()._default_word) + from sage.misc.latex import latex + latex_exp = lambda i: "^{%s}"%latex(i) if i > 1 else "" + ret_str = ' '.join("f_{%s}%s"%(latex(al[i]), latex_exp(exp)) + for i, exp in enumerate(lusztig_datum) if exp) + if ret_str == '': + return '1' + return ret_str + + def lusztig_datum(self, word=None): + """ + Return the Lusztig datum of ``self`` with respect to the reduced + expression of the long word ``word``. + """ + if word is None: + word = self.parent()._default_word + else: + self.parent()._check_is_long_word(word) + pbw_datum = self.pbw_datum.convert_to_new_long_word(word) + return tuple(pbw_datum.lusztig_datum) + + def __eq__(self, other): + """ + Check equality of ``self`` with ``other``. + """ + other_long_word = other.pbw_datum.long_word + other_lusztig_datum = other.pbw_datum.lusztig_datum + equiv_pbw_datum = self.pbw_datum.convert_to_new_long_word(other_long_word) + return equiv_pbw_datum.lusztig_datum == other_lusztig_datum + + def _cmp_(self, other): + """ + Return comparison of ``self`` and ``other``. + """ + word = self.parent().pbw_datum_parent._long_word_begin_with(1) + lusztig_datum = tuple(self.pbw_datum.convert_to_new_long_word(word).lusztig_datum) + other_lusztig_datum = tuple(other.pbw_datum.convert_to_new_long_word(word).lusztig_datum) + return cmp(lusztig_datum, other_lusztig_datum) + + @cached_method + def __hash__(self): + i = self.parent().index_set()[0] + word = self.parent().pbw_datum_parent._long_word_begin_with(i) + pbw_datum = self.pbw_datum.convert_to_new_long_word(word) + return hash(tuple(pbw_datum.lusztig_datum)) + + def f(self, i): + """ + EXAMPLES:: + + sage: B = PBWCrystal("D4") + sage: b = B.module_generators[0] + sage: c = b.f_string([1,2,3,1,2,3,4]) + sage: c == b.f_string([1,2,4,1,2,3,3]) + True + """ + equiv_PBWDatum = self.pbw_datum.convert_to_long_word_with_first_letter(i) + new_long_word = equiv_PBWDatum.long_word + new_lusztig_datum = list(equiv_PBWDatum.lusztig_datum) + new_lusztig_datum[0] += 1 + return type(self)(self.parent(), new_long_word, tuple(new_lusztig_datum)) + + def e(self, i): + equiv_pbw_datum = self.pbw_datum.convert_to_long_word_with_first_letter(i) + new_long_word = equiv_pbw_datum.long_word + new_lusztig_datum = list(equiv_pbw_datum.lusztig_datum) + if new_lusztig_datum[0] == 0: + return None + new_lusztig_datum[0] -= 1 + return type(self)(self.parent(), new_long_word, tuple(new_lusztig_datum)) + + def epsilon(self,i): + """ + EXAMPLES:: + + sage: B = PBWCrystal(["A2"]) + sage: s = B((1,2,1),(3,0,0)) + sage: s.epsilon(1) + 3 + """ + equiv_pbw_datum = self.pbw_datum.convert_to_long_word_with_first_letter(i) + return equiv_pbw_datum.lusztig_datum[0] + + def star(self): + r""" + Return the starred crystal element corresponding + to ``self``. + + EXAMPLES:: + + sage: P = PBWCrystal(["A2"]) + sage: P((1,2,1),(1,2,3)).star() == P((1,2,1),(3,2,1)) + True + """ + starred_pbw_datum = self.pbw_datum.star() + return type(self)(self.parent(), starred_pbw_datum.long_word, + starred_pbw_datum.lusztig_datum) + + def weight(self): + """ + Return weight of ``self``. + + EXAMPLES:: + + sage: B = PBWCrystal(["A",2]) + sage: s = B((1,2,1),(2,2,2)) + sage: s.weight() + -4*alpha[1] - 4*alpha[2] + """ + WLR = self.parent().weight_lattice_realization() + al = WLR.simple_roots() + return WLR.sum(c*al[i] for i,c in self.pbw_datum.wt()) + + def phi(self,i): + """ + EXAMPLES:: + + sage: B = PBWCrystal(["A2"]) + sage: s = B((1,2,1),(3,0,0)) + sage: s.phi(1) + -3 + sage: s.phi(2) + 3 + """ + WLR = self.parent().weight_lattice_realization() + h = WLR.simple_coroots() + return self.epsilon(i) + self.weight().scalar(h[i]) + +class PBWCrystal(Parent, UniqueRepresentation): + """ + Crystal of `B(\infty)` given by PBW monomials. + """ + @staticmethod + def __classcall_private__(cls, cartan_type): + """ + Normalize input to ensure a unique representation. + """ + return super(PBWCrystal, cls).__classcall__(cls, CartanType(cartan_type)) + + def __init__(self, cartan_type): + """ + Initialize ``self``. + """ + self._cartan_type = cartan_type + self.pbw_datum_parent = PBWData(self._cartan_type) + category = (HighestWeightCrystals(), InfiniteEnumeratedSets()) + Parent.__init__(self, category=category) + + # There must be a better way to do the following + i = self._cartan_type.index_set()[0] + self._default_word = self.pbw_datum_parent._long_word_begin_with(i) + zero_lusztig_datum = [0]*len(self._default_word) + self.module_generators = (self.element_class(self, + self._default_word, + zero_lusztig_datum),) + + def _repr_(self): + """ + Return a string representation of ``self``. + """ + return "Crystal of PBW data of type {}".format(self._cartan_type) + + def default_long_word(self): + """ + Return the default long word used to express elements of ``self``. + """ + return self._default_word + + def _check_is_long_word(self, word): + """ + Check if ``word`` is a reduced expression of the long of the + Coxeter group of ``self``. + """ + W = self.pbw_datum_parent.coxeter_group + if (len(word) != len(self._default_word) + or W.from_reduced_word(word) != W.long_element()): + raise ValueError("not a reduced word of the long element") + + def set_default_long_word(self, word): + """ + Set the default long word used to express elements of ``self``. + """ + self._check_is_long_word(word) + self._default_word = tuple(word) + + Element = PBWCrystalElement + diff --git a/src/sage/combinat/crystals/pbw_datum.py b/src/sage/combinat/crystals/pbw_datum.py new file mode 100644 index 00000000000..258f3b2ad37 --- /dev/null +++ b/src/sage/combinat/crystals/pbw_datum.py @@ -0,0 +1,258 @@ +r""" +PBW Data + +This contains helper classes and functions which encode PBW data +in finite type. + +AUTHORS: + +- Dinakar Muthiah (2015-05): initial version +""" + +#from sage.misc.lazy_attribute import lazy_attribute +from sage.misc.cachefunc import cached_method +#from sage.structure.parent import Parent +#from sage.structure.element import Element +from sage.combinat.root_system.cartan_type import CartanType +from sage.combinat.root_system.coxeter_group import CoxeterGroup +from sage.combinat.root_system.root_system import RootSystem +from sage.combinat.crystals.braid_move_calculator import (BraidMoveCalculator, + enhance_braid_move_chain) + +class PBWDatum(object): + def __init__(self, parent, long_word, lusztig_datum): + self.parent = parent + self.long_word = tuple(long_word) + self.lusztig_datum = tuple(lusztig_datum) + + def __repr__(self): + return_str = "PBW Datum element of type {cartan_type} with ".format( + cartan_type=self.parent.cartan_type) + return_str += "long word {long_word} and Lusztig datum {lusztig_datum}".format( + long_word=self.long_word, + lusztig_datum=self.lusztig_datum) + return return_str + + def __eq__(self, other_PBWDatum): + """ + EXAMPLES:: + + sage: P = PBWData(["A2"]) + sage: L1 = P((1,2,1),(1,4,7)) + sage: L2 = P((1,2,1),(1,4,7)) + sage: L1 == L2 + True + """ + return (self.parent == other_PBWDatum.parent and + self.long_word == other_PBWDatum.long_word and + self.lusztig_datum == other_PBWDatum.lusztig_datum) + + def is_equivalent_to(self, other_PBWDatum): + r""" + Return whether ``self`` is equivalent to ``other_PBWDatum``. + modulo the tropical Plucker relations. + + EXAMPLES:: + + sage: P = PBWData(["A2"]) + sage: L1 = P((1,2,1),(1,0,1)) + sage: L2 = P((2,1,2),(0,1,0)) + sage: L1.is_equivalent_to(L2) + True + """ + other_long_word = other_PBWDatum.long_word + other_lusztig_datum = other_PBWDatum.lusztig_datum + equiv_PBWDatum = self.convert_to_new_long_word(other_long_word) + return equiv_PBWDatum.lusztig_datum == other_lusztig_datum + + def convert_to_long_word_with_first_letter(self, i): + r""" + Return a new PBWDatum equivalent to ``self`` + whose long word begins with ``i``. + """ + return self.convert_to_new_long_word(self.parent._long_word_begin_with(i)) + + def convert_to_new_long_word(self,new_long_word): + r""" + Return a new PBWDatum equivalent to ``self`` + whose long word is ``new_long_word``. + + EXAMPLES:: + + sage: P = PBWData(["A2"]) + sage: P.convert_to_new_long_word(P((1,2,1),(1,0,1)),(2,1,2)).long_word + (2, 1, 2) + sage: P.convert_to_new_long_word(P((1,2,1),(1,0,1)),(2,1,2)).lusztig_datum + (0, 1, 0) + """ + return self.parent.convert_to_new_long_word(self,new_long_word) + + def wt(self): + """ + EXAMPLES:: + + sage: P = PBWData(["A",2]) + sage: L = P((1,2,1),(1,1,1)) + sage: L.wt() + -2*alpha[1] - 2*alpha[2] + """ + root_list = self.parent._root_list_from(tuple(self.long_word)) + R = self.parent.root_lattice + return R.linear_combination((root_list[i], -coeff) + for i, coeff in enumerate(self.lusztig_datum)) + + def star(self): + """ + Return the starred version of ``self``, i.e., + with reversed `long_word` and `lusztig_datum` + + EXAMPLES:: + + sage: P = PBWData(["A2"]) + sage: L1 = P((1,2,1),(1,2,3)) + sage: L1.star() == P((1,2,1),(3,2,1)) + True + """ + reversed_long_word = reversed(self.long_word) + reversed_lusztig_datum = reversed(self.lusztig_datum) + return PBWDatum(self.parent, reversed_long_word, reversed_lusztig_datum) + + +class PBWData(object): # UniqueRepresentation? + def __init__(self, cartan_type): + self.cartan_type = CartanType(cartan_type) + self.root_system = RootSystem(self.cartan_type) + self.root_lattice = self.root_system.root_lattice() + self.weyl_group = self.root_lattice.weyl_group() + # Is there a more intelligent way to recover the Weyl group + # from cartan_type? + self._braid_move_calc = BraidMoveCalculator(self.weyl_group) + + def convert_to_new_long_word(self, pbw_datum, new_long_word): + assert pbw_datum.parent == self + chain = self._braid_move_calc.chain_of_reduced_words(pbw_datum.long_word, + new_long_word) + enhanced_braid_chain = enhance_braid_move_chain(chain, + self.cartan_type) + new_lusztig_datum = compute_new_lusztig_datum(enhanced_braid_chain, + pbw_datum.lusztig_datum) + return PBWDatum(self, new_long_word, new_lusztig_datum) + + @cached_method + def _root_list_from(self, reduced_word): + """ + Return the list of positive roots in the order determined by + ``reduced_word``. + + .. WARNING:: + + No error checking is done to verify that ``reduced_word`` + is reduced. + + INPUT: + + - ``reduced_word`` -- a tuple corresponding to a reduced word + + EXAMPLES:: + + sage: P = PBWData(["A",2]) + sage: P._root_list_from((1,2,1)) + [alpha[1], alpha[1] + alpha[2], alpha[2]] + """ + al = self.root_lattice.simple_roots() + cur = [] + for i in reversed(reduced_word): + cur = [al[i]] + [x.simple_reflection(i) for x in cur] + return cur + + @cached_method + def _long_word_begin_with(self, i): + """ + Return a reduced expression of the long word which begins with ``i``. + """ + s = self.weyl_group.simple_reflections() + w0 = self.weyl_group.long_element() + return tuple([i] + (s[i] * w0).reduced_word()) + +# Replaced by a doctest +def convert_to_new_long_word_test(): + P = PBWData(["A2"]) + P.convert_to_new_long_word(P((1,2,1),(1,0,1)),(2,1,2)) + assert P.convert_to_new_long_word(P((1,2,1),(1,0,1)),(2,1,2)).long_word == (2,1,2) + assert P.convert_to_new_long_word(P((1,2,1),(1,0,1)),(2,1,2)).lusztig_datum == (0,1,0) + + +#enhanced_braid_chain is an ugly data structure. +def compute_new_lusztig_datum(enhanced_braid_chain, initial_lusztig_datum): + """ + Return the lusztig datum obtained by applying Tropical Plucker relations along + ``enhanced_braid_chain`` starting with ``initial_lusztig_datum`` + + EXAMPLES:: + + sage: W = CoxeterGroup(CartanType(["A2"])) + sage: B = BraidMoveCalculator(W) + sage: chain = B.chain_of_reduced_words((1,2,1),(2,1,2)) + sage: enhanced_braid_chain = enhance_braid_move_chain(chain,CartanType(["A",2])) + sage: compute_new_lusztig_datum(enhanced_braid_chain,(1,0,1)) + (0, 1, 0) + """ + # Does not currently check that len(initial_lusztig_datum) is appropriate + new_lusztig_datum = list(initial_lusztig_datum) #shallow copy + for _, interval_of_change, type_data in enhanced_braid_chain[1:]: + old_interval_datum = new_lusztig_datum.__getslice__(*interval_of_change) + new_interval_datum = tropical_plucker_relation(type_data, old_interval_datum) + new_lusztig_datum.__setslice__(interval_of_change[0], interval_of_change[1], + new_interval_datum) + return tuple(new_lusztig_datum) + +# Replaced by a doctest +def compute_new_lusztig_datum_test(): + W = CoxeterGroup(CartanType(["A2"])) + B = BraidMoveCalculator(W) + chain = B.chain_of_reduced_words((1,2,1),(2,1,2)) + enhanced_braid_chain = enhance_braid_move_chain(chain,CartanType(["A",2])) + #print compute_new_lusztig_datum(enhanced_braid_chain,(1,0,1)) + assert compute_new_lusztig_datum(enhanced_braid_chain,(1,0,1)) == (0,1,0) + + +# The tropical plucker relations +def tropical_plucker_relation(a, lusztig_datum): + r""" + Apply the tropical Plucker relation of type ``a`` to ``lusztig_datum``. + + INPUT: + + - ``a`` -- a pair ``(x, y)`` of the off-diagonal entries of a + `2 \times 2` Cartan matrix + + EXAMPLES:: + + sage: tropical_plucker_relation((0,0), (2,3)) + (3, 2) + """ + n = lusztig_datum + if a == (0, 0): # A1xA1 + return (n[1], n[0]) + elif a == (-1, -1): # A2 + p = min(n[0], n[2]) + return (n[1]+n[2]-p, p, n[0]+n[1]-p) + elif a == (-1, -2): # B2 + # I believe this is condition (iii) in Proposition 5.2 of Joel's thesis. + # (I'm pretty sure this is correct). + p1 = min(n[0]+n[1], n[0]+n[3], n[2]+n[3]) + p2 = min(n[0]+2*n[1], n[0]+2*n[3], n[2]+2*n[3]) + return (n[1]+n[2]+n[3]-p1, + 2*p1-p2, + p2-p1, + n[0]+2*n[1]+n[2]-p2) + elif a == (-2, -1): # C2 + p1 = min(n[0]+n[1], n[0]+n[3], n[2]+n[3]) + p2 = min(2*n[0]+n[1], 2*n[0]+n[3], 2*n[2]+n[3]) + return (n[1]+2*n[2]+n[3]-p2, + p2-p1, + 2*p1-p2, + n[0]+n[1]+n[2]-p1) + elif a == (-3, -1): # G2 + raise NotImplementedError("type G2 not implemented") + From c8def2d4d10328d02671d4c8f3663e24b5d09d09 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Mon, 16 Nov 2015 23:53:55 -0600 Subject: [PATCH 031/452] Minor tweaks. --- src/sage/combinat/crystals/pbw_datum.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/sage/combinat/crystals/pbw_datum.py b/src/sage/combinat/crystals/pbw_datum.py index 258f3b2ad37..d48fa49fbc1 100644 --- a/src/sage/combinat/crystals/pbw_datum.py +++ b/src/sage/combinat/crystals/pbw_datum.py @@ -47,7 +47,7 @@ def __eq__(self, other_PBWDatum): self.long_word == other_PBWDatum.long_word and self.lusztig_datum == other_PBWDatum.lusztig_datum) - def is_equivalent_to(self, other_PBWDatum): + def is_equivalent_to(self, other_pbw_datum): r""" Return whether ``self`` is equivalent to ``other_PBWDatum``. modulo the tropical Plucker relations. @@ -60,10 +60,10 @@ def is_equivalent_to(self, other_PBWDatum): sage: L1.is_equivalent_to(L2) True """ - other_long_word = other_PBWDatum.long_word - other_lusztig_datum = other_PBWDatum.lusztig_datum - equiv_PBWDatum = self.convert_to_new_long_word(other_long_word) - return equiv_PBWDatum.lusztig_datum == other_lusztig_datum + other_long_word = other_pbw_datum.long_word + other_lusztig_datum = other_pbw_datum.lusztig_datum + equiv_pbw_datum = self.convert_to_new_long_word(other_long_word) + return equiv_pbw_datum.lusztig_datum == other_lusztig_datum def convert_to_long_word_with_first_letter(self, i): r""" @@ -72,7 +72,7 @@ def convert_to_long_word_with_first_letter(self, i): """ return self.convert_to_new_long_word(self.parent._long_word_begin_with(i)) - def convert_to_new_long_word(self,new_long_word): + def convert_to_new_long_word(self, new_long_word): r""" Return a new PBWDatum equivalent to ``self`` whose long word is ``new_long_word``. @@ -83,10 +83,10 @@ def convert_to_new_long_word(self,new_long_word): sage: P.convert_to_new_long_word(P((1,2,1),(1,0,1)),(2,1,2)).long_word (2, 1, 2) sage: P.convert_to_new_long_word(P((1,2,1),(1,0,1)),(2,1,2)).lusztig_datum - (0, 1, 0) - """ - return self.parent.convert_to_new_long_word(self,new_long_word) - + (0, 1, 0) + """ + return self.parent.convert_to_new_long_word(self, new_long_word) + def wt(self): """ EXAMPLES:: From 32d3be8f3cdb8e03c41ecd87e4d28f272d750bab Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sat, 28 Nov 2015 09:12:30 -0600 Subject: [PATCH 032/452] Fixing set_default_long_word. --- src/sage/combinat/crystals/pbw_crystal.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/crystals/pbw_crystal.py b/src/sage/combinat/crystals/pbw_crystal.py index 8d16a4897db..cc4c1c1657f 100644 --- a/src/sage/combinat/crystals/pbw_crystal.py +++ b/src/sage/combinat/crystals/pbw_crystal.py @@ -208,7 +208,7 @@ def _check_is_long_word(self, word): Check if ``word`` is a reduced expression of the long of the Coxeter group of ``self``. """ - W = self.pbw_datum_parent.coxeter_group + W = self.pbw_datum_parent.weyl_group if (len(word) != len(self._default_word) or W.from_reduced_word(word) != W.long_element()): raise ValueError("not a reduced word of the long element") From 45d16e2c9301626ff1da1bb229f955209f17e93a Mon Sep 17 00:00:00 2001 From: Benjamin Hackl Date: Fri, 19 Feb 2016 00:05:17 +0200 Subject: [PATCH 033/452] simplify substituted expression before series expansion --- 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 3a5c8647269..175bcaddf5b 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -4076,7 +4076,7 @@ cdef class Expression(CommutativeRingElement): a = 0 if a == infinity: return (-self.subs({x: 1/x}) / x**2).residue(x == 0) - return self.subs({x: x+a}).series(x == 0, 0).coefficient(x, -1) + return self.subs({x: x+a}).canonicalize_radical().series(x == 0, 0).coefficient(x, -1) def taylor(self, *args): r""" From 87193643462062096a9b48dd07c76765bb525002 Mon Sep 17 00:00:00 2001 From: Benjamin Hackl Date: Fri, 19 Feb 2016 07:52:28 +0200 Subject: [PATCH 034/452] add a doctest --- src/sage/symbolic/expression.pyx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 175bcaddf5b..f4c50dbd016 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -4067,6 +4067,11 @@ cdef class Expression(CommutativeRingElement): sage: (1/(x^2 - x - 1)).residue(x == 1/2*sqrt(5) + 1/2) 1/5*sqrt(5) + + Check that :trac:`20084` is fixed:: + + sage: (1/(1 - 2^-x)).residue(x == 2*pi*I/log(2)) + 1/log(2) """ if symbol.is_relational(): x = symbol.lhs() From bb3a5203a0dd88c928391f969d55df7ac785c4e6 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sun, 6 Dec 2015 19:00:05 -0600 Subject: [PATCH 035/452] Some more cleanup and doing some more caching for speed. --- .../crystals/braid_move_calculator.py | 190 ++++------------ src/sage/combinat/crystals/mv_polytope.py | 50 ++++- src/sage/combinat/crystals/pbw_crystal.py | 125 +++++++---- src/sage/combinat/crystals/pbw_datum.py | 206 ++++++++++++++---- 4 files changed, 327 insertions(+), 244 deletions(-) diff --git a/src/sage/combinat/crystals/braid_move_calculator.py b/src/sage/combinat/crystals/braid_move_calculator.py index 24937814209..1762406800e 100644 --- a/src/sage/combinat/crystals/braid_move_calculator.py +++ b/src/sage/combinat/crystals/braid_move_calculator.py @@ -1,49 +1,66 @@ +""" +Braid Move Calculator + +EXAMPLES:: -## Dinakar Muthiah June 3, 2014 + sage: W = CoxeterGroup(['A',5]) + sage: load('BraidMoveCalculator.sage'); B = BraidMoveCalculator(W) + sage: view(B.chain_of_reduced_words((1,2,1,3,2,1,4,3,2,1,5,4,3,2,1),(5,4,5,3,4,5,2,3,4,5,1,2,3,4,5))) -""" Sample usage -W = CoxeterGroup(['A',5]) -load('BraidMoveCalculator.sage'); B = BraidMoveCalculator(W) -view(B.chain_of_reduced_words((1,2,1,3,2,1,4,3,2,1,5,4,3,2,1),(5,4,5,3,4,5,2,3,4,5,1,2,3,4,5))) +AUTHORS: +- Dinakar Muthiah (2014-06-03): initial version """ -from sage.combinat.root_system.cartan_type import CartanType +#***************************************************************************** +# Copyright (C) 2014 Dinakar Muthiah +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# http://www.gnu.org/licenses/ +#***************************************************************************** + +from sage.combinat.root_system.cartan_type import CartanType +from sage.misc.cachefunc import cached_method class BraidMoveCalculator(object): + """ + Helper class to compute braid moves. + """ def __init__(self,coxeter_group): self.coxeter_group = coxeter_group + self.coxeter_matrix = coxeter_group.coxeter_matrix() + # Unused self.simple_reflections = self.coxeter_group.simple_reflections() - + + # Unused def multiply_word(self,word): return self.coxeter_group.from_reduced_word(word) #return prod([self.s[i] for i in word]) - - def is_reduced(self,word): + + # Unused + def is_reduced(self, word): return (len(word) == self.multiply_word(word).length()) - def braid_word(self,i,j): + # Unused + def braid_word(self, i, j): s = self.simple_reflections # m_ij = (s[i]*s[j]).order() #For some reason this is no longer implemented - m_ij = self.coxeter_group.coxeter_matrix()[i-1,j-1] - num_pairs = int(m_ij)/int(2) - extra_term = int(m_ij)%2 + m_ij = int(self.coxeter_matrix[i-1,j-1]) + num_pairs = m_ij // 2 + extra_term = m_ij % 2 return (i,j)*num_pairs + (i,)*extra_term def _apply_put_in_front_recur_step(self, k, input_word, coxeter_matrix_entry): - #print "k:", k - #print "input_word:", input_word - #print "coxeter_matrix_entry:", coxeter_matrix_entry i = input_word[0] - def partial_braid_word(length,swap=False,i=i,k=k): + def partial_braid_word(length, swap=False, i=i, k=k): if swap: i,k = k,i - running_braid_word = [] - for counter in xrange(length): - if counter % 2 == 0: - running_braid_word.append(i) - else: - running_braid_word.append(k) + running_braid_word = [i,k]*(length//2) + if length % 2 == 1: + running_braid_word.append(i) return tuple(running_braid_word) current_last_word = input_word @@ -58,13 +75,10 @@ def partial_braid_word(length,swap=False,i=i,k=k): else: current_first_letter = k current_last_word = current_word_list[-1] - #print "counter:", counter - #print "current_last_word", current_last_word - #print "current_first_letter", current_first_letter if i != k: - output_word_list += [partial_braid_word(coxeter_matrix_entry,swap=True) + + output_word_list += [partial_braid_word(coxeter_matrix_entry, swap=True) + current_last_word[1:]] - return output_word_list + return tuple(output_word_list) def put_in_front(self, k, input_word): """ @@ -75,126 +89,18 @@ def put_in_front(self, k, input_word): i = input_word[0] if i == 0 or k == 0: raise NotImplementedError - entry = self.coxeter_group.coxeter_matrix()[i, k] + entry = self.coxeter_matrix[i, k] return self._apply_put_in_front_recur_step(k, input_word, entry) + @cached_method def chain_of_reduced_words(self, start_word, end_word): if start_word == end_word: - return [start_word] + return (start_word,) k = end_word[0] first_word_list = self.put_in_front(k, start_word) first_last_word = first_word_list[-1] return (first_word_list[:-1] + - [ (k,) + word for word in - self.chain_of_reduced_words(first_last_word[1:], - end_word[1:])]) - - -# Maybe we need to be more specific, and pass not the Cartan type, but the root lattice? -# TODO: Move to PBW_data? -def enhance_braid_move_chain(braid_move_chain, cartan_type): - r""" - Return a list of tuples that records the data of the long words in - ``braid_move_chain`` plus the data of the intervals where the braid moves - occur and the data of the off-diagonal entries of the `2 \times 2` Cartan - submatrices of each braid move. - - INPUT: - - - ``braid_move_chain`` -- a chain of reduced words in the Weyl group - of ``cartan_type`` - - ``cartan_type`` -- a finite-type CartanType - - OUTPUT: - A list of 3-tuples ``(reduced_word,interval_of_change,cartan_sub_matrix)`` - where - - ``reduced_word`` agrees with the elements of ``braid_move_chain`` - - ``interval_of_change`` is the (half-open) interval of indices where the - braid move occurs. This is `None` for the first tuple. - - ``cartan_sub_matrix`` is the off-diagonal entries of the `2 \times 2` - submatrix of the cartan matrix corresponding to the braid move. - This is `None` for the first tuple. - - For a matrix:: - - [2 a] - [b 2] - - the ``cartan_sub_matrix`` is the pair ``(a, b)``. - """ - cartan_type = CartanType(cartan_type) - if not cartan_type.is_finite(): - raise ValueError("cartan_type must be finite type") - cartan_matrix = cartan_type.cartan_matrix() - output_list = [] - output_list.append( (braid_move_chain[0],None,None) ) - for k,current_word in enumerate(braid_move_chain[1:]): - previous_word = braid_move_chain[k] - interval_of_change = diff_interval(previous_word,current_word) - i = previous_word[interval_of_change[0]] - 1 # -1 for indexing - j = current_word[interval_of_change[0]] - 1 # -1 for indexing - cartan_sub_matrix = (cartan_matrix[i,j], cartan_matrix[j,i]) - output_list.append( (current_word,interval_of_change,cartan_sub_matrix) ) - return output_list - - -def enhanced_braid_chain_test(): - braid_chain = [(1, 2, 1, 3, 2, 1), - (1, 2, 3, 1, 2, 1), - (1, 2, 3, 2, 1, 2), - (1, 3, 2, 3, 1, 2), - (3, 1, 2, 3, 1, 2), - (3, 1, 2, 1, 3, 2), - (3, 2, 1, 2, 3, 2), - (3, 2, 1, 3, 2, 3)] - - enhanced_chain = enhance_braid_move_chain(braid_chain,CartanType(["A",5])) - assert enhanced_chain[0][1] == None - assert enhanced_chain[0][2] == None - assert enhanced_chain[7][1] == (3, 6) - assert enhanced_chain[7][2] == (-1, -1) - - -def diff_interval(list1,list2): - """ - Return the smallest contiguous half-open interval [a,b) - that contains the indices where ``list1`` and ``list2`` differ. - Return ``None`` if the lists don't differ. - - INPUT: - - - ``list1``, ``list2`` -- two lists of the same length (no length checking) - """ - min_diff = None - max_diff = None - for i,elem1 in enumerate(list1): - if elem1 != list2[i]: - min_diff = i - break - if min_diff is None: - if len(list1) == len(list2): - return None - else: - raise IndexError - for j in xrange(len(list2), min_diff, -1): - if list1[j-1] != list2[j-1]: - max_diff = j - break - return (min_diff, max_diff) - - -def diff_interval_test(): - assert diff_interval([1,2,3,4],[1,2,3,4]) == None - assert diff_interval([1,2,3,4],[1,3,2,4]) == (1,3) - assert diff_interval([1,2,4,4,5],[1,3,45,6,3]) == (1,5) - try: - diff_interval([1],[2,3]) - raise AssertionError, "IndexError not raised" - except IndexError: - pass - try: - diff_interval([],[2,3]) - raise AssertionError, "IndexError not raised" - except IndexError: - pass + tuple([ (k,) + word for word in + self.chain_of_reduced_words(first_last_word[1:], + end_word[1:]) ])) diff --git a/src/sage/combinat/crystals/mv_polytope.py b/src/sage/combinat/crystals/mv_polytope.py index 09ff0417f0f..5a0b489454d 100644 --- a/src/sage/combinat/crystals/mv_polytope.py +++ b/src/sage/combinat/crystals/mv_polytope.py @@ -1,9 +1,24 @@ +# -*- coding: utf-8 -*- r""" -A module for implementing ``MVPolytopes``. +Crystal Of Mirković-Vilonen (MV) Polytopes """ +#***************************************************************************** +# Copyright (C) 2015 Dinakar Muthiah +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# http://www.gnu.org/licenses/ +#***************************************************************************** + from sage.structure.parent import Parent +from sage.structure.unique_representation import UniqueRepresentation from sage.structure.element import Element +from sage.categories.highest_weight_crystals import HighestWeightCrystals +from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets +from sage.combinat.root_system.cartan_type import CartanType class MVPolytope(Element): @@ -13,13 +28,30 @@ def __init__(self, parent, long_word, lusztig_datum): self._lusztig_datum = tuple(lusztig_datum) self._lusztig_data_dict = {self._initial_long_word: self._lusztig_datum} -class MVPolytopes(Parent): - def __init__(self, root_system): - Parent.__init__(self) - if not root_system.is_finite(): - raise ValueError("{} is not a finite root system".format(root_system)) - self.root_system = root_system +class MVPolytopes(UniqueRepresentation, Parent): + @staticmethod + def __classcall_private__(cls, cartan_type): + """ + Normalize input to ensure a unique representation. + """ + return super(MVPolytopes, cls).__classcall__(cls, CartanType(cartan_type)) + + def __init__(self, cartan_type): + """ + Initialize ``self``. + """ + self._cartan_type = cartan_type + Parent.__init__(self, category=(HighestWeightCrystals(), InfiniteEnumeratedSets())) + if not cartan_type.is_finite(): + raise NotImplementedError("only implemented for finite Cartan types") + + # There must be a better way to do the following + i = self._cartan_type.index_set()[0] + self._default_word = self._pbw_datum_parent._long_word_begin_with(i) + zero_lusztig_datum = [0]*len(self._default_word) + self.module_generators = (self.element_class(self, + self._default_word, + zero_lusztig_datum),) - def _element_constructor_(self, *args): - return self.element_class(self, *args) + Element = MVPolytope diff --git a/src/sage/combinat/crystals/pbw_crystal.py b/src/sage/combinat/crystals/pbw_crystal.py index cc4c1c1657f..8368544bbb4 100644 --- a/src/sage/combinat/crystals/pbw_crystal.py +++ b/src/sage/combinat/crystals/pbw_crystal.py @@ -2,11 +2,21 @@ The crystal of PBWData up to equivalence. A model of the crystal `B(\infty)` whose elements are PBWDatum up to equivalence by the tropical Plucker relations. + +AUTHORS: + +- Dinakar Muthiah (2015-05-11): initial version """ -# Date: May 11, 2015 -# Author: Dinakar Muthiah -# This borrows some interface ideas -# from a file written Peter Tingley and Adam Schultz + +#***************************************************************************** +# Copyright (C) 2015 Dinakar Muthiah +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# http://www.gnu.org/licenses/ +#***************************************************************************** from sage.misc.cachefunc import cached_method from sage.structure.element import Element @@ -18,27 +28,32 @@ from sage.combinat.crystals.pbw_datum import PBWData, PBWDatum class PBWCrystalElement(Element): + """ + A crystal element in the PBW model. + """ def __init__(self, parent, long_word, lusztig_datum): + """ + Initialize ``self``. + """ Element.__init__(self, parent) - self.pbw_datum = PBWDatum(parent.pbw_datum_parent, long_word, lusztig_datum) + self._pbw_datum = PBWDatum(parent._pbw_datum_parent, long_word, lusztig_datum) def _repr_(self): """ Return a string representation of ``self``. """ - pbw_datum = self.pbw_datum.convert_to_new_long_word(self.parent()._default_word) + pbw_datum = self._pbw_datum.convert_to_new_long_word(self.parent()._default_word) return "PBW monomial with Lusztig datum {}".format(pbw_datum.lusztig_datum) def _latex_(self): """ Return a latex representation of ``self``. """ - pbw_datum = self.pbw_datum.convert_to_new_long_word(self.parent()._default_word) + pbw_datum = self._pbw_datum.convert_to_new_long_word(self.parent()._default_word) lusztig_datum = list(pbw_datum.lusztig_datum) - al = self.parent().pbw_datum_parent._root_list_from(self.parent()._default_word) + al = self.parent()._pbw_datum_parent._root_list_from(self.parent()._default_word) from sage.misc.latex import latex - latex_exp = lambda i: "^{%s}"%latex(i) if i > 1 else "" - ret_str = ' '.join("f_{%s}%s"%(latex(al[i]), latex_exp(exp)) + ret_str = ' '.join("f_{%s}%s"%(latex(al[i]), "^{%s}"%latex(exp) if i > 1 else "") for i, exp in enumerate(lusztig_datum) if exp) if ret_str == '': return '1' @@ -53,36 +68,42 @@ def lusztig_datum(self, word=None): word = self.parent()._default_word else: self.parent()._check_is_long_word(word) - pbw_datum = self.pbw_datum.convert_to_new_long_word(word) + pbw_datum = self._pbw_datum.convert_to_new_long_word(word) return tuple(pbw_datum.lusztig_datum) def __eq__(self, other): """ Check equality of ``self`` with ``other``. """ - other_long_word = other.pbw_datum.long_word - other_lusztig_datum = other.pbw_datum.lusztig_datum - equiv_pbw_datum = self.pbw_datum.convert_to_new_long_word(other_long_word) + other_long_word = other._pbw_datum.long_word + other_lusztig_datum = other._pbw_datum.lusztig_datum + equiv_pbw_datum = self._pbw_datum.convert_to_new_long_word(other_long_word) return equiv_pbw_datum.lusztig_datum == other_lusztig_datum def _cmp_(self, other): """ Return comparison of ``self`` and ``other``. """ - word = self.parent().pbw_datum_parent._long_word_begin_with(1) - lusztig_datum = tuple(self.pbw_datum.convert_to_new_long_word(word).lusztig_datum) - other_lusztig_datum = tuple(other.pbw_datum.convert_to_new_long_word(word).lusztig_datum) + i = self.parent().index_set()[0] + word = self.parent()._pbw_datum_parent._long_word_begin_with(i) + lusztig_datum = tuple(self._pbw_datum.convert_to_new_long_word(word).lusztig_datum) + other_lusztig_datum = tuple(other._pbw_datum.convert_to_new_long_word(word).lusztig_datum) return cmp(lusztig_datum, other_lusztig_datum) @cached_method def __hash__(self): + """ + Return the hash of ``self``. + """ i = self.parent().index_set()[0] - word = self.parent().pbw_datum_parent._long_word_begin_with(i) - pbw_datum = self.pbw_datum.convert_to_new_long_word(word) + word = self.parent()._pbw_datum_parent._long_word_begin_with(i) + pbw_datum = self._pbw_datum.convert_to_new_long_word(word) return hash(tuple(pbw_datum.lusztig_datum)) def f(self, i): """ + Return the action of `f_i` on ``self``. + EXAMPLES:: sage: B = PBWCrystal("D4") @@ -91,14 +112,17 @@ def f(self, i): sage: c == b.f_string([1,2,4,1,2,3,3]) True """ - equiv_PBWDatum = self.pbw_datum.convert_to_long_word_with_first_letter(i) + equiv_PBWDatum = self._pbw_datum.convert_to_long_word_with_first_letter(i) new_long_word = equiv_PBWDatum.long_word new_lusztig_datum = list(equiv_PBWDatum.lusztig_datum) new_lusztig_datum[0] += 1 return type(self)(self.parent(), new_long_word, tuple(new_lusztig_datum)) def e(self, i): - equiv_pbw_datum = self.pbw_datum.convert_to_long_word_with_first_letter(i) + """ + Return the action of `e_i` on ``self``. + """ + equiv_pbw_datum = self._pbw_datum.convert_to_long_word_with_first_letter(i) new_long_word = equiv_pbw_datum.long_word new_lusztig_datum = list(equiv_pbw_datum.lusztig_datum) if new_lusztig_datum[0] == 0: @@ -106,8 +130,10 @@ def e(self, i): new_lusztig_datum[0] -= 1 return type(self)(self.parent(), new_long_word, tuple(new_lusztig_datum)) - def epsilon(self,i): - """ + def epsilon(self, i): + r""" + Return `\varepsilon_i` of ``self``. + EXAMPLES:: sage: B = PBWCrystal(["A2"]) @@ -115,23 +141,25 @@ def epsilon(self,i): sage: s.epsilon(1) 3 """ - equiv_pbw_datum = self.pbw_datum.convert_to_long_word_with_first_letter(i) + equiv_pbw_datum = self._pbw_datum.convert_to_long_word_with_first_letter(i) return equiv_pbw_datum.lusztig_datum[0] - def star(self): + def phi(self, i): r""" - Return the starred crystal element corresponding - to ``self``. + Return `\varphi_i` of ``self``. EXAMPLES:: - sage: P = PBWCrystal(["A2"]) - sage: P((1,2,1),(1,2,3)).star() == P((1,2,1),(3,2,1)) - True + sage: B = PBWCrystal(["A2"]) + sage: s = B((1,2,1),(3,0,0)) + sage: s.phi(1) + -3 + sage: s.phi(2) + 3 """ - starred_pbw_datum = self.pbw_datum.star() - return type(self)(self.parent(), starred_pbw_datum.long_word, - starred_pbw_datum.lusztig_datum) + WLR = self.parent().weight_lattice_realization() + h = WLR.simple_coroots() + return self.epsilon(i) + self.weight().scalar(h[i]) def weight(self): """ @@ -146,22 +174,23 @@ def weight(self): """ WLR = self.parent().weight_lattice_realization() al = WLR.simple_roots() - return WLR.sum(c*al[i] for i,c in self.pbw_datum.wt()) + return WLR.sum(c*al[i] for i,c in self._pbw_datum.wt()) + + def star(self): + r""" + Return the starred crystal element corresponding + to ``self``. - def phi(self,i): - """ EXAMPLES:: - sage: B = PBWCrystal(["A2"]) - sage: s = B((1,2,1),(3,0,0)) - sage: s.phi(1) - -3 - sage: s.phi(2) - 3 + sage: P = PBWCrystal(["A2"]) + sage: P((1,2,1),(1,2,3)).star() == P((1,2,1),(3,2,1)) + True """ - WLR = self.parent().weight_lattice_realization() - h = WLR.simple_coroots() - return self.epsilon(i) + self.weight().scalar(h[i]) + starred_pbw_datum = self._pbw_datum.star() + return type(self)(self.parent(), starred_pbw_datum.long_word, + starred_pbw_datum.lusztig_datum) + class PBWCrystal(Parent, UniqueRepresentation): """ @@ -179,13 +208,13 @@ def __init__(self, cartan_type): Initialize ``self``. """ self._cartan_type = cartan_type - self.pbw_datum_parent = PBWData(self._cartan_type) + self._pbw_datum_parent = PBWData(self._cartan_type) category = (HighestWeightCrystals(), InfiniteEnumeratedSets()) Parent.__init__(self, category=category) # There must be a better way to do the following i = self._cartan_type.index_set()[0] - self._default_word = self.pbw_datum_parent._long_word_begin_with(i) + self._default_word = self._pbw_datum_parent._long_word_begin_with(i) zero_lusztig_datum = [0]*len(self._default_word) self.module_generators = (self.element_class(self, self._default_word, @@ -208,7 +237,7 @@ def _check_is_long_word(self, word): Check if ``word`` is a reduced expression of the long of the Coxeter group of ``self``. """ - W = self.pbw_datum_parent.weyl_group + W = self._pbw_datum_parent.weyl_group if (len(word) != len(self._default_word) or W.from_reduced_word(word) != W.long_element()): raise ValueError("not a reduced word of the long element") diff --git a/src/sage/combinat/crystals/pbw_datum.py b/src/sage/combinat/crystals/pbw_datum.py index d48fa49fbc1..5c21b0ed5db 100644 --- a/src/sage/combinat/crystals/pbw_datum.py +++ b/src/sage/combinat/crystals/pbw_datum.py @@ -9,15 +9,22 @@ - Dinakar Muthiah (2015-05): initial version """ +#***************************************************************************** +# Copyright (C) 2015 Dinakar Muthiah +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# http://www.gnu.org/licenses/ +#***************************************************************************** + #from sage.misc.lazy_attribute import lazy_attribute from sage.misc.cachefunc import cached_method -#from sage.structure.parent import Parent -#from sage.structure.element import Element from sage.combinat.root_system.cartan_type import CartanType from sage.combinat.root_system.coxeter_group import CoxeterGroup from sage.combinat.root_system.root_system import RootSystem -from sage.combinat.crystals.braid_move_calculator import (BraidMoveCalculator, - enhance_braid_move_chain) +from sage.combinat.crystals.braid_move_calculator import BraidMoveCalculator class PBWDatum(object): def __init__(self, parent, long_word, lusztig_datum): @@ -27,10 +34,10 @@ def __init__(self, parent, long_word, lusztig_datum): def __repr__(self): return_str = "PBW Datum element of type {cartan_type} with ".format( - cartan_type=self.parent.cartan_type) + cartan_type=self.parent.cartan_type) return_str += "long word {long_word} and Lusztig datum {lusztig_datum}".format( - long_word=self.long_word, - lusztig_datum=self.lusztig_datum) + long_word=self.long_word, + lusztig_datum=self.lusztig_datum) return return_str def __eq__(self, other_PBWDatum): @@ -49,7 +56,7 @@ def __eq__(self, other_PBWDatum): def is_equivalent_to(self, other_pbw_datum): r""" - Return whether ``self`` is equivalent to ``other_PBWDatum``. + Return whether ``self`` is equivalent to ``other_pbw_datum``. modulo the tropical Plucker relations. EXAMPLES:: @@ -119,6 +126,9 @@ def star(self): class PBWData(object): # UniqueRepresentation? + """ + Helper class for the set of PBW data. + """ def __init__(self, cartan_type): self.cartan_type = CartanType(cartan_type) self.root_system = RootSystem(self.cartan_type) @@ -129,11 +139,24 @@ def __init__(self, cartan_type): self._braid_move_calc = BraidMoveCalculator(self.weyl_group) def convert_to_new_long_word(self, pbw_datum, new_long_word): - assert pbw_datum.parent == self + """ + Convert the PBW datum ``pbw_datum`` from its long word to + ``new_long_word``. + + EXAMPLES:: + + sage: P = PBWData("A2") + sage: datum = P.convert_to_new_long_word(P((1,2,1),(1,0,1)),(2,1,2)) + sage: datum + sage: datum.long_word + (2, 1, 2) + sage: datum.lusztig_datum + (0, 1, 0) + """ + assert pbw_datum.parent is self chain = self._braid_move_calc.chain_of_reduced_words(pbw_datum.long_word, new_long_word) - enhanced_braid_chain = enhance_braid_move_chain(chain, - self.cartan_type) + enhanced_braid_chain = enhance_braid_move_chain(chain, self.cartan_type) new_lusztig_datum = compute_new_lusztig_datum(enhanced_braid_chain, pbw_datum.lusztig_datum) return PBWDatum(self, new_long_word, new_lusztig_datum) @@ -170,52 +193,51 @@ def _long_word_begin_with(self, i): """ Return a reduced expression of the long word which begins with ``i``. """ - s = self.weyl_group.simple_reflections() + si = self.weyl_group.simple_reflection(i) w0 = self.weyl_group.long_element() - return tuple([i] + (s[i] * w0).reduced_word()) - -# Replaced by a doctest -def convert_to_new_long_word_test(): - P = PBWData(["A2"]) - P.convert_to_new_long_word(P((1,2,1),(1,0,1)),(2,1,2)) - assert P.convert_to_new_long_word(P((1,2,1),(1,0,1)),(2,1,2)).long_word == (2,1,2) - assert P.convert_to_new_long_word(P((1,2,1),(1,0,1)),(2,1,2)).lusztig_datum == (0,1,0) - + return tuple([i] + (si * w0).reduced_word()) #enhanced_braid_chain is an ugly data structure. def compute_new_lusztig_datum(enhanced_braid_chain, initial_lusztig_datum): """ - Return the lusztig datum obtained by applying Tropical Plucker relations along - ``enhanced_braid_chain`` starting with ``initial_lusztig_datum`` + Return the lusztig datum obtained by applying Tropical Plucker + relations along ``enhanced_braid_chain`` starting with + ``initial_lusztig_datum``. EXAMPLES:: - sage: W = CoxeterGroup(CartanType(["A2"])) + sage: from sage.combinat.crystals.braid_move_calculator import BraidMoveCalculator + sage: from sage.combinat.crystals.pbw_datum import enhance_braid_move_chain + sage: from sage.combinat.crystals.pbw_datum import compute_new_lusztig_datum + sage: W = CoxeterGroup("A2") sage: B = BraidMoveCalculator(W) sage: chain = B.chain_of_reduced_words((1,2,1),(2,1,2)) sage: enhanced_braid_chain = enhance_braid_move_chain(chain,CartanType(["A",2])) sage: compute_new_lusztig_datum(enhanced_braid_chain,(1,0,1)) (0, 1, 0) + + TESTS:: + + sage: from sage.combinat.crystals.braid_move_calculator import BraidMoveCalculator + sage: from sage.combinat.crystals.pbw_datum import enhance_braid_move_chain + sage: from sage.combinat.crystals.pbw_datum import compute_new_lusztig_datum + sage: ct = CartanType(['A', 2]) + sage: W = CoxeterGroup(ct) + sage: B = BraidMoveCalculator(W) + sage: chain = B.chain_of_reduced_words((1,2,1), (2,1,2)) + sage: enhanced_braid_chain = enhance_braid_move_chain(chain, ct) + sage: compute_new_lusztig_datum(enhanced_braid_chain,(1,0,1)) == (0,1,0) + True """ # Does not currently check that len(initial_lusztig_datum) is appropriate new_lusztig_datum = list(initial_lusztig_datum) #shallow copy - for _, interval_of_change, type_data in enhanced_braid_chain[1:]: - old_interval_datum = new_lusztig_datum.__getslice__(*interval_of_change) + for interval_of_change, type_data in enhanced_braid_chain[1:]: + a,b = interval_of_change + old_interval_datum = new_lusztig_datum[a:b] new_interval_datum = tropical_plucker_relation(type_data, old_interval_datum) - new_lusztig_datum.__setslice__(interval_of_change[0], interval_of_change[1], - new_interval_datum) + new_lusztig_datum[a:b] = new_interval_datum return tuple(new_lusztig_datum) -# Replaced by a doctest -def compute_new_lusztig_datum_test(): - W = CoxeterGroup(CartanType(["A2"])) - B = BraidMoveCalculator(W) - chain = B.chain_of_reduced_words((1,2,1),(2,1,2)) - enhanced_braid_chain = enhance_braid_move_chain(chain,CartanType(["A",2])) - #print compute_new_lusztig_datum(enhanced_braid_chain,(1,0,1)) - assert compute_new_lusztig_datum(enhanced_braid_chain,(1,0,1)) == (0,1,0) - - # The tropical plucker relations def tropical_plucker_relation(a, lusztig_datum): r""" @@ -238,6 +260,13 @@ def tropical_plucker_relation(a, lusztig_datum): p = min(n[0], n[2]) return (n[1]+n[2]-p, p, n[0]+n[1]-p) elif a == (-1, -2): # B2 + p1 = min(n[0]+n[1], n[0]+n[3], n[2]+n[3]) + p2 = min(2*n[0]+n[1], 2*n[0]+n[3], 2*n[2]+n[3]) + return (n[1]+2*n[2]+n[3]-p2, + p2-p1, + 2*p1-p2, + n[0]+n[1]+n[2]-p1) + elif a == (-2, -1): # C2 # I believe this is condition (iii) in Proposition 5.2 of Joel's thesis. # (I'm pretty sure this is correct). p1 = min(n[0]+n[1], n[0]+n[3], n[2]+n[3]) @@ -246,13 +275,100 @@ def tropical_plucker_relation(a, lusztig_datum): 2*p1-p2, p2-p1, n[0]+2*n[1]+n[2]-p2) - elif a == (-2, -1): # C2 - p1 = min(n[0]+n[1], n[0]+n[3], n[2]+n[3]) - p2 = min(2*n[0]+n[1], 2*n[0]+n[3], 2*n[2]+n[3]) - return (n[1]+2*n[2]+n[3]-p2, - p2-p1, - 2*p1-p2, - n[0]+n[1]+n[2]-p1) elif a == (-3, -1): # G2 raise NotImplementedError("type G2 not implemented") +# Maybe we need to be more specific, and pass not the Cartan type, but the root lattice? +# TODO: Move to PBW_data? +def enhance_braid_move_chain(braid_move_chain, cartan_type): + r""" + Return a list of tuples that records the data of the long words in + ``braid_move_chain`` plus the data of the intervals where the braid moves + occur and the data of the off-diagonal entries of the `2 \times 2` Cartan + submatrices of each braid move. + + INPUT: + + - ``braid_move_chain`` -- a chain of reduced words in the Weyl group + of ``cartan_type`` + - ``cartan_type`` -- a finite Cartan type + + OUTPUT: + + A list of 3-tuples + ``(reduced_word, interval_of_change, cartan_sub_matrix)`` where + + - ``interval_of_change`` is the (half-open) interval of indices where + the braid move occurs; this is `None` for the first tuple + - ``cartan_sub_matrix`` is the off-diagonal entries of the `2 \times 2` + submatrix of the cartan matrix corresponding to the braid move; + this is `None` for the first tuple + + For a matrix:: + + [2 a] + [b 2] + + the ``cartan_sub_matrix`` is the pair ``(a, b)``. + + TESTS:: + + sage: from sage.combinat.crystals.braid_move_calculator import enhance_braid_move_chain + sage: braid_chain = [(1, 2, 1, 3, 2, 1), + ....: (1, 2, 3, 1, 2, 1), + ....: (1, 2, 3, 2, 1, 2), + ....: (1, 3, 2, 3, 1, 2), + ....: (3, 1, 2, 3, 1, 2), + ....: (3, 1, 2, 1, 3, 2), + ....: (3, 2, 1, 2, 3, 2), + ....: (3, 2, 1, 3, 2, 3)] + sage: enhanced_chain = enhance_braid_move_chain(braid_chain, CartanType(["A",5])) + sage: enhanced_chain[0] + (None, None) + sage: enhanced_chain[7] + ((3, 6), (-1, -1)) + """ + cartan_matrix = cartan_type.cartan_matrix() + output_list = [] + output_list.append( (None, None) ) + previous_word = braid_move_chain[0] + # TODO - Optimize this by avoiding calls to diff_interval + # This likely could be done when performing chain_of_reduced_words + # Things in here get called the most (about 50x more than enhance_braid_move_chain) + for current_word in braid_move_chain[1:]: + interval_of_change = diff_interval(previous_word, current_word) + i = previous_word[interval_of_change[0]] - 1 # -1 for indexing + j = current_word[interval_of_change[0]] - 1 # -1 for indexing + cartan_sub_matrix = (cartan_matrix[i,j], cartan_matrix[j,i]) + output_list.append( (interval_of_change, cartan_sub_matrix) ) + previous_word = current_word + return output_list + +# TODO: Cythonize this if this is still necessary +def diff_interval(list1, list2): + """ + Return the smallest contiguous half-open interval [a,b) + that contains the indices where ``list1`` and ``list2`` differ. + Return ``None`` if the lists don't differ. + + INPUT: + + - ``list1``, ``list2`` -- two lists of the same length + + .. NOTE:: + + The input is not checked for speed. + + TESTS:: + + sage: diff_interval([1,2,3,4], [1,2,3,4]) + sage: diff_interval([1,2,3,4], [1,3,2,4]) + (1, 3) + sage: diff_interval([1,2,4,4,5], [1,3,45,6,3]) + (1, 5) + """ + L = [i for i,elt in enumerate(list1) if elt != list2[i]] + if not L: + return None + return (L[0], L[-1]+1) + From c985b332cf23935eb2d2bd3b3811cb39b49577ba Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sun, 21 Feb 2016 20:52:13 -0600 Subject: [PATCH 036/452] Removed unused functions in BraidMoveCalculator. --- .../crystals/braid_move_calculator.py | 27 ++++--------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/src/sage/combinat/crystals/braid_move_calculator.py b/src/sage/combinat/crystals/braid_move_calculator.py index 1762406800e..e763f5cecc6 100644 --- a/src/sage/combinat/crystals/braid_move_calculator.py +++ b/src/sage/combinat/crystals/braid_move_calculator.py @@ -29,29 +29,12 @@ class BraidMoveCalculator(object): """ Helper class to compute braid moves. """ - def __init__(self,coxeter_group): + def __init__(self, coxeter_group): + """ + Initialize ``self``. + """ self.coxeter_group = coxeter_group self.coxeter_matrix = coxeter_group.coxeter_matrix() - # Unused - self.simple_reflections = self.coxeter_group.simple_reflections() - - # Unused - def multiply_word(self,word): - return self.coxeter_group.from_reduced_word(word) - #return prod([self.s[i] for i in word]) - - # Unused - def is_reduced(self, word): - return (len(word) == self.multiply_word(word).length()) - - # Unused - def braid_word(self, i, j): - s = self.simple_reflections - # m_ij = (s[i]*s[j]).order() #For some reason this is no longer implemented - m_ij = int(self.coxeter_matrix[i-1,j-1]) - num_pairs = m_ij // 2 - extra_term = m_ij % 2 - return (i,j)*num_pairs + (i,)*extra_term def _apply_put_in_front_recur_step(self, k, input_word, coxeter_matrix_entry): i = input_word[0] @@ -87,7 +70,7 @@ def put_in_front(self, k, input_word): is ``k``. There still remains an issue with 0 indices. """ i = input_word[0] - if i == 0 or k == 0: + if i == 0 or k == 0: # Is this for affine types? - Travis raise NotImplementedError entry = self.coxeter_matrix[i, k] return self._apply_put_in_front_recur_step(k, input_word, entry) From 0885a77e8952660e23b8e54c869e2449c7cbc5cb Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 23 Feb 2016 12:20:54 -0600 Subject: [PATCH 037/452] Renaming mv_polytope.py to mv_polytopes.py. --- src/sage/combinat/crystals/{mv_polytope.py => mv_polytopes.py} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/sage/combinat/crystals/{mv_polytope.py => mv_polytopes.py} (100%) diff --git a/src/sage/combinat/crystals/mv_polytope.py b/src/sage/combinat/crystals/mv_polytopes.py similarity index 100% rename from src/sage/combinat/crystals/mv_polytope.py rename to src/sage/combinat/crystals/mv_polytopes.py From eda38df2d9888a85c0b4819af636487e3608130f Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 23 Feb 2016 12:21:13 -0600 Subject: [PATCH 038/452] Implementing crystal of MV polytopes and added plotting. --- .../crystals/braid_move_calculator.py | 10 +- .../crystals/catalog_infinity_crystals.py | 2 + src/sage/combinat/crystals/mv_polytopes.py | 95 +++++++++---- src/sage/combinat/crystals/pbw_crystal.py | 130 +++++++++++++----- src/sage/combinat/crystals/pbw_datum.py | 79 +++++++---- .../root_system/root_lattice_realizations.py | 73 ++++++++++ 6 files changed, 300 insertions(+), 89 deletions(-) diff --git a/src/sage/combinat/crystals/braid_move_calculator.py b/src/sage/combinat/crystals/braid_move_calculator.py index e763f5cecc6..00aa517e18e 100644 --- a/src/sage/combinat/crystals/braid_move_calculator.py +++ b/src/sage/combinat/crystals/braid_move_calculator.py @@ -22,7 +22,6 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from sage.combinat.root_system.cartan_type import CartanType from sage.misc.cachefunc import cached_method class BraidMoveCalculator(object): @@ -77,6 +76,15 @@ def put_in_front(self, k, input_word): @cached_method def chain_of_reduced_words(self, start_word, end_word): + """ + Compute the chain of reduced words from ``stard_word`` + to ``end_word``. + + INPUT: + + - ``start_word``, ``end_word`` -- two reduced expressions + for the long word + """ if start_word == end_word: return (start_word,) k = end_word[0] diff --git a/src/sage/combinat/crystals/catalog_infinity_crystals.py b/src/sage/combinat/crystals/catalog_infinity_crystals.py index 03657d139ab..f2c33547ef2 100644 --- a/src/sage/combinat/crystals/catalog_infinity_crystals.py +++ b/src/sage/combinat/crystals/catalog_infinity_crystals.py @@ -6,6 +6,7 @@ * :class:`GeneralizedYoungWalls ` * :class:`LSPaths ` +* :class:`MVPolytopes ` * :class:`NakajimaMonomials ` * :class:`PBW ` * :class:`PolyhedralRealization ` @@ -20,6 +21,7 @@ from infinity_crystals import InfinityCrystalOfTableaux as Tableaux from sage.combinat.crystals.polyhedral_realization import InfinityCrystalAsPolyhedralRealization as PolyhedralRealization from sage.combinat.crystals.pbw_crystal import PBWCrystal as PBW +from sage.combinat.crystals.mv_polytopes import MVPolytopes from sage.combinat.crystals.star_crystal import StarCrystal as Star from sage.combinat.crystals.littelmann_path import InfinityCrystalOfLSPaths as LSPaths diff --git a/src/sage/combinat/crystals/mv_polytopes.py b/src/sage/combinat/crystals/mv_polytopes.py index 5a0b489454d..8efda42f8a5 100644 --- a/src/sage/combinat/crystals/mv_polytopes.py +++ b/src/sage/combinat/crystals/mv_polytopes.py @@ -15,43 +15,88 @@ from sage.structure.parent import Parent from sage.structure.unique_representation import UniqueRepresentation -from sage.structure.element import Element from sage.categories.highest_weight_crystals import HighestWeightCrystals from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets from sage.combinat.root_system.cartan_type import CartanType +from sage.combinat.crystals.pbw_crystal import PBWCrystalElement, PBWCrystal +class MVPolytope(PBWCrystalElement): + """ + A Mirković-Vilonen (MV) polytope. + """ + def _repr_(self): + """ + Return a string representation of ``self``. + """ + pbw_datum = self._pbw_datum.convert_to_new_long_word(self.parent()._default_word) + return "MV polytope with Lusztig datum {}".format(pbw_datum.lusztig_datum) -class MVPolytope(Element): - def __init__(self, parent, long_word, lusztig_datum): - Element.__init__(self, parent) - self._initial_long_word = tuple(long_word) - self._lusztig_datum = tuple(lusztig_datum) - self._lusztig_data_dict = {self._initial_long_word: self._lusztig_datum} + def _latex_(self): + """ + Return a latex representation of ``self``. + """ + from sage.misc.latex import latex + return latex(self.polytope()) -class MVPolytopes(UniqueRepresentation, Parent): - @staticmethod - def __classcall_private__(cls, cartan_type): + def _polytope_vertices(self, P): """ - Normalize input to ensure a unique representation. + Return a list of the vertices of ``self`` in ``P``. """ - return super(MVPolytopes, cls).__classcall__(cls, CartanType(cartan_type)) + pbw_data = self._pbw_datum.parent + W = pbw_data.weyl_group + w0 = W.long_element() + al = P.simple_roots() + + vertices = set([P.zero()]) + for red in w0.reduced_words(): + cur = P.zero() + red = tuple(red) + roots = [P.sum(c*al[a] for a,c in root) + for root in pbw_data._root_list_from(red)] + datum = pbw_data.convert_to_new_long_word(self._pbw_datum, red) + for i,c in enumerate(datum.lusztig_datum): + cur = cur + roots[i] * c + vertices.add(cur) + return list(vertices) - def __init__(self, cartan_type): + def polytope(self, P=None): """ - Initialize ``self``. + Return a polytope of ``self``. + + INPUT: + + - ``P`` -- (optional) a space to realize the polytope; default is + the weight lattice realization of the crystal """ - self._cartan_type = cartan_type - Parent.__init__(self, category=(HighestWeightCrystals(), InfiniteEnumeratedSets())) - if not cartan_type.is_finite(): - raise NotImplementedError("only implemented for finite Cartan types") + if P is None: + P = self.parent().weight_lattice_realization() - # There must be a better way to do the following - i = self._cartan_type.index_set()[0] - self._default_word = self._pbw_datum_parent._long_word_begin_with(i) - zero_lusztig_datum = [0]*len(self._default_word) - self.module_generators = (self.element_class(self, - self._default_word, - zero_lusztig_datum),) + from sage.geometry.polyhedron.constructor import Polyhedron + return Polyhedron([v.to_vector() for v in self._polytope_vertices(P)]) + + def plot(self, P=None, **options): + """ + Plot ``self``. + + INPUT: + + - ``P`` -- (optional) a space to realize the polytope; default is + the weight lattice realization of the crystal + + .. SEEALSO:: + + :meth:`~sage.combiant.root_system.root_lattice_realizations.RootLatticeRealizations.ParentMethods.plot_mv_polytope` + """ + if P is None: + P = self.parent().weight_lattice_realization() + return P.plot_mv_polytope(self, **options) + +class MVPolytopes(PBWCrystal): + def _repr_(self): + """ + Return a string representation of ``self``. + """ + return "MV polytopes of type {}".format(self._cartan_type) Element = MVPolytope diff --git a/src/sage/combinat/crystals/pbw_crystal.py b/src/sage/combinat/crystals/pbw_crystal.py index 8368544bbb4..407ed61c6ac 100644 --- a/src/sage/combinat/crystals/pbw_crystal.py +++ b/src/sage/combinat/crystals/pbw_crystal.py @@ -1,7 +1,5 @@ -r""" -The crystal of PBWData up to equivalence. A model of the crystal -`B(\infty)` whose elements are PBWDatum up to equivalence by the -tropical Plucker relations. +r""" +`\mathcal{B}(\infty)` Crystal Of PBW Monomials. AUTHORS: @@ -75,20 +73,18 @@ def __eq__(self, other): """ Check equality of ``self`` with ``other``. """ + if other not in self.parent(): + return False other_long_word = other._pbw_datum.long_word other_lusztig_datum = other._pbw_datum.lusztig_datum equiv_pbw_datum = self._pbw_datum.convert_to_new_long_word(other_long_word) return equiv_pbw_datum.lusztig_datum == other_lusztig_datum - def _cmp_(self, other): + def __ne__(self, other): """ - Return comparison of ``self`` and ``other``. + Check inequality of ``self`` with ``other``. """ - i = self.parent().index_set()[0] - word = self.parent()._pbw_datum_parent._long_word_begin_with(i) - lusztig_datum = tuple(self._pbw_datum.convert_to_new_long_word(word).lusztig_datum) - other_lusztig_datum = tuple(other._pbw_datum.convert_to_new_long_word(word).lusztig_datum) - return cmp(lusztig_datum, other_lusztig_datum) + return not (self == other) @cached_method def __hash__(self): @@ -100,14 +96,37 @@ def __hash__(self): pbw_datum = self._pbw_datum.convert_to_new_long_word(word) return hash(tuple(pbw_datum.lusztig_datum)) + def e(self, i): + """ + Return the action of `e_i` on ``self``. + + EXAMPLES:: + + sage: B = crystals.infinity.PBW(['B', 3]) + sage: b = B.highest_weight_vector() + sage: c = b.f_string([2,1,3,2,1,3,2,2]); c + PBW monomial with Lusztig datum (0, 1, 0, 1, 0, 0, 0, 1, 2) + sage: c.e(2) + PBW monomial with Lusztig datum (0, 1, 0, 1, 0, 0, 0, 1, 1) + sage: c.e_string([2,2,1,3,2,1,3,2]) == b + True + """ + equiv_pbw_datum = self._pbw_datum.convert_to_long_word_with_first_letter(i) + new_long_word = equiv_pbw_datum.long_word + new_lusztig_datum = list(equiv_pbw_datum.lusztig_datum) + if new_lusztig_datum[0] == 0: + return None + new_lusztig_datum[0] -= 1 + return type(self)(self.parent(), new_long_word, tuple(new_lusztig_datum)) + def f(self, i): """ Return the action of `f_i` on ``self``. EXAMPLES:: - sage: B = PBWCrystal("D4") - sage: b = B.module_generators[0] + sage: B = crystals.infinity.PBW("D4") + sage: b = B.highest_weight_vector() sage: c = b.f_string([1,2,3,1,2,3,4]) sage: c == b.f_string([1,2,4,1,2,3,3]) True @@ -118,28 +137,18 @@ def f(self, i): new_lusztig_datum[0] += 1 return type(self)(self.parent(), new_long_word, tuple(new_lusztig_datum)) - def e(self, i): - """ - Return the action of `e_i` on ``self``. - """ - equiv_pbw_datum = self._pbw_datum.convert_to_long_word_with_first_letter(i) - new_long_word = equiv_pbw_datum.long_word - new_lusztig_datum = list(equiv_pbw_datum.lusztig_datum) - if new_lusztig_datum[0] == 0: - return None - new_lusztig_datum[0] -= 1 - return type(self)(self.parent(), new_long_word, tuple(new_lusztig_datum)) - def epsilon(self, i): r""" Return `\varepsilon_i` of ``self``. EXAMPLES:: - sage: B = PBWCrystal(["A2"]) - sage: s = B((1,2,1),(3,0,0)) + sage: B = crystals.infinity.PBW(["A2"]) + sage: s = B((1,2,1), (3,0,0)) sage: s.epsilon(1) 3 + sage: s.epsilon(2) + 0 """ equiv_pbw_datum = self._pbw_datum.convert_to_long_word_with_first_letter(i) return equiv_pbw_datum.lusztig_datum[0] @@ -150,8 +159,8 @@ def phi(self, i): EXAMPLES:: - sage: B = PBWCrystal(["A2"]) - sage: s = B((1,2,1),(3,0,0)) + sage: B = crystals.infinity.PBW(['A', 2]) + sage: s = B((1,2,1), (3,0,0)) sage: s.phi(1) -3 sage: s.phi(2) @@ -167,14 +176,14 @@ def weight(self): EXAMPLES:: - sage: B = PBWCrystal(["A",2]) - sage: s = B((1,2,1),(2,2,2)) + sage: B = crystals.infinity.PBW(['A', 2]) + sage: s = B((1,2,1), (2,2,2)) sage: s.weight() - -4*alpha[1] - 4*alpha[2] + (-4, 0, 4) """ WLR = self.parent().weight_lattice_realization() al = WLR.simple_roots() - return WLR.sum(c*al[i] for i,c in self._pbw_datum.wt()) + return WLR.sum(c*al[i] for i,c in self._pbw_datum.weight()) def star(self): r""" @@ -183,7 +192,7 @@ def star(self): EXAMPLES:: - sage: P = PBWCrystal(["A2"]) + sage: P = crystals.infinity.PBW(['A', 2]) sage: P((1,2,1),(1,2,3)).star() == P((1,2,1),(3,2,1)) True """ @@ -193,19 +202,35 @@ def star(self): class PBWCrystal(Parent, UniqueRepresentation): - """ - Crystal of `B(\infty)` given by PBW monomials. + r""" + Crystal of `\mathcal{B}(\infty)` given by PBW monomials. + + A model of the crystal `\mathcal{B}(\infty)` whose elements are + PBW datum up to equivalence by the tropical Plucker relations. """ @staticmethod - def __classcall_private__(cls, cartan_type): + def __classcall__(cls, cartan_type): """ Normalize input to ensure a unique representation. + + EXAMPLES:: + + sage: B1 = crystals.infinity.PBW(['A', 2]) + sage: B2 = crystals.infinity.PBW("A2") + sage: B3 = crystals.infinity.PBW(CartanType("A2")) + sage: B1 is B2 and B2 is B3 + True """ return super(PBWCrystal, cls).__classcall__(cls, CartanType(cartan_type)) def __init__(self, cartan_type): """ Initialize ``self``. + + EXAMPLES:: + + sage: B = crystals.infinity.PBW(['B', 2]) + sage: TestSuite(B).run() """ self._cartan_type = cartan_type self._pbw_datum_parent = PBWData(self._cartan_type) @@ -223,19 +248,48 @@ def __init__(self, cartan_type): def _repr_(self): """ Return a string representation of ``self``. + + EXAMPLES:: + + sage: crystals.infinity.PBW(['G', 2]) + Crystal of PBW data of type ['G', 2] """ return "Crystal of PBW data of type {}".format(self._cartan_type) def default_long_word(self): """ Return the default long word used to express elements of ``self``. + + EXAMPLES:: + + sage: B = crystals.infinity.PBW(['E', 6]) + sage: B.default_long_word() + [1, 3, 4, 5, 6, 2, 4, 5, 3, 4, 1, 3, 2, 4, 5, 6, 2, 4, + 5, 3, 4, 1, 3, 2, 4, 5, 3, 4, 1, 3, 2, 4, 1, 3, 2, 1] """ - return self._default_word + return list(self._default_word) def _check_is_long_word(self, word): """ Check if ``word`` is a reduced expression of the long of the Coxeter group of ``self``. + + EXAMPLES:: + + sage: B = crystals.infinity.PBW(['A', 3]) + sage: B._check_is_long_word([1,2,1,3,2,1]) + sage: B._check_is_long_word([1,3,2,3,2,1]) + Traceback (most recent call last): + ... + ValueError: not a reduced word of the long element + sage: B._check_is_long_word([1,2,1,3,2]) + Traceback (most recent call last): + ... + ValueError: not a reduced word of the long element + sage: B._check_is_long_word([1,2,1,3,2,1,2]) + Traceback (most recent call last): + ... + ValueError: not a reduced word of the long element """ W = self._pbw_datum_parent.weyl_group if (len(word) != len(self._default_word) diff --git a/src/sage/combinat/crystals/pbw_datum.py b/src/sage/combinat/crystals/pbw_datum.py index 5c21b0ed5db..2ca8886b358 100644 --- a/src/sage/combinat/crystals/pbw_datum.py +++ b/src/sage/combinat/crystals/pbw_datum.py @@ -28,11 +28,17 @@ class PBWDatum(object): def __init__(self, parent, long_word, lusztig_datum): + """ + Initialize ``self``. + """ self.parent = parent self.long_word = tuple(long_word) self.lusztig_datum = tuple(lusztig_datum) def __repr__(self): + """ + Return a string representation of ``self``. + """ return_str = "PBW Datum element of type {cartan_type} with ".format( cartan_type=self.parent.cartan_type) return_str += "long word {long_word} and Lusztig datum {lusztig_datum}".format( @@ -42,11 +48,14 @@ def __repr__(self): def __eq__(self, other_PBWDatum): """ + Check equality. + EXAMPLES:: - sage: P = PBWData(["A2"]) - sage: L1 = P((1,2,1),(1,4,7)) - sage: L2 = P((1,2,1),(1,4,7)) + sage: from sage.combinat.crystals.pbw_datum import PBWData, PBWDatum + sage: P = PBWData("A2") + sage: L1 = PBWDatum(P, (1,2,1), (1,4,7)) + sage: L2 = PBWDatum(P, (1,2,1), (1,4,7)) sage: L1 == L2 True """ @@ -61,11 +70,14 @@ def is_equivalent_to(self, other_pbw_datum): EXAMPLES:: - sage: P = PBWData(["A2"]) - sage: L1 = P((1,2,1),(1,0,1)) - sage: L2 = P((2,1,2),(0,1,0)) + sage: from sage.combinat.crystals.pbw_datum import PBWData, PBWDatum + sage: P = PBWData("A2") + sage: L1 = PBWDatum(P, (1,2,1), (1,0,1)) + sage: L2 = PBWDatum(P, (2,1,2), (0,1,0)) sage: L1.is_equivalent_to(L2) True + sage: L1 == L2 + False """ other_long_word = other_pbw_datum.long_word other_lusztig_datum = other_pbw_datum.lusztig_datum @@ -86,21 +98,27 @@ def convert_to_new_long_word(self, new_long_word): EXAMPLES:: - sage: P = PBWData(["A2"]) - sage: P.convert_to_new_long_word(P((1,2,1),(1,0,1)),(2,1,2)).long_word + sage: from sage.combinat.crystals.pbw_datum import PBWData, PBWDatum + sage: P = PBWData("A2") + sage: datum = PBWDatum(P, (1,2,1), (1,0,1)) + sage: new_datum = P.convert_to_new_long_word(datum, (2,1,2)) + sage: new_datum.long_word (2, 1, 2) - sage: P.convert_to_new_long_word(P((1,2,1),(1,0,1)),(2,1,2)).lusztig_datum + sage: new_datum.lusztig_datum (0, 1, 0) """ return self.parent.convert_to_new_long_word(self, new_long_word) - def wt(self): + def weight(self): """ + Return the weight of ``self``. + EXAMPLES:: - sage: P = PBWData(["A",2]) - sage: L = P((1,2,1),(1,1,1)) - sage: L.wt() + sage: from sage.combinat.crystals.pbw_datum import PBWData, PBWDatum + sage: P = PBWData("A2") + sage: L = PBWDatum(P, (1,2,1), (1,1,1)) + sage: L.weight() -2*alpha[1] - 2*alpha[2] """ root_list = self.parent._root_list_from(tuple(self.long_word)) @@ -115,9 +133,10 @@ def star(self): EXAMPLES:: - sage: P = PBWData(["A2"]) - sage: L1 = P((1,2,1),(1,2,3)) - sage: L1.star() == P((1,2,1),(3,2,1)) + sage: from sage.combinat.crystals.pbw_datum import PBWData, PBWDatum + sage: P = PBWData("A2") + sage: L1 = PBWDatum(P, (1,2,1), (1,2,3)) + sage: L1.star() == PBWDatum(P, (1,2,1), (3,2,1)) True """ reversed_long_word = reversed(self.long_word) @@ -130,12 +149,13 @@ class PBWData(object): # UniqueRepresentation? Helper class for the set of PBW data. """ def __init__(self, cartan_type): + """ + Initialize ``self``. + """ self.cartan_type = CartanType(cartan_type) self.root_system = RootSystem(self.cartan_type) self.root_lattice = self.root_system.root_lattice() self.weyl_group = self.root_lattice.weyl_group() - # Is there a more intelligent way to recover the Weyl group - # from cartan_type? self._braid_move_calc = BraidMoveCalculator(self.weyl_group) def convert_to_new_long_word(self, pbw_datum, new_long_word): @@ -145,12 +165,16 @@ def convert_to_new_long_word(self, pbw_datum, new_long_word): EXAMPLES:: + sage: from sage.combinat.crystals.pbw_datum import PBWData, PBWDatum sage: P = PBWData("A2") - sage: datum = P.convert_to_new_long_word(P((1,2,1),(1,0,1)),(2,1,2)) - sage: datum - sage: datum.long_word + sage: datum = PBWDatum(P, (1,2,1), (1,0,1)) + sage: new_datum = P.convert_to_new_long_word(datum,(2,1,2)) + sage: new_datum + PBW Datum element of type ['A', 2] with long word (2, 1, 2) + and Lusztig datum (0, 1, 0) + sage: new_datum.long_word (2, 1, 2) - sage: datum.lusztig_datum + sage: new_datum.lusztig_datum (0, 1, 0) """ assert pbw_datum.parent is self @@ -178,6 +202,7 @@ def _root_list_from(self, reduced_word): EXAMPLES:: + sage: from sage.combinat.crystals.pbw_datum import PBWData sage: P = PBWData(["A",2]) sage: P._root_list_from((1,2,1)) [alpha[1], alpha[1] + alpha[2], alpha[2]] @@ -209,10 +234,11 @@ def compute_new_lusztig_datum(enhanced_braid_chain, initial_lusztig_datum): sage: from sage.combinat.crystals.braid_move_calculator import BraidMoveCalculator sage: from sage.combinat.crystals.pbw_datum import enhance_braid_move_chain sage: from sage.combinat.crystals.pbw_datum import compute_new_lusztig_datum - sage: W = CoxeterGroup("A2") + sage: ct = CartanType(['A', 2]) + sage: W = CoxeterGroup(ct) sage: B = BraidMoveCalculator(W) sage: chain = B.chain_of_reduced_words((1,2,1),(2,1,2)) - sage: enhanced_braid_chain = enhance_braid_move_chain(chain,CartanType(["A",2])) + sage: enhanced_braid_chain = enhance_braid_move_chain(chain, ct) sage: compute_new_lusztig_datum(enhanced_braid_chain,(1,0,1)) (0, 1, 0) @@ -250,8 +276,10 @@ def tropical_plucker_relation(a, lusztig_datum): EXAMPLES:: + sage: from sage.combinat.crystals.pbw_datum import tropical_plucker_relation sage: tropical_plucker_relation((0,0), (2,3)) (3, 2) + # Add more doctests """ n = lusztig_datum if a == (0, 0): # A1xA1 @@ -313,7 +341,7 @@ def enhance_braid_move_chain(braid_move_chain, cartan_type): TESTS:: - sage: from sage.combinat.crystals.braid_move_calculator import enhance_braid_move_chain + sage: from sage.combinat.crystals.pbw_datum import enhance_braid_move_chain sage: braid_chain = [(1, 2, 1, 3, 2, 1), ....: (1, 2, 3, 1, 2, 1), ....: (1, 2, 3, 2, 1, 2), @@ -361,6 +389,7 @@ def diff_interval(list1, list2): TESTS:: + sage: from sage.combinat.crystals.pbw_datum import diff_interval sage: diff_interval([1,2,3,4], [1,2,3,4]) sage: diff_interval([1,2,3,4], [1,3,2,4]) (1, 3) diff --git a/src/sage/combinat/root_system/root_lattice_realizations.py b/src/sage/combinat/root_system/root_lattice_realizations.py index 1fae1573a31..ab19ab4fc28 100644 --- a/src/sage/combinat/root_system/root_lattice_realizations.py +++ b/src/sage/combinat/root_system/root_lattice_realizations.py @@ -2049,6 +2049,7 @@ def plot(self, - :meth:`plot_alcoves` - :meth:`plot_alcove_walk` - :meth:`plot_ls_paths` + - :meth:`plot_mv_polytope` - :meth:`plot_crystal` """ plot_options = self.plot_parse_options(**options) @@ -3025,6 +3026,78 @@ def plot_ls_paths(self, paths, plot_labels=None, colored_labels=True, **options) G += plot_options.text(b, prev + prev.normalized()*plot_labels) return G + def plot_mv_polytope(self, mv_polytope, mark_endpoints=True, + circle_size=0.06, circle_thickness=1.6, + wireframe='blue', fill='green', alpha=1, + **options): + r""" + Plot an MV polytope. + + INPUT: + + - ``mv_polytope`` -- an MV polytope + - ``mark_endpoints`` -- (default: ``True``) mark the endpoints + of the MV polytope + - ``circle_size`` -- (default: 0.06) the size of the circles + - ``circle_thickness`` -- (default: 1.6) the thinkness of the + extra rings of circles + - ``wireframe`` -- (default=``'blue'``) color to draw the + wireframe of the polytope with + - ``fill`` -- (default=``'green'``) color to fill the polytope with + - ``alpha`` -- (default: 1) the alpha value (opacity) of the fill + - ``**options`` -- plotting options + + .. SEEALSO:: + + - :meth:`plot` for a description of the plotting options + - :ref:`sage.combinat.root_system.plot` for a tutorial + on root system plotting + + EXAMPLES:: + + sage: B = crystals.infinity.MVPolytopes(['C',2]) + sage: L = RootSystem(['C',2]).ambient_space() + sage: p = B.highest_weight_vector().f_string([1,2,1,2]) + sage: L.plot_fundamental_weights() + L.plot_mv_polytope(p) + Graphics object consisting of 14 graphics primitives + + This also works in 3 dimensions:: + + sage: B = crystals.infinity.MVPolytopes(['A',3]) + sage: L = RootSystem(['A',3]).ambient_space() + sage: p = B.highest_weight_vector().f_string([2,1,3,2]) + sage: L = RootSystem(['A',3]).ambient_space() + sage: L.plot_mv_polytope(p) + """ + from sage.geometry.polyhedron.all import Polyhedron + plot_options = self.plot_parse_options(**options) + + # Setup the shift for plotting + pbw_data = mv_polytope._pbw_datum.parent + al = self.simple_roots() + red = tuple(mv_polytope._pbw_datum.long_word) + roots = [self.sum(c*al[a] for a,c in root) + for root in pbw_data._root_list_from(red)] + datum = mv_polytope._pbw_datum.lusztig_datum + end_pt = self.sum(roots[i] * c for i,c in enumerate(datum)) + shift = plot_options.projection(end_pt) + + vertices = [plot_options.projection(vertex) - shift + for vertex in mv_polytope._polytope_vertices(self)] + p = Polyhedron(vertices=vertices).plot(wireframe=wireframe, + fill=fill, alpha=alpha) + if mark_endpoints: + from sage.plot.circle import circle + + p += circle(plot_options.projection(self.zero()), + circle_size, fill=True, + thickness=circle_thickness, color=wireframe) + + p += circle(-shift, + circle_size, fill=True, + thickness=circle_thickness, color=wireframe) + return p + def plot_crystal(self, crystal, plot_labels=True, label_color='black', edge_labels=False, From 35473fcd61c70545fd5846d1918333e0f3148d95 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 23 Feb 2016 15:01:28 -0600 Subject: [PATCH 039/452] Fixing some things. --- src/sage/combinat/crystals/pbw_crystal.py | 20 ++++++++++++++++---- src/sage/combinat/crystals/pbw_datum.py | 4 ++-- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/sage/combinat/crystals/pbw_crystal.py b/src/sage/combinat/crystals/pbw_crystal.py index 407ed61c6ac..e140d83225e 100644 --- a/src/sage/combinat/crystals/pbw_crystal.py +++ b/src/sage/combinat/crystals/pbw_crystal.py @@ -51,7 +51,7 @@ def _latex_(self): lusztig_datum = list(pbw_datum.lusztig_datum) al = self.parent()._pbw_datum_parent._root_list_from(self.parent()._default_word) from sage.misc.latex import latex - ret_str = ' '.join("f_{%s}%s"%(latex(al[i]), "^{%s}"%latex(exp) if i > 1 else "") + ret_str = ' '.join("f_{%s}%s"%(latex(al[i]), "^{%s}"%latex(exp) if exp > 1 else "") for i, exp in enumerate(lusztig_datum) if exp) if ret_str == '': return '1' @@ -66,6 +66,7 @@ def lusztig_datum(self, word=None): word = self.parent()._default_word else: self.parent()._check_is_long_word(word) + word = tuple(word) pbw_datum = self._pbw_datum.convert_to_new_long_word(word) return tuple(pbw_datum.lusztig_datum) @@ -86,6 +87,17 @@ def __ne__(self, other): """ return not (self == other) + # Necessary for displaying subcrystals + def _cmp_(self, other): + """ + Return comparison of ``self`` and ``other``. + """ + i = self.parent().index_set()[0] + word = self.parent()._pbw_datum_parent._long_word_begin_with(i) + lusztig_datum = tuple(self._pbw_datum.convert_to_new_long_word(word).lusztig_datum) + other_lusztig_datum = tuple(other._pbw_datum.convert_to_new_long_word(word).lusztig_datum) + return cmp(lusztig_datum, other_lusztig_datum) + @cached_method def __hash__(self): """ @@ -111,8 +123,8 @@ def e(self, i): sage: c.e_string([2,2,1,3,2,1,3,2]) == b True """ - equiv_pbw_datum = self._pbw_datum.convert_to_long_word_with_first_letter(i) - new_long_word = equiv_pbw_datum.long_word + equiv_pbw_datum = self._pbw_datum.convert_to_long_word_with_first_letter(i) + new_long_word = equiv_pbw_datum.long_word new_lusztig_datum = list(equiv_pbw_datum.lusztig_datum) if new_lusztig_datum[0] == 0: return None @@ -177,7 +189,7 @@ def weight(self): EXAMPLES:: sage: B = crystals.infinity.PBW(['A', 2]) - sage: s = B((1,2,1), (2,2,2)) + sage: s = B((1,2,1), (2,2,2)) sage: s.weight() (-4, 0, 4) """ diff --git a/src/sage/combinat/crystals/pbw_datum.py b/src/sage/combinat/crystals/pbw_datum.py index 2ca8886b358..a3c76bf4ee7 100644 --- a/src/sage/combinat/crystals/pbw_datum.py +++ b/src/sage/combinat/crystals/pbw_datum.py @@ -323,8 +323,8 @@ def enhance_braid_move_chain(braid_move_chain, cartan_type): OUTPUT: - A list of 3-tuples - ``(reduced_word, interval_of_change, cartan_sub_matrix)`` where + A list of 2-tuples + ``(interval_of_change, cartan_sub_matrix)`` where - ``interval_of_change`` is the (half-open) interval of indices where the braid move occurs; this is `None` for the first tuple From f4295b2db678e171fbd147c15223dcddb3b6b1d0 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 24 Feb 2016 23:46:37 -0600 Subject: [PATCH 040/452] Adding tikz latex output for 2d lattice polytopes. --- src/sage/combinat/crystals/mv_polytopes.py | 138 ++++++++++++++++++++- 1 file changed, 135 insertions(+), 3 deletions(-) diff --git a/src/sage/combinat/crystals/mv_polytopes.py b/src/sage/combinat/crystals/mv_polytopes.py index 8efda42f8a5..e2a798d33dd 100644 --- a/src/sage/combinat/crystals/mv_polytopes.py +++ b/src/sage/combinat/crystals/mv_polytopes.py @@ -27,16 +27,79 @@ class MVPolytope(PBWCrystalElement): def _repr_(self): """ Return a string representation of ``self``. + + EXAMPLES:: + + sage: MV = crystals.infinity.MVPolytopes(['E',6]) + sage: b = MV.module_generators[0].f_string([1,2,6,4,3,2,5,2]) + sage: b + MV polytope with Lusztig datum (0, 1, ..., 1, 0, 0, 0, 0, 0, 0, 3, 1) """ pbw_datum = self._pbw_datum.convert_to_new_long_word(self.parent()._default_word) return "MV polytope with Lusztig datum {}".format(pbw_datum.lusztig_datum) def _latex_(self): - """ + r""" Return a latex representation of ``self``. + + EXAMPLES:: + + sage: MV = crystals.infinity.MVPolytopes(['C',2]) + sage: b = MV.module_generators[0].f_string([1,2,1,2]) + sage: latex(b) + \begin{tikzpicture} + \draw (0, 0) -- (-1, 1) -- (-1, 1) -- (-2, 0) -- (-2, -2); + \draw (0, 0) -- (0, -2) -- (-1, -3) -- (-1, -3) -- (-2, -2); + \draw[fill=black] (0, 0) circle (0.1); + \draw[fill=black] (-2, -2) circle (0.1); + \end{tikzpicture} + + :: + + sage: MV = crystals.infinity.MVPolytopes(['D',4]) + sage: b = MV.module_generators[0].f_string([1,2,1,2]) + sage: latex(b) + \text{\texttt{MV{ }polytope{ }...}} """ - from sage.misc.latex import latex - return latex(self.polytope()) + latex_options = self.parent()._latex_options + P = latex_options['P'] + plot_options = P.plot_parse_options(projection=latex_options["projection"]) + proj = plot_options.projection + if proj(P.zero()).parent().dimension() != 2: + from sage.misc.latex import latex + return latex(repr(self)) + + # We need this to use tikz + from sage.graphs.graph_latex import setup_latex_preamble + setup_latex_preamble() + + pbw_data = self._pbw_datum.parent + W = pbw_data.weyl_group + w0 = W.long_element() + al = P.simple_roots() + ret = "\\begin{tikzpicture}\n" + + final = None + for red in w0.reduced_words(): + ret += "\\draw " + cur = proj(P.zero()) + red = tuple(red) + ret += str(cur) + roots = [proj(P.sum(c*al[a] for a,c in root)) + for root in pbw_data._root_list_from(red)] + datum = pbw_data.convert_to_new_long_word(self._pbw_datum, red) + for i in reversed(range(len(datum.lusztig_datum))): + cur -= roots[i] * datum.lusztig_datum[i] + ret += " -- " + str(cur) + final = cur + ret += ";\n" + + if latex_options["mark_endpoints"]: + circle_size = latex_options["circle_size"] + ret += "\\draw[fill=black] {} circle ({});\n".format(proj(P.zero()), circle_size) + ret += "\\draw[fill=black] {} circle ({});\n".format(proj(final), circle_size) + ret += "\\end{tikzpicture}" + return ret def _polytope_vertices(self, P): """ @@ -92,11 +155,80 @@ def plot(self, P=None, **options): return P.plot_mv_polytope(self, **options) class MVPolytopes(PBWCrystal): + def __init__(self, cartan_type): + """ + Initialize ``self``. + + EXAMPLES:: + + sage: MV = crystals.infinity.MVPolytopes(['B',2]) + sage: TestSuite(MV).run() + """ + PBWCrystal.__init__(self, cartan_type) + self._latex_options = {"projection": True, + "mark_endpoints": True, + "P": self.weight_lattice_realization(), + "circle_size": 0.1} + def _repr_(self): """ Return a string representation of ``self``. + + EXAMPLES:: + + sage: crystals.infinity.MVPolytopes(['F',4]) + MV polytopes of type ['F', 4] """ return "MV polytopes of type {}".format(self._cartan_type) + def set_latex_options(self, **kwds): + """ + Set the latex options for the elements of ``self``. + + INPUT: + + - ``projection`` -- the projection; set to ``True`` to use the + default projection of the specified weight lattice realization + (initial: ``True``) + - ``P`` -- the weight lattice realization to use (initial: the + weight lattice realization of ``self``) + - ``mark_endpoints`` -- whether to mark the endpoints (initial: ``True``) + - ``circle_size`` -- the size of the endpoint circles (initial: 0.1) + """ + if "projection" in kwds: + self._latex_options["projection"] = True + del kwds["projection"] + + if 'P' in kwds: + self._latex_options['P'] = kwds['P'] + del kwds['P'] + + if "mark_endpoints" in kwds: + self._latex_options = kwds["mark_endpoints"] + del kwds["mark_endpoints"] + + if "circle_size" in kwds: + self._latex_options["circle_size"] = True + del kwds["circle_size"] + + if not kwds: + raise ValueError("invalid latex option") + + def latex_options(self): + """ + Return the latex options of ``self``. + + EXAMPLES:: + + sage: MV = crystals.infinity.MVPolytopes(['F',4]) + sage: MV.latex_options() + {'P': Ambient space of the Root system of type ['F', 4], + 'circle_size': 0.1, + 'mark_endpoints': True, + 'projection': True} + """ + from copy import copy + return copy(self._latex_options) + Element = MVPolytope From b3f2f59ddace504706eb3cfd0caa15c22475d8c7 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 25 Feb 2016 11:17:00 -0600 Subject: [PATCH 041/452] Full coverage of mv_polytopes.py and pbw_crystal.py. --- src/doc/en/reference/combinat/module_list.rst | 6 +- src/sage/combinat/crystals/mv_polytopes.py | 99 +++++++++++++-- src/sage/combinat/crystals/pbw_crystal.py | 118 +++++++++++++++++- 3 files changed, 206 insertions(+), 17 deletions(-) diff --git a/src/doc/en/reference/combinat/module_list.rst b/src/doc/en/reference/combinat/module_list.rst index 11602a135e3..94889b98a39 100644 --- a/src/doc/en/reference/combinat/module_list.rst +++ b/src/doc/en/reference/combinat/module_list.rst @@ -51,6 +51,7 @@ Comprehensive Module list sage/combinat/crystals/affinization sage/combinat/crystals/alcove_path sage/combinat/crystals/all + sage/combinat/crystals/braid_move_calculator sage/combinat/crystals/catalog sage/combinat/crystals/catalog_elementary_crystals sage/combinat/crystals/catalog_infinity_crystals @@ -63,12 +64,15 @@ Comprehensive Module list sage/combinat/crystals/highest_weight_crystals sage/combinat/crystals/induced_structure sage/combinat/crystals/infinity_crystals - sage/combinat/crystals/polyhedral_realization sage/combinat/crystals/kirillov_reshetikhin sage/combinat/crystals/kyoto_path_model sage/combinat/crystals/letters sage/combinat/crystals/littelmann_path sage/combinat/crystals/monomial_crystals + sage/combinat/crystals/mv_polytopes + sage/combinat/crystals/pbw_crystal + sage/combinat/crystals/pbw_datum + sage/combinat/crystals/polyhedral_realization sage/combinat/crystals/spins sage/combinat/crystals/star_crystal sage/combinat/crystals/tensor_product diff --git a/src/sage/combinat/crystals/mv_polytopes.py b/src/sage/combinat/crystals/mv_polytopes.py index e2a798d33dd..b34da6a0704 100644 --- a/src/sage/combinat/crystals/mv_polytopes.py +++ b/src/sage/combinat/crystals/mv_polytopes.py @@ -30,7 +30,7 @@ def _repr_(self): EXAMPLES:: - sage: MV = crystals.infinity.MVPolytopes(['E',6]) + sage: MV = crystals.infinity.MVPolytopes(['E', 6]) sage: b = MV.module_generators[0].f_string([1,2,6,4,3,2,5,2]) sage: b MV polytope with Lusztig datum (0, 1, ..., 1, 0, 0, 0, 0, 0, 0, 3, 1) @@ -44,7 +44,7 @@ def _latex_(self): EXAMPLES:: - sage: MV = crystals.infinity.MVPolytopes(['C',2]) + sage: MV = crystals.infinity.MVPolytopes(['C', 2]) sage: b = MV.module_generators[0].f_string([1,2,1,2]) sage: latex(b) \begin{tikzpicture} @@ -104,6 +104,24 @@ def _latex_(self): def _polytope_vertices(self, P): """ Return a list of the vertices of ``self`` in ``P``. + + EXAMPLES:: + + sage: MV = crystals.infinity.MVPolytopes(['C', 3]) + sage: b = MV.module_generators[0].f_string([1,2,1,2]) + sage: sorted(b._polytope_vertices(MV.weight_lattice_realization()), key=list) + [(0, 0, 0), (2, 0, -2), (0, 2, -2)] + + sage: MV = crystals.infinity.MVPolytopes(['D', 4]) + sage: b = MV.module_generators[0].f_string([1,2,3,4]) + sage: P = RootSystem(['D',4]).weight_lattice() + sage: sorted(b._polytope_vertices(P), key=list) # long time + [0, + -Lambda[1] + Lambda[3] + Lambda[4], + Lambda[1] - Lambda[2] + Lambda[3] + Lambda[4], + -2*Lambda[2] + 2*Lambda[3] + 2*Lambda[4], + -Lambda[2] + 2*Lambda[3], + -Lambda[2] + 2*Lambda[4]] """ pbw_data = self._pbw_datum.parent W = pbw_data.weyl_group @@ -130,6 +148,20 @@ def polytope(self, P=None): - ``P`` -- (optional) a space to realize the polytope; default is the weight lattice realization of the crystal + + EXAMPLES:: + + sage: MV = crystals.infinity.MVPolytopes(['C', 3]) + sage: b = MV.module_generators[0].f_string([3,2,3,2,1]) + sage: P = b.polytope(); P + A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 6 vertices + sage: P.vertices() + (A vertex at (0, 0, 0), + A vertex at (0, 1, -1), + A vertex at (0, 1, 1), + A vertex at (1, -1, 0), + A vertex at (1, 1, -2), + A vertex at (1, 1, 2)) """ if P is None: P = self.parent().weight_lattice_realization() @@ -148,7 +180,24 @@ def plot(self, P=None, **options): .. SEEALSO:: - :meth:`~sage.combiant.root_system.root_lattice_realizations.RootLatticeRealizations.ParentMethods.plot_mv_polytope` + :meth:`~sage.combinat.root_system.root_lattice_realizations.RootLatticeRealizations.ParentMethods.plot_mv_polytope` + + EXAMPLES:: + + sage: MV = crystals.infinity.MVPolytopes(['C', 2]) + sage: b = MV.module_generators[0].f_string([1,2,1,2]) + sage: b.plot() + Graphics object consisting of 10 graphics primitives + + .. PLOT:: + :width: 300 px + + MV = crystals.infinity.MVPolytopes(['C', 2]) + b = MV.module_generators[0].f_string([1,2,1,2]) + L = RootSystem(['C', 2, 1]).ambient_space() + p = L.plot(reflection_hyperplanes=False) + b.plot() + p.axes(False) + sphinx_plot(p) """ if P is None: P = self.parent().weight_lattice_realization() @@ -161,7 +210,7 @@ def __init__(self, cartan_type): EXAMPLES:: - sage: MV = crystals.infinity.MVPolytopes(['B',2]) + sage: MV = crystals.infinity.MVPolytopes(['B', 2]) sage: TestSuite(MV).run() """ PBWCrystal.__init__(self, cartan_type) @@ -176,13 +225,13 @@ def _repr_(self): EXAMPLES:: - sage: crystals.infinity.MVPolytopes(['F',4]) + sage: crystals.infinity.MVPolytopes(['F', 4]) MV polytopes of type ['F', 4] """ return "MV polytopes of type {}".format(self._cartan_type) def set_latex_options(self, **kwds): - """ + r""" Set the latex options for the elements of ``self``. INPUT: @@ -194,6 +243,36 @@ def set_latex_options(self, **kwds): weight lattice realization of ``self``) - ``mark_endpoints`` -- whether to mark the endpoints (initial: ``True``) - ``circle_size`` -- the size of the endpoint circles (initial: 0.1) + + EXAMPLES:: + + sage: MV = crystals.infinity.MVPolytopes(['C', 2]) + sage: P = RootSystem(['C', 2]).weight_lattice() + sage: b = MV.highest_weight_vector().f_string([1,2,1,2]) + sage: latex(b) + \begin{tikzpicture} + \draw (0, 0) -- (-1, 1) -- (-1, 1) -- (-2, 0) -- (-2, -2); + \draw (0, 0) -- (0, -2) -- (-1, -3) -- (-1, -3) -- (-2, -2); + \draw[fill=black] (0, 0) circle (0.1); + \draw[fill=black] (-2, -2) circle (0.1); + \end{tikzpicture} + sage: MV.set_latex_options(P=P, circle_size=float(0.2)) + sage: latex(b) + \begin{tikzpicture} + \draw (0, 0) -- (-2, 1) -- (-2, 1) -- (-2, 0) -- (0, -2); + \draw (0, 0) -- (2, -2) -- (2, -3) -- (2, -3) -- (0, -2); + \draw[fill=black] (0, 0) circle (0.2); + \draw[fill=black] (0, -2) circle (0.2); + \end{tikzpicture} + sage: MV.set_latex_options(mark_endpoints=False) + sage: latex(b) + \begin{tikzpicture} + \draw (0, 0) -- (-2, 1) -- (-2, 1) -- (-2, 0) -- (0, -2); + \draw (0, 0) -- (2, -2) -- (2, -3) -- (2, -3) -- (0, -2); + \end{tikzpicture} + sage: MV.set_latex_options(P=MV.weight_lattice_realization(), + ....: circle_size=0.2, + ....: mark_endpoints=True) """ if "projection" in kwds: self._latex_options["projection"] = True @@ -204,14 +283,14 @@ def set_latex_options(self, **kwds): del kwds['P'] if "mark_endpoints" in kwds: - self._latex_options = kwds["mark_endpoints"] + self._latex_options["mark_endpoints"] = kwds["mark_endpoints"] del kwds["mark_endpoints"] if "circle_size" in kwds: - self._latex_options["circle_size"] = True + self._latex_options["circle_size"] = kwds["circle_size"] del kwds["circle_size"] - if not kwds: + if kwds: raise ValueError("invalid latex option") def latex_options(self): @@ -220,7 +299,7 @@ def latex_options(self): EXAMPLES:: - sage: MV = crystals.infinity.MVPolytopes(['F',4]) + sage: MV = crystals.infinity.MVPolytopes(['F', 4]) sage: MV.latex_options() {'P': Ambient space of the Root system of type ['F', 4], 'circle_size': 0.1, diff --git a/src/sage/combinat/crystals/pbw_crystal.py b/src/sage/combinat/crystals/pbw_crystal.py index e140d83225e..1f73539e19c 100644 --- a/src/sage/combinat/crystals/pbw_crystal.py +++ b/src/sage/combinat/crystals/pbw_crystal.py @@ -32,6 +32,13 @@ class PBWCrystalElement(Element): def __init__(self, parent, long_word, lusztig_datum): """ Initialize ``self``. + + EXAMPLES:: + + sage: B = crystals.infinity.PBW(['F', 4]) + sage: u = B.highest_weight_vector() + sage: b = u.f_string([1,2,3,4,2,3,2,3,4,1,2]) + sage: TestSuite(b).run() """ Element.__init__(self, parent) self._pbw_datum = PBWDatum(parent._pbw_datum_parent, long_word, lusztig_datum) @@ -39,13 +46,33 @@ def __init__(self, parent, long_word, lusztig_datum): def _repr_(self): """ Return a string representation of ``self``. + + EXAMPLES:: + + sage: B = crystals.infinity.PBW(['B', 4]) + sage: u = B.highest_weight_vector() + sage: u.f_string([1,2,3,4,2,3,2,3,4,1,2]) + PBW monomial with Lusztig datum + (0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 1, 2) """ pbw_datum = self._pbw_datum.convert_to_new_long_word(self.parent()._default_word) return "PBW monomial with Lusztig datum {}".format(pbw_datum.lusztig_datum) def _latex_(self): - """ + r""" Return a latex representation of ``self``. + + EXAMPLES:: + + sage: B = crystals.infinity.PBW(['F', 4]) + sage: u = B.highest_weight_vector() + sage: b = u.f_string([1,2,3,4,2,3,2,3,4,1,2]) + sage: latex(b) + f_{\alpha_{4}}^{2} + f_{\alpha_{3}} + f_{\alpha_{1} + \alpha_{2} + 2\alpha_{3}} + f_{\alpha_{1} + \alpha_{2}} + f_{\alpha_{2}}^{2} """ pbw_datum = self._pbw_datum.convert_to_new_long_word(self.parent()._default_word) lusztig_datum = list(pbw_datum.lusztig_datum) @@ -61,6 +88,16 @@ def lusztig_datum(self, word=None): """ Return the Lusztig datum of ``self`` with respect to the reduced expression of the long word ``word``. + + EXAMPLES:: + + sage: B = crystals.infinity.PBW(['A', 2]) + sage: u = B.highest_weight_vector() + sage: b = u.f_string([2,1,2,2,2,2,1,1,2,1,2,1,2,1,2,2]) + sage: b.lusztig_datum() + (6, 0, 10) + sage: b.lusztig_datum(word=[2,1,2]) + (4, 6, 0) """ if word is None: word = self.parent()._default_word @@ -73,6 +110,15 @@ def lusztig_datum(self, word=None): def __eq__(self, other): """ Check equality of ``self`` with ``other``. + + EXAMPLES:: + + sage: B = crystals.infinity.PBW(['A', 2]) + sage: u = B.highest_weight_vector() + sage: b = u.f_string([2,1,2,2,2,2,1,1,2,1,2,1,2,1,2,2]) + sage: bp = u.f_string([2,1,2,2,1,1,2,2,2,1,2,1,2,2,1,2]) + sage: b == bp + True """ if other not in self.parent(): return False @@ -84,6 +130,15 @@ def __eq__(self, other): def __ne__(self, other): """ Check inequality of ``self`` with ``other``. + + EXAMPLES:: + + sage: B = crystals.infinity.PBW(['A', 2]) + sage: u = B.highest_weight_vector() + sage: b = u.f_string([2,1,2,2,2,2,1,1,2,1,2,1,2,1,2,2]) + sage: bp = u.f_string([2,1,2,2,1,1,2,2,2,1,2,1,2,2,1,2]) + sage: b != bp + False """ return not (self == other) @@ -91,6 +146,16 @@ def __ne__(self, other): def _cmp_(self, other): """ Return comparison of ``self`` and ``other``. + + EXAMPLES:: + + sage: B = crystals.infinity.PBW(['A', 2]) + sage: u = B.highest_weight_vector() + sage: b = u.f_string([2,1,2,2,2,2,1,1,2,1,2,1,2,1,2,2]) + sage: bp = u.f_string([2,1,2,2,1,1,2,2,2,1,2,1,2]) + sage: w = [1, 2, 1] + sage: cmp(b, bp) == cmp(b.lusztig_datum(w), bp.lusztig_datum(w)) + True """ i = self.parent().index_set()[0] word = self.parent()._pbw_datum_parent._long_word_begin_with(i) @@ -102,6 +167,15 @@ def _cmp_(self, other): def __hash__(self): """ Return the hash of ``self``. + + EXAMPLES:: + + sage: B = crystals.infinity.PBW(['A', 2]) + sage: u = B.highest_weight_vector() + sage: b = u.f_string([2,1,2,2,2,2,1,1,2,1,2,1,2,1,2,2]) + sage: bp = u.f_string([2,1,2,2,1,1,2,2,2,1,2,1,2,2,1,2]) + sage: hash(b) == hash(bp) + True """ i = self.parent().index_set()[0] word = self.parent()._pbw_datum_parent._long_word_begin_with(i) @@ -139,7 +213,8 @@ def f(self, i): sage: B = crystals.infinity.PBW("D4") sage: b = B.highest_weight_vector() - sage: c = b.f_string([1,2,3,1,2,3,4]) + sage: c = b.f_string([1,2,3,1,2,3,4]); c + PBW monomial with Lusztig datum (0, 1, 0, 0, 0, 0, 0, 2, 0, 0, 2, 0) sage: c == b.f_string([1,2,4,1,2,3,3]) True """ @@ -205,7 +280,13 @@ def star(self): EXAMPLES:: sage: P = crystals.infinity.PBW(['A', 2]) - sage: P((1,2,1),(1,2,3)).star() == P((1,2,1),(3,2,1)) + sage: P((1,2,1), (1,2,3)).star() == P((1,2,1), (3,2,1)) + True + + sage: B = crystals.infinity.PBW(['E', 6]) + sage: b = B.highest_weight_vector() + sage: c = b.f_string([1,2,6,3,4,2,5,2,3,4,1,6]) + sage: c == c.star().star() True """ starred_pbw_datum = self._pbw_datum.star() @@ -233,7 +314,10 @@ def __classcall__(cls, cartan_type): sage: B1 is B2 and B2 is B3 True """ - return super(PBWCrystal, cls).__classcall__(cls, CartanType(cartan_type)) + cartan_type = CartanType(cartan_type) + if not cartan_type.is_finite(): + raise NotImplementedError("only implemented for finite types") + return super(PBWCrystal, cls).__classcall__(cls, cartan_type) def __init__(self, cartan_type): """ @@ -263,8 +347,8 @@ def _repr_(self): EXAMPLES:: - sage: crystals.infinity.PBW(['G', 2]) - Crystal of PBW data of type ['G', 2] + sage: crystals.infinity.PBW(['C', 3]) + Crystal of PBW data of type ['C', 3] """ return "Crystal of PBW data of type {}".format(self._cartan_type) @@ -311,6 +395,28 @@ def _check_is_long_word(self, word): def set_default_long_word(self, word): """ Set the default long word used to express elements of ``self``. + + EXAMPLES:: + + sage: B = crystals.infinity.PBW(['C', 3]) + sage: B.default_long_word() + [1, 3, 2, 3, 1, 2, 3, 1, 2] + sage: x = B.highest_weight_vector().f_string([2,1,3,2,3,1,2,3,3,1]) + sage: x + PBW monomial with Lusztig datum (1, 2, 2, 0, 0, 0, 0, 0, 1) + sage: B.set_default_long_word([2,1,3,2,1,3,2,3,1]) + sage: B.default_long_word() + [2, 1, 3, 2, 1, 3, 2, 3, 1] + sage: x + PBW monomial with Lusztig datum (2, 0, 0, 0, 0, 0, 1, 3, 2) + + TESTS:: + + sage: B = crystals.infinity.PBW(['A', 3]) + sage: B._check_is_long_word([1,2,1,3,2,1,2]) + Traceback (most recent call last): + ... + ValueError: not a reduced word of the long element """ self._check_is_long_word(word) self._default_word = tuple(word) From 9c4d2a080aed23e3c4204ad0ad75fad6c88724bf Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 25 Feb 2016 20:26:28 -0600 Subject: [PATCH 042/452] Adding some documentation. --- src/sage/combinat/crystals/mv_polytopes.py | 40 +++++++++++++++++-- .../root_system/root_lattice_realizations.py | 4 +- 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/sage/combinat/crystals/mv_polytopes.py b/src/sage/combinat/crystals/mv_polytopes.py index b34da6a0704..cf76bdfc3cb 100644 --- a/src/sage/combinat/crystals/mv_polytopes.py +++ b/src/sage/combinat/crystals/mv_polytopes.py @@ -23,6 +23,27 @@ class MVPolytope(PBWCrystalElement): """ A Mirković-Vilonen (MV) polytope. + + EXAMPLES: + + We can create an animation showing how the MV polytope changes + under a string of crystal operators:: + + sage: MV = crystals.infinity.MVPolytopes(['C', 2]) + sage: u = MV.highest_weight_vector() + sage: L = RootSystem(['C',2,1]).ambient_space() + sage: s = [1,2,1,2,2,2,1,1,1,1,2,1,2,2,1,2] + sage: BB = [[-9, 2], [-10, 2]] + sage: p = L.plot(reflection_hyperplanes=False, bounding_box=BB) # long time + sage: frames = [p + L.plot_mv_polytope(u.f_string(s[:i]), # long time + ....: circle_size=0.1, + ....: wireframe='green', + ....: fill='purple', + ....: bounding_box=BB) + ....: for i in range(len(s))] + sage: for f in frames: # long time + ....: f.axes(False) + sage: animate(frames).show(delay=60) # optional -- ImageMagick # long time """ def _repr_(self): """ @@ -185,17 +206,21 @@ def plot(self, P=None, **options): EXAMPLES:: sage: MV = crystals.infinity.MVPolytopes(['C', 2]) - sage: b = MV.module_generators[0].f_string([1,2,1,2]) + sage: b = MV.highest_weight_vector().f_string([1,2,1,2,2,2,1,1,1,1,2,1]) sage: b.plot() - Graphics object consisting of 10 graphics primitives + Graphics object consisting of 12 graphics primitives + + Here is the above example placed inside the ambient space + of type `C_2`:: .. PLOT:: :width: 300 px MV = crystals.infinity.MVPolytopes(['C', 2]) - b = MV.module_generators[0].f_string([1,2,1,2]) + b = MV.highest_weight_vector().f_string([1,2,1,2,2,2,1,1,1,1,2,1]) L = RootSystem(['C', 2, 1]).ambient_space() - p = L.plot(reflection_hyperplanes=False) + b.plot() + p = L.plot(reflection_hyperplanes=False, bounding_box=[[-8,2], [-8,2]]) + p += b.plot() p.axes(False) sphinx_plot(p) """ @@ -204,6 +229,13 @@ def plot(self, P=None, **options): return P.plot_mv_polytope(self, **options) class MVPolytopes(PBWCrystal): + """ + The crystal of Mirković-Vilonen (MV) polytopes. + + INPUT: + + - ``cartan_type`` -- a Cartan type + """ def __init__(self, cartan_type): """ Initialize ``self``. diff --git a/src/sage/combinat/root_system/root_lattice_realizations.py b/src/sage/combinat/root_system/root_lattice_realizations.py index ab19ab4fc28..8267ef8a6ec 100644 --- a/src/sage/combinat/root_system/root_lattice_realizations.py +++ b/src/sage/combinat/root_system/root_lattice_realizations.py @@ -3041,9 +3041,9 @@ def plot_mv_polytope(self, mv_polytope, mark_endpoints=True, - ``circle_size`` -- (default: 0.06) the size of the circles - ``circle_thickness`` -- (default: 1.6) the thinkness of the extra rings of circles - - ``wireframe`` -- (default=``'blue'``) color to draw the + - ``wireframe`` -- (default: ``'blue'``) color to draw the wireframe of the polytope with - - ``fill`` -- (default=``'green'``) color to fill the polytope with + - ``fill`` -- (default: ``'green'``) color to fill the polytope with - ``alpha`` -- (default: 1) the alpha value (opacity) of the fill - ``**options`` -- plotting options From 0b24161ae121cc0a8dd1a73321be1553f1c9da46 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 25 Feb 2016 23:21:44 -0600 Subject: [PATCH 043/452] Full doctest coverage. --- .../crystals/braid_move_calculator.py | 61 ++++++++++++++++--- src/sage/combinat/crystals/pbw_datum.py | 59 +++++++++++++++++- 2 files changed, 109 insertions(+), 11 deletions(-) diff --git a/src/sage/combinat/crystals/braid_move_calculator.py b/src/sage/combinat/crystals/braid_move_calculator.py index 00aa517e18e..96c5d88277a 100644 --- a/src/sage/combinat/crystals/braid_move_calculator.py +++ b/src/sage/combinat/crystals/braid_move_calculator.py @@ -1,12 +1,6 @@ """ Braid Move Calculator -EXAMPLES:: - - sage: W = CoxeterGroup(['A',5]) - sage: load('BraidMoveCalculator.sage'); B = BraidMoveCalculator(W) - sage: view(B.chain_of_reduced_words((1,2,1,3,2,1,4,3,2,1,5,4,3,2,1),(5,4,5,3,4,5,2,3,4,5,1,2,3,4,5))) - AUTHORS: - Dinakar Muthiah (2014-06-03): initial version @@ -31,11 +25,32 @@ class BraidMoveCalculator(object): def __init__(self, coxeter_group): """ Initialize ``self``. + + EXAMPLES:: + + sage: from sage.combinat.crystals.braid_move_calculator import BraidMoveCalculator + sage: W = CoxeterGroup(['C',3]) + sage: B = BraidMoveCalculator(W) + sage: TestSuite(B).run(skip="_test_pickling") """ self.coxeter_group = coxeter_group self.coxeter_matrix = coxeter_group.coxeter_matrix() def _apply_put_in_front_recur_step(self, k, input_word, coxeter_matrix_entry): + """ + Recurrence step for :meth:`put_in_front`. + + EXAMPLES:: + + sage: from sage.combinat.crystals.braid_move_calculator import BraidMoveCalculator + sage: W = CoxeterGroup(['C',3]) + sage: B = BraidMoveCalculator(W) + sage: B.put_in_front(2, (3, 2, 3, 1, 2, 3, 1, 2, 1)) # indirect doctest + ((3, 2, 3, 1, 2, 3, 1, 2, 1), + (3, 2, 3, 1, 2, 1, 3, 2, 1), + (3, 2, 3, 2, 1, 2, 3, 2, 1), + (2, 3, 2, 3, 1, 2, 3, 2, 1)) + """ i = input_word[0] def partial_braid_word(length, swap=False, i=i, k=k): if swap: @@ -64,9 +79,29 @@ def partial_braid_word(length, swap=False, i=i, k=k): def put_in_front(self, k, input_word): """ - Return a list of reduced words beginning with - ``input_word`` and ending with a reduced word whose first letter - is ``k``. There still remains an issue with 0 indices. + Return a list of reduced words starting with ``input_word`` + and ending with a reduced word whose first letter is ``k``. + There still remains an issue with 0 indices. + + EXAMPLES:: + + sage: from sage.combinat.crystals.braid_move_calculator import BraidMoveCalculator + sage: W = CoxeterGroup(['C',3]) + sage: B = BraidMoveCalculator(W) + sage: B.put_in_front(2, (3, 2, 3, 1, 2, 3, 1, 2, 1)) + ((3, 2, 3, 1, 2, 3, 1, 2, 1), + (3, 2, 3, 1, 2, 1, 3, 2, 1), + (3, 2, 3, 2, 1, 2, 3, 2, 1), + (2, 3, 2, 3, 1, 2, 3, 2, 1)) + sage: B.put_in_front(1, (3, 2, 3, 1, 2, 3, 1, 2, 1)) + ((3, 2, 3, 1, 2, 3, 1, 2, 1), + (3, 2, 1, 3, 2, 3, 1, 2, 1), + (3, 2, 1, 3, 2, 3, 2, 1, 2), + (3, 2, 1, 2, 3, 2, 3, 1, 2), + (3, 1, 2, 1, 3, 2, 3, 1, 2), + (1, 3, 2, 1, 3, 2, 3, 1, 2)) + sage: B.put_in_front(1, (1, 3, 2, 3, 2, 1, 2, 3, 2)) + ((1, 3, 2, 3, 2, 1, 2, 3, 2),) """ i = input_word[0] if i == 0 or k == 0: # Is this for affine types? - Travis @@ -84,6 +119,14 @@ def chain_of_reduced_words(self, start_word, end_word): - ``start_word``, ``end_word`` -- two reduced expressions for the long word + + EXAMPLES:: + + sage: from sage.combinat.crystals.braid_move_calculator import BraidMoveCalculator + sage: W = CoxeterGroup(['A',5]) + sage: B = BraidMoveCalculator(W) + sage: B.chain_of_reduced_words((1,2,1,3,2,1,4,3,2,1,5,4,3,2,1), # not tested + ....: (5,4,5,3,4,5,2,3,4,5,1,2,3,4,5)) """ if start_word == end_word: return (start_word,) diff --git a/src/sage/combinat/crystals/pbw_datum.py b/src/sage/combinat/crystals/pbw_datum.py index a3c76bf4ee7..63a18ef0c2e 100644 --- a/src/sage/combinat/crystals/pbw_datum.py +++ b/src/sage/combinat/crystals/pbw_datum.py @@ -27,9 +27,19 @@ from sage.combinat.crystals.braid_move_calculator import BraidMoveCalculator class PBWDatum(object): + """ + Helper class which represents a PBW datum. + """ def __init__(self, parent, long_word, lusztig_datum): """ Initialize ``self``. + + EXAMPLES:: + + sage: from sage.combinat.crystals.pbw_datum import PBWData, PBWDatum + sage: P = PBWData("A2") + sage: L = PBWDatum(P, (1,2,1), (1,4,7)) + sage: TestSuite(L).run(skip="_test_pickling") """ self.parent = parent self.long_word = tuple(long_word) @@ -38,6 +48,14 @@ def __init__(self, parent, long_word, lusztig_datum): def __repr__(self): """ Return a string representation of ``self``. + + EXAMPLES:: + + sage: from sage.combinat.crystals.pbw_datum import PBWData, PBWDatum + sage: P = PBWData("A2") + sage: PBWDatum(P, (1,2,1), (1,4,7)) + PBW Datum element of type ['A', 2] with long word (1, 2, 1) + and Lusztig datum (1, 4, 7) """ return_str = "PBW Datum element of type {cartan_type} with ".format( cartan_type=self.parent.cartan_type) @@ -88,6 +106,21 @@ def convert_to_long_word_with_first_letter(self, i): r""" Return a new PBWDatum equivalent to ``self`` whose long word begins with ``i``. + + EXAMPLES:: + + sage: from sage.combinat.crystals.pbw_datum import PBWData, PBWDatum + sage: P = PBWData("A3") + sage: datum = PBWDatum(P, (1,2,1,3,2,1), (1,0,1,4,2,3)) + sage: datum.convert_to_long_word_with_first_letter(1) + PBW Datum element of type ['A', 3] with long word (1, 2, 3, 1, 2, 1) + and Lusztig datum (1, 0, 4, 1, 2, 3) + sage: datum.convert_to_long_word_with_first_letter(2) + PBW Datum element of type ['A', 3] with long word (2, 1, 2, 3, 2, 1) + and Lusztig datum (0, 1, 0, 4, 2, 3) + sage: datum.convert_to_long_word_with_first_letter(3) + PBW Datum element of type ['A', 3] with long word (3, 1, 2, 3, 1, 2) + and Lusztig datum (8, 1, 0, 4, 1, 2) """ return self.convert_to_new_long_word(self.parent._long_word_begin_with(i)) @@ -101,7 +134,7 @@ def convert_to_new_long_word(self, new_long_word): sage: from sage.combinat.crystals.pbw_datum import PBWData, PBWDatum sage: P = PBWData("A2") sage: datum = PBWDatum(P, (1,2,1), (1,0,1)) - sage: new_datum = P.convert_to_new_long_word(datum, (2,1,2)) + sage: new_datum = datum.convert_to_new_long_word((2,1,2)) sage: new_datum.long_word (2, 1, 2) sage: new_datum.lusztig_datum @@ -151,6 +184,12 @@ class PBWData(object): # UniqueRepresentation? def __init__(self, cartan_type): """ Initialize ``self``. + + EXAMPLES:: + + sage: from sage.combinat.crystals.pbw_datum import PBWData + sage: P = PBWData(["A",2]) + sage: TestSuite(P).run(skip="_test_pickling") """ self.cartan_type = CartanType(cartan_type) self.root_system = RootSystem(self.cartan_type) @@ -217,6 +256,17 @@ def _root_list_from(self, reduced_word): def _long_word_begin_with(self, i): """ Return a reduced expression of the long word which begins with ``i``. + + EXAMPLES:: + + sage: from sage.combinat.crystals.pbw_datum import PBWData + sage: P = PBWData(["C",3]) + sage: P._long_word_begin_with(1) + (1, 3, 2, 3, 1, 2, 3, 1, 2) + sage: P._long_word_begin_with(2) + (2, 3, 2, 3, 1, 2, 3, 2, 1) + sage: P._long_word_begin_with(3) + (3, 2, 3, 1, 2, 3, 1, 2, 1) """ si = self.weyl_group.simple_reflection(i) w0 = self.weyl_group.long_element() @@ -279,7 +329,12 @@ def tropical_plucker_relation(a, lusztig_datum): sage: from sage.combinat.crystals.pbw_datum import tropical_plucker_relation sage: tropical_plucker_relation((0,0), (2,3)) (3, 2) - # Add more doctests + sage: tropical_plucker_relation((-1,-1), (1,2,3)) + (4, 1, 2) + sage: tropical_plucker_relation((-1,-2), (1,2,3,4)) + (8, 1, 2, 3) + sage: tropical_plucker_relation((-2,-1), (1,2,3,4)) + (6, 1, 2, 3) """ n = lusztig_datum if a == (0, 0): # A1xA1 From 9db23dea0bd39693ad444cd164fd8842ef98b50a Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Mon, 29 Feb 2016 09:30:27 +0100 Subject: [PATCH 044/452] package version / checksum --- build/pkgs/pynac/checksums.ini | 6 +++--- build/pkgs/pynac/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/pynac/checksums.ini b/build/pkgs/pynac/checksums.ini index 4b4253e8b07..77e4c191651 100644 --- a/build/pkgs/pynac/checksums.ini +++ b/build/pkgs/pynac/checksums.ini @@ -1,4 +1,4 @@ tarball=pynac-VERSION.tar.bz2 -sha1=fe11b0fe2345eb16b3988077707d86c1b8fa0fd3 -md5=71edb1a2fb003b6c16abda4a0d73c3cf -cksum=1406756294 +sha1=bf92bb96fe78a8933248c8e5f71f482c17a8e88c +md5=a13b1ab28ddb0ee65b01a65a7eb33ec4 +cksum=3434973278 diff --git a/build/pkgs/pynac/package-version.txt b/build/pkgs/pynac/package-version.txt index b6160487433..844f6a91acb 100644 --- a/build/pkgs/pynac/package-version.txt +++ b/build/pkgs/pynac/package-version.txt @@ -1 +1 @@ -0.6.2 +0.6.3 From 7785109f7a21e04e3759a144dfbc2bc18dd611aa Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Mon, 29 Feb 2016 09:32:03 +0100 Subject: [PATCH 045/452] coth/acoth BuiltinFunction --> GinacFunction and fixes --- src/sage/functions/hyperbolic.py | 90 ++++++++++---------------------- 1 file changed, 29 insertions(+), 61 deletions(-) diff --git a/src/sage/functions/hyperbolic.py b/src/sage/functions/hyperbolic.py index 575e4e2fae2..9380f8bda10 100644 --- a/src/sage/functions/hyperbolic.py +++ b/src/sage/functions/hyperbolic.py @@ -195,7 +195,7 @@ def __init__(self): tanh = Function_tanh() -class Function_coth(HyperbolicFunction): +class Function_coth(GinacFunction): def __init__(self): r""" The hyperbolic cotangent function. @@ -204,45 +204,33 @@ def __init__(self): sage: coth(pi) coth(pi) - sage: coth(3.1415) - 1.00374256795520 - sage: float(coth(pi)) - 1.0037418731973213 - sage: RR(coth(pi)) - 1.00374187319732 - - sage: latex(coth(x)) - \coth\left(x\right) - """ - HyperbolicFunction.__init__(self, "coth", latex_name=r"\coth", - evalf_float=lambda x: 1/math.tanh(x)) - - def _eval_(self, x): - """ - EXAMPLES:: - sage: coth(0) - +Infinity + Infinity sage: coth(pi*I) - +Infinity + Infinity sage: coth(pi*I/2) 0 sage: coth(7*pi*I/2) 0 sage: coth(8*pi*I/2) - +Infinity + Infinity sage: coth(7.*pi*I/2) - coth(3.50000000000000*I*pi) + -I*cot(3.50000000000000*pi) + sage: coth(3.1415) + 1.00374256795520 + sage: float(coth(pi)) + 1.0037418731973213 + sage: RR(coth(pi)) + 1.00374187319732 + + sage: bool(diff(coth(x), x) == diff(1/tanh(x), x)) + True + sage: diff(coth(x), x) + -1/sinh(x)^2 + sage: latex(coth(x)) + \operatorname{coth}\left(x\right) """ - if x.is_zero(): - return Infinity - if isinstance(x, Expression): - y = 2 * x / pi / I - if y.is_integer(): - if ZZ(y) % 2 == 1: - return 0 - else: - return Infinity + GinacFunction.__init__(self, "coth", latex_name=r"\operatorname{coth}") def _eval_numpy_(self, x): """ @@ -255,18 +243,6 @@ def _eval_numpy_(self, x): """ return 1 / tanh(x) - def _derivative_(self, *args, **kwds): - """ - EXAMPLES:: - - sage: bool(diff(coth(x), x) == diff(1/tanh(x), x)) - True - sage: diff(coth(x), x) - -csch(x)^2 - """ - x = args[0] - return -csch(x)**2 - coth = Function_coth() @@ -617,7 +593,7 @@ def __init__(self): arctanh = atanh = Function_arctanh() -class Function_arccoth(HyperbolicFunction): +class Function_arccoth(GinacFunction): def __init__(self): r""" The inverse of the hyperbolic cotangent function. @@ -633,6 +609,11 @@ def __init__(self): sage: arccoth(2).n(200) 0.54930614433405484569762261846126285232374527891137472586735 + sage: bool(diff(acoth(x), x) == diff(atanh(x), x)) + True + sage: diff(acoth(x), x) + -1/(x^2 - 1) + Using first the `.n(53)` method is slightly more precise than converting directly to a ``float``:: @@ -646,12 +627,11 @@ def __init__(self): TESTS:: sage: latex(arccoth(x)) - {\rm arccoth}\left(x\right) + \operatorname{arccoth}\left(x\right) """ - HyperbolicFunction.__init__(self, "arccoth", - latex_name=r"{\rm arccoth}", - conversions=dict(maxima='acoth', sympy='acoth'), - evalf_float=lambda x: atanh(float(1/x))) + GinacFunction.__init__(self, "arccoth", + latex_name=r"\operatorname{arccoth}", + conversions=dict(maxima='acoth', sympy='acoth')) def _eval_numpy_(self, x): """ @@ -664,18 +644,6 @@ def _eval_numpy_(self, x): """ return arctanh(1.0 / x) - def _derivative_(self, *args, **kwds): - """ - EXAMPLES:: - - sage: bool(diff(acoth(x), x) == diff(atanh(x), x)) - True - sage: diff(acoth(x), x) - -1/(x^2 - 1) - """ - x = args[0] - return -1/(x**2 - 1) - arccoth = acoth = Function_arccoth() From 2fab819852116989ae3676d1a4ff61ecd4adc9b9 Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Mon, 29 Feb 2016 09:33:43 +0100 Subject: [PATCH 046/452] doctest fixes --- src/sage/functions/special.py | 2 +- src/sage/symbolic/assumptions.py | 6 ------ src/sage/symbolic/expression.pyx | 2 +- src/sage/symbolic/relation.py | 6 +++--- 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/src/sage/functions/special.py b/src/sage/functions/special.py index 829b090cb6c..66c6236eea6 100644 --- a/src/sage/functions/special.py +++ b/src/sage/functions/special.py @@ -366,7 +366,7 @@ def _eval_(self, *args): Here arccoth doesn't have 1 in its domain, so we just hold the expression: - sage: elliptic_e(arccoth(1), x^2*e) + sage: elliptic_e(arccoth(1, hold=True), x^2*e) elliptic_e(arccoth(1), x^2*e) Since Maxima works only with double precision, numerical diff --git a/src/sage/symbolic/assumptions.py b/src/sage/symbolic/assumptions.py index 5b2ef9d6cb2..416323905d9 100644 --- a/src/sage/symbolic/assumptions.py +++ b/src/sage/symbolic/assumptions.py @@ -79,8 +79,6 @@ class GenericDeclaration(SageObject): sage: decl = GenericDeclaration(x, 'integer') sage: decl.assume() sage: sin(x*pi) - sin(pi*x) - sage: sin(x*pi).simplify() 0 sage: decl.forget() sage: sin(x*pi) @@ -115,8 +113,6 @@ def __init__(self, var, assumption): sage: decl = GenericDeclaration(x, 'integer') sage: decl.assume() sage: sin(x*pi) - sin(pi*x) - sage: sin(x*pi).simplify() 0 sage: decl.forget() sage: sin(x*pi) @@ -425,8 +421,6 @@ def assume(*args): Simplifying certain well-known identities works as well:: sage: sin(n*pi) - sin(pi*n) - sage: sin(n*pi).simplify() 0 sage: forget() sage: sin(n*pi).simplify() diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 156f53c93ae..72345c9fce9 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -3170,7 +3170,7 @@ cdef class Expression(CommutativeRingElement): sage: (-1.0*x)*(1.0/x) -1.00000000000000 sage: sin(1.0*pi) - sin(1.00000000000000*pi) + 0 """ cdef GEx x cdef Expression _right = right diff --git a/src/sage/symbolic/relation.py b/src/sage/symbolic/relation.py index f19d2ef0f3b..b6971329979 100644 --- a/src/sage/symbolic/relation.py +++ b/src/sage/symbolic/relation.py @@ -76,7 +76,7 @@ sage: x = var('x') sage: m = x == 5*x + 1 - sage: n = sin(x) == sin(x+2*pi) + sage: n = sin(x) == sin(x+2*pi, hold=True) sage: m * n x*sin(x) == (5*x + 1)*sin(2*pi + x) sage: m = 2*x == 3*x^2 - 5 @@ -87,11 +87,11 @@ sage: x = var('x') sage: m = x == 5*x + 1 - sage: n = sin(x) == sin(x+2*pi) + sage: n = sin(x) == sin(x+2*pi, hold=True) sage: m/n x/sin(x) == (5*x + 1)/sin(2*pi + x) sage: m = x != 5*x + 1 - sage: n = sin(x) != sin(x+2*pi) + sage: n = sin(x) != sin(x+2*pi, hold=True) sage: m/n x/sin(x) != (5*x + 1)/sin(2*pi + x) From 867bd3d983538fad02a597875f0346ffe6f61296 Mon Sep 17 00:00:00 2001 From: Benjamin Hackl Date: Fri, 4 Mar 2016 00:12:48 +0200 Subject: [PATCH 047/452] doctests for reduction of exp-arguments --- src/sage/functions/log.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/sage/functions/log.py b/src/sage/functions/log.py index f3146eb35d2..737446bc210 100644 --- a/src/sage/functions/log.py +++ b/src/sage/functions/log.py @@ -66,6 +66,15 @@ def __init__(self): sage: exp(7*pi*I/2) -I + For the sake of simplification, the argument is reduced the + period of the complex exponential function, `2\pi i`:: + + sage: k = var('k', domain='integer') + sage: exp(2*k*pi*I) + 1 + sage: exp(log(2) + 2*k*pi*I) + 2 + The precision for the result is deduced from the precision of the input. Convert the input to a higher precision explicitly if a result with higher precision is desired:: From f868e90c6492e4ee0f46fa238a1544eed18f77a8 Mon Sep 17 00:00:00 2001 From: Benjamin Hackl Date: Fri, 4 Mar 2016 00:13:08 +0200 Subject: [PATCH 048/452] doctests for argument reduction of sin, cos, tan --- src/sage/functions/trig.py | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/sage/functions/trig.py b/src/sage/functions/trig.py index 7f5f6ec8fad..fc8323dab53 100644 --- a/src/sage/functions/trig.py +++ b/src/sage/functions/trig.py @@ -32,6 +32,17 @@ def __init__(self): sage: a = sin(0,hold=True); a.simplify() 0 + If possible, the argument is also reduced modulo the + period length `2\pi`, and well-known identities are + directly evaluated:: + + sage: k = var('k', domain='integer') + sage: sin(1 + 2*k*pi) + sin(1) + sage: sin(k*pi) + 0 + + TESTS:: sage: conjugate(sin(x)) @@ -109,6 +120,19 @@ def __init__(self): sage: a = cos(0,hold=True); a.simplify() 1 + If possible, the argument is also reduced modulo the + period length `2\pi`, and well-known identities are + directly evaluated:: + + sage: k = var('k', domain='integer') + sage: cos(1 + 2*k*pi) + cos(1) + sage: cos(k*pi) + (-1)^k + sage: cos(pi/3 + 2*k*pi) + 1/2 + + TESTS:: sage: conjugate(cos(x)) @@ -153,6 +177,16 @@ def __init__(self): sage: a = tan(pi/4,hold=True); a.simplify() 1 + If possible, the argument is also reduced modulo the + period length `\pi`, and well-known identities are + directly evaluated:: + + sage: k = var('k', domain='integer') + sage: tan(1 + 2*k*pi) + tan(1) + sage: tan(k*pi) + 0 + TESTS:: sage: conjugate(tan(x)) From 16045ae2a4f0765a879a78be0aa85f4d7451525c Mon Sep 17 00:00:00 2001 From: Benjamin Hackl Date: Fri, 4 Mar 2016 00:17:54 +0200 Subject: [PATCH 049/452] additional doctest for computation of residues --- src/sage/symbolic/expression.pyx | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 72345c9fce9..75f27501a6d 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -4058,6 +4058,15 @@ cdef class Expression(CommutativeRingElement): sage: zeta(s).residue(s == 1) 1 + We can also compute the residue at more general places, + given that the pole is recognized:: + + sage: k = var('k', domain='integer') + sage: (gamma(1+x)/(1 - exp(-x))).residue(x==2*I*pi*k) + gamma(2*I*pi*k + 1) + sage: csc(x).residue(x==2*pi*k) + 1 + TESTS:: sage: (exp(x)/sin(x)^4).residue(x == 0) From 553f4bd02ba21860755fee20f15fe8ab144f042b Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 5 Apr 2016 17:05:41 -0500 Subject: [PATCH 050/452] Fixing the category for alcove paths. --- src/sage/combinat/crystals/alcove_path.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/crystals/alcove_path.py b/src/sage/combinat/crystals/alcove_path.py index f038f93aabe..a8586dd68f9 100644 --- a/src/sage/combinat/crystals/alcove_path.py +++ b/src/sage/combinat/crystals/alcove_path.py @@ -27,6 +27,7 @@ from sage.structure.unique_representation import UniqueRepresentation from sage.categories.finite_crystals import FiniteCrystals from sage.categories.classical_crystals import ClassicalCrystals +from sage.categories.affine_derived_crystals import AffineDerivedSubalgebraCrystals from sage.graphs.all import DiGraph from sage.combinat.root_system.cartan_type import CartanType from sage.combinat.root_system.root_system import RootSystem @@ -324,11 +325,11 @@ def __init__(self, starting_weight, highest_weight_crystal): if cartan_type.is_finite() and highest_weight_crystal: - Parent.__init__(self, category=ClassicalCrystals() ) + Parent.__init__(self, category=ClassicalCrystals()) self._R = RootsWithHeight(starting_weight) self._finite_cartan_type = True elif cartan_type.is_finite() and not highest_weight_crystal: - Parent.__init__(self, category=FiniteCrystals() ) + Parent.__init__(self, category=AffineDerivedSubalgebraCrystals().Finite()) self._R = RootsWithHeight(starting_weight) self._finite_cartan_type = True self._cartan_type = cartan_type.affine() From c64b35fe2cca4c23e4dbf7976b202d4211d1f55f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 17 Apr 2016 16:41:44 +0200 Subject: [PATCH 051/452] trac #18655 make the doc build --- src/sage/combinat/crystals/mv_polytopes.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/crystals/mv_polytopes.py b/src/sage/combinat/crystals/mv_polytopes.py index cf76bdfc3cb..3e87e3b05d0 100644 --- a/src/sage/combinat/crystals/mv_polytopes.py +++ b/src/sage/combinat/crystals/mv_polytopes.py @@ -211,7 +211,7 @@ def plot(self, P=None, **options): Graphics object consisting of 12 graphics primitives Here is the above example placed inside the ambient space - of type `C_2`:: + of type `C_2`: .. PLOT:: :width: 300 px From ba6a2f2e5e0e21fc58a46a71671f22a5bcd21460 Mon Sep 17 00:00:00 2001 From: Emily Gunawan Date: Fri, 1 Jul 2016 00:31:13 -0700 Subject: [PATCH 052/452] 20915: initial version of plot method. todo: allow base_set to contain things other than natural numbers. also, we should look into using 180 degrees instead of pi radians? --- src/sage/combinat/set_partition.py | 31 ++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index d7c2cae7a6b..ee691419593 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -955,6 +955,37 @@ def arcs(self): arcs.append((p[i], p[i+1])) return arcs + def plot(self, color='black'): + """ + Return a plot of ``self``. + + INPUT: + + - ``color`` -- color of the arcs + + EXAMPLES:: + + sage: P=SetPartition([[1,3,4],[5]]) + sage: print(P.plot().description()) + """ + from sage.plot.graphics import Graphics + from sage.plot.point import point + from sage.plot.text import text + from sage.plot.arc import arc + from sage.functions.other import sqrt + from sage.symbolic.constants import pi + #from sage.plot.circle import circle + #from sage.plot.arrow import arrow + + diag = Graphics() + for i in self.base_set(): + diag += point((i,0),size=30, color='black') + diag += text(i, (i,-0.2), color='black') + for (k,l) in self.arcs(): + diag += arc(((k+l)/2,(k-l)/2),(l-k)/sqrt(2),sector=(pi/4,3*pi/4),color='black') + diag.axes(False) + return diag + class SetPartitions(UniqueRepresentation, Parent): r""" An (unordered) partition of a set `S` is a set of pairwise From 3f5548bac4ab46762ea99f539ff8d1cce1cf514b Mon Sep 17 00:00:00 2001 From: Emily Gunawan Date: Fri, 1 Jul 2016 11:22:28 -0700 Subject: [PATCH 053/452] 20915: turn pos into float instead of int. change variable lower case ell to be j. allow input to be string and float. prepare to take a dictionary of base_set as input but not implemented yet --- src/sage/combinat/set_partition.py | 34 ++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index ee691419593..55a8eae2f2e 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -955,18 +955,25 @@ def arcs(self): arcs.append((p[i], p[i+1])) return arcs - def plot(self, color='black'): + def plot(self, color='black', base_set_dict=None): """ Return a plot of ``self``. INPUT: - ``color`` -- color of the arcs + - ``base_set_dict`` -- dictionary asigning positions to elements of self.base_set() EXAMPLES:: - sage: P=SetPartition([[1,3,4],[5]]) - sage: print(P.plot().description()) + sage: p=SetPartition([[1,3,4],[2,5]]) + sage: print(p.plot().description()) + + sage: p=SetPartition([['a','c'],['b',-1],[20.2]]) + sage: print(p.plot().description()) + + sage: p=SetPartition([['a','c'],['b',-1],[20.2]],{0:'a',1:'b',2:'c',-2.3:-1,5.4:20.2}) + sage: print(p.plot().description()) """ from sage.plot.graphics import Graphics from sage.plot.point import point @@ -974,15 +981,20 @@ def plot(self, color='black'): from sage.plot.arc import arc from sage.functions.other import sqrt from sage.symbolic.constants import pi - #from sage.plot.circle import circle - #from sage.plot.arrow import arrow - + diag = Graphics() - for i in self.base_set(): - diag += point((i,0),size=30, color='black') - diag += text(i, (i,-0.2), color='black') - for (k,l) in self.arcs(): - diag += arc(((k+l)/2,(k-l)/2),(l-k)/sqrt(2),sector=(pi/4,3*pi/4),color='black') + vertices_list=list(self.base_set()) + vertices_list.sort() + vertices_dict = dict() + for pos in range(len(vertices_list)): + vertices_dict[pos]=vertices_list[pos] + + for pos in range(0,len(vertices_list)): + diag += point((pos,0),size=30, color=color) + diag += text(vertices_list[pos], (pos,-0.2), color=color) + for (k,j) in self.arcs(): + pos_k,pos_j=float(vertices_list.index(k)),float(vertices_list.index(j)) + diag += arc(((pos_k+pos_j)/2,(pos_k-pos_j)/2),(pos_j-pos_k)/sqrt(2),sector=(pi/4,3*pi/4),color=color) diag.axes(False) return diag From 397b2a6360404b630745935e12efe3900f62343c Mon Sep 17 00:00:00 2001 From: Emily Gunawan Date: Fri, 1 Jul 2016 12:03:24 -0700 Subject: [PATCH 054/452] 20915: put vertices_dict --- src/sage/combinat/set_partition.py | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index 55a8eae2f2e..b3b2a2627ba 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -962,7 +962,7 @@ def plot(self, color='black', base_set_dict=None): INPUT: - ``color`` -- color of the arcs - - ``base_set_dict`` -- dictionary asigning positions to elements of self.base_set() + - ``base_set_dict`` -- dictionary with keys elements of self.base_set() and values as integer or float EXAMPLES:: @@ -972,7 +972,7 @@ def plot(self, color='black', base_set_dict=None): sage: p=SetPartition([['a','c'],['b',-1],[20.2]]) sage: print(p.plot().description()) - sage: p=SetPartition([['a','c'],['b',-1],[20.2]],{0:'a',1:'b',2:'c',-2.3:-1,5.4:20.2}) + sage: p=SetPartition([['a','c'],['b',-1],[20.2]],{'a':0,'b':1,'c':2,-1:-2.3,20.2:5.4}) sage: print(p.plot().description()) """ from sage.plot.graphics import Graphics @@ -983,17 +983,18 @@ def plot(self, color='black', base_set_dict=None): from sage.symbolic.constants import pi diag = Graphics() - vertices_list=list(self.base_set()) - vertices_list.sort() + sorted_vertices_list=list(self.base_set()) + sorted_vertices_list.sort() vertices_dict = dict() - for pos in range(len(vertices_list)): - vertices_dict[pos]=vertices_list[pos] + for pos in range(len(sorted_vertices_list)): + vertices_dict[sorted_vertices_list[pos]]=pos - for pos in range(0,len(vertices_list)): + for elt in vertices_dict: + pos = vertices_dict[elt] diag += point((pos,0),size=30, color=color) - diag += text(vertices_list[pos], (pos,-0.2), color=color) + diag += text(elt, (pos,-0.1), color=color) for (k,j) in self.arcs(): - pos_k,pos_j=float(vertices_list.index(k)),float(vertices_list.index(j)) + pos_k,pos_j=float(vertices_dict[k]),float(vertices_dict[j]) diag += arc(((pos_k+pos_j)/2,(pos_k-pos_j)/2),(pos_j-pos_k)/sqrt(2),sector=(pi/4,3*pi/4),color=color) diag.axes(False) return diag From 791bba85fab99f9d54fb979c46cca04c8d0663a4 Mon Sep 17 00:00:00 2001 From: Emily Gunawan Date: Fri, 1 Jul 2016 12:25:20 -0700 Subject: [PATCH 055/452] 20915: set base_set_dict input option. currently works if base_set_dict=None --- src/sage/combinat/set_partition.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index b3b2a2627ba..2de963dd4d2 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -972,8 +972,8 @@ def plot(self, color='black', base_set_dict=None): sage: p=SetPartition([['a','c'],['b',-1],[20.2]]) sage: print(p.plot().description()) - sage: p=SetPartition([['a','c'],['b',-1],[20.2]],{'a':0,'b':1,'c':2,-1:-2.3,20.2:5.4}) - sage: print(p.plot().description()) + sage: p=SetPartition([['a','c'],['b',-1],[20.2]]) + sage: print(p.plot(base_set_dict={'a':0,'b':1,'c':2,-1:-2.3,20.2:5.4}).description()) """ from sage.plot.graphics import Graphics from sage.plot.point import point @@ -986,8 +986,12 @@ def plot(self, color='black', base_set_dict=None): sorted_vertices_list=list(self.base_set()) sorted_vertices_list.sort() vertices_dict = dict() - for pos in range(len(sorted_vertices_list)): - vertices_dict[sorted_vertices_list[pos]]=pos + + if base_set_dict: + vertices_dict = base_set_dict + else: + for pos in range(len(sorted_vertices_list)): + vertices_dict[sorted_vertices_list[pos]]=pos for elt in vertices_dict: pos = vertices_dict[elt] @@ -995,7 +999,7 @@ def plot(self, color='black', base_set_dict=None): diag += text(elt, (pos,-0.1), color=color) for (k,j) in self.arcs(): pos_k,pos_j=float(vertices_dict[k]),float(vertices_dict[j]) - diag += arc(((pos_k+pos_j)/2,(pos_k-pos_j)/2),(pos_j-pos_k)/sqrt(2),sector=(pi/4,3*pi/4),color=color) + diag += arc(center=((pos_k+pos_j)/2,(pos_k-pos_j)/2),r1=abs((pos_j-pos_k)/sqrt(2)),sector=(pi/4,3*pi/4),color=color) diag.axes(False) return diag From 8ac8fa2f7e4f240df2a008d0980ec6b6515eb956 Mon Sep 17 00:00:00 2001 From: Vivien Ripoll Date: Fri, 1 Jul 2016 14:17:09 -0700 Subject: [PATCH 056/452] 20915: Added parameter angle (first basic version) --- src/sage/combinat/set_partition.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index 2de963dd4d2..d13c5773547 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -955,12 +955,13 @@ def arcs(self): arcs.append((p[i], p[i+1])) return arcs - def plot(self, color='black', base_set_dict=None): + def plot(self, angle=pi/4, color='black', base_set_dict=None): """ Return a plot of ``self``. INPUT: + - ``angle`` -- the angle at which the arcs start (w.r.t. the horizontal direction) - ``color`` -- color of the arcs - ``base_set_dict`` -- dictionary with keys elements of self.base_set() and values as integer or float @@ -981,6 +982,8 @@ def plot(self, color='black', base_set_dict=None): from sage.plot.arc import arc from sage.functions.other import sqrt from sage.symbolic.constants import pi + from sage.functions.trig import tan + from sage.functions.trig import sin diag = Graphics() sorted_vertices_list=list(self.base_set()) @@ -998,8 +1001,8 @@ def plot(self, color='black', base_set_dict=None): diag += point((pos,0),size=30, color=color) diag += text(elt, (pos,-0.1), color=color) for (k,j) in self.arcs(): - pos_k,pos_j=float(vertices_dict[k]),float(vertices_dict[j]) - diag += arc(center=((pos_k+pos_j)/2,(pos_k-pos_j)/2),r1=abs((pos_j-pos_k)/sqrt(2)),sector=(pi/4,3*pi/4),color=color) + pos_k,pos_j = float(vertices_dict[k]),float(vertices_dict[j]) + diag += arc(center=((pos_k+pos_j)/2,-abs(pos_j-pos_k)/(2*tan(angle)), r1=abs((pos_j-pos_k)/(2*sin(angle)), sector=(pi/2-angle,pi/2+angle),color=color) diag.axes(False) return diag From 27b847d9099a6948ff98ce5070ae21a71f8c108d Mon Sep 17 00:00:00 2001 From: Vivien Ripoll Date: Fri, 1 Jul 2016 14:50:01 -0700 Subject: [PATCH 057/452] Changed the default angle pi/4 to 3.14/4 --- src/sage/combinat/set_partition.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index d13c5773547..b9ccf8c9e25 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -955,7 +955,7 @@ def arcs(self): arcs.append((p[i], p[i+1])) return arcs - def plot(self, angle=pi/4, color='black', base_set_dict=None): + def plot(self, angle=3.14/4, color='black', base_set_dict=None): """ Return a plot of ``self``. From d511ab40ea8a56e17924e8b27a8775b00eb2b80f Mon Sep 17 00:00:00 2001 From: Vivien Ripoll Date: Fri, 1 Jul 2016 15:06:14 -0700 Subject: [PATCH 058/452] corrected syntax error --- src/sage/combinat/set_partition.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index b9ccf8c9e25..b1b7191898f 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -1002,7 +1002,7 @@ def plot(self, angle=3.14/4, color='black', base_set_dict=None): diag += text(elt, (pos,-0.1), color=color) for (k,j) in self.arcs(): pos_k,pos_j = float(vertices_dict[k]),float(vertices_dict[j]) - diag += arc(center=((pos_k+pos_j)/2,-abs(pos_j-pos_k)/(2*tan(angle)), r1=abs((pos_j-pos_k)/(2*sin(angle)), sector=(pi/2-angle,pi/2+angle),color=color) + diag += arc(center=((pos_k+pos_j)/2,-abs(pos_j-pos_k)/(2*tan(angle)), r1=abs((pos_j-pos_k)/(2*sin(angle))), sector=(pi/2-angle,pi/2+angle),color=color) diag.axes(False) return diag From 48382d8b42a464df95b2b35c71f00d44c2758826 Mon Sep 17 00:00:00 2001 From: Vivien Ripoll Date: Fri, 1 Jul 2016 15:07:54 -0700 Subject: [PATCH 059/452] Corrected syntax error 2 --- src/sage/combinat/set_partition.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index b1b7191898f..349860beb37 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -1002,7 +1002,7 @@ def plot(self, angle=3.14/4, color='black', base_set_dict=None): diag += text(elt, (pos,-0.1), color=color) for (k,j) in self.arcs(): pos_k,pos_j = float(vertices_dict[k]),float(vertices_dict[j]) - diag += arc(center=((pos_k+pos_j)/2,-abs(pos_j-pos_k)/(2*tan(angle)), r1=abs((pos_j-pos_k)/(2*sin(angle))), sector=(pi/2-angle,pi/2+angle),color=color) + diag += arc(center=((pos_k+pos_j)/2,-abs(pos_j-pos_k)/(2*tan(angle)), r1=abs((pos_j-pos_k)/(2*sin(angle))), sector=(pi/2-angle,pi/2+angle),color=color)) diag.axes(False) return diag From 926930b0b4f8292a6e13bb50600d8f017c42385a Mon Sep 17 00:00:00 2001 From: Vivien Ripoll Date: Fri, 1 Jul 2016 15:13:51 -0700 Subject: [PATCH 060/452] fixed syntax error 3! --- src/sage/combinat/set_partition.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index 349860beb37..e07e0a96824 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -1002,7 +1002,7 @@ def plot(self, angle=3.14/4, color='black', base_set_dict=None): diag += text(elt, (pos,-0.1), color=color) for (k,j) in self.arcs(): pos_k,pos_j = float(vertices_dict[k]),float(vertices_dict[j]) - diag += arc(center=((pos_k+pos_j)/2,-abs(pos_j-pos_k)/(2*tan(angle)), r1=abs((pos_j-pos_k)/(2*sin(angle))), sector=(pi/2-angle,pi/2+angle),color=color)) + diag += arc(center=((pos_k+pos_j)/2,-abs(pos_j-pos_k)/(2*tan(angle))), r1=abs((pos_j-pos_k)/(2*sin(angle))), sector=(pi/2-angle,pi/2+angle),color=color) diag.axes(False) return diag From c4cb7f329de1c9372ed5da6e5de9a5894df3a653 Mon Sep 17 00:00:00 2001 From: Vivien Ripoll Date: Fri, 1 Jul 2016 15:21:49 -0700 Subject: [PATCH 061/452] 20915: first basic implementation of the angle parameter --- src/sage/combinat/set_partition.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index e07e0a96824..8c386eaa816 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -955,13 +955,13 @@ def arcs(self): arcs.append((p[i], p[i+1])) return arcs - def plot(self, angle=3.14/4, color='black', base_set_dict=None): + def plot(self, angle=pi/4, color='black', base_set_dict=None): """ Return a plot of ``self``. INPUT: - - ``angle`` -- the angle at which the arcs start (w.r.t. the horizontal direction) + - ``angle`` -- the angle at which the arcs start (w.r.t. the horizontal direction); if angle is negative, the arcs are drawn below the horizontal line - ``color`` -- color of the arcs - ``base_set_dict`` -- dictionary with keys elements of self.base_set() and values as integer or float @@ -999,10 +999,11 @@ def plot(self, angle=3.14/4, color='black', base_set_dict=None): for elt in vertices_dict: pos = vertices_dict[elt] diag += point((pos,0),size=30, color=color) - diag += text(elt, (pos,-0.1), color=color) + diag += text(elt, (pos,-sgn(angle)*0.1), color=color) + # TODO: change 0.1 to something proportional to the height of the picture for (k,j) in self.arcs(): pos_k,pos_j = float(vertices_dict[k]),float(vertices_dict[j]) - diag += arc(center=((pos_k+pos_j)/2,-abs(pos_j-pos_k)/(2*tan(angle))), r1=abs((pos_j-pos_k)/(2*sin(angle))), sector=(pi/2-angle,pi/2+angle),color=color) + diag += arc(center=((pos_k+pos_j)/2,-abs(pos_j-pos_k)/(2*tan(angle))), r1=abs((pos_j-pos_k)/(2*sin(angle))), sector=(sgn(angle)*(pi/2-angle),sgn(angle)*(pi/2+angle)),color=color) diag.axes(False) return diag From 5e89b984e0c4234b02b297c3f3620760f73e6a86 Mon Sep 17 00:00:00 2001 From: Vivien Ripoll Date: Fri, 1 Jul 2016 16:03:08 -0700 Subject: [PATCH 062/452] 20915: first implementation of the angle parameter (sorry for the long list of useless commits before this one!) --- src/sage/combinat/set_partition.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index 8c386eaa816..a95f3cd2616 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -955,13 +955,13 @@ def arcs(self): arcs.append((p[i], p[i+1])) return arcs - def plot(self, angle=pi/4, color='black', base_set_dict=None): + def plot(self, angle=None, color='black', base_set_dict=None): """ Return a plot of ``self``. INPUT: - - ``angle`` -- the angle at which the arcs start (w.r.t. the horizontal direction); if angle is negative, the arcs are drawn below the horizontal line + - ``angle`` -- the angle at which the arcs take off (if angle is negative, the arcs are drawn below the horizontal line) - ``color`` -- color of the arcs - ``base_set_dict`` -- dictionary with keys elements of self.base_set() and values as integer or float @@ -984,11 +984,16 @@ def plot(self, angle=pi/4, color='black', base_set_dict=None): from sage.symbolic.constants import pi from sage.functions.trig import tan from sage.functions.trig import sin + from sage.functions.generalized import sgn diag = Graphics() sorted_vertices_list=list(self.base_set()) sorted_vertices_list.sort() vertices_dict = dict() + + if not angle: + angle = pi/4 + # the case angle = 0 should maybe treated separately if base_set_dict: vertices_dict = base_set_dict From 3ebb689e00430e616cf7faf0e1807a3360c81497 Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Fri, 1 Jul 2016 19:18:13 -0400 Subject: [PATCH 063/452] Add cycle and planar latex tikz code --- src/sage/combinat/set_partition.py | 132 ++++++++++++++++++++++++++++- 1 file changed, 131 insertions(+), 1 deletion(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index 2de963dd4d2..519fb4dd8b3 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -46,6 +46,7 @@ from sage.combinat.combinat import bell_number, stirling_number2 from sage.combinat.permutation import Permutation from functools import reduce +from sage.misc.latex import latex class SetPartition(ClonableArray): @@ -138,6 +139,7 @@ def __init__(self, parent, s): sage: SetPartition([]) {} """ + self._latex_options = {} ClonableArray.__init__(self, parent, sorted(map(Set, s), key=min)) def check(self): @@ -408,6 +410,60 @@ def _repr_(self): """ return '{' + ', '.join(('{' + repr(sorted(x))[1:-1] + '}' for x in self)) + '}' + def set_latex_options(self, opts): + r""" + Set the latex options for use in the ``_latex_`` function. The default + values are set in the ``__init__`` function. + + - ``tikz_scale`` -- (default: 1) scale for use with tikz package. + + - ``plot`` -- (default: ``) ```` returns the set notation, ``linear`` + returns a linear plot, ``cyclic`` returns a cyclic plot + + - ``color`` -- (default: black) the arc colors. + + - ``fill`` -- (default: False) If True then fills black, else you can + pass in a color to alter the fill color. *Only works with cyclic plot* + + - ``show_labels`` -- (default: True) If True shows labels - *only works + with plots* + + - ``radius`` -- (default: "1cm") Radius of circle for cyclic plot. *Only + works with cyclic plot* + + INPUT: + + - ``opts`` -- a dictionary with a list of latex parameters to change + + EXAMPLES:: + + """ + + for opt in opts: + self._latex_options[opt] = opts[opt] + def latex_options(self): + r""" + Return the latex options for use in the ``_latex_`` function as a + dictionary. The default values are set using the global options. + + Options can be found in set_latex_options() + + EXAMPLES:: + """ + opts = self._latex_options.copy() + if "tikz_scale" not in opts: + opts["tikz_scale"] = 1 + if "plot" not in opts: + opts["plot"] = '' + if "color" not in opts: + opts['color']= 'black' + if "fill" not in opts: + opts["fill"] = False + if "show_labels" not in opts: + opts['show_labels'] = True + if "radius" not in opts: + opts['radius'] = "1cm" + return opts def _latex_(self): r""" Return a `\LaTeX` string representation of ``self``. @@ -418,7 +474,81 @@ def _latex_(self): sage: latex(x) \{\{1, 2\}, \{3, 4, 5\}\} """ - return repr(self).replace("{",r"\{").replace("}",r"\}") + latex_options = self.latex_options() + if latex_options["plot"] == "": + return repr(self).replace("{",r"\{").replace("}",r"\}") + else: + latex.add_package_to_preamble_if_available("tikz") + res = "\\begin{tikzpicture}[scale="+str(latex_options['tikz_scale'])+"]\n" + + cardinality = self.base_set_cardinality() + base_set = self.base_set().list() + color= latex_options['color'] + + # If we want cyclic plots + if latex_options['plot'] == 'cyclic' or latex_options['plot'] == 'cycle' or latex_options['plot'] == 'circle': + degrees = 360 / cardinality + radius = latex_options['radius'] + + # Add nodes + for k,i in enumerate(base_set): + location = (cardinality - k) * degrees - 270 + res += "\t\\node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black" + if latex_options['show_labels']: + res += ",label=" + str(location) + ":" + str(i) + res += "] (" + str(k) + ") at (" + str(location) + ":" + radius + ") {};\n" + + # Add the circle + for k,i in enumerate(base_set): + xangle = k * degrees + yangle = (k+1) * degrees + res += "\t\\draw[-] (" + str(xangle) + ":" + radius + ")" + res += " arc " + res += "(" + str(xangle) + ":" + str(yangle) + ":" + radius + ");\n" + + # Setup partitions + for partition in self: + res += "\t\t\\draw[-,thick,color="+color + if latex_options['fill'] != False: + if isinstance(latex_options['fill'],str): + res += ",fill="+latex_options['fill'] + else: + res += ",fill={rgb:" + color + ",1;white,10}" + res += "] " + firstDone = False + for j in partition: + if firstDone: + res += " -- (" + str(base_set.index(j)) + ".center)" + else: + firstDone = True + res += "(" + str(base_set.index(j)) + ".center)" + res += " -- cycle;\n" + + # If we want line plots + if latex_options['plot'] == 'linear' or latex_options['plot'] == 'line' or latex_options['plot'] == 'planar': + # setup line + for k,i in enumerate(base_set): + if latex_options['show_labels']: + res += "\t\\node[below=.05cm] at (" + str(k) + ",0) {$" + str(i) + "$};\n" + res += "\t\\node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black] " + res += "(" + str(k) + ") at (" + str(k) + ",0) {};\n" + #res += "\t\\draw (0) -- (" + str(cardinality - 1) + ");\n" + + # setup arcs + for partition in self: + if partition.cardinality() > 1: + for k,i in enumerate(partition.list()): + if k != 0: + #res += "\\draw (" + str(base_set.index(partition[0])) + ")" + #res += " to [out=90,in=90] " + #res += "(" + str(base_set.index(partition[-1])) + ");" + #else: + res += "\t\\draw[color=" + color + "] (" + str(base_set.index(partition[k])) + ")" + res += " to [out=90,in=90] " + res += "(" + str(base_set.index(partition[k-1])) + ");\n" + + res += "\\end{tikzpicture}" + return res cardinality = ClonableArray.__len__ From 6b346a42c77fd16aee0b9ea73df007dbb436ccc5 Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Fri, 1 Jul 2016 20:01:04 -0400 Subject: [PATCH 064/452] Doc tests - there exist 4 failures - to do later --- src/sage/combinat/set_partition.py | 42 ++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index e545854d447..9aaeee8a24e 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -431,12 +431,16 @@ def set_latex_options(self, opts): - ``radius`` -- (default: "1cm") Radius of circle for cyclic plot. *Only works with cyclic plot* + - ``angle`` -- (default: 0) Angle for linear + INPUT: - ``opts`` -- a dictionary with a list of latex parameters to change EXAMPLES:: + sage: SP = SetPartition([[1,6], [3,5,4]]) + sage: SP.set_latex_options({'tikz_scale':2,'plot':'linear', 'fill':True, 'color':'blue', 'angle':45}) """ for opt in opts: @@ -449,6 +453,15 @@ def latex_options(self): Options can be found in set_latex_options() EXAMPLES:: + sage: SP = SetPartition([[1,6], [3,5,4]]); SP.latex_options() + {'angle': 0, + 'color': 'black', + 'fill': False, + 'plot': '', + 'radius': '1cm', + 'show_labels': True, + 'tikz_scale': 1} + """ opts = self._latex_options.copy() if "tikz_scale" not in opts: @@ -463,6 +476,8 @@ def latex_options(self): opts['show_labels'] = True if "radius" not in opts: opts['radius'] = "1cm" + if "angle" not in opts: + opts['angle'] = 0 return opts def _latex_(self): r""" @@ -473,6 +488,16 @@ def _latex_(self): sage: x = SetPartition([[1,2], [3,5,4]]) sage: latex(x) \{\{1, 2\}, \{3, 4, 5\}\} + sage: SP = SetPartition([[1,2]]) + sage: SP.set_latex_options({'tikz_scale':2,'plot':'linear', 'fill':True, 'color':'blue', 'angle':45}) + sage: latex(SP) + \begin{tikzpicture}[scale=2] + \node[below=05cm] at (0,0) {$1$}; + \node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black] (0) at (0,0) {}; + \node[below=.05cm] at (1,0) {$2$}; + \node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black] (1) at (1,0) {}; + \draw[color=blue] (1) to [out=135,in=45] (0); + \end{tikzpicture} """ latex_options = self.latex_options() if latex_options["plot"] == "": @@ -493,7 +518,7 @@ def _latex_(self): # Add nodes for k,i in enumerate(base_set): location = (cardinality - k) * degrees - 270 - res += "\t\\node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black" + res += " \\node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black" if latex_options['show_labels']: res += ",label=" + str(location) + ":" + str(i) res += "] (" + str(k) + ") at (" + str(location) + ":" + radius + ") {};\n" @@ -502,13 +527,13 @@ def _latex_(self): for k,i in enumerate(base_set): xangle = k * degrees yangle = (k+1) * degrees - res += "\t\\draw[-] (" + str(xangle) + ":" + radius + ")" + res += " \\draw[-] (" + str(xangle) + ":" + radius + ")" res += " arc " res += "(" + str(xangle) + ":" + str(yangle) + ":" + radius + ");\n" # Setup partitions for partition in self: - res += "\t\t\\draw[-,thick,color="+color + res += " \\draw[-,thick,color="+color if latex_options['fill'] != False: if isinstance(latex_options['fill'],str): res += ",fill="+latex_options['fill'] @@ -526,11 +551,12 @@ def _latex_(self): # If we want line plots if latex_options['plot'] == 'linear' or latex_options['plot'] == 'line' or latex_options['plot'] == 'planar': + angle = latex_options['angle'] # setup line for k,i in enumerate(base_set): if latex_options['show_labels']: - res += "\t\\node[below=.05cm] at (" + str(k) + ",0) {$" + str(i) + "$};\n" - res += "\t\\node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black] " + res += " \\node[below=.05cm] at (" + str(k) + ",0) {$" + str(i) + "$};\n" + res += " \\node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black] " res += "(" + str(k) + ") at (" + str(k) + ",0) {};\n" #res += "\t\\draw (0) -- (" + str(cardinality - 1) + ");\n" @@ -543,8 +569,8 @@ def _latex_(self): #res += " to [out=90,in=90] " #res += "(" + str(base_set.index(partition[-1])) + ");" #else: - res += "\t\\draw[color=" + color + "] (" + str(base_set.index(partition[k])) + ")" - res += " to [out=90,in=90] " + res += " \\draw[color=" + color + "] (" + str(base_set.index(partition[k])) + ")" + res += " to [out=" + str(90+angle) + ",in=" + str(90-angle) + "] " res += "(" + str(base_set.index(partition[k-1])) + ");\n" res += "\\end{tikzpicture}" @@ -1120,7 +1146,7 @@ def plot(self, angle=None, color='black', base_set_dict=None): sorted_vertices_list=list(self.base_set()) sorted_vertices_list.sort() vertices_dict = dict() - + if not angle: angle = pi/4 # the case angle = 0 should maybe treated separately From eaeb0119e9c3a923d43cc713764dc41c4ad61c9a Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Sat, 2 Jul 2016 11:58:01 -0400 Subject: [PATCH 065/452] Fix doc tests and add circular to plot types for latex --- src/sage/combinat/set_partition.py | 79 +++++++++++++++++++++++------- 1 file changed, 62 insertions(+), 17 deletions(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index 9aaeee8a24e..7b811238bc8 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -488,16 +488,25 @@ def _latex_(self): sage: x = SetPartition([[1,2], [3,5,4]]) sage: latex(x) \{\{1, 2\}, \{3, 4, 5\}\} - sage: SP = SetPartition([[1,2]]) - sage: SP.set_latex_options({'tikz_scale':2,'plot':'linear', 'fill':True, 'color':'blue', 'angle':45}) - sage: latex(SP) + sage: p=SetPartition([['a','c'],['b',1],[20]]) + sage: p.set_latex_options({'plot':'circle', 'color':'blue', 'angle':45, 'fill':True, 'tikz_scale':2}) + sage: latex(p) \begin{tikzpicture}[scale=2] - \node[below=05cm] at (0,0) {$1$}; - \node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black] (0) at (0,0) {}; - \node[below=.05cm] at (1,0) {$2$}; - \node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black] (1) at (1,0) {}; - \draw[color=blue] (1) to [out=135,in=45] (0); + \node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black,label=90:a] (0) at (90:1cm) {}; + \node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black,label=18:1] (1) at (18:1cm) {}; + \node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black,label=-54:c] (2) at (-54:1cm) {}; + \node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black,label=-126:b] (3) at (-126:1cm) {}; + \node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black,label=-198:20] (4) at (-198:1cm) {}; + \draw[-] (0:1cm) arc (0:72:1cm); + \draw[-] (72:1cm) arc (72:144:1cm); + \draw[-] (144:1cm) arc (144:216:1cm); + \draw[-] (216:1cm) arc (216:288:1cm); + \draw[-] (288:1cm) arc (288:360:1cm); + \draw[-,thick,color=blue,fill={rgb:blue,1;white,10}] (1.center) -- (3.center) -- cycle; + \draw[-,thick,color=blue,fill={rgb:blue,1;white,10}] (4.center) -- cycle; + \draw[-,thick,color=blue,fill={rgb:blue,1;white,10}] (0.center) -- (2.center) -- cycle; \end{tikzpicture} + """ latex_options = self.latex_options() if latex_options["plot"] == "": @@ -511,14 +520,14 @@ def _latex_(self): color= latex_options['color'] # If we want cyclic plots - if latex_options['plot'] == 'cyclic' or latex_options['plot'] == 'cycle' or latex_options['plot'] == 'circle': + if latex_options['plot'] == 'cyclic' or latex_options['plot'] == 'cycle' or latex_options['plot'] == 'circle' or latex_options['plot'] == 'circular': degrees = 360 / cardinality radius = latex_options['radius'] # Add nodes for k,i in enumerate(base_set): location = (cardinality - k) * degrees - 270 - res += " \\node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black" + res += "\\node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black" if latex_options['show_labels']: res += ",label=" + str(location) + ":" + str(i) res += "] (" + str(k) + ") at (" + str(location) + ":" + radius + ") {};\n" @@ -527,13 +536,13 @@ def _latex_(self): for k,i in enumerate(base_set): xangle = k * degrees yangle = (k+1) * degrees - res += " \\draw[-] (" + str(xangle) + ":" + radius + ")" + res += "\\draw[-] (" + str(xangle) + ":" + radius + ")" res += " arc " res += "(" + str(xangle) + ":" + str(yangle) + ":" + radius + ");\n" # Setup partitions for partition in self: - res += " \\draw[-,thick,color="+color + res += "\\draw[-,thick,color="+color if latex_options['fill'] != False: if isinstance(latex_options['fill'],str): res += ",fill="+latex_options['fill'] @@ -555,8 +564,8 @@ def _latex_(self): # setup line for k,i in enumerate(base_set): if latex_options['show_labels']: - res += " \\node[below=.05cm] at (" + str(k) + ",0) {$" + str(i) + "$};\n" - res += " \\node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black] " + res += "\\node[below=.05cm] at (" + str(k) + ",0) {$" + str(i) + "$};\n" + res += "\\node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black] " res += "(" + str(k) + ") at (" + str(k) + ",0) {};\n" #res += "\t\\draw (0) -- (" + str(cardinality - 1) + ");\n" @@ -569,7 +578,7 @@ def _latex_(self): #res += " to [out=90,in=90] " #res += "(" + str(base_set.index(partition[-1])) + ");" #else: - res += " \\draw[color=" + color + "] (" + str(base_set.index(partition[k])) + ")" + res += "\\draw[color=" + color + "] (" + str(base_set.index(partition[k])) + ")" res += " to [out=" + str(90+angle) + ",in=" + str(90-angle) + "] " res += "(" + str(base_set.index(partition[k-1])) + ");\n" @@ -1125,12 +1134,48 @@ def plot(self, angle=None, color='black', base_set_dict=None): sage: p=SetPartition([[1,3,4],[2,5]]) sage: print(p.plot().description()) - + Point set defined by 1 point(s): [(0.0, 0.0)] + Point set defined by 1 point(s): [(1.0, 0.0)] + Point set defined by 1 point(s): [(2.0, 0.0)] + Point set defined by 1 point(s): [(3.0, 0.0)] + Point set defined by 1 point(s): [(4.0, 0.0)] + Text '1' at the point (0.0,-0.1) + Text '2' at the point (1.0,-0.1) + Text '3' at the point (2.0,-0.1) + Text '4' at the point (3.0,-0.1) + Text '5' at the point (4.0,-0.1) + Arc with center (1.0,-1.0) radii (1.41421356237,1.41421356237) angle 0.0 inside the sector (0.785398163397,2.35619449019) + Arc with center (2.5,-0.5) radii (0.707106781187,0.707106781187) angle 0.0 inside the sector (0.785398163397,2.35619449019) + Arc with center (2.5,-1.5) radii (2.12132034356,2.12132034356) angle 0.0 inside the sector (0.785398163397,2.35619449019) sage: p=SetPartition([['a','c'],['b',-1],[20.2]]) sage: print(p.plot().description()) - + Point set defined by 1 point(s): [(0.0, 0.0)] + Point set defined by 1 point(s): [(1.0, 0.0)] + Point set defined by 1 point(s): [(2.0, 0.0)] + Point set defined by 1 point(s): [(3.0, 0.0)] + Point set defined by 1 point(s): [(4.0, 0.0)] + Text '-1' at the point (0.0,-0.1) + Text '20.2000000000000' at the point (1.0,-0.1) + Text 'a' at the point (2.0,-0.1) + Text 'b' at the point (3.0,-0.1) + Text 'c' at the point (4.0,-0.1) + Arc with center (1.5,-1.5) radii (2.12132034356,2.12132034356) angle 0.0 inside the sector (0.785398163397,2.35619449019) + Arc with center (3.0,-1.0) radii (1.41421356237,1.41421356237) angle 0.0 inside the sector (0.785398163397,2.35619449019) sage: p=SetPartition([['a','c'],['b',-1],[20.2]]) sage: print(p.plot(base_set_dict={'a':0,'b':1,'c':2,-1:-2.3,20.2:5.4}).description()) + Point set defined by 1 point(s): [(-2.3, 0.0)] + Point set defined by 1 point(s): [(0.0, 0.0)] + Point set defined by 1 point(s): [(1.0, 0.0)] + Point set defined by 1 point(s): [(2.0, 0.0)] + Point set defined by 1 point(s): [(5.4, 0.0)] + Text '-1' at the point (-2.3,-0.1) + Text '20.2000000000000' at the point (5.4,-0.1) + Text 'a' at the point (0.0,-0.1) + Text 'b' at the point (1.0,-0.1) + Text 'c' at the point (2.0,-0.1) + Arc with center (-0.65,-1.65) radii (2.33345237792,2.33345237792) angle 0.0 inside the sector (0.785398163397,2.35619449019) + Arc with center (1.0,-1.0) radii (1.41421356237,1.41421356237) angle 0.0 inside the sector (0.785398163397,2.35619449019) + """ from sage.plot.graphics import Graphics from sage.plot.point import point From 4e35a31a6a77c8dd2534b75aa7c56107dccd6177 Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Sat, 2 Jul 2016 13:45:16 -0400 Subject: [PATCH 066/452] Add error message if it's a plot type we don't know --- src/sage/combinat/set_partition.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index 7b811238bc8..0d59b5414b6 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -581,6 +581,8 @@ def _latex_(self): res += "\\draw[color=" + color + "] (" + str(base_set.index(partition[k])) + ")" res += " to [out=" + str(90+angle) + ",in=" + str(90-angle) + "] " res += "(" + str(base_set.index(partition[k-1])) + ");\n" + else: + raise ValueError("plot must be blank, 'cyclic', or 'linear'") res += "\\end{tikzpicture}" return res From 526cc78d4e04219c0c33d642c1ce8f5eade92b95 Mon Sep 17 00:00:00 2001 From: Andrey Novoseltsev Date: Wed, 20 Jul 2016 19:15:40 -0600 Subject: [PATCH 067/452] Add two unpickle overrides for backward compatibility. --- src/sage/rings/finite_rings/finite_field_base.pyx | 4 ++++ src/sage/rings/finite_rings/finite_field_prime_modn.py | 9 +++++++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/finite_rings/finite_field_base.pyx b/src/sage/rings/finite_rings/finite_field_base.pyx index 4abc6b6a6c1..59c63e89d06 100644 --- a/src/sage/rings/finite_rings/finite_field_base.pyx +++ b/src/sage/rings/finite_rings/finite_field_base.pyx @@ -32,6 +32,7 @@ AUTHORS: from sage.categories.finite_fields import FiniteFields from sage.structure.parent cimport Parent +from sage.structure.sage_object import register_unpickle_override from sage.misc.cachefunc import cached_method from sage.misc.prandom import randrange @@ -1571,6 +1572,9 @@ def unpickle_FiniteField_prm(_type, order, variable_name, kwargs): """ return _type(order, variable_name, **kwargs) +register_unpickle_override( + 'sage.rings.ring', 'unpickle_FiniteField_prm', unpickle_FiniteField_prm) + def is_FiniteField(x): """ diff --git a/src/sage/rings/finite_rings/finite_field_prime_modn.py b/src/sage/rings/finite_rings/finite_field_prime_modn.py index d1cd765448c..c6183de81a7 100644 --- a/src/sage/rings/finite_rings/finite_field_prime_modn.py +++ b/src/sage/rings/finite_rings/finite_field_prime_modn.py @@ -35,8 +35,9 @@ from sage.rings.integer_ring import ZZ from sage.rings.finite_rings.integer_mod_ring import IntegerModRing_generic -import sage.structure.factorization as factorization -from sage.structure.parent import Parent + +from sage.structure.sage_object import register_unpickle_override + class FiniteField_prime_modn(FiniteField_generic, integer_mod_ring.IntegerModRing_generic): r""" @@ -297,3 +298,7 @@ def degree(self): 1 """ return Integer(1) + +register_unpickle_override( + 'sage.rings.finite_field_prime_modn', 'FiniteField_prime_modn', + FiniteField_prime_modn) From 64cf0c655098e3fdb8dcf84db15e0b5f9b884a30 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Mon, 25 Jul 2016 22:16:30 -0500 Subject: [PATCH 068/452] Adding __future__ imports to make sure the new file is Python3 compatible. --- src/sage/categories/affine_derived_crystals.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sage/categories/affine_derived_crystals.py b/src/sage/categories/affine_derived_crystals.py index 32854f1e3fa..eec2316acb2 100644 --- a/src/sage/categories/affine_derived_crystals.py +++ b/src/sage/categories/affine_derived_crystals.py @@ -8,6 +8,8 @@ # http://www.gnu.org/licenses/ #****************************************************************************** +from __future__ import print_function, division, absolute_import + from sage.misc.abstract_method import abstract_method from sage.misc.cachefunc import cached_method from sage.categories.category_singleton import Category_singleton From 10630d53a00ade831ee6b62c3d33b6ea9809a027 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 27 Jul 2016 11:00:45 -0500 Subject: [PATCH 069/452] Adding back in test for 1D config sum. --- src/sage/categories/affine_derived_crystals.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/sage/categories/affine_derived_crystals.py b/src/sage/categories/affine_derived_crystals.py index a8d30eb4f63..28d8939d395 100644 --- a/src/sage/categories/affine_derived_crystals.py +++ b/src/sage/categories/affine_derived_crystals.py @@ -797,6 +797,13 @@ def one_dimensional_configuration_sum(self, q=None, group_components=True): sage: T = crystals.TensorProduct(K1,K2) sage: T.one_dimensional_configuration_sum() == T.one_dimensional_configuration_sum(group_components=False) True + + sage: RC = RiggedConfigurations(['A',3,1],[[1,1],[1,2]]) + sage: B = crystals.KirillovReshetikhin(['A',3,1],1,1) + sage: B1 = crystals.KirillovReshetikhin(['A',3,1],1,2) + sage: T = crystals.TensorProduct(B,B1) + sage: RC.fermionic_formula() == T.one_dimensional_configuration_sum() + True """ if q is None: from sage.rings.all import QQ From 95d58376288d4343db27c21197e81c138abc7571 Mon Sep 17 00:00:00 2001 From: Daniel Krenn Date: Sat, 6 Aug 2016 11:10:45 +0200 Subject: [PATCH 070/452] Trac #21180: allow keyword arguments in cantor_product --- src/sage/misc/mrange.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/sage/misc/mrange.py b/src/sage/misc/mrange.py index 3e0abc3f647..d7b6ee96cba 100644 --- a/src/sage/misc/mrange.py +++ b/src/sage/misc/mrange.py @@ -621,6 +621,9 @@ def cantor_product(*args, **kwds): - ``repeat`` -- an optional integer. If it is provided, the input is repeated ``repeat`` times. + Other keyword arguments are passed to + :class:`sage.combinat.integer_lists.invlex.IntegerListsLex`. + EXAMPLES:: sage: from sage.misc.mrange import cantor_product @@ -677,7 +680,13 @@ def cantor_product(*args, **kwds): sage: next(cantor_product(count(), toto='hey')) Traceback (most recent call last): ... - TypeError: 'toto' is an invalid keyword argument for this function + TypeError: __init__() got an unexpected keyword argument 'toto' + + :: + + sage: list(cantor_product(srange(5), repeat=2, min_slope=1)) + [(0, 1), (0, 2), (1, 2), (0, 3), (1, 3), + (0, 4), (2, 3), (1, 4), (2, 4), (3, 4)] """ from itertools import count from sage.combinat.integer_lists import IntegerListsLex @@ -692,8 +701,6 @@ def cantor_product(*args, **kwds): return elif repeat < 0: raise ValueError("repeat argument cannot be negative") - if kwds: - raise TypeError("'{}' is an invalid keyword argument for this function".format(next(kwds.iterkeys()))) mm = m * repeat for n in count(0): @@ -710,7 +717,7 @@ def cantor_product(*args, **kwds): # iterate through what we have ceiling = [n if lengths[i] is None else lengths[i]-1 for i in range(m)] * repeat - for v in IntegerListsLex(n, length=mm, ceiling=ceiling): + for v in IntegerListsLex(n, length=mm, ceiling=ceiling, **kwds): yield tuple(data[i%m][v[i]] for i in range(mm)) if all(l is not None for l in lengths) and repeat*sum(l-1 for l in lengths) == n: From fc6a1757b9e37d95eb5c93131dca28f34024167f Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Fri, 12 Aug 2016 16:15:30 -0500 Subject: [PATCH 071/452] Do not need to reproject the final endpoint for adding the vertex. --- src/sage/combinat/crystals/mv_polytopes.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/sage/combinat/crystals/mv_polytopes.py b/src/sage/combinat/crystals/mv_polytopes.py index 3e87e3b05d0..4f964e0a654 100644 --- a/src/sage/combinat/crystals/mv_polytopes.py +++ b/src/sage/combinat/crystals/mv_polytopes.py @@ -75,12 +75,23 @@ def _latex_(self): \draw[fill=black] (-2, -2) circle (0.1); \end{tikzpicture} - :: - sage: MV = crystals.infinity.MVPolytopes(['D',4]) sage: b = MV.module_generators[0].f_string([1,2,1,2]) sage: latex(b) \text{\texttt{MV{ }polytope{ }...}} + + TESTS:: + + sage: MV = crystals.infinity.MVPolytopes(['A',2]) + sage: u = MV.highest_weight_vector() + sage: b = u.f_string([1,2,2,1]) + sage: latex(b) + \begin{tikzpicture} + \draw (0, 0) -- (3/2, -989/1142) -- (3/2, -2967/1142) -- (0, -1978/571); + \draw (0, 0) -- (-3/2, -989/1142) -- (-3/2, -2967/1142) -- (0, -1978/571); + \draw[fill=black] (0, 0) circle (0.1); + \draw[fill=black] (0, -1978/571) circle (0.1); + \end{tikzpicture} """ latex_options = self.parent()._latex_options P = latex_options['P'] @@ -118,7 +129,7 @@ def _latex_(self): if latex_options["mark_endpoints"]: circle_size = latex_options["circle_size"] ret += "\\draw[fill=black] {} circle ({});\n".format(proj(P.zero()), circle_size) - ret += "\\draw[fill=black] {} circle ({});\n".format(proj(final), circle_size) + ret += "\\draw[fill=black] {} circle ({});\n".format(final, circle_size) ret += "\\end{tikzpicture}" return ret From fb9a4647e24ab24f84a9561b264d070231c0f4a0 Mon Sep 17 00:00:00 2001 From: Dinakar Muthiah Date: Mon, 3 Oct 2016 14:57:37 -0600 Subject: [PATCH 072/452] Trac #18655: Add tropical Plucker relations for G2. --- src/sage/combinat/crystals/pbw_datum.py | 30 +++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/crystals/pbw_datum.py b/src/sage/combinat/crystals/pbw_datum.py index 63a18ef0c2e..f824e4ab15f 100644 --- a/src/sage/combinat/crystals/pbw_datum.py +++ b/src/sage/combinat/crystals/pbw_datum.py @@ -342,7 +342,7 @@ def tropical_plucker_relation(a, lusztig_datum): elif a == (-1, -1): # A2 p = min(n[0], n[2]) return (n[1]+n[2]-p, p, n[0]+n[1]-p) - elif a == (-1, -2): # B2 + elif a == (-1, -2): # B2 p1 = min(n[0]+n[1], n[0]+n[3], n[2]+n[3]) p2 = min(2*n[0]+n[1], 2*n[0]+n[3], 2*n[2]+n[3]) return (n[1]+2*n[2]+n[3]-p2, @@ -359,7 +359,33 @@ def tropical_plucker_relation(a, lusztig_datum): p2-p1, n[0]+2*n[1]+n[2]-p2) elif a == (-3, -1): # G2 - raise NotImplementedError("type G2 not implemented") + t1,t2,t3,t4,t5,t6 = tuple(n) + pi1 = min(t1+t2+3*t3+t4, + t1+t2+2*min(t3,t5)+t6, + min(t1,t3)+t4+2*t5+t6) + pi2 = min(2*t1+2*t2+3*t3+t4, + 2*t1+2*t2+3*min(t3,t5)+t6, + 2*min(t1,t3)+2*t4+3*t5+t6, + t1+t2+t4+2*t5+t6+min(t1+t3,2*t3,t3+t5,t1+t5)) + pi3 = min(3*t1+2*t2+3*t3+t4, + 3*t1+2*t2+3*min(t3,t5)+t6, + 3*min(t1,t3)+2*t4+3*t5+t6, + 2*t1+t2+t4+2*t5+t6+min(t1+t3,2*t3,t3+t5,t1+t5)) + pi4 = min(2*t1+2*t2+3*t3+t4+min(t1+t2+3*t3+t4, + t1+t2+3*min(t3,t5)+t6, + min(t1+t3,2*t2,t3+t5,t1+t5)+t4+2*t5+t6), + 2*t6+3*min(t1+t2+2*min(t3,t5),min(t1,t3)+t4+2*t5)) + return (t2+3*t3+2*t4+3*t5+t6-pi3, + pi3-pi2, + 3*pi2-pi2-pi4, + pi4-pi1-pi2, + 3*pi1-pi4, + t1+t2+2*t3+t4+t5-pi1) + elif a == (-1,-3): #G2 + reversed_lusztig_datum = tuple(reversed(lusztig_datum)) + return tuple(reversed( + tropical_plucker_relation(tuple(reversed(a)), + reversed_lusztig_datum))) # Maybe we need to be more specific, and pass not the Cartan type, but the root lattice? # TODO: Move to PBW_data? From a81b2134f04acc6abcccf49284be7c5c1f6d3be3 Mon Sep 17 00:00:00 2001 From: Dinakar Muthiah Date: Mon, 3 Oct 2016 15:14:49 -0600 Subject: [PATCH 073/452] Trac #18655: Swap tropical Plucker relations for B2 and C2. This fixes an earlier error having to do with the Langlands dual root datum being used incorrectly. --- src/sage/combinat/crystals/pbw_datum.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/crystals/pbw_datum.py b/src/sage/combinat/crystals/pbw_datum.py index f824e4ab15f..f4bd083c7cb 100644 --- a/src/sage/combinat/crystals/pbw_datum.py +++ b/src/sage/combinat/crystals/pbw_datum.py @@ -342,14 +342,14 @@ def tropical_plucker_relation(a, lusztig_datum): elif a == (-1, -1): # A2 p = min(n[0], n[2]) return (n[1]+n[2]-p, p, n[0]+n[1]-p) - elif a == (-1, -2): # B2 + elif a == (-2, -1): # B2 p1 = min(n[0]+n[1], n[0]+n[3], n[2]+n[3]) p2 = min(2*n[0]+n[1], 2*n[0]+n[3], 2*n[2]+n[3]) return (n[1]+2*n[2]+n[3]-p2, p2-p1, 2*p1-p2, n[0]+n[1]+n[2]-p1) - elif a == (-2, -1): # C2 + elif a == (-1, -2): # C2 # I believe this is condition (iii) in Proposition 5.2 of Joel's thesis. # (I'm pretty sure this is correct). p1 = min(n[0]+n[1], n[0]+n[3], n[2]+n[3]) From 1ea3d272c72d933a5b1af7119757a2034b43f840 Mon Sep 17 00:00:00 2001 From: Dinakar Muthiah Date: Mon, 3 Oct 2016 15:35:47 -0600 Subject: [PATCH 074/452] Trac #18655: Fix doctests to account for B2 and C2 switch. --- src/sage/combinat/crystals/mv_polytopes.py | 42 ++++++++++++---------- src/sage/combinat/crystals/pbw_crystal.py | 22 ++++++------ src/sage/combinat/crystals/pbw_datum.py | 4 +-- 3 files changed, 36 insertions(+), 32 deletions(-) diff --git a/src/sage/combinat/crystals/mv_polytopes.py b/src/sage/combinat/crystals/mv_polytopes.py index 4f964e0a654..0dabf1fa28b 100644 --- a/src/sage/combinat/crystals/mv_polytopes.py +++ b/src/sage/combinat/crystals/mv_polytopes.py @@ -69,12 +69,11 @@ def _latex_(self): sage: b = MV.module_generators[0].f_string([1,2,1,2]) sage: latex(b) \begin{tikzpicture} - \draw (0, 0) -- (-1, 1) -- (-1, 1) -- (-2, 0) -- (-2, -2); - \draw (0, 0) -- (0, -2) -- (-1, -3) -- (-1, -3) -- (-2, -2); + \draw (0, 0) -- (-2, 2) -- (-2, 2) -- (-2, 2) -- (-2, -2); + \draw (0, 0) -- (0, 0) -- (0, 0) -- (-4, 0) -- (-4, 0); \draw[fill=black] (0, 0) circle (0.1); - \draw[fill=black] (-2, -2) circle (0.1); + \draw[fill=black] (-4, 0) circle (0.1); \end{tikzpicture} - sage: MV = crystals.infinity.MVPolytopes(['D',4]) sage: b = MV.module_generators[0].f_string([1,2,1,2]) sage: latex(b) @@ -186,14 +185,19 @@ def polytope(self, P=None): sage: MV = crystals.infinity.MVPolytopes(['C', 3]) sage: b = MV.module_generators[0].f_string([3,2,3,2,1]) sage: P = b.polytope(); P - A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 6 vertices + A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 11 vertices sage: P.vertices() (A vertex at (0, 0, 0), - A vertex at (0, 1, -1), - A vertex at (0, 1, 1), - A vertex at (1, -1, 0), - A vertex at (1, 1, -2), - A vertex at (1, 1, 2)) + A vertex at (0, 0, 2), + A vertex at (2, 2, 0), + A vertex at (0, 2, 0), + A vertex at (1, -1, 0), + A vertex at (1, -1, 2), + A vertex at (1, 0, -1), + A vertex at (1, 1, 2), + A vertex at (1, 2, -1), + A vertex at (1, 2, 1), + A vertex at (2, 0, 2)) """ if P is None: P = self.parent().weight_lattice_realization() @@ -219,7 +223,7 @@ def plot(self, P=None, **options): sage: MV = crystals.infinity.MVPolytopes(['C', 2]) sage: b = MV.highest_weight_vector().f_string([1,2,1,2,2,2,1,1,1,1,2,1]) sage: b.plot() - Graphics object consisting of 12 graphics primitives + Graphics object consisting of 10 graphics primitives Here is the above example placed inside the ambient space of type `C_2`: @@ -294,24 +298,24 @@ def set_latex_options(self, **kwds): sage: b = MV.highest_weight_vector().f_string([1,2,1,2]) sage: latex(b) \begin{tikzpicture} - \draw (0, 0) -- (-1, 1) -- (-1, 1) -- (-2, 0) -- (-2, -2); - \draw (0, 0) -- (0, -2) -- (-1, -3) -- (-1, -3) -- (-2, -2); + \draw (0, 0) -- (-2, 2) -- (-2, 2) -- (-2, 2) -- (-2, -2); + \draw (0, 0) -- (0, 0) -- (0, 0) -- (-4, 0) -- (-4, 0); \draw[fill=black] (0, 0) circle (0.1); - \draw[fill=black] (-2, -2) circle (0.1); + \draw[fill=black] (-4, 0) circle (0.1); \end{tikzpicture} sage: MV.set_latex_options(P=P, circle_size=float(0.2)) sage: latex(b) \begin{tikzpicture} - \draw (0, 0) -- (-2, 1) -- (-2, 1) -- (-2, 0) -- (0, -2); - \draw (0, 0) -- (2, -2) -- (2, -3) -- (2, -3) -- (0, -2); + \draw (0, 0) -- (-4, 2) -- (-4, 2) -- (-4, 2) -- (0, -2); + \draw (0, 0) -- (0, 0) -- (0, 0) -- (-4, 0) -- (-4, 0); \draw[fill=black] (0, 0) circle (0.2); - \draw[fill=black] (0, -2) circle (0.2); + \draw[fill=black] (-4, 0) circle (0.2); \end{tikzpicture} sage: MV.set_latex_options(mark_endpoints=False) sage: latex(b) \begin{tikzpicture} - \draw (0, 0) -- (-2, 1) -- (-2, 1) -- (-2, 0) -- (0, -2); - \draw (0, 0) -- (2, -2) -- (2, -3) -- (2, -3) -- (0, -2); + \draw (0, 0) -- (-4, 2) -- (-4, 2) -- (-4, 2) -- (0, -2); + \draw (0, 0) -- (0, 0) -- (0, 0) -- (-4, 0) -- (-4, 0); \end{tikzpicture} sage: MV.set_latex_options(P=MV.weight_lattice_realization(), ....: circle_size=0.2, diff --git a/src/sage/combinat/crystals/pbw_crystal.py b/src/sage/combinat/crystals/pbw_crystal.py index 1f73539e19c..e966697aac3 100644 --- a/src/sage/combinat/crystals/pbw_crystal.py +++ b/src/sage/combinat/crystals/pbw_crystal.py @@ -52,8 +52,8 @@ def _repr_(self): sage: B = crystals.infinity.PBW(['B', 4]) sage: u = B.highest_weight_vector() sage: u.f_string([1,2,3,4,2,3,2,3,4,1,2]) - PBW monomial with Lusztig datum - (0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 1, 2) + PBW monomial with Lusztig datum + (0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 2) """ pbw_datum = self._pbw_datum.convert_to_new_long_word(self.parent()._default_word) return "PBW monomial with Lusztig datum {}".format(pbw_datum.lusztig_datum) @@ -68,11 +68,11 @@ def _latex_(self): sage: u = B.highest_weight_vector() sage: b = u.f_string([1,2,3,4,2,3,2,3,4,1,2]) sage: latex(b) - f_{\alpha_{4}}^{2} - f_{\alpha_{3}} - f_{\alpha_{1} + \alpha_{2} + 2\alpha_{3}} - f_{\alpha_{1} + \alpha_{2}} - f_{\alpha_{2}}^{2} + f_{\alpha_{1}} + f_{\alpha_{4}} + f_{\alpha_{2} + 2\alpha_{3} + 2\alpha_{4}} + f_{\alpha_{2} + 2\alpha_{3}}^{2} + f_{\alpha_{1} + \alpha_{2}} """ pbw_datum = self._pbw_datum.convert_to_new_long_word(self.parent()._default_word) lusztig_datum = list(pbw_datum.lusztig_datum) @@ -191,9 +191,9 @@ def e(self, i): sage: B = crystals.infinity.PBW(['B', 3]) sage: b = B.highest_weight_vector() sage: c = b.f_string([2,1,3,2,1,3,2,2]); c - PBW monomial with Lusztig datum (0, 1, 0, 1, 0, 0, 0, 1, 2) + PBW monomial with Lusztig datum (0, 0, 0, 1, 1, 0, 0, 0, 1) sage: c.e(2) - PBW monomial with Lusztig datum (0, 1, 0, 1, 0, 0, 0, 1, 1) + PBW monomial with Lusztig datum (0, 0, 2, 0, 0, 0, 0, 0, 1) sage: c.e_string([2,2,1,3,2,1,3,2]) == b True """ @@ -403,12 +403,12 @@ def set_default_long_word(self, word): [1, 3, 2, 3, 1, 2, 3, 1, 2] sage: x = B.highest_weight_vector().f_string([2,1,3,2,3,1,2,3,3,1]) sage: x - PBW monomial with Lusztig datum (1, 2, 2, 0, 0, 0, 0, 0, 1) + PBW monomial with Lusztig datum (1, 3, 0, 1, 0, 0, 0, 1, 1) sage: B.set_default_long_word([2,1,3,2,1,3,2,3,1]) sage: B.default_long_word() [2, 1, 3, 2, 1, 3, 2, 3, 1] sage: x - PBW monomial with Lusztig datum (2, 0, 0, 0, 0, 0, 1, 3, 2) + PBW monomial with Lusztig datum (0, 0, 1, 0, 1, 1, 0, 0, 2) TESTS:: diff --git a/src/sage/combinat/crystals/pbw_datum.py b/src/sage/combinat/crystals/pbw_datum.py index f4bd083c7cb..edb8a0a92ed 100644 --- a/src/sage/combinat/crystals/pbw_datum.py +++ b/src/sage/combinat/crystals/pbw_datum.py @@ -332,9 +332,9 @@ def tropical_plucker_relation(a, lusztig_datum): sage: tropical_plucker_relation((-1,-1), (1,2,3)) (4, 1, 2) sage: tropical_plucker_relation((-1,-2), (1,2,3,4)) - (8, 1, 2, 3) - sage: tropical_plucker_relation((-2,-1), (1,2,3,4)) (6, 1, 2, 3) + sage: tropical_plucker_relation((-2,-1), (1,2,3,4)) + (8, 1, 2, 3) """ n = lusztig_datum if a == (0, 0): # A1xA1 From 4104e22470e352eb1280177723c095845cbfb80d Mon Sep 17 00:00:00 2001 From: Dinakar Muthiah Date: Mon, 3 Oct 2016 18:42:20 -0600 Subject: [PATCH 075/452] Trac #18655: Add reference and change notation to follow reference. The reference is a paper by Berenstein and Zelevinsky. The tropical Plucker relations are obtained by tropicalizing the relations in that paper. The notation of the function reflects that more closely. --- src/sage/combinat/crystals/pbw_datum.py | 46 +++++++++++++------------ 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/src/sage/combinat/crystals/pbw_datum.py b/src/sage/combinat/crystals/pbw_datum.py index edb8a0a92ed..8fdff40939c 100644 --- a/src/sage/combinat/crystals/pbw_datum.py +++ b/src/sage/combinat/crystals/pbw_datum.py @@ -317,7 +317,9 @@ def compute_new_lusztig_datum(enhanced_braid_chain, initial_lusztig_datum): # The tropical plucker relations def tropical_plucker_relation(a, lusztig_datum): r""" - Apply the tropical Plucker relation of type ``a`` to ``lusztig_datum``. + Apply the tropical Plucker relation of type ``a`` to ``lusztig_datum``. The + relations are obtained by tropicalizing the relations in Proposition 7.1 + of the paper of Berenstein and Zelevinsky cited below. INPUT: @@ -335,31 +337,31 @@ def tropical_plucker_relation(a, lusztig_datum): (6, 1, 2, 3) sage: tropical_plucker_relation((-2,-1), (1,2,3,4)) (8, 1, 2, 3) + + REFERENCES: + .. [Berenstein-Zelevinsky01] \A. Berenstein, A. Zelevinsky + *Tensor product multiplicities, canonical bases and + totally positive varieties* + Invent. Math. **143** (2002). no. 1. 77-128. """ - n = lusztig_datum if a == (0, 0): # A1xA1 - return (n[1], n[0]) + t1,t2 = lusztig_datum + return (t2,t1) elif a == (-1, -1): # A2 - p = min(n[0], n[2]) - return (n[1]+n[2]-p, p, n[0]+n[1]-p) + t1,t2,t3 = lusztig_datum + return (t2+t3-min(t1,t3), + min(t1,t3), + t1+t2-min(t1,t3)) elif a == (-2, -1): # B2 - p1 = min(n[0]+n[1], n[0]+n[3], n[2]+n[3]) - p2 = min(2*n[0]+n[1], 2*n[0]+n[3], 2*n[2]+n[3]) - return (n[1]+2*n[2]+n[3]-p2, - p2-p1, - 2*p1-p2, - n[0]+n[1]+n[2]-p1) - elif a == (-1, -2): # C2 - # I believe this is condition (iii) in Proposition 5.2 of Joel's thesis. - # (I'm pretty sure this is correct). - p1 = min(n[0]+n[1], n[0]+n[3], n[2]+n[3]) - p2 = min(n[0]+2*n[1], n[0]+2*n[3], n[2]+2*n[3]) - return (n[1]+n[2]+n[3]-p1, - 2*p1-p2, - p2-p1, - n[0]+2*n[1]+n[2]-p2) + t1,t2,t3,t4 = lusztig_datum + pi1 = min(t1+t2,min(t1,t3)+t4) + pi2 = min(2*t1+t2,2*min(t1,t3)+t4) + return (t2+2*t3+t4-pi2, + pi2-pi1, + 2*pi1-pi2, + t1+t2+t3-pi1) elif a == (-3, -1): # G2 - t1,t2,t3,t4,t5,t6 = tuple(n) + t1,t2,t3,t4,t5,t6 = lusztig_datum pi1 = min(t1+t2+3*t3+t4, t1+t2+2*min(t3,t5)+t6, min(t1,t3)+t4+2*t5+t6) @@ -381,7 +383,7 @@ def tropical_plucker_relation(a, lusztig_datum): pi4-pi1-pi2, 3*pi1-pi4, t1+t2+2*t3+t4+t5-pi1) - elif a == (-1,-3): #G2 + else: # (-1,-2) and (-1,-3) reversed_lusztig_datum = tuple(reversed(lusztig_datum)) return tuple(reversed( tropical_plucker_relation(tuple(reversed(a)), From 72c7494801fb15210d35f1b71a1353cc29b6178a Mon Sep 17 00:00:00 2001 From: Dinakar Muthiah Date: Tue, 11 Oct 2016 10:09:04 -0600 Subject: [PATCH 076/452] Fix transpose error (i.e. B2 <-> C2 error). Trac #18655 --- src/sage/combinat/crystals/pbw_datum.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/crystals/pbw_datum.py b/src/sage/combinat/crystals/pbw_datum.py index 8fdff40939c..8fa1b7ff3d0 100644 --- a/src/sage/combinat/crystals/pbw_datum.py +++ b/src/sage/combinat/crystals/pbw_datum.py @@ -352,7 +352,7 @@ def tropical_plucker_relation(a, lusztig_datum): return (t2+t3-min(t1,t3), min(t1,t3), t1+t2-min(t1,t3)) - elif a == (-2, -1): # B2 + elif a == (-1, -2): # B2 t1,t2,t3,t4 = lusztig_datum pi1 = min(t1+t2,min(t1,t3)+t4) pi2 = min(2*t1+t2,2*min(t1,t3)+t4) @@ -360,7 +360,7 @@ def tropical_plucker_relation(a, lusztig_datum): pi2-pi1, 2*pi1-pi2, t1+t2+t3-pi1) - elif a == (-3, -1): # G2 + elif a == (-1, -3): # G2 t1,t2,t3,t4,t5,t6 = lusztig_datum pi1 = min(t1+t2+3*t3+t4, t1+t2+2*min(t3,t5)+t6, From 29be4fa7579eae4f8e225bc62e01ebf1cd874110 Mon Sep 17 00:00:00 2001 From: Dinakar Muthiah Date: Tue, 11 Oct 2016 10:09:50 -0600 Subject: [PATCH 077/452] Fix transcription errors for G2 tropical plucker relations. Trac #18655. --- src/sage/combinat/crystals/pbw_datum.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/crystals/pbw_datum.py b/src/sage/combinat/crystals/pbw_datum.py index 8fa1b7ff3d0..23cf0ca7fb9 100644 --- a/src/sage/combinat/crystals/pbw_datum.py +++ b/src/sage/combinat/crystals/pbw_datum.py @@ -375,11 +375,11 @@ def tropical_plucker_relation(a, lusztig_datum): 2*t1+t2+t4+2*t5+t6+min(t1+t3,2*t3,t3+t5,t1+t5)) pi4 = min(2*t1+2*t2+3*t3+t4+min(t1+t2+3*t3+t4, t1+t2+3*min(t3,t5)+t6, - min(t1+t3,2*t2,t3+t5,t1+t5)+t4+2*t5+t6), + min(t1+t3,2*t3,t3+t5,t1+t5)+t4+2*t5+t6), 2*t6+3*min(t1+t2+2*min(t3,t5),min(t1,t3)+t4+2*t5)) return (t2+3*t3+2*t4+3*t5+t6-pi3, pi3-pi2, - 3*pi2-pi2-pi4, + 3*pi2-pi3-pi4, pi4-pi1-pi2, 3*pi1-pi4, t1+t2+2*t3+t4+t5-pi1) From 62032fca75be69f273f7382577cc8d5915f54163 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 11 Oct 2016 15:59:45 -0500 Subject: [PATCH 078/452] One more transcription error. --- src/sage/combinat/crystals/pbw_datum.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/crystals/pbw_datum.py b/src/sage/combinat/crystals/pbw_datum.py index 23cf0ca7fb9..5b9b9bedb2b 100644 --- a/src/sage/combinat/crystals/pbw_datum.py +++ b/src/sage/combinat/crystals/pbw_datum.py @@ -362,7 +362,7 @@ def tropical_plucker_relation(a, lusztig_datum): t1+t2+t3-pi1) elif a == (-1, -3): # G2 t1,t2,t3,t4,t5,t6 = lusztig_datum - pi1 = min(t1+t2+3*t3+t4, + pi1 = min(t1+t2+2*t3+t4, t1+t2+2*min(t3,t5)+t6, min(t1,t3)+t4+2*t5+t6) pi2 = min(2*t1+2*t2+3*t3+t4, From e5d223f42c6527b24157ac8bb826c839558f0993 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 8 Nov 2016 19:47:28 +0100 Subject: [PATCH 079/452] trac 18655 fixing documentation --- src/sage/combinat/crystals/pbw_datum.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/combinat/crystals/pbw_datum.py b/src/sage/combinat/crystals/pbw_datum.py index 5b9b9bedb2b..4e3d940c7ac 100644 --- a/src/sage/combinat/crystals/pbw_datum.py +++ b/src/sage/combinat/crystals/pbw_datum.py @@ -339,6 +339,7 @@ def tropical_plucker_relation(a, lusztig_datum): (8, 1, 2, 3) REFERENCES: + .. [Berenstein-Zelevinsky01] \A. Berenstein, A. Zelevinsky *Tensor product multiplicities, canonical bases and totally positive varieties* @@ -479,8 +480,7 @@ def diff_interval(list1, list2): sage: diff_interval([1,2,4,4,5], [1,3,45,6,3]) (1, 5) """ - L = [i for i,elt in enumerate(list1) if elt != list2[i]] + L = [i for i, elt in enumerate(list1) if elt != list2[i]] if not L: return None - return (L[0], L[-1]+1) - + return (L[0], L[-1] + 1) From 689fa0c8582e26752f8b5b7b9933a457de8f968a Mon Sep 17 00:00:00 2001 From: Kevin Dilks Date: Tue, 8 Nov 2016 18:24:43 -0600 Subject: [PATCH 080/452] Initial implementation of linear extensions, with excessive amounts of documentation. --- src/sage/combinat/posets/linear_extensions.py | 63 ++++++++++++++++--- 1 file changed, 54 insertions(+), 9 deletions(-) diff --git a/src/sage/combinat/posets/linear_extensions.py b/src/sage/combinat/posets/linear_extensions.py index 2b32694bbec..637869717fd 100644 --- a/src/sage/combinat/posets/linear_extensions.py +++ b/src/sage/combinat/posets/linear_extensions.py @@ -449,18 +449,63 @@ def cardinality(self): 1 sage: Posets.ChainPoset(1).linear_extensions().cardinality() 1 + sage: Posets.BooleanLattice(4).linear_extensions().cardinality() + 1680384 """ from sage.rings.integer import Integer - H = self._poset.order_ideals_lattice(as_ideals=False)._hasse_diagram - L = H.level_sets() - c = [0] * H.order() - for l in L[0]: - c[l] = 1 - for lev in L[1:]: - for l in lev: - c[l] = sum(c[i] for i in H.lower_covers_iterator(l)) - return Integer(sum(c[i] for i in H.sinks())) + n=len(self._poset) + up=self._poset._hasse_diagram.to_dictionary() + # Convert to the Hasse diagram so our poset can be realized on the set {0,...,n-1} + # with a nice dictionary of edges + for i in range(0,n): + up[n-1-i]=sorted(set(up[n-1-i]+[item for x in up[n-1-i] for item in up[x] ])) + # Compute the principal order filter for each element. + Jup={1:[]} # Jup will be a dictionary giving up edges in J(P) + # We will perform a loop where after k loops, we will have a list of up edges + # for the lattice of order ideals for P restricted to entries 0,...,k. + loc=[1] * n + # This list will be indexed by entries in P. After k loops, the entry loc[i] + # will correspond to the element of J(P) that is the principal order ideal of i, + # restricted to the elements 0,...,k . + m=1 # m keeps track of how many elements we currently have in J(P). + # We start with just the empty order ideal, and no relations. + for x in range(n): + # Use the existing Jup table to compute all covering relations in J(P) + # for things that are above loc(x). + K=[[loc[x]]] + j=0 + while len(K[j])>0: + K.append([]) + for a in K[j]: + for b in Jup[a]: + K[j+1]=K[j+1]+[b] + j=j+1 + K=sorted(set([item for sublist in K for item in sublist])) + for j in range(0,len(K)): + i=m+j+1 + Jup[i]= [m+K.index(a)+1 for a in Jup[K[j]]] + # These are copies of the covering relations with elements from K, + # but now with the underlying elements containing x. + Jup[K[j]]= Jup[K[j]]+[i] + # There are the new covering relations we get between ideals that + # don't contain x and those that do. + for y in up[x]: + loc[y]=K.index(loc[y])+m+1 + # Updates loc[y] if y is above x. + m=m+len(K) + # Now we have a dictionary of covering relations for J(P). The following + # shortcut works to count maximal chains, since we made J(P) naturally + # labelled, and J(P) has a unique maximal element and minimum element. + Jup[m]=1 + while m>1: + m=m-1 + ct=0 + for j in Jup[m]: + ct=ct+Jup[j] + Jup[m]=ct + return ct + def __iter__(self): r""" From 6d326b777bb45e069d5a8f1fda719ca07fa394a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 11 Nov 2016 22:36:07 +0100 Subject: [PATCH 081/452] trac 18655 remove xrange, trying to fix doc again --- .../combinat/crystals/braid_move_calculator.py | 2 +- src/sage/combinat/crystals/pbw_datum.py | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/sage/combinat/crystals/braid_move_calculator.py b/src/sage/combinat/crystals/braid_move_calculator.py index 96c5d88277a..e59b9fa9216 100644 --- a/src/sage/combinat/crystals/braid_move_calculator.py +++ b/src/sage/combinat/crystals/braid_move_calculator.py @@ -63,7 +63,7 @@ def partial_braid_word(length, swap=False, i=i, k=k): current_last_word = input_word current_first_letter = k output_word_list = [current_last_word] - for counter in xrange(1, coxeter_matrix_entry): + for counter in range(1, coxeter_matrix_entry): current_word_list = self.put_in_front(current_first_letter, current_last_word[1:]) output_word_list += [partial_braid_word(counter) + word for word in current_word_list[1:]] diff --git a/src/sage/combinat/crystals/pbw_datum.py b/src/sage/combinat/crystals/pbw_datum.py index 4e3d940c7ac..747766411a1 100644 --- a/src/sage/combinat/crystals/pbw_datum.py +++ b/src/sage/combinat/crystals/pbw_datum.py @@ -317,9 +317,11 @@ def compute_new_lusztig_datum(enhanced_braid_chain, initial_lusztig_datum): # The tropical plucker relations def tropical_plucker_relation(a, lusztig_datum): r""" - Apply the tropical Plucker relation of type ``a`` to ``lusztig_datum``. The - relations are obtained by tropicalizing the relations in Proposition 7.1 - of the paper of Berenstein and Zelevinsky cited below. + Apply the tropical Plucker relation of type ``a`` to ``lusztig_datum``. + + The relations are obtained by tropicalizing the relations in + Proposition 7.1 of the paper of Berenstein and Zelevinsky cited + below. INPUT: @@ -341,13 +343,12 @@ def tropical_plucker_relation(a, lusztig_datum): REFERENCES: .. [Berenstein-Zelevinsky01] \A. Berenstein, A. Zelevinsky - *Tensor product multiplicities, canonical bases and - totally positive varieties* + *Tensor product multiplicities, canonical bases and totally positive varieties* Invent. Math. **143** (2002). no. 1. 77-128. """ if a == (0, 0): # A1xA1 - t1,t2 = lusztig_datum - return (t2,t1) + t1, t2 = lusztig_datum + return (t2, t1) elif a == (-1, -1): # A2 t1,t2,t3 = lusztig_datum return (t2+t3-min(t1,t3), From 044d8c137512871bf8ac64fcbc7e1eefa9b07633 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20R=C3=BCth?= Date: Sun, 13 Nov 2016 09:07:56 -0500 Subject: [PATCH 082/452] use itertools.product instead of CartesianProduct --- src/sage/rings/function_field/function_field.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/rings/function_field/function_field.py b/src/sage/rings/function_field/function_field.py index cd18331c774..a26566f482b 100644 --- a/src/sage/rings/function_field/function_field.py +++ b/src/sage/rings/function_field/function_field.py @@ -354,14 +354,14 @@ def _test_derivation(self, **options): d = self.derivation() except NotImplementedError: return # some function fields no not implement derivation() yet - from sage.combinat.cartesian_product import CartesianProduct + from itertools import product # Leibniz's law - for x,y in tester.some_elements(CartesianProduct(S, S)): + for x,y in tester.some_elements(product(S, S)): tester.assert_(d(x*y) == x*d(y) + d(x)*y) # Linearity - for x,y in tester.some_elements(CartesianProduct(S, S)): + for x,y in tester.some_elements(product(S, S)): tester.assert_(d(x+y) == d(x) + d(y)) - for c,x in tester.some_elements(CartesianProduct(K, S)): + for c,x in tester.some_elements(product(K, S)): tester.assert_(d(c*x) == c*d(x)) # Constants map to zero for c in tester.some_elements(K): From 96676252b03fc865ffb897a89002adab9d35f26b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20R=C3=BCth?= Date: Sun, 13 Nov 2016 09:08:06 -0500 Subject: [PATCH 083/452] use relative imports --- src/sage/rings/function_field/function_field.py | 2 +- src/sage/rings/function_field/maps.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/function_field/function_field.py b/src/sage/rings/function_field/function_field.py index a26566f482b..00da4d21d41 100644 --- a/src/sage/rings/function_field/function_field.py +++ b/src/sage/rings/function_field/function_field.py @@ -1236,7 +1236,7 @@ def derivation(self): NotImplementedError: construction of separable models not implemented """ - from maps import FunctionFieldDerivation_separable + from .maps import FunctionFieldDerivation_separable if self.polynomial().gcd(self.polynomial().derivative()).is_one(): return FunctionFieldDerivation_separable(self, self.base_ring().derivation()) else: diff --git a/src/sage/rings/function_field/maps.py b/src/sage/rings/function_field/maps.py index 0f539ebf85d..e70bc38327b 100644 --- a/src/sage/rings/function_field/maps.py +++ b/src/sage/rings/function_field/maps.py @@ -216,7 +216,7 @@ def __init__(self, L, d): """ if not isinstance(d, FunctionFieldDerivation): raise TypeError("d must be a derivation on a function field") - from function_field import is_FunctionField + from .function_field import is_FunctionField if not is_FunctionField(L): raise TypeError("L must be a function field") if d.domain() is not L.base_ring(): From e8c39d6e98ffe0d2786c0d052e85a20a652e1132 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sun, 13 Nov 2016 18:27:02 -0600 Subject: [PATCH 084/452] Removing cmp, fixing doctests from B/C correction, and moving braid_move_calculator.py. --- src/sage/combinat/crystals/mv_polytopes.py | 41 ++++++++----------- src/sage/combinat/crystals/pbw_crystal.py | 29 +++++++------ src/sage/combinat/crystals/pbw_datum.py | 15 ++++--- .../braid_move_calculator.py | 9 ++-- 4 files changed, 45 insertions(+), 49 deletions(-) rename src/sage/combinat/{crystals => root_system}/braid_move_calculator.py (92%) diff --git a/src/sage/combinat/crystals/mv_polytopes.py b/src/sage/combinat/crystals/mv_polytopes.py index 0dabf1fa28b..af8a06d05e1 100644 --- a/src/sage/combinat/crystals/mv_polytopes.py +++ b/src/sage/combinat/crystals/mv_polytopes.py @@ -69,10 +69,10 @@ def _latex_(self): sage: b = MV.module_generators[0].f_string([1,2,1,2]) sage: latex(b) \begin{tikzpicture} - \draw (0, 0) -- (-2, 2) -- (-2, 2) -- (-2, 2) -- (-2, -2); - \draw (0, 0) -- (0, 0) -- (0, 0) -- (-4, 0) -- (-4, 0); + \draw (0, 0) -- (-1, 1) -- (-1, 1) -- (-2, 0) -- (-2, -2); + \draw (0, 0) -- (0, -2) -- (-1, -3) -- (-1, -3) -- (-2, -2); \draw[fill=black] (0, 0) circle (0.1); - \draw[fill=black] (-4, 0) circle (0.1); + \draw[fill=black] (-2, -2) circle (0.1); \end{tikzpicture} sage: MV = crystals.infinity.MVPolytopes(['D',4]) sage: b = MV.module_generators[0].f_string([1,2,1,2]) @@ -185,19 +185,14 @@ def polytope(self, P=None): sage: MV = crystals.infinity.MVPolytopes(['C', 3]) sage: b = MV.module_generators[0].f_string([3,2,3,2,1]) sage: P = b.polytope(); P - A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 11 vertices + A 3-dimensional polyhedron in QQ^3 defined as the convex hull of 6 vertices sage: P.vertices() (A vertex at (0, 0, 0), - A vertex at (0, 0, 2), - A vertex at (2, 2, 0), - A vertex at (0, 2, 0), - A vertex at (1, -1, 0), - A vertex at (1, -1, 2), - A vertex at (1, 0, -1), - A vertex at (1, 1, 2), - A vertex at (1, 2, -1), - A vertex at (1, 2, 1), - A vertex at (2, 0, 2)) + A vertex at (0, 1, -1), + A vertex at (0, 1, 1), + A vertex at (1, -1, 0), + A vertex at (1, 1, -2), + A vertex at (1, 1, 2)) """ if P is None: P = self.parent().weight_lattice_realization() @@ -223,7 +218,7 @@ def plot(self, P=None, **options): sage: MV = crystals.infinity.MVPolytopes(['C', 2]) sage: b = MV.highest_weight_vector().f_string([1,2,1,2,2,2,1,1,1,1,2,1]) sage: b.plot() - Graphics object consisting of 10 graphics primitives + Graphics object consisting of 12 graphics primitives Here is the above example placed inside the ambient space of type `C_2`: @@ -298,24 +293,24 @@ def set_latex_options(self, **kwds): sage: b = MV.highest_weight_vector().f_string([1,2,1,2]) sage: latex(b) \begin{tikzpicture} - \draw (0, 0) -- (-2, 2) -- (-2, 2) -- (-2, 2) -- (-2, -2); - \draw (0, 0) -- (0, 0) -- (0, 0) -- (-4, 0) -- (-4, 0); + \draw (0, 0) -- (-1, 1) -- (-1, 1) -- (-2, 0) -- (-2, -2); + \draw (0, 0) -- (0, -2) -- (-1, -3) -- (-1, -3) -- (-2, -2); \draw[fill=black] (0, 0) circle (0.1); - \draw[fill=black] (-4, 0) circle (0.1); + \draw[fill=black] (-2, -2) circle (0.1); \end{tikzpicture} sage: MV.set_latex_options(P=P, circle_size=float(0.2)) sage: latex(b) \begin{tikzpicture} - \draw (0, 0) -- (-4, 2) -- (-4, 2) -- (-4, 2) -- (0, -2); - \draw (0, 0) -- (0, 0) -- (0, 0) -- (-4, 0) -- (-4, 0); + \draw (0, 0) -- (-2, 1) -- (-2, 1) -- (-2, 0) -- (0, -2); + \draw (0, 0) -- (2, -2) -- (2, -3) -- (2, -3) -- (0, -2); \draw[fill=black] (0, 0) circle (0.2); - \draw[fill=black] (-4, 0) circle (0.2); + \draw[fill=black] (0, -2) circle (0.2); \end{tikzpicture} sage: MV.set_latex_options(mark_endpoints=False) sage: latex(b) \begin{tikzpicture} - \draw (0, 0) -- (-4, 2) -- (-4, 2) -- (-4, 2) -- (0, -2); - \draw (0, 0) -- (0, 0) -- (0, 0) -- (-4, 0) -- (-4, 0); + \draw (0, 0) -- (-2, 1) -- (-2, 1) -- (-2, 0) -- (0, -2); + \draw (0, 0) -- (2, -2) -- (2, -3) -- (2, -3) -- (0, -2); \end{tikzpicture} sage: MV.set_latex_options(P=MV.weight_lattice_realization(), ....: circle_size=0.2, diff --git a/src/sage/combinat/crystals/pbw_crystal.py b/src/sage/combinat/crystals/pbw_crystal.py index e966697aac3..81850c6cc3f 100644 --- a/src/sage/combinat/crystals/pbw_crystal.py +++ b/src/sage/combinat/crystals/pbw_crystal.py @@ -20,6 +20,7 @@ from sage.structure.element import Element from sage.structure.parent import Parent from sage.structure.unique_representation import UniqueRepresentation +from sage.structure.sage_object import richcmp from sage.categories.highest_weight_crystals import HighestWeightCrystals from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets from sage.combinat.root_system.cartan_type import CartanType @@ -53,7 +54,7 @@ def _repr_(self): sage: u = B.highest_weight_vector() sage: u.f_string([1,2,3,4,2,3,2,3,4,1,2]) PBW monomial with Lusztig datum - (0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 2) + (0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 1, 2) """ pbw_datum = self._pbw_datum.convert_to_new_long_word(self.parent()._default_word) return "PBW monomial with Lusztig datum {}".format(pbw_datum.lusztig_datum) @@ -68,11 +69,11 @@ def _latex_(self): sage: u = B.highest_weight_vector() sage: b = u.f_string([1,2,3,4,2,3,2,3,4,1,2]) sage: latex(b) - f_{\alpha_{1}} - f_{\alpha_{4}} - f_{\alpha_{2} + 2\alpha_{3} + 2\alpha_{4}} - f_{\alpha_{2} + 2\alpha_{3}}^{2} - f_{\alpha_{1} + \alpha_{2}} + f_{\alpha_{4}}^{2} + f_{\alpha_{3}} + f_{\alpha_{1} + \alpha_{2} + 2\alpha_{3}} + f_{\alpha_{1} + \alpha_{2}} + f_{\alpha_{2}}^{2} """ pbw_datum = self._pbw_datum.convert_to_new_long_word(self.parent()._default_word) lusztig_datum = list(pbw_datum.lusztig_datum) @@ -143,7 +144,7 @@ def __ne__(self, other): return not (self == other) # Necessary for displaying subcrystals - def _cmp_(self, other): + def _richcmp_(self, other, op): """ Return comparison of ``self`` and ``other``. @@ -154,14 +155,16 @@ def _cmp_(self, other): sage: b = u.f_string([2,1,2,2,2,2,1,1,2,1,2,1,2,1,2,2]) sage: bp = u.f_string([2,1,2,2,1,1,2,2,2,1,2,1,2]) sage: w = [1, 2, 1] - sage: cmp(b, bp) == cmp(b.lusztig_datum(w), bp.lusztig_datum(w)) + sage: (b < bp) == (b.lusztig_datum(w) < bp.lusztig_datum(w)) + True + sage: (b > bp) == (b.lusztig_datum(w) > bp.lusztig_datum(w)) True """ i = self.parent().index_set()[0] word = self.parent()._pbw_datum_parent._long_word_begin_with(i) lusztig_datum = tuple(self._pbw_datum.convert_to_new_long_word(word).lusztig_datum) other_lusztig_datum = tuple(other._pbw_datum.convert_to_new_long_word(word).lusztig_datum) - return cmp(lusztig_datum, other_lusztig_datum) + return richcmp(lusztig_datum, other_lusztig_datum, op) @cached_method def __hash__(self): @@ -191,9 +194,9 @@ def e(self, i): sage: B = crystals.infinity.PBW(['B', 3]) sage: b = B.highest_weight_vector() sage: c = b.f_string([2,1,3,2,1,3,2,2]); c - PBW monomial with Lusztig datum (0, 0, 0, 1, 1, 0, 0, 0, 1) + PBW monomial with Lusztig datum (0, 1, 0, 1, 0, 0, 0, 1, 2) sage: c.e(2) - PBW monomial with Lusztig datum (0, 0, 2, 0, 0, 0, 0, 0, 1) + PBW monomial with Lusztig datum (0, 1, 0, 1, 0, 0, 0, 1, 1) sage: c.e_string([2,2,1,3,2,1,3,2]) == b True """ @@ -403,12 +406,12 @@ def set_default_long_word(self, word): [1, 3, 2, 3, 1, 2, 3, 1, 2] sage: x = B.highest_weight_vector().f_string([2,1,3,2,3,1,2,3,3,1]) sage: x - PBW monomial with Lusztig datum (1, 3, 0, 1, 0, 0, 0, 1, 1) + PBW monomial with Lusztig datum (1, 2, 2, 0, 0, 0, 0, 0, 1) sage: B.set_default_long_word([2,1,3,2,1,3,2,3,1]) sage: B.default_long_word() [2, 1, 3, 2, 1, 3, 2, 3, 1] sage: x - PBW monomial with Lusztig datum (0, 0, 1, 0, 1, 1, 0, 0, 2) + PBW monomial with Lusztig datum (2, 0, 0, 0, 0, 0, 1, 3, 2) TESTS:: diff --git a/src/sage/combinat/crystals/pbw_datum.py b/src/sage/combinat/crystals/pbw_datum.py index 747766411a1..172c3478c86 100644 --- a/src/sage/combinat/crystals/pbw_datum.py +++ b/src/sage/combinat/crystals/pbw_datum.py @@ -24,7 +24,7 @@ from sage.combinat.root_system.cartan_type import CartanType from sage.combinat.root_system.coxeter_group import CoxeterGroup from sage.combinat.root_system.root_system import RootSystem -from sage.combinat.crystals.braid_move_calculator import BraidMoveCalculator +from sage.combinat.root_system.braid_move_calculator import BraidMoveCalculator class PBWDatum(object): """ @@ -281,7 +281,7 @@ def compute_new_lusztig_datum(enhanced_braid_chain, initial_lusztig_datum): EXAMPLES:: - sage: from sage.combinat.crystals.braid_move_calculator import BraidMoveCalculator + sage: from sage.combinat.root_system.braid_move_calculator import BraidMoveCalculator sage: from sage.combinat.crystals.pbw_datum import enhance_braid_move_chain sage: from sage.combinat.crystals.pbw_datum import compute_new_lusztig_datum sage: ct = CartanType(['A', 2]) @@ -294,7 +294,7 @@ def compute_new_lusztig_datum(enhanced_braid_chain, initial_lusztig_datum): TESTS:: - sage: from sage.combinat.crystals.braid_move_calculator import BraidMoveCalculator + sage: from sage.combinat.root_system.braid_move_calculator import BraidMoveCalculator sage: from sage.combinat.crystals.pbw_datum import enhance_braid_move_chain sage: from sage.combinat.crystals.pbw_datum import compute_new_lusztig_datum sage: ct = CartanType(['A', 2]) @@ -336,9 +336,9 @@ def tropical_plucker_relation(a, lusztig_datum): sage: tropical_plucker_relation((-1,-1), (1,2,3)) (4, 1, 2) sage: tropical_plucker_relation((-1,-2), (1,2,3,4)) - (6, 1, 2, 3) - sage: tropical_plucker_relation((-2,-1), (1,2,3,4)) (8, 1, 2, 3) + sage: tropical_plucker_relation((-2,-1), (1,2,3,4)) + (6, 1, 2, 3) REFERENCES: @@ -387,9 +387,8 @@ def tropical_plucker_relation(a, lusztig_datum): t1+t2+2*t3+t4+t5-pi1) else: # (-1,-2) and (-1,-3) reversed_lusztig_datum = tuple(reversed(lusztig_datum)) - return tuple(reversed( - tropical_plucker_relation(tuple(reversed(a)), - reversed_lusztig_datum))) + return tuple(reversed(tropical_plucker_relation((a[1], a[0]), + reversed_lusztig_datum))) # Maybe we need to be more specific, and pass not the Cartan type, but the root lattice? # TODO: Move to PBW_data? diff --git a/src/sage/combinat/crystals/braid_move_calculator.py b/src/sage/combinat/root_system/braid_move_calculator.py similarity index 92% rename from src/sage/combinat/crystals/braid_move_calculator.py rename to src/sage/combinat/root_system/braid_move_calculator.py index e59b9fa9216..02f4e4b356e 100644 --- a/src/sage/combinat/crystals/braid_move_calculator.py +++ b/src/sage/combinat/root_system/braid_move_calculator.py @@ -28,12 +28,11 @@ def __init__(self, coxeter_group): EXAMPLES:: - sage: from sage.combinat.crystals.braid_move_calculator import BraidMoveCalculator + sage: from sage.combinat.root_system.braid_move_calculator import BraidMoveCalculator sage: W = CoxeterGroup(['C',3]) sage: B = BraidMoveCalculator(W) sage: TestSuite(B).run(skip="_test_pickling") """ - self.coxeter_group = coxeter_group self.coxeter_matrix = coxeter_group.coxeter_matrix() def _apply_put_in_front_recur_step(self, k, input_word, coxeter_matrix_entry): @@ -42,7 +41,7 @@ def _apply_put_in_front_recur_step(self, k, input_word, coxeter_matrix_entry): EXAMPLES:: - sage: from sage.combinat.crystals.braid_move_calculator import BraidMoveCalculator + sage: from sage.combinat.root_system.braid_move_calculator import BraidMoveCalculator sage: W = CoxeterGroup(['C',3]) sage: B = BraidMoveCalculator(W) sage: B.put_in_front(2, (3, 2, 3, 1, 2, 3, 1, 2, 1)) # indirect doctest @@ -85,7 +84,7 @@ def put_in_front(self, k, input_word): EXAMPLES:: - sage: from sage.combinat.crystals.braid_move_calculator import BraidMoveCalculator + sage: from sage.combinat.root_system.braid_move_calculator import BraidMoveCalculator sage: W = CoxeterGroup(['C',3]) sage: B = BraidMoveCalculator(W) sage: B.put_in_front(2, (3, 2, 3, 1, 2, 3, 1, 2, 1)) @@ -122,7 +121,7 @@ def chain_of_reduced_words(self, start_word, end_word): EXAMPLES:: - sage: from sage.combinat.crystals.braid_move_calculator import BraidMoveCalculator + sage: from sage.combinat.root_system.braid_move_calculator import BraidMoveCalculator sage: W = CoxeterGroup(['A',5]) sage: B = BraidMoveCalculator(W) sage: B.chain_of_reduced_words((1,2,1,3,2,1,4,3,2,1,5,4,3,2,1), # not tested From bc02a86bd465726ec9a6569bdb01d493354952b5 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sun, 13 Nov 2016 19:35:08 -0600 Subject: [PATCH 085/452] Cythonizing PBW datum file. --- .../crystals/{pbw_datum.py => pbw_datum.pyx} | 45 ++++++++++--------- 1 file changed, 23 insertions(+), 22 deletions(-) rename src/sage/combinat/crystals/{pbw_datum.py => pbw_datum.pyx} (95%) diff --git a/src/sage/combinat/crystals/pbw_datum.py b/src/sage/combinat/crystals/pbw_datum.pyx similarity index 95% rename from src/sage/combinat/crystals/pbw_datum.py rename to src/sage/combinat/crystals/pbw_datum.pyx index 172c3478c86..f774fc65996 100644 --- a/src/sage/combinat/crystals/pbw_datum.py +++ b/src/sage/combinat/crystals/pbw_datum.pyx @@ -273,7 +273,7 @@ def _long_word_begin_with(self, i): return tuple([i] + (si * w0).reduced_word()) #enhanced_braid_chain is an ugly data structure. -def compute_new_lusztig_datum(enhanced_braid_chain, initial_lusztig_datum): +cpdef tuple compute_new_lusztig_datum(enhanced_braid_chain, initial_lusztig_datum): """ Return the lusztig datum obtained by applying Tropical Plucker relations along ``enhanced_braid_chain`` starting with @@ -305,8 +305,9 @@ def compute_new_lusztig_datum(enhanced_braid_chain, initial_lusztig_datum): sage: compute_new_lusztig_datum(enhanced_braid_chain,(1,0,1)) == (0,1,0) True """ + cdef tuple interval_of_change # Does not currently check that len(initial_lusztig_datum) is appropriate - new_lusztig_datum = list(initial_lusztig_datum) #shallow copy + cdef list new_lusztig_datum = list(initial_lusztig_datum) #shallow copy for interval_of_change, type_data in enhanced_braid_chain[1:]: a,b = interval_of_change old_interval_datum = new_lusztig_datum[a:b] @@ -315,7 +316,7 @@ def compute_new_lusztig_datum(enhanced_braid_chain, initial_lusztig_datum): return tuple(new_lusztig_datum) # The tropical plucker relations -def tropical_plucker_relation(a, lusztig_datum): +cpdef tuple tropical_plucker_relation(tuple a, lusztig_datum): r""" Apply the tropical Plucker relation of type ``a`` to ``lusztig_datum``. @@ -392,7 +393,7 @@ def tropical_plucker_relation(a, lusztig_datum): # Maybe we need to be more specific, and pass not the Cartan type, but the root lattice? # TODO: Move to PBW_data? -def enhance_braid_move_chain(braid_move_chain, cartan_type): +cpdef enhance_braid_move_chain(braid_move_chain, cartan_type): r""" Return a list of tuples that records the data of the long words in ``braid_move_chain`` plus the data of the intervals where the braid moves @@ -440,11 +441,13 @@ def enhance_braid_move_chain(braid_move_chain, cartan_type): sage: enhanced_chain[7] ((3, 6), (-1, -1)) """ - cartan_matrix = cartan_type.cartan_matrix() - output_list = [] + cdef int i, j + cdef tuple interval_of_change, cartan_sub_matrix + cdef list output_list = [] output_list.append( (None, None) ) previous_word = braid_move_chain[0] - # TODO - Optimize this by avoiding calls to diff_interval + cartan_matrix = cartan_type.cartan_matrix() + # TODO - Optimize this by avoiding calls to diff_interval? # This likely could be done when performing chain_of_reduced_words # Things in here get called the most (about 50x more than enhance_braid_move_chain) for current_word in braid_move_chain[1:]: @@ -456,8 +459,7 @@ def enhance_braid_move_chain(braid_move_chain, cartan_type): previous_word = current_word return output_list -# TODO: Cythonize this if this is still necessary -def diff_interval(list1, list2): +cdef tuple diff_interval(tuple t1, tuple t2): """ Return the smallest contiguous half-open interval [a,b) that contains the indices where ``list1`` and ``list2`` differ. @@ -465,22 +467,21 @@ def diff_interval(list1, list2): INPUT: - - ``list1``, ``list2`` -- two lists of the same length + - ``t1``, ``t2`` -- two tuples of the same length .. NOTE:: The input is not checked for speed. - - TESTS:: - - sage: from sage.combinat.crystals.pbw_datum import diff_interval - sage: diff_interval([1,2,3,4], [1,2,3,4]) - sage: diff_interval([1,2,3,4], [1,3,2,4]) - (1, 3) - sage: diff_interval([1,2,4,4,5], [1,3,45,6,3]) - (1, 5) """ - L = [i for i, elt in enumerate(list1) if elt != list2[i]] - if not L: + cdef int first = -1 # Set when >= 0 + cdef int last + cdef int i, elt + for i,elt in enumerate(t1): + if elt != t2[i]: + if first == -1: + first = i + last = i + if first == -1: return None - return (L[0], L[-1] + 1) + return (first, last + 1) + From 1b87cef92b9143a88b433fc07fa5c0ddbea04391 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sun, 13 Nov 2016 19:41:26 -0600 Subject: [PATCH 086/452] Moving reference to master file. --- src/doc/en/reference/references/index.rst | 5 +++++ src/sage/combinat/crystals/pbw_datum.pyx | 9 +-------- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 5e2203d6bc2..e1f4c6ce014 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -292,6 +292,11 @@ REFERENCES: complexes and posets. I*. Trans. of Amer. Math. Soc. **348** No. 4. (1996) +.. [BZ01] \A. Berenstein, A. Zelevinsky + *Tensor product multiplicities, canonical bases + and totally positive varieties* + Invent. Math. **143** No. 1. (2002), 77-128. + .. _ref-C: **C** diff --git a/src/sage/combinat/crystals/pbw_datum.pyx b/src/sage/combinat/crystals/pbw_datum.pyx index f774fc65996..1af6661bfec 100644 --- a/src/sage/combinat/crystals/pbw_datum.pyx +++ b/src/sage/combinat/crystals/pbw_datum.pyx @@ -321,8 +321,7 @@ cpdef tuple tropical_plucker_relation(tuple a, lusztig_datum): Apply the tropical Plucker relation of type ``a`` to ``lusztig_datum``. The relations are obtained by tropicalizing the relations in - Proposition 7.1 of the paper of Berenstein and Zelevinsky cited - below. + Proposition 7.1 of [BZ01]_. INPUT: @@ -340,12 +339,6 @@ cpdef tuple tropical_plucker_relation(tuple a, lusztig_datum): (8, 1, 2, 3) sage: tropical_plucker_relation((-2,-1), (1,2,3,4)) (6, 1, 2, 3) - - REFERENCES: - - .. [Berenstein-Zelevinsky01] \A. Berenstein, A. Zelevinsky - *Tensor product multiplicities, canonical bases and totally positive varieties* - Invent. Math. **143** (2002). no. 1. 77-128. """ if a == (0, 0): # A1xA1 t1, t2 = lusztig_datum From 8a15c13097654109157e2105dc37bf1cc21b7b10 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sun, 13 Nov 2016 20:59:51 -0600 Subject: [PATCH 087/452] Allow input [Lusztig_data, (reduced_word)] for constructing elements. --- src/sage/combinat/crystals/pbw_crystal.py | 31 +++++++++++++++++------ 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/sage/combinat/crystals/pbw_crystal.py b/src/sage/combinat/crystals/pbw_crystal.py index 81850c6cc3f..882a7b8f81c 100644 --- a/src/sage/combinat/crystals/pbw_crystal.py +++ b/src/sage/combinat/crystals/pbw_crystal.py @@ -30,7 +30,7 @@ class PBWCrystalElement(Element): """ A crystal element in the PBW model. """ - def __init__(self, parent, long_word, lusztig_datum): + def __init__(self, parent, lusztig_datum, long_word=None): """ Initialize ``self``. @@ -42,6 +42,8 @@ def __init__(self, parent, long_word, lusztig_datum): sage: TestSuite(b).run() """ Element.__init__(self, parent) + if long_word is None: + long_word = parent._default_word self._pbw_datum = PBWDatum(parent._pbw_datum_parent, long_word, lusztig_datum) def _repr_(self): @@ -206,7 +208,7 @@ def e(self, i): if new_lusztig_datum[0] == 0: return None new_lusztig_datum[0] -= 1 - return type(self)(self.parent(), new_long_word, tuple(new_lusztig_datum)) + return type(self)(self.parent(), tuple(new_lusztig_datum), new_long_word) def f(self, i): """ @@ -225,7 +227,7 @@ def f(self, i): new_long_word = equiv_PBWDatum.long_word new_lusztig_datum = list(equiv_PBWDatum.lusztig_datum) new_lusztig_datum[0] += 1 - return type(self)(self.parent(), new_long_word, tuple(new_lusztig_datum)) + return type(self)(self.parent(), tuple(new_lusztig_datum), new_long_word) def epsilon(self, i): r""" @@ -293,16 +295,29 @@ def star(self): True """ starred_pbw_datum = self._pbw_datum.star() - return type(self)(self.parent(), starred_pbw_datum.long_word, - starred_pbw_datum.lusztig_datum) + return type(self)(self.parent(), starred_pbw_datum.lusztig_datum, + starred_pbw_datum.long_word) class PBWCrystal(Parent, UniqueRepresentation): r""" Crystal of `\mathcal{B}(\infty)` given by PBW monomials. - A model of the crystal `\mathcal{B}(\infty)` whose elements are + A model of the crystal `\mathcal{B}(\infty)` whose elements are PBW datum up to equivalence by the tropical Plucker relations. + + EXAMPLES:: + + sage: PBW = crystals.infinity.PBW(['B', 3]) + sage: hw = PBW.highest_weight_vector() + sage: hw.f_string([1,2,2,3,3,1,3,3,2,3,2,1,3,1,2,3,1,2,1,3,2]) + PBW monomial with Lusztig datum (1, 1, 1, 3, 1, 0, 0, 1, 1) + sage: PBW([1,1,1,3,1,0,0,1,1]) + PBW monomial with Lusztig datum (1, 1, 1, 3, 1, 0, 0, 1, 1) + sage: x = PBW([1,1,1,3,1,0,0,1,1], [3,2,1,3,2,3,2,1,2]); x + PBW monomial with Lusztig datum (1, 1, 1, 0, 1, 0, 5, 1, 1) + sage: x.to_highest_weight()[1] + [1, 2, 2, 2, 2, 2, 1, 3, 3, 3, 3, 2, 3, 2, 3, 3, 2, 3, 3, 2, 1, 3] """ @staticmethod def __classcall__(cls, cartan_type): @@ -341,8 +356,8 @@ def __init__(self, cartan_type): self._default_word = self._pbw_datum_parent._long_word_begin_with(i) zero_lusztig_datum = [0]*len(self._default_word) self.module_generators = (self.element_class(self, - self._default_word, - zero_lusztig_datum),) + zero_lusztig_datum, + self._default_word),) def _repr_(self): """ From fa41d5de69991dc8f7f794766d2acba8e4d3893b Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Mon, 14 Nov 2016 15:43:04 -0600 Subject: [PATCH 088/452] File moved, so reference needs to move too. --- src/doc/en/reference/combinat/module_list.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/en/reference/combinat/module_list.rst b/src/doc/en/reference/combinat/module_list.rst index 022f1f2c035..d488ab4e609 100644 --- a/src/doc/en/reference/combinat/module_list.rst +++ b/src/doc/en/reference/combinat/module_list.rst @@ -53,7 +53,6 @@ Comprehensive Module list sage/combinat/crystals/affinization sage/combinat/crystals/alcove_path sage/combinat/crystals/all - sage/combinat/crystals/braid_move_calculator sage/combinat/crystals/catalog sage/combinat/crystals/catalog_elementary_crystals sage/combinat/crystals/catalog_infinity_crystals @@ -214,6 +213,7 @@ Comprehensive Module list sage/combinat/root_system/all sage/combinat/root_system/ambient_space sage/combinat/root_system/associahedron + sage/combinat/root_system/braid_move_calculator sage/combinat/root_system/branching_rules sage/combinat/root_system/cartan_matrix sage/combinat/root_system/cartan_type From 67d76b7b283a66fab3b038d7d9eca57b2819cdca Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 15 Nov 2016 10:05:01 -0600 Subject: [PATCH 089/452] Fixing the star involution. --- src/sage/combinat/crystals/pbw_crystal.py | 44 ++++++++++++++++++++--- src/sage/combinat/crystals/pbw_datum.pyx | 5 +-- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/src/sage/combinat/crystals/pbw_crystal.py b/src/sage/combinat/crystals/pbw_crystal.py index 882a7b8f81c..51482ee015b 100644 --- a/src/sage/combinat/crystals/pbw_crystal.py +++ b/src/sage/combinat/crystals/pbw_crystal.py @@ -236,7 +236,7 @@ def epsilon(self, i): EXAMPLES:: sage: B = crystals.infinity.PBW(["A2"]) - sage: s = B((1,2,1), (3,0,0)) + sage: s = B((3,0,0), (1,2,1)) sage: s.epsilon(1) 3 sage: s.epsilon(2) @@ -252,7 +252,7 @@ def phi(self, i): EXAMPLES:: sage: B = crystals.infinity.PBW(['A', 2]) - sage: s = B((1,2,1), (3,0,0)) + sage: s = B((3,0,0), (1,2,1)) sage: s.phi(1) -3 sage: s.phi(2) @@ -269,7 +269,7 @@ def weight(self): EXAMPLES:: sage: B = crystals.infinity.PBW(['A', 2]) - sage: s = B((1,2,1), (2,2,2)) + sage: s = B((2,2,2), (1,2,1)) sage: s.weight() (-4, 0, 4) """ @@ -282,10 +282,18 @@ def star(self): Return the starred crystal element corresponding to ``self``. + Let `b` be an element of ``self`` with Lusztig datum + `(b_1, \ldots, b_N)` with respect to `w_0 = s_{i_1} \cdots s_{i_N}`. + Then `b^*` is the element with Lusztig datum `(b_N, \ldots, b_1)` + with respect to `w_0 = s_{i_N^*} \cdots s_{i_1^*}`, where + `i_j^* = \omega(i_j)` with `\omega` being the :meth:`automorphism + ` + given by the action of `w_0` on the simple roots. + EXAMPLES:: sage: P = crystals.infinity.PBW(['A', 2]) - sage: P((1,2,1), (1,2,3)).star() == P((1,2,1), (3,2,1)) + sage: P((1,2,3), (1,2,1)).star() == P((3,2,1), (2,1,2)) True sage: B = crystals.infinity.PBW(['E', 6]) @@ -293,6 +301,34 @@ def star(self): sage: c = b.f_string([1,2,6,3,4,2,5,2,3,4,1,6]) sage: c == c.star().star() True + + TESTS:: + + sage: from itertools import product + sage: def test_star(PBW, depth): + ....: S = crystals.infinity.Star(PBW) + ....: for f_str in product(*([PBW.index_set()]*depth)): + ....: x = PBW.highest_weight_vector().f_string(f_str).star() + ....: y = S.highest_weight_vector().f_string(f_str) + ....: assert x.lusztig_datum() == y.value.lusztig_datum() + sage: P = crystals.infinity.PBW(['A', 2]) + sage: test_star(P, 5) + sage: P = crystals.infinity.PBW(['A', 3]) + sage: test_star(P, 5) + sage: P = crystals.infinity.PBW(['B', 3]) + sage: test_star(P, 5) + sage: P = crystals.infinity.PBW(['C', 3]) + sage: test_star(P, 5) + sage: P = crystals.infinity.PBW(['D', 4]) + sage: test_star(P, 5) # long time + sage: P = crystals.infinity.PBW(['D', 5]) + sage: test_star(P, 4) # long time + sage: P = crystals.infinity.PBW(['E', 6]) + sage: test_star(P, 4) # long time + sage: P = crystals.infinity.PBW(['F', 4]) + sage: test_star(P, 4) # long time + sage: P = crystals.infinity.PBW(['G', 2]) + sage: test_star(P, 5) """ starred_pbw_datum = self._pbw_datum.star() return type(self)(self.parent(), starred_pbw_datum.lusztig_datum, diff --git a/src/sage/combinat/crystals/pbw_datum.pyx b/src/sage/combinat/crystals/pbw_datum.pyx index 1af6661bfec..cb0d8c5f065 100644 --- a/src/sage/combinat/crystals/pbw_datum.pyx +++ b/src/sage/combinat/crystals/pbw_datum.pyx @@ -169,10 +169,11 @@ class PBWDatum(object): sage: from sage.combinat.crystals.pbw_datum import PBWData, PBWDatum sage: P = PBWData("A2") sage: L1 = PBWDatum(P, (1,2,1), (1,2,3)) - sage: L1.star() == PBWDatum(P, (1,2,1), (3,2,1)) + sage: L1.star() == PBWDatum(P, (2,1,2), (3,2,1)) True """ - reversed_long_word = reversed(self.long_word) + aut = self.parent.cartan_type.opposition_automorphism() + reversed_long_word = [aut[i] for i in reversed(self.long_word)] reversed_lusztig_datum = reversed(self.lusztig_datum) return PBWDatum(self.parent, reversed_long_word, reversed_lusztig_datum) From 01163ca76ce77b5900094484f8145e9c35dfdbc4 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 16 Nov 2016 09:51:00 -0600 Subject: [PATCH 090/452] Trivial doctest fix. --- src/sage/combinat/root_system/root_lattice_realizations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/root_system/root_lattice_realizations.py b/src/sage/combinat/root_system/root_lattice_realizations.py index 522ccc87b79..0f73f79fa0c 100644 --- a/src/sage/combinat/root_system/root_lattice_realizations.py +++ b/src/sage/combinat/root_system/root_lattice_realizations.py @@ -3068,8 +3068,8 @@ def plot_mv_polytope(self, mv_polytope, mark_endpoints=True, sage: B = crystals.infinity.MVPolytopes(['A',3]) sage: L = RootSystem(['A',3]).ambient_space() sage: p = B.highest_weight_vector().f_string([2,1,3,2]) - sage: L = RootSystem(['A',3]).ambient_space() sage: L.plot_mv_polytope(p) + Graphics3d Object """ from sage.geometry.polyhedron.all import Polyhedron plot_options = self.plot_parse_options(**options) From bf3828fc04d0cb0a8380cfcc58c3d0a03136e1e6 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Fri, 18 Nov 2016 10:05:46 -0600 Subject: [PATCH 091/452] Updating things --- src/doc/en/reference/references/index.rst | 13 ++++++++++++ .../categories/affine_derived_crystals.py | 21 ++++--------------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 09cb94087f7..08c9aeafd5c 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -614,6 +614,10 @@ REFERENCES: curves". LMS Journal of Computation and Mathematics (2014), volume 17, issue 01, pp. 1-23. +.. [FOS2010] \G. Fourier, M. Okado, A. Schilling. *Perfectness of + Kirillov-Reshetikhin crystals for nonexceptional types*. + Contemp. Math. 506 (2010) 127-143 ( :arxiv:`0811.1604` ) + .. [FP1996] Komei Fukuda, Alain Prodon: Double Description Method Revisited, Combinatorics and Computer Science, volume 1120 of Lecture Notes in Computer Science, page @@ -856,6 +860,10 @@ REFERENCES: actions, 2.2 p. 70. BI-Wissenschaftsverlag, Mannheim, 1991. +.. [KKMMNN1992] S-J. Kang, M. Kashiwara, K. C. Misra, T. Miwa, T. Nakashima, + and A. Nakayashiki. *Affine crystals and vertex models*. + Int. J. Mod. Phys. A, **7** (suppl. 1A), (1992) pp. 449-484. + .. [KL2008] Chris Kurth and Ling Long, "Computations with finite index subgroups of `{\rm PSL}_2(\ZZ)` using Farey symbols", Advances in algebra and combinatorics, 225--242, World @@ -1344,6 +1352,11 @@ REFERENCES: manifolds and complexes into a cubic lattice", *Uspekhi Mat. Nauk* 47 (1992), 219-220. +.. [ST2011] \A. Schilling, P. Tingley. *Demazure crystals, + Kirillov-Reshetikhin crystals, and the energy function*. + Electronic Journal of Combinatorics. **19(2)**. 2012. + :arXiv:`1104.2359` + .. [Sta2007] Stanley, Richard: *Hyperplane Arrangements*, Geometric Combinatorics (E. Miller, V. Reiner, and B. Sturmfels, eds.), IAS/Park City Mathematics Series, vol. 13, diff --git a/src/sage/categories/affine_derived_crystals.py b/src/sage/categories/affine_derived_crystals.py index 28d8939d395..4d89e3a3922 100644 --- a/src/sage/categories/affine_derived_crystals.py +++ b/src/sage/categories/affine_derived_crystals.py @@ -378,7 +378,7 @@ def R_matrix(self, K): sage: K2 = crystals.KirillovReshetikhin(['A',2,1],2,1) sage: T1 = crystals.TensorProduct(K1,K2) sage: T2 = crystals.TensorProduct(K2,K1) - sage: T1.digraph().is_isomorphic(T2.digraph(), edge_labels = True, certify = True) #todo: not implemented (see #10904 and #10549) + sage: T1.digraph().is_isomorphic(T2.digraph(), edge_labels=True, certificate=True) #todo: not implemented (see #10904 and #10549) (True, {[[[1]], [[2], [3]]]: [[[1], [3]], [[2]]], [[[3]], [[2], [3]]]: [[[2], [3]], [[3]]], [[[3]], [[1], [3]]]: [[[1], [3]], [[3]]], [[[1]], [[1], [3]]]: [[[1], [3]], [[1]]], [[[1]], [[1], [2]]]: [[[1], [2]], [[1]]], [[[2]], [[1], [2]]]: [[[1], [2]], [[2]]], [[[3]], @@ -486,9 +486,7 @@ def is_perfect(self, ell=None): REFERENCES: - .. [FOS2010] \G. Fourier, M. Okado, A. Schilling. *Perfectness of - Kirillov-Reshetikhin crystals for nonexceptional types*. - Contemp. Math. 506 (2010) 127-143 ( :arxiv:`0811.1604` ) + [FOS2010]_ EXAMPLES:: @@ -849,7 +847,7 @@ def energy_function(self, algorithm=None): grading of the maximal vector in `T`. Then the energy of ``self`` is given by `d - g`. - For more details, see Theorem 7.5 in [SchillingTingley2011]_. + For more details, see Theorem 7.5 in [ST2011]_. INPUT: @@ -866,14 +864,6 @@ def energy_function(self, algorithm=None): OUTPUT: an integer - REFERENCES: - - .. [SchillingTingley2011] \A. Schilling, P. Tingley. - *Demazure crystals, Kirillov-Reshetikhin crystals, and - the energy function*. - Electronic Journal of Combinatorics. **19(2)**. 2012. - :arXiv:`1104.2359` - EXAMPLES:: sage: K = crystals.KirillovReshetikhin(['A',2,1], 1, 1) @@ -1089,10 +1079,7 @@ class LocalEnergyFunction(Map): REFERENCES: - .. [KKMMNN92] S-J. Kang, M. Kashiwara, K. C. Misra, T. Miwa, - T. Nakashima, and A. Nakayashiki. - *Affine crystals and vertex models*. - Int. J. Mod. Phys. A, **7** (suppl. 1A), (1992) pp. 449-484. + [KKMMNN1992]_ """ def __init__(self, B, Bp, normalization=0): """ From 9b17d31ecf0a63f5bfd3663dcba375080a9a48a9 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sat, 19 Nov 2016 17:24:55 -0600 Subject: [PATCH 092/452] Giving HochschildComplex a proper element and making it pass the TestSuite. --- src/sage/homology/hochschild_complex.py | 278 +++++++++++++++++++++++- 1 file changed, 272 insertions(+), 6 deletions(-) diff --git a/src/sage/homology/hochschild_complex.py b/src/sage/homology/hochschild_complex.py index 7d71d01acb9..99500b98aec 100644 --- a/src/sage/homology/hochschild_complex.py +++ b/src/sage/homology/hochschild_complex.py @@ -14,13 +14,14 @@ from sage.misc.cachefunc import cached_method from sage.structure.unique_representation import UniqueRepresentation -from sage.structure.category_object import CategoryObject +from sage.structure.parent import Parent +from sage.structure.element import ModuleElement from sage.categories.category_types import ChainComplexes from sage.categories.tensor import tensor from sage.combinat.free_module import CombinatorialFreeModule -from sage.homology.chain_complex import ChainComplex +from sage.homology.chain_complex import ChainComplex, Chain_class -class HochschildComplex(UniqueRepresentation, CategoryObject): +class HochschildComplex(UniqueRepresentation, Parent): r""" The Hochschild complex. @@ -96,12 +97,12 @@ def __init__(self, A, M): Some methods required by the category are not implemented:: - sage: TestSuite(H).run() # known bug (#21386) + sage: TestSuite(H).run() """ self._A = A self._M = M - CategoryObject.__init__(self, base=A.base_ring(), - category=ChainComplexes(A.base_ring())) + Parent.__init__(self, base=A.base_ring(), + category=ChainComplexes(A.base_ring())) def _repr_(self): """ @@ -452,3 +453,268 @@ def cohomology(self, d): unitriangular=True) return ker.quotient_module(im_retract) + def _element_constructor_(self, vectors): + """ + Construct an element of ``self`` from ``vectors``. + + TESTS:: + + sage: E. = ExteriorAlgebra(QQ) + sage: H = E.hochschild_complex(E) + sage: H(0) + Trivial chain + sage: H(x+2*y) + Chain(0: x + 2*y) + sage: H({0: H.free_module(0).an_element()}) + Chain(0: 2 + 2*x + 3*y) + sage: H({2: H.free_module(2).an_element()}) + Chain(2: 2*1 # 1 # 1 + 2*1 # 1 # x + 3*1 # 1 # y) + sage: H({0:x-y, 2: H.free_module(2).an_element()}) + Chain with 2 nonzero terms over Rational Field + """ + if not vectors: # special case: the zero chain + return self.element_class(self, {}) + # special case: an element of the defining module + if isinstance(vectors, self._M.element_class) and vectors.parent() is self._M: + mc = vectors.monomial_coefficients(copy=False) + vec = self.free_module(0)._from_dict({(k,): mc[k] for k in mc}) + return self.element_class(self, {0: vec}) + if isinstance(vectors, (Chain_class, self.element_class)): + vectors = vectors._vec + data = dict() + # Special handling for the 0 free module + # FIXME: Allow coercions between the 0 free module and the defining module + if 0 in vectors: + vec = vectors.pop(0) + if vec.parent() is self._M: + mc = vec.monomial_coefficients(copy=False) + data[0] = self.free_module(0)._from_dict({(k,): mc[k] for k in mc}) + else: + data[0] = self.free_module(0)(vec) + for degree in vectors: + vec = self.free_module(degree)(vectors[degree]) + if not vec: + continue + data[degree] = vec + return self.element_class(self, data) + + def _an_element_(self): + """ + Return an element of ``self``. + + EXAMPLES:: + + sage: F. = FreeAlgebra(ZZ) + sage: H = F.hochschild_complex(F) + sage: v = H.an_element() + sage: [v.vector(i) for i in range(6)] + [2*F[1] + 2*F[x] + 3*F[y], + 2*F[1] # F[1] + 2*F[1] # F[x] + 3*F[1] # F[y], + 2*F[1] # F[1] # F[1] + 2*F[1] # F[1] # F[x] + 3*F[1] # F[1] # F[y], + 2*F[1] # F[1] # F[1] # F[1] + 2*F[1] # F[1] # F[1] # F[x] + + 3*F[1] # F[1] # F[1] # F[y], + 0, + 0] + """ + return self.element_class(self, {d: self.free_module(d).an_element() + for d in range(4)}) + + class Element(ModuleElement): + def __init__(self, parent, vectors): + """ + Initialize ``self``. + + EXAMPLES:: + + sage: F. = FreeAlgebra(ZZ) + sage: H = F.hochschild_complex(F) + sage: a = H({0: x-y, 2: H.free_module(2).basis().an_element()}) + sage: TestSuite(a).run() + """ + self._vec = vectors + ModuleElement.__init__(self, parent) + + def vector(self, degree): + """ + Return the free module element in ``degree``. + + EXAMPLES:: + + sage: F. = FreeAlgebra(ZZ) + sage: H = F.hochschild_complex(F) + sage: a = H({0: x-y, 2: H.free_module(2).basis().an_element()}) + sage: [a.vector(i) for i in range(3)] + [F[x] - F[y], 0, F[1] # F[1] # F[1]] + """ + try: + return self._vec[degree] + except KeyError: + return self.parent().free_module(degree).zero() + + def _repr_(self): + """ + Print representation. + + EXAMPLES:: + + sage: E. = ExteriorAlgebra(QQ) + sage: H = E.hochschild_complex(E) + sage: H(0) + Trivial chain + sage: H(x+2*y) + Chain(0: x + 2*y) + sage: H({2: H.free_module(2).an_element()}) + Chain(2: 2*1 # 1 # 1 + 2*1 # 1 # x + 3*1 # 1 # y) + sage: H({0:x-y, 2: H.free_module(2).an_element()}) + Chain with 2 nonzero terms over Rational Field + """ + n = len(self._vec) + if n == 0: + return 'Trivial chain' + + if n == 1: + deg, vec = self._vec.items()[0] + return 'Chain({0}: {1})'.format(deg, vec) + + return 'Chain with {0} nonzero terms over {1}'.format(n, + self.parent().base_ring()) + + def _ascii_art_(self): + """ + Return an ascii art representation. + + Note that arrows go to the left so that composition of + differentials is the usual matrix multiplication. + + EXAMPLES:: + + sage: F. = FreeAlgebra(ZZ) + sage: H = F.hochschild_complex(F) + sage: a = H({0: x - y, + ....: 1: H.free_module(1).basis().an_element(), + ....: 2: H.free_module(2).basis().an_element()}) + sage: ascii_art(a) + d_0 d_1 d_2 d_3 + 0 <---- F - F <---- 1 # 1 <---- 1 # 1 # 1 <---- 0 + x y + """ + from sage.typeset.ascii_art import AsciiArt, ascii_art + + if not self._vec: # 0 chain + return AsciiArt(['0']) + + def arrow_art(d): + d_str = [' d_{0} '.format(d)] + arrow = ' <' + '-'*(len(d_str[0])-3) + ' ' + d_str.append(arrow) + return AsciiArt(d_str, baseline=0) + + result = AsciiArt(['0']) + max_deg = max(self._vec) + for deg in range(min(self._vec), max_deg+1): + A = ascii_art(self.vector(deg)) + A._baseline = A.height() // 2 + result += arrow_art(deg) + A + return result + arrow_art(max_deg+1) + AsciiArt(['0']) + + def _add_(self, other): + """ + Module addition + + EXAMPLES:: + + sage: F. = FreeAlgebra(ZZ) + sage: H = F.hochschild_complex(F) + sage: a = H({0: x - y, + ....: 1: H.free_module(1).basis().an_element(), + ....: 2: H.free_module(2).basis().an_element()}) + sage: [a.vector(i) for i in range(3)] + [F[x] - F[y], F[1] # F[1], F[1] # F[1] # F[1]] + sage: [H.an_element().vector(i) for i in range(3)] + [2*F[1] + 2*F[x] + 3*F[y], + 2*F[1] # F[1] + 2*F[1] # F[x] + 3*F[1] # F[y], + 2*F[1] # F[1] # F[1] + 2*F[1] # F[1] # F[x] + 3*F[1] # F[1] # F[y]] + + sage: v = a + H.an_element() + sage: [v.vector(i) for i in range(3)] + [2*F[1] + 3*F[x] + 2*F[y], + 3*F[1] # F[1] + 2*F[1] # F[x] + 3*F[1] # F[y], + 3*F[1] # F[1] # F[1] + 2*F[1] # F[1] # F[x] + 3*F[1] # F[1] # F[y]] + """ + vectors = dict(self._vec) # Make a (shallow) copy + for d in other._vec: + if d in vectors: + vectors[d] += other._vec[d] + if not vectors[d]: + del vectors[d] + else: + vectors[d] = other._vec + parent = self.parent() + return parent.element_class(parent, vectors) + + def _lmul_(self, scalar): + """ + Scalar multiplication + + EXAMPLES:: + + sage: F. = FreeAlgebra(ZZ) + sage: H = F.hochschild_complex(F) + sage: a = H({0: x - y, + ....: 1: H.free_module(1).basis().an_element(), + ....: 2: H.free_module(2).basis().an_element()}) + sage: v = 3*a + sage: [v.vector(i) for i in range(3)] + [3*F[x] - 3*F[y], 3*F[1] # F[1], 3*F[1] # F[1] # F[1]] + """ + if scalar == 0: + return self.zero() + vectors = dict() + for d in self._vec: + vec = scalar * self._vec[d] + if vec: + vectors[d] = vec + return self.__class__(self.parent(), vectors) + + def __eq__(self, other): + """ + Return ``True`` if ``self`` is equal to ``other``. + + EXAMPLES:: + + sage: F. = FreeAlgebra(ZZ) + sage: H = F.hochschild_complex(F) + sage: a = H({0: x - y, + ....: 1: H.free_module(1).basis().an_element(), + ....: 2: H.free_module(2).basis().an_element()}) + sage: a == 3*a + False + sage: a + a == 2*a + True + sage: a == H.zero() + False + """ + return (type(self) == type(other) + and self.parent() is other.parent() + and self._vec == other._vec) + + def __ne__(self, other): + """ + Return ``True`` if ``self`` is not equal to ``other``. + + EXAMPLES:: + + sage: F. = FreeAlgebra(ZZ) + sage: H = F.hochschild_complex(F) + sage: a = H({0: x - y, + ....: 1: H.free_module(1).basis().an_element(), + ....: 2: H.free_module(2).basis().an_element()}) + sage: a != 3*a + True + sage: a + a != 2*a + False + sage: a != H.zero() + True + """ + return not self == other + From cf2e4e4abd2278ae9183e19ac8872ca4cfed4550 Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Fri, 30 Dec 2016 08:11:30 -0500 Subject: [PATCH 093/452] Fix to doctest --- src/sage/combinat/set_partition.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index 7266b983699..2b20bd53059 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -419,18 +419,18 @@ def set_latex_options(self, opts): - ``tikz_scale`` -- (default: 1) scale for use with tikz package. - ``plot`` -- (default: ``) ```` returns the set notation, ``linear`` - returns a linear plot, ``cyclic`` returns a cyclic plot + returns a linear plot, ``cyclic`` returns a cyclic plot - ``color`` -- (default: black) the arc colors. - ``fill`` -- (default: False) If True then fills black, else you can - pass in a color to alter the fill color. *Only works with cyclic plot* + pass in a color to alter the fill color. *Only works with cyclic plot* - ``show_labels`` -- (default: True) If True shows labels - *only works - with plots* + with plots* - ``radius`` -- (default: "1cm") Radius of circle for cyclic plot. *Only - works with cyclic plot* + works with cyclic plot* - ``angle`` -- (default: 0) Angle for linear @@ -454,6 +454,7 @@ def latex_options(self): Options can be found in set_latex_options() EXAMPLES:: + sage: SP = SetPartition([[1,6], [3,5,4]]); SP.latex_options() {'angle': 0, 'color': 'black', @@ -462,7 +463,6 @@ def latex_options(self): 'radius': '1cm', 'show_labels': True, 'tikz_scale': 1} - """ opts = self._latex_options.copy() if "tikz_scale" not in opts: @@ -560,7 +560,7 @@ def _latex_(self): res += " -- cycle;\n" # If we want line plots - if latex_options['plot'] == 'linear' or latex_options['plot'] == 'line' or latex_options['plot'] == 'planar': + elif latex_options['plot'] == 'linear' or latex_options['plot'] == 'line' or latex_options['plot'] == 'planar': angle = latex_options['angle'] # setup line for k,i in enumerate(base_set): From 5d06a22c9192dd795201050e93dc7b461e707eb1 Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Sun, 8 Jan 2017 14:59:19 -0500 Subject: [PATCH 094/452] Include suggestions of tscrim --- src/sage/combinat/set_partition.py | 54 +++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 16 deletions(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index 2b20bd53059..a099f42072b 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -411,15 +411,16 @@ def _repr_(self): """ return '{' + ', '.join(('{' + repr(sorted(x))[1:-1] + '}' for x in self)) + '}' - def set_latex_options(self, opts): + def set_latex_options(self, **kwargs): r""" - Set the latex options for use in the ``_latex_`` function. The default - values are set in the ``__init__`` function. + Set the latex options for use in the ``_latex_`` function. - ``tikz_scale`` -- (default: 1) scale for use with tikz package. - - ``plot`` -- (default: ``) ```` returns the set notation, ``linear`` - returns a linear plot, ``cyclic`` returns a cyclic plot + - ``plot`` -- (default: ``''``) ``''`` returns the set notation, + ``linear`` returns a linear plot, ``cyclic`` returns a cyclic + plot. + - ``color`` -- (default: black) the arc colors. @@ -434,18 +435,34 @@ def set_latex_options(self, opts): - ``angle`` -- (default: 0) Angle for linear - INPUT: - - - ``opts`` -- a dictionary with a list of latex parameters to change - EXAMPLES:: sage: SP = SetPartition([[1,6], [3,5,4]]) - sage: SP.set_latex_options({'tikz_scale':2,'plot':'linear', 'fill':True, 'color':'blue', 'angle':45}) + sage: SP.set_latex_options(tikz_scale=2,plot='linear',fill=True,color='blue',angle=45) + sage: SP.set_latex_options(plot='cyclic') + sage: SP.latex_options() + {'angle': 45, + 'color': 'blue', + 'fill': True, + 'plot': 'cyclic', + 'radius': '1cm', + 'show_labels': True, + 'tikz_scale': 2} + """ + valid_args = ['tikz_scale', 'plot', 'color', 'fill', 'show_labels', + 'radius', 'angle'] + + for key in kwargs: + if key not in valid_args: + raise ValueError("unknown keyword argument: %s"%key) + if key == 'plot': + if kwargs['plot'] != 'cyclic' and kwargs['plot'] != 'linear' and kwargs['plot'] != '': + raise ValueError("plot must be blank, 'cyclic', or 'linear'") + + for opt in kwargs: + self._latex_options[opt] = kwargs[opt] - for opt in opts: - self._latex_options[opt] = opts[opt] def latex_options(self): r""" Return the latex options for use in the ``_latex_`` function as a @@ -480,6 +497,7 @@ def latex_options(self): if "angle" not in opts: opts['angle'] = 0 return opts + def _latex_(self): r""" Return a `\LaTeX` string representation of ``self``. @@ -490,7 +508,7 @@ def _latex_(self): sage: latex(x) \{\{1, 2\}, \{3, 4, 5\}\} sage: p=SetPartition([['a','c'],['b',1],[20]]) - sage: p.set_latex_options({'plot':'circle', 'color':'blue', 'angle':45, 'fill':True, 'tikz_scale':2}) + sage: p.set_latex_options(plot='cyclic', color='blue', angle=45, fill=True, tikz_scale=2) sage: latex(p) \begin{tikzpicture}[scale=2] \node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black,label=90:a] (0) at (90:1cm) {}; @@ -521,7 +539,7 @@ def _latex_(self): color= latex_options['color'] # If we want cyclic plots - if latex_options['plot'] == 'cyclic' or latex_options['plot'] == 'cycle' or latex_options['plot'] == 'circle' or latex_options['plot'] == 'circular': + if latex_options['plot'] == 'cyclic': degrees = 360 / cardinality radius = latex_options['radius'] @@ -560,7 +578,7 @@ def _latex_(self): res += " -- cycle;\n" # If we want line plots - elif latex_options['plot'] == 'linear' or latex_options['plot'] == 'line' or latex_options['plot'] == 'planar': + elif latex_options['plot'] == 'linear': angle = latex_options['angle'] # setup line for k,i in enumerate(base_set): @@ -1127,6 +1145,11 @@ def plot(self, angle=None, color='black', base_set_dict=None): """ Return a plot of ``self``. + .. PLOT:: + + p=SetPartition([[1,10,11],[2,3,7],[4,5,6],[8,9]]) + sphinx_plot(p.plot()) + INPUT: - ``angle`` -- the angle at which the arcs take off (if angle is negative, the arcs are drawn below the horizontal line) @@ -1949,7 +1972,6 @@ def cyclic_permutations_of_set_partition(set_part): """ return list(cyclic_permutations_of_set_partition_iterator(set_part)) - def cyclic_permutations_of_set_partition_iterator(set_part): """ Iterates over all combinations of cyclic permutations of each cell From b7d3c0b027556df25e9adcc240fddb352d404d5a Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Sun, 8 Jan 2017 16:00:37 -0500 Subject: [PATCH 095/452] Fixing sentence structures and whitespace --- src/sage/combinat/set_partition.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index a099f42072b..8e92173e818 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -413,27 +413,27 @@ def _repr_(self): def set_latex_options(self, **kwargs): r""" - Set the latex options for use in the ``_latex_`` function. + Set the latex options for use in the ``_latex_`` function - - ``tikz_scale`` -- (default: 1) scale for use with tikz package. + - ``tikz_scale`` -- (default: 1) scale for use with tikz package - ``plot`` -- (default: ``''``) ``''`` returns the set notation, ``linear`` returns a linear plot, ``cyclic`` returns a cyclic - plot. + plot - - ``color`` -- (default: black) the arc colors. + - ``color`` -- (default: black) the arc colors - - ``fill`` -- (default: False) If True then fills black, else you can - pass in a color to alter the fill color. *Only works with cyclic plot* + - ``fill`` -- (default: False) if True then fills black, else you can + pass in a color to alter the fill color - *only works with cyclic plot* - - ``show_labels`` -- (default: True) If True shows labels - *only works + - ``show_labels`` -- (default: True) if True shows labels - *only works with plots* - - ``radius`` -- (default: "1cm") Radius of circle for cyclic plot. *Only + - ``radius`` -- (default: "1cm") radius of circle for cyclic plot - *Only works with cyclic plot* - - ``angle`` -- (default: 0) Angle for linear + - ``angle`` -- (default: 0) angle for linear EXAMPLES:: @@ -748,7 +748,7 @@ def apply_permutation(self, p): INPUT: - - ``p`` -- A permutation + - ``p`` -- a permutation EXAMPLES:: @@ -1152,9 +1152,13 @@ def plot(self, angle=None, color='black', base_set_dict=None): INPUT: - - ``angle`` -- the angle at which the arcs take off (if angle is negative, the arcs are drawn below the horizontal line) + - ``angle`` -- the angle at which the arcs take off (if angle is negative, + the arcs are drawn below the horizontal line) + - ``color`` -- color of the arcs - - ``base_set_dict`` -- dictionary with keys elements of self.base_set() and values as integer or float + + - ``base_set_dict`` -- dictionary with keys elements of self.base_set() + and values as integer or float EXAMPLES:: From 7467913b56d7ac5deefb7bd3abc0b9ed62265b6d Mon Sep 17 00:00:00 2001 From: Jeroen Demeyer Date: Mon, 9 Jan 2017 13:55:33 +0100 Subject: [PATCH 096/452] Upgrade to libpng-1.6.28 --- build/pkgs/libpng/SPKG.txt | 40 ++++++++++---------- build/pkgs/libpng/checksums.ini | 6 +-- build/pkgs/libpng/package-version.txt | 2 +- build/pkgs/libpng/patches/pngconf.h.patch | 24 ------------ build/pkgs/libpng/spkg-install | 32 ++-------------- build/pkgs/tachyon/patches/Make-config.patch | 2 +- 6 files changed, 28 insertions(+), 78 deletions(-) delete mode 100644 build/pkgs/libpng/patches/pngconf.h.patch diff --git a/build/pkgs/libpng/SPKG.txt b/build/pkgs/libpng/SPKG.txt index 9ef5facecad..fd1619c178c 100644 --- a/build/pkgs/libpng/SPKG.txt +++ b/build/pkgs/libpng/SPKG.txt @@ -27,26 +27,26 @@ This spkg depends on: == Special Update/Build Instructions == - * No changes went into src. There are two different tarballs, but we use the - one with configure. - * On Darwin, the symbolic links libpng.* created by libpng12 may interfere - with a system-wide libPng.dylib. - This system-wide library is likely to be a different version and on top of - that the symbols exported there are prefixed with "_cg" (for "Core Graphics"), - so even if by chance the functionalities of the two libraries were interchangeable, - libraries or applications looking for one and being presented the other won't - find the symbols they expect. - Note the uppercase "P" which could prevent this conflict; unfortunately, the - default filesystem used by Apple is case-insensitive. - Also note there would be no problem if the system-wide library was not looked - for when Sage is being built or run, but that's not the case either; - it is at least looked for by the "ImageIO" framework: + * On Darwin, the symbolic links libpng.* created by libpng16 may + interfere with a system-wide libPng.dylib. + + This system-wide library is likely to be a different version and on + top of that, the symbols exported there are prefixed with "_cg" + (for "Core Graphics"). So even if by chance the functionalities of + the two libraries were interchangeable, libraries or applications + looking for one and being presented the other won't find the symbols + they expect. Note the uppercase "P" which could prevent this + conflict; unfortunately, the default filesystem used by Apple is + case-insensitive. + + Note there would be no problem if the system-wide library was not + looked for when Sage is being built or run, but that's not the case + either; it is at least looked for by the "ImageIO" framework: - when Python is built with Mac OS extensions, fixed in #4008; - when Mercurial is built because it uses $EDITOR, cf. #4678; - when R is built and it finds -lpng, cf. #4409 and #11696. - As not all of these problems are easily dealt with and new ones may arise, - we chose to delete the $SAGE_LOCAL/lib/libpng.* symlinks on Darwin. - Therefore, some package as matplotlib (cf. #11686) which by default looks for - -lpng are patched to look for -lpng12 (unless pkg-config is installed; in - this case indeed we can use a non-conflicting libpng.pc symlinking to - libpng12.pc). + + As not all of these problems are easily dealt with and new ones may + arise, we chose to delete the $SAGE_LOCAL/lib/libpng.* symlinks. + Therefore, some packages like Tachyon, which by default look for + -lpng are patched to look for -lpng16 instead. diff --git a/build/pkgs/libpng/checksums.ini b/build/pkgs/libpng/checksums.ini index 91023d7b42e..a1f7ec7bd90 100644 --- a/build/pkgs/libpng/checksums.ini +++ b/build/pkgs/libpng/checksums.ini @@ -1,4 +1,4 @@ tarball=libpng-VERSION.tar.gz -sha1=5175be08c4fa767b0d3d025f636e73e78780f988 -md5=e358f9a265f2063b36f10dc454ee0e17 -cksum=291518548 +sha1=004556d65f21baed83755f8e094112711e39ebae +md5=897ccec1ebfb0922e83c2bfaa1be8748 +cksum=1138517817 diff --git a/build/pkgs/libpng/package-version.txt b/build/pkgs/libpng/package-version.txt index ff64d17007a..10010a4bcea 100644 --- a/build/pkgs/libpng/package-version.txt +++ b/build/pkgs/libpng/package-version.txt @@ -1 +1 @@ -1.2.51.p0 +1.6.28 diff --git a/build/pkgs/libpng/patches/pngconf.h.patch b/build/pkgs/libpng/patches/pngconf.h.patch deleted file mode 100644 index 94ef6868a8b..00000000000 --- a/build/pkgs/libpng/patches/pngconf.h.patch +++ /dev/null @@ -1,24 +0,0 @@ ---- src/pngconf.h 2009-02-14 22:59:26.000000000 +0100 -+++ src.new/pngconf.h 2013-12-21 13:59:30.898443798 +0100 -@@ -311,6 +311,12 @@ - # define PNG_SETJMP_SUPPORTED - #endif - -+ -+#if !(defined(PNG_SKIP_SETJMP_CHECK) && PNG_SKIP_SETJMP_CHECK) -+ -+/* This is an attempt to get libfreetype 2.5.2 compiled (in sage) with -+ *this* version of libpng */ -+ - #ifdef PNG_SETJMP_SUPPORTED - /* This is an attempt to force a single setjmp behaviour on Linux. If - * the X config stuff didn't define _BSD_SOURCE we wouldn't need this. -@@ -343,6 +349,8 @@ - # endif /* __linux__ */ - #endif /* PNG_SETJMP_SUPPORTED */ - -+#endif /* !(defined(PNG_SKIP_SETJMP_CHECK) && PNG_SKIP_SETJMP_CHECK) */ -+ - #ifdef BSD - # include - #else diff --git a/build/pkgs/libpng/spkg-install b/build/pkgs/libpng/spkg-install index ff25ceb026a..cc8f94fa7b6 100755 --- a/build/pkgs/libpng/spkg-install +++ b/build/pkgs/libpng/spkg-install @@ -46,32 +46,6 @@ if [ $? -ne 0 ]; then exit 1 fi -# On Darwin, the symbolic links libpng.* created by libpng12 may interfere -# with a system-wide libPng.dylib. -# This system-wide library is likely to be a different version and on top of -# that the symbols exported there are prefixed with "_cg" (for "Core Graphics"), -# so even if by chance the functionalities of the two libraries were interchangeable, -# libraries or applications looking for one and being presented the other won't -# find the symbols they expect. -# Note the uppercase "P" which could prevent this conflict; unfortunately, the -# default filesystem used by Apple is case-insensitive. -# Also note there would be no problem if the system-wide library was not looked -# for when Sage is being built or run, but that's not the case either; -# it is at least looked for by the "ImageIO" framework: -# - when Python is built with Mac OS extensions, fixed in #4008; -# - when Mercurial is built because it uses $EDITOR, cf. #4678; -# - when R is built and it finds -lpng, cf. #4409 and #11696. -# As not all of these problems are easily dealt with and new ones may arise, -# we chose to delete the $SAGE_LOCAL/lib/libpng.* symlinks on Darwin. -# Therefore, some package as matplotlib (cf. #11686) which by default looks for -# -lpng are patched to look for -lpng12 (unless pkg-config is installed; in -# this case indeed we can use a non-conflicting libpng.pc symlinking to -# libpng12.pc). -if [ "$UNAME" = "Darwin" ]; then - echo "Deleting libpng.*..." - rm -rf "$SAGE_LOCAL"/lib/libpng.* - if [ $? -ne 0 ]; then - echo >&2 "Error deleting symlinks." - exit 1 - fi -fi + +# Delete libpng.* symlinks, see SPKG.txt for details +rm -f "$SAGE_LOCAL"/lib/libpng.* diff --git a/build/pkgs/tachyon/patches/Make-config.patch b/build/pkgs/tachyon/patches/Make-config.patch index 7e4bfc156b3..384a83c23b5 100644 --- a/build/pkgs/tachyon/patches/Make-config.patch +++ b/build/pkgs/tachyon/patches/Make-config.patch @@ -71,7 +71,7 @@ -PNGLIB= +USEPNG= -DUSEPNG +PNGINC= -I$(SAGE_LOCAL)/include -+PNGLIB= -L$(SAGE_LOCAL)/lib -lpng12 -lz $(LDFLAGS) ++PNGLIB= -L$(SAGE_LOCAL)/lib -lpng16 -lz $(LDFLAGS) -# Uncomment the following lines to enable PNG support -#USEPNG= -DUSEPNG From f96fe12adb044d5ec132f2ca26c15dd09f43d9c1 Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Fri, 20 Jan 2017 09:51:01 +0100 Subject: [PATCH 097/452] 22209: Differentiation of conj/imag/real/abs functions --- src/sage/calculus/wester.py | 6 ++++++ src/sage/symbolic/expression.pyx | 23 ++++++++++++++++++++++- 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/sage/calculus/wester.py b/src/sage/calculus/wester.py index b0528d72634..89b65be312f 100644 --- a/src/sage/calculus/wester.py +++ b/src/sage/calculus/wester.py @@ -508,7 +508,13 @@ sage: # (OK-ish) D(x)Abs(x) sage: # Verify(D(x) Abs(x), Sign(x)); sage: diff(abs(x)) + 1/2*(x + conjugate(x))/abs(x) + sage: _.simplify_full() x/abs(x) + sage: _ = var('x', domain='real') + sage: diff(abs(x)) + x/abs(x) + sage: forget() :: diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 80c7149d13c..f8cd5c0648d 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -3812,7 +3812,28 @@ cdef class Expression(CommutativeRingElement): sage: f.derivative(2) x |--> 6*x - sin(x) - :: + Some expressions can't be cleanly differentiated by the + chain rule:: + + sage: _ = var('x', domain='real') + sage: _ = var('w z') + sage: (x^z).conjugate().diff(x) + conjugate(x^(z - 1))*conjugate(z) + sage: (w^z).conjugate().diff(w) + w^(z - 1)*z*D[0](conjugate)(w^z) + sage: atanh(x).real_part().diff(x) + -1/(x^2 - 1) + sage: atanh(x).imag_part().diff(x) + 0 + sage: atanh(w).real_part().diff(w) + -D[0](real_part)(arctanh(w))/(w^2 - 1) + sage: atanh(w).imag_part().diff(w) + -D[0](imag_part)(arctanh(w))/(w^2 - 1) + sage: abs(log(x)).diff(x) + 1/2*(conjugate(log(x))/x + log(x)/x)/abs(log(x)) + sage: abs(log(z)).diff(z) + 1/2*(conjugate(log(z))/z + log(z)/conjugate(z))/abs(log(z)) + sage: forget() sage: t = sin(x+y^2)*tan(x*y) sage: t.derivative(x) From 7da09f63de125f14a9a77bab53464b21a14d9a8c Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Thu, 2 Feb 2017 14:45:28 -0800 Subject: [PATCH 098/452] Trac 22294: document that we can't move the Sage installation. --- src/doc/en/installation/binary.rst | 41 +++++++++++++++++------------- src/doc/en/installation/source.rst | 9 +++---- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/doc/en/installation/binary.rst b/src/doc/en/installation/binary.rst index 828140bd499..63b2db5400b 100644 --- a/src/doc/en/installation/binary.rst +++ b/src/doc/en/installation/binary.rst @@ -29,21 +29,36 @@ in a directory which you have permission to read and write:: tar zxvf sage-x.y.z-x86_64-Linux.tgz -You can move the resulting directory ``sage-x.y.z-x86_64-Linux`` +You can move the resulting directory ``SageMath`` anywhere and still run ``./sage`` from it, as long as the full path name -has **no spaces** in it. You can also copy the file ``sage`` from -that directory and put it anywhere, e.g., ``/usr/local/bin/``, but +has **no spaces** in it. The first time you run Sage, you will see a +message like + +:: + + Rewriting paths for your new installation directory + =================================================== + + This might take a few minutes but only has to be done once. + + patching ... (long list of files) + +At this point, you can no longer move your Sage installation and +expect Sage to function. + +You can also copy the file ``sage`` from +the ``SageMath`` directory and put it anywhere, e.g., ``/usr/local/bin/``, but then you have to edit the ``#SAGE_ROOT=/path/to/sage-version`` line at the top of the copied file ``/usr/local/bin/sage`` (you should not edit the original ``sage`` executable). The variable ``SAGE_ROOT`` should point to the directory -``sage-x.y.z-x86_64-Linux`` of the extracted Sage tarball. +``SageMath`` of the extracted Sage tarball. As long as ``/usr/local/bin`` is in your ``$PATH``, you can then type ``sage`` from the command line to run Sage. Another approach is to create a symbolic link, say -``/usr/local/bin/sage``, pointing to ``sage-x.y.z-x86_64-Linux/sage`` :: +``/usr/local/bin/sage``, pointing to ``SageMath/sage`` :: - ln -s /path/to/sage-x.y.z-x86_64-Linux/sage /usr/local/bin/sage + ln -s /path/to/SageMath/sage /usr/local/bin/sage With this approach, there is no need to edit ``/usr/local/bin/sage``, the ``SAGE_ROOT`` path will be discovered automatically thanks to the @@ -51,19 +66,9 @@ symbolic link. When you want to install a new version of Sage, just delete the old link and create a new one. -Any time you move the Sage directory, you may see a message like - -:: - - The Sage installation tree may have moved - (from /foo to /bar). - Changing various hardcoded paths... - (Please wait at most a few minutes.) - DO NOT INTERRUPT THIS. - -We currently distribute ``.dmg`` files for OS X 10.4.x and 10.6.x. But +We currently distribute ``.dmg`` files for recent versions of OS X, but we would like to make Sage more of a native application. Work for that -is ongoing, but help is always welcome. +is ongoing, and help is always welcome. Microsoft Windows diff --git a/src/doc/en/installation/source.rst b/src/doc/en/installation/source.rst index 211a6f361a5..51ee8507fb2 100644 --- a/src/doc/en/installation/source.rst +++ b/src/doc/en/installation/source.rst @@ -460,10 +460,9 @@ Running Sage from a directory with spaces in its name will also fail. fast filesystem, avoiding `NFS `_ and the like. On personal computers, any subdirectory of your :envvar:`HOME` directory - should do. - The directory where you built Sage is **NOT** hardcoded. - You should be able to safely move or rename that directory. - (It's a bug if this is not the case.) + should do. Note that once you have built Sage (by running ``make``, + as described below), you will not be able to move or rename its + directory without likely breaking Sage. #. Extract the tarfile:: @@ -1416,4 +1415,4 @@ would be appropriate if you have a Core i3/5/7 processor with AVX support. -**This page was last updated in January 2017 (Sage 7.5).** +**This page was last updated in February 2017 (Sage 7.6).** From 68f5933575d8979488f04554908e70372936ba44 Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Thu, 2 Feb 2017 15:22:41 -0800 Subject: [PATCH 099/452] Trac 22295: updates to the installation guide. --- src/doc/en/installation/source.rst | 64 ++++-------------------------- 1 file changed, 7 insertions(+), 57 deletions(-) diff --git a/src/doc/en/installation/source.rst b/src/doc/en/installation/source.rst index 51ee8507fb2..05c5cdd87d3 100644 --- a/src/doc/en/installation/source.rst +++ b/src/doc/en/installation/source.rst @@ -126,10 +126,6 @@ variable :envvar:`SAGE_INSTALL_GCC`, see :ref:`section_compilers` and Other notes ^^^^^^^^^^^ -Although some of Sage is written in `Python `_, you do -not need Python pre-installed on your computer, since the Sage installation -includes virtually everything you need. - After extracting the Sage tarball, the subdirectory :file:`upstream` contains the source distributions for everything on which Sage depends. If cloned from a git repository, the upstream tarballs will be downloaded, @@ -328,28 +324,23 @@ but provide additional capablities: - **dvipng**. - **ffmpeg**. - **ImageMagick**. -- **latex**: highly recommended. +- **LaTeX**: highly recommended. It is highly recommended that you have -`Latex `_ +`LaTeX `_ installed, but it is not required. - -The most popular packaging is `TeX Live `_ , -which you can install locally inside Sage with the commands:: - - sage -sh -c '$SAGE_ROOT/src/ext/texlive/texlive-install' - +The most popular packaging is `TeX Live `_, +which can be installed following the directions on their web site. On Linux systems you can alternatively install your distribution's texlive packages:: sudo apt-get install texlive # debian sudo yum install texlive # redhat -or similar commands. In addition to the base texlive install you will -probably need a number of optional texlive packages, for example +or similar commands. In addition to the base TeX Live install, you may +need some optional TeX Live packages, for example country-specific babel packages for the localized Sage -documentation. The required texlive packages are listed in -``SAGE_ROOT/src/ext/texlive/package-list.txt``. +documentation. If you don't have either ImageMagick or ffmpeg, you won't be able to view animations. @@ -1371,47 +1362,6 @@ the directory where you want to install Sage. processes. You can also omit ``long`` to skip tests which take a long time. -Some common problems --------------------- - -ATLAS -~~~~~ - -Usually Sage will build ATLAS with architectural defaults that are not tuned -to your particular CPU. -In particular, if your CPU has powersaving enabled then no accurate timings -can be made to tune the ATLAS build for your hardware. -If BLAS performance is critical for you, you must recompile ATLAS after -installing Sage either with architecture settings that match your hardware, -or run through ATLAS' automatic tuning process where timings of different -implementations are compared and the best choice used to build a custom ATLAS -library. -To do so, you have to - -- Leave the computer idle while you are reinstalling ATLAS. - Most of ATLAS will intentionally only compile/run on a single core. - Accurate timings of cache edges require that the CPU is otherwise idle. - -- Make sure that CPU powersaving mode (that is, anything but the - ``performance`` CPU scaling governor in Linux) is turned off when building - ATLAS. - This requires administrator privileges. - -- If your architecture is listed in :envvar:`SAGE_ATLAS_ARCH`, you should set - it as it can help ATLAS in narrowing down the timing search. - -To help you disable CPU power saving, Sage includes an ``atlas-config`` script -that will turn off CPU powersave and rebuild ATLAS. -The script will call ``sudo`` to gain the necessary rights, which may prompt -you for your password. For example:: - - atlas-config - -will run through the full automated tuning, and:: - - SAGE_ATLAS_ARCH=Corei2,AVX,SSE3,SSE2,SSE1 atlas-config - -would be appropriate if you have a Core i3/5/7 processor with AVX support. From 325a20b12351c8af8e6e633d7e81d0fa019316ec Mon Sep 17 00:00:00 2001 From: Peter Bruin Date: Fri, 3 Feb 2017 15:08:05 +0100 Subject: [PATCH 100/452] Trac 13733: add doctest --- src/sage/symbolic/integration/integral.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/sage/symbolic/integration/integral.py b/src/sage/symbolic/integration/integral.py index 960ba47b63a..28f3cc59e08 100644 --- a/src/sage/symbolic/integration/integral.py +++ b/src/sage/symbolic/integration/integral.py @@ -764,6 +764,14 @@ def integrate(expression, v=None, a=None, b=None, algorithm=None, hold=False): sage: integrate(cos(w+T) / (1+c*cos(T))^2, T, 0, 2*pi) 2*pi*sqrt(-c^2 + 1)*c*cos(w)/(c^4 - 2*c^2 + 1) + Check that :trac:`13733` is fixed:: + + sage: a = integral(log(cot(x)-1),x,0,pi/4); a # long time (about 6 s) + -1/4*pi*log(2) - 1/2*I*dilog(I + 1) + 1/2*I*dilog(-I + 1) + 1/2*I*dilog(1/2*I + 1/2) - 1/2*I*dilog(-1/2*I + 1/2) + sage: N(a) # long time + 0.272198261287950 + sage: N(pi*log(2)/8) + 0.272198261287950 """ expression, v, a, b = _normalize_integral_input(expression, v, a, b) if algorithm is not None: From 1f333b872f56f34d7f126104bc1d95fc4142967b Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sat, 4 Feb 2017 22:01:44 -0600 Subject: [PATCH 101/452] Use normaliz when available. --- .../rigged_configurations/kleber_tree.py | 28 ++++++++++++------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/sage/combinat/rigged_configurations/kleber_tree.py b/src/sage/combinat/rigged_configurations/kleber_tree.py index 7f75e44a26c..b89ceb7fe86 100644 --- a/src/sage/combinat/rigged_configurations/kleber_tree.py +++ b/src/sage/combinat/rigged_configurations/kleber_tree.py @@ -615,11 +615,6 @@ def __init__(self, cartan_type, B, classical_ct): """ Parent.__init__(self, category=FiniteEnumeratedSets()) - if classical_ct.rank() >= 7: - self._child_itr = self._children_iter - else: - self._child_itr = self._children_iter_vector - self._cartan_type = cartan_type self.B = B self._classical_ct = classical_ct @@ -724,6 +719,12 @@ def _build_tree(self): depth = 1 growth = True + # self._has_normaliz is set by _children_iter + if self._classical_ct.rank() >= 7 or self._has_normaliz: + child_itr = self._children_iter + else: + child_itr = self._children_iter_vector + while growth: growth = False depth += 1 @@ -738,12 +739,12 @@ def _build_tree(self): x.weight += L[a][i] * weight_basis[I[a]] if x in leaves: - for new_child in self._child_itr(x): + for new_child in child_itr(x): if not self._prune(new_child, depth): new_children.append(new_child) else: for x in leaves: - for new_child in self._child_itr(x): + for new_child in child_itr(x): if not self._prune(new_child, depth): new_children.append(new_child) @@ -817,13 +818,20 @@ def _children_iter(self, node): v[0] = c v[i+1] = 1 ieqs.append(v) - poly = Polyhedron(ieqs=ieqs) + + try: + poly = Polyhedron(ieqs=ieqs, backend='normaliz') + self._has_normaliz = True + except ImportError: + poly = Polyhedron(ieqs=ieqs) + self._has_normaliz = False # Build the nodes from the polytope # Sort for a consistent ordering (it is typically a small list) for pt in sorted(poly.integral_points(), reverse=True): - up_root = Q._from_dict({I[i]: -val for i,val in enumerate(pt) if val != 0}, remove_zeros=False, ) - wt = node.weight + sum(val*P.simple_root(I[i]) for i,val in enumerate(pt)) + up_root = Q._from_dict({I[i]: -val for i,val in enumerate(pt) if val != 0}, + remove_zeros=False) + wt = node.weight + sum(val * P.simple_root(I[i]) for i,val in enumerate(pt)) yield KleberTreeNode(self, wt, up_root, node) def _children_iter_vector(self, node): From 59bb147f4c66f3f519d0d388c0b86e40f407e047 Mon Sep 17 00:00:00 2001 From: Peter Bruin Date: Tue, 7 Feb 2017 13:16:28 +0100 Subject: [PATCH 102/452] Trac 13733: fix doctest --- src/sage/symbolic/integration/integral.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/sage/symbolic/integration/integral.py b/src/sage/symbolic/integration/integral.py index 28f3cc59e08..3cd9a61d72a 100644 --- a/src/sage/symbolic/integration/integral.py +++ b/src/sage/symbolic/integration/integral.py @@ -766,12 +766,10 @@ def integrate(expression, v=None, a=None, b=None, algorithm=None, hold=False): Check that :trac:`13733` is fixed:: - sage: a = integral(log(cot(x)-1),x,0,pi/4); a # long time (about 6 s) + sage: a = integral(log(cot(x) - 1), x, 0, pi/4); a # long time (about 6 s) -1/4*pi*log(2) - 1/2*I*dilog(I + 1) + 1/2*I*dilog(-I + 1) + 1/2*I*dilog(1/2*I + 1/2) - 1/2*I*dilog(-1/2*I + 1/2) - sage: N(a) # long time - 0.272198261287950 - sage: N(pi*log(2)/8) - 0.272198261287950 + sage: abs(N(a - pi*log(2)/8)) < 1e-15 # long time + True """ expression, v, a, b = _normalize_integral_input(expression, v, a, b) if algorithm is not None: From 1a9ac6f1eb7b4c1da8e14864beae802b75636c2c Mon Sep 17 00:00:00 2001 From: Jeroen Demeyer Date: Wed, 22 Feb 2017 10:30:29 +0100 Subject: [PATCH 103/452] Declare MtxLibDir size in header file + increase to 1024 bytes --- build/pkgs/meataxe/package-version.txt | 2 +- build/pkgs/meataxe/patches/mtxdirs.patch | 37 ++++++++++++++++++++++++ src/sage/libs/meataxe.pxd | 2 +- 3 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 build/pkgs/meataxe/patches/mtxdirs.patch diff --git a/build/pkgs/meataxe/package-version.txt b/build/pkgs/meataxe/package-version.txt index 208b2a0070d..715ebf8a08c 100644 --- a/build/pkgs/meataxe/package-version.txt +++ b/build/pkgs/meataxe/package-version.txt @@ -1 +1 @@ -2.4.24.p1 +2.4.24.p2 diff --git a/build/pkgs/meataxe/patches/mtxdirs.patch b/build/pkgs/meataxe/patches/mtxdirs.patch new file mode 100644 index 00000000000..794cbf24f66 --- /dev/null +++ b/build/pkgs/meataxe/patches/mtxdirs.patch @@ -0,0 +1,37 @@ +Declare array sizes in header file, use 1024 as size + +diff -ru meataxe-2.4.24//src/args.c b/src/args.c +--- meataxe-2.4.24//src/args.c 2009-05-23 21:35:19.000000000 +0200 ++++ b/src/args.c 2017-02-22 10:32:01.324405681 +0100 +@@ -125,7 +125,7 @@ + ** directory, which was selected when building the MeatAxe, is used. + **/ + +-char MtxBinDir[250] = MTXBIN; ++char MtxBinDir[] = MTXBIN; + + + /** +@@ -139,7 +139,7 @@ + ** @see MtxBinDir + **/ + +-char MtxLibDir[250] = MTXLIB; ++char MtxLibDir[] = MTXLIB; + + + +diff -ru meataxe-2.4.24//src/meataxe.h b/src/meataxe.h +--- meataxe-2.4.24//src/meataxe.h 2011-08-08 00:15:19.000000000 +0200 ++++ b/src/meataxe.h 2017-02-22 10:31:52.685290030 +0100 +@@ -246,8 +246,8 @@ + Application framework + ------------------------------------------------------------------ */ + +-extern char MtxBinDir[]; /* MeatAxe library directory */ +-extern char MtxLibDir[]; /* MeatAxe program directory */ ++extern char MtxBinDir[1024]; /* MeatAxe library directory */ ++extern char MtxLibDir[1024]; /* MeatAxe program directory */ + + #define APP_MAX_ARGS 50 + diff --git a/src/sage/libs/meataxe.pxd b/src/sage/libs/meataxe.pxd index 68878f3fa19..780e2ea9b46 100644 --- a/src/sage/libs/meataxe.pxd +++ b/src/sage/libs/meataxe.pxd @@ -30,7 +30,7 @@ cdef extern from "meataxe.h": cdef extern size_t FfCurrentRowSize # The byte size of a single row in memory, # always a multiple of sizeof(long) cdef extern size_t FfCurrentRowSizeIo # The number of bytes actually used in a row. - cdef extern char MtxLibDir[250] # Where to search/create multiplication tables + cdef extern char MtxLibDir[1024] # Where to search/create multiplication tables # we only wrap MeatAxe for small fields (size < 255) cdef extern FEL mtx_tmult[256][256] From 143f95d7010d6a99e25fd82316c4b30be0f3fb30 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 23 Feb 2017 09:42:22 -0600 Subject: [PATCH 104/452] Cleaning some stuff up with some crystals. --- src/sage/combinat/crystals/direct_sum.py | 29 +- .../combinat/crystals/kirillov_reshetikhin.py | 908 ++++++++++-------- src/sage/combinat/crystals/tensor_product.py | 95 +- 3 files changed, 557 insertions(+), 475 deletions(-) diff --git a/src/sage/combinat/crystals/direct_sum.py b/src/sage/combinat/crystals/direct_sum.py index c0aef6c6479..29356ff74af 100644 --- a/src/sage/combinat/crystals/direct_sum.py +++ b/src/sage/combinat/crystals/direct_sum.py @@ -105,10 +105,7 @@ def __classcall_private__(cls, crystals, facade=True, keepkey=False, category=No if not isinstance(facade, bool) or not isinstance(keepkey, bool): raise TypeError # Normalize the facade-keepkey by giving keepkey dominance - if keepkey: - facade = False - else: - facade = True + facade = not keepkey # We expand out direct sums of crystals ret = [] @@ -136,24 +133,21 @@ def __init__(self, crystals, facade, keepkey, category, **options): sage: isinstance(B, DirectSumOfCrystals) True """ - if facade: - Parent.__init__(self, facade=tuple(crystals), category=category) - else: - Parent.__init__(self, category=category) - DisjointUnionEnumeratedSets.__init__(self, crystals, keepkey=keepkey, facade=facade) + DisjointUnionEnumeratedSets.__init__(self, crystals, keepkey=keepkey, + facade=facade, category=category) self.rename("Direct sum of the crystals {}".format(crystals)) self._keepkey = keepkey self.crystals = crystals if len(crystals) == 0: - raise ValueError("The direct sum is empty") + raise ValueError("the direct sum is empty") else: assert(crystal.cartan_type() == crystals[0].cartan_type() for crystal in crystals) self._cartan_type = crystals[0].cartan_type() if keepkey: - self.module_generators = [ self(tuple([i,b])) for i in range(len(crystals)) - for b in crystals[i].module_generators ] + self.module_generators = tuple([ self((i,b)) for i,B in enumerate(crystals) + for b in B.module_generators ]) else: - self.module_generators = sum( (list(B.module_generators) for B in crystals), []) + self.module_generators = sum((tuple(B.module_generators) for B in crystals), ()) def weight_lattice_realization(self): r""" @@ -183,12 +177,11 @@ def weight_lattice_realization(self): class Element(ElementWrapper): r""" - A class for elements of direct sums of crystals + A class for elements of direct sums of crystals. """ - def e(self, i): r""" - Returns the action of `e_i` on self. + Return the action of `e_i` on ``self``. EXAMPLES:: @@ -206,7 +199,7 @@ def e(self, i): def f(self, i): r""" - Returns the action of `f_i` on self. + Return the action of `f_i` on ``self``. EXAMPLES:: @@ -224,7 +217,7 @@ def f(self, i): def weight(self): r""" - Returns the weight of self. + Return the weight of ``self``. EXAMPLES:: diff --git a/src/sage/combinat/crystals/kirillov_reshetikhin.py b/src/sage/combinat/crystals/kirillov_reshetikhin.py index 8eac1105507..9a58e382e1f 100644 --- a/src/sage/combinat/crystals/kirillov_reshetikhin.py +++ b/src/sage/combinat/crystals/kirillov_reshetikhin.py @@ -38,9 +38,10 @@ from sage.categories.map import Map from sage.rings.integer import Integer from sage.rings.all import QQ -from sage.combinat.crystals.affine import AffineCrystalFromClassical, \ - AffineCrystalFromClassicalElement, AffineCrystalFromClassicalAndPromotion, \ - AffineCrystalFromClassicalAndPromotionElement +from sage.combinat.crystals.affine import (AffineCrystalFromClassical, + AffineCrystalFromClassicalElement, + AffineCrystalFromClassicalAndPromotion, + AffineCrystalFromClassicalAndPromotionElement) from sage.combinat.crystals.highest_weight_crystals import HighestWeightCrystal from sage.combinat.crystals.littelmann_path import CrystalOfProjectedLevelZeroLSPaths from sage.combinat.crystals.direct_sum import DirectSumOfCrystals @@ -446,7 +447,7 @@ class KirillovReshetikhinGenericCrystal(AffineCrystalFromClassical): ``cartan_type``. """ - def __init__(self, cartan_type, r, s, dual = None): + def __init__(self, cartan_type, r, s, dual=None): r""" Initializes a generic Kirillov-Reshetikhin crystal. @@ -487,7 +488,7 @@ def _element_constructor_(self, *args, **options): EXAMPLES:: sage: K = crystals.KirillovReshetikhin(['A', 4, 1], 2, 1) - sage: K(columns=[[2,1]]) # indirect doctest + sage: K(columns=[[2,1]]) [[1], [2]] """ from sage.combinat.rigged_configurations.kr_tableaux import KirillovReshetikhinTableauxElement @@ -496,7 +497,7 @@ def _element_constructor_(self, *args, **options): # Check to make sure it can be converted if elt.cartan_type() != self.cartan_type() \ or elt.parent().r() != self._r or elt.parent().s() != self._s: - raise ValueError("The Kirillov-Reshetikhin tableau must have the same Cartan type and shape") + raise ValueError("the Kirillov-Reshetikhin tableau must have the same Cartan type and shape") to_hw = elt.to_classical_highest_weight() rows = [] @@ -523,7 +524,8 @@ def classical_decomposition(self): def module_generator(self): r""" - Returns the unique module generator of classical weight `s \Lambda_r` of a Kirillov-Reshetikhin crystal `B^{r,s}` + Return the unique module generator of classical weight `s \Lambda_r` + of a Kirillov-Reshetikhin crystal `B^{r,s}` EXAMPLES:: @@ -543,11 +545,11 @@ def module_generator(self): r = self.r() s = self.s() weight = s*Lambda[r] - s*Lambda[0] * Lambda[r].level() / Lambda[0].level() - return [ b for b in self.module_generators if b.weight() == weight][0] + return [b for b in self.module_generators if b.weight() == weight][0] def r(self): """ - Returns r of the underlying Kirillov-Reshetikhin crystal `B^{r,s}` + Return `r` of the underlying Kirillov-Reshetikhin crystal `B^{r,s}`. EXAMPLES:: @@ -559,7 +561,7 @@ def r(self): def s(self): """ - Returns s of the underlying Kirillov-Reshetikhin crystal `B^{r,s}` + Return `s` of the underlying Kirillov-Reshetikhin crystal `B^{r,s}`. EXAMPLES:: @@ -571,17 +573,18 @@ def s(self): def is_perfect(self): r""" - Returns True or False depending on whether ``self`` is a perfect crystal or not, respectively. + Return whether ``self`` is a perfect crystal or not. - If ``self`` is the Kirillov-Reshetikhin crystal `B^{r,s}`, then it was proven in [FOS2010]_ - that it is perfect if and only if `s/c_r` is an integer (where `c_r` is a constant related to the + If ``self`` is the Kirillov-Reshetikhin crystal `B^{r,s}`, + then it was proven in [FOS2010]_ that it is perfect if and only if + `s/c_r` is an integer (where `c_r` is a constant related to the type of the crystal). REFERENCES: - .. [FOS2010] \G. Fourier, M. Okado, A. Schilling. - Perfectness of Kirillov-Reshetikhin crystals for nonexceptional types - Contemp. Math. 506 (2010) 127-143 ( arXiv:0811.1604 [math.RT] ) + .. [FOS2010] \G. Fourier, M. Okado, A. Schilling. + *Perfectness of Kirillov-Reshetikhin crystals for nonexceptional types*. + Contemp. Math. 506 (2010) 127-143 ( arXiv:0811.1604 [math.RT] ) EXAMPLES:: @@ -602,11 +605,12 @@ def is_perfect(self): def level(self): r""" - Returns the level of ``self`` assuming that it is a perfect crystal. + Return the level of ``self`` assuming that it is a perfect crystal. - If ``self`` is the Kirillov-Reshetikhin crystal `B^{r,s}`, then it was proven in [FOS2010]_ - that its level is `s/c_r` which is an integer if ``self`` is perfect - (here `c_r` is a constant related to the type of the crystal). + If ``self`` is the Kirillov-Reshetikhin crystal `B^{r,s}`, then it + was proven in [FOS2010]_ that its level is `s/c_r` which is an + integer if ``self`` is perfect (here `c_r` is a constant related + to the type of the crystal). EXAMPLES:: @@ -628,22 +632,27 @@ def level(self): """ if not self.is_perfect(): raise ValueError("this crystal is not perfect") - return self.s()/self.cartan_type().c()[self.r()] + return self.s() / self.cartan_type().c()[self.r()] @cached_method def R_matrix(self, K): r""" + Return the combinatorial `R`-matrix between ``self`` and ``K``. + INPUT: - ``self`` -- a crystal `L` - ``K`` -- a Kirillov-Reshetikhin crystal of the same type as `L` - Returns the *combinatorial `R`-matrix* from `L \otimes K \to K - \otimes L`, where the combinatorial `R`-matrix is the affine - crystal isomorphism which maps `u_{L} \otimes u_K` to `u_K - \otimes u_{L}`, where `u_K` is the unique element in `K = - B^{r,s}` of weight `s\Lambda_r - s c \Lambda_0` (see - module_generator). + The *combinatorial `R`-matrix* + .. MATH:: + + R: L \otimes K \to K \otimes L + + is the unique affine crystal isomorphism which maps + `u_L \otimes u_K` to `u_K \otimes u_L`, where `u_K` is the unique + element in `K = B^{r,s}` of weight `s\Lambda_r - s c \Lambda_0` + (see :meth:`module_generator`). EXAMPLES:: @@ -652,23 +661,23 @@ def R_matrix(self, K): sage: f = K.R_matrix(L) sage: [[b,f(b)] for b in crystals.TensorProduct(K,L)] [[[[[1]], [[1, 1]]], [[[1, 1]], [[1]]]], - [[[[1]], [[1, 2]]], [[[1, 1]], [[2]]]], - [[[[1]], [[2, 2]]], [[[1, 2]], [[2]]]], - [[[[1]], [[1, 3]]], [[[1, 1]], [[3]]]], - [[[[1]], [[2, 3]]], [[[1, 2]], [[3]]]], - [[[[1]], [[3, 3]]], [[[1, 3]], [[3]]]], - [[[[2]], [[1, 1]]], [[[1, 2]], [[1]]]], - [[[[2]], [[1, 2]]], [[[2, 2]], [[1]]]], - [[[[2]], [[2, 2]]], [[[2, 2]], [[2]]]], - [[[[2]], [[1, 3]]], [[[2, 3]], [[1]]]], - [[[[2]], [[2, 3]]], [[[2, 2]], [[3]]]], - [[[[2]], [[3, 3]]], [[[2, 3]], [[3]]]], - [[[[3]], [[1, 1]]], [[[1, 3]], [[1]]]], - [[[[3]], [[1, 2]]], [[[1, 3]], [[2]]]], - [[[[3]], [[2, 2]]], [[[2, 3]], [[2]]]], - [[[[3]], [[1, 3]]], [[[3, 3]], [[1]]]], - [[[[3]], [[2, 3]]], [[[3, 3]], [[2]]]], - [[[[3]], [[3, 3]]], [[[3, 3]], [[3]]]]] + [[[[1]], [[1, 2]]], [[[1, 1]], [[2]]]], + [[[[1]], [[2, 2]]], [[[1, 2]], [[2]]]], + [[[[1]], [[1, 3]]], [[[1, 1]], [[3]]]], + [[[[1]], [[2, 3]]], [[[1, 2]], [[3]]]], + [[[[1]], [[3, 3]]], [[[1, 3]], [[3]]]], + [[[[2]], [[1, 1]]], [[[1, 2]], [[1]]]], + [[[[2]], [[1, 2]]], [[[2, 2]], [[1]]]], + [[[[2]], [[2, 2]]], [[[2, 2]], [[2]]]], + [[[[2]], [[1, 3]]], [[[2, 3]], [[1]]]], + [[[[2]], [[2, 3]]], [[[2, 2]], [[3]]]], + [[[[2]], [[3, 3]]], [[[2, 3]], [[3]]]], + [[[[3]], [[1, 1]]], [[[1, 3]], [[1]]]], + [[[[3]], [[1, 2]]], [[[1, 3]], [[2]]]], + [[[[3]], [[2, 2]]], [[[2, 3]], [[2]]]], + [[[[3]], [[1, 3]]], [[[3, 3]], [[1]]]], + [[[[3]], [[2, 3]]], [[[3, 3]], [[2]]]], + [[[[3]], [[3, 3]]], [[[3, 3]], [[3]]]]] sage: K = crystals.KirillovReshetikhin(['D',4,1],1,1) sage: L = crystals.KirillovReshetikhin(['D',4,1],2,1) @@ -678,14 +687,14 @@ def R_matrix(self, K): sage: f(b) [[[2], [-2]], [[1]]] - Alternatively, one can compute the combinatorial `R`-matrix using the isomorphism method - of digraphs:: + Alternatively, one can compute the combinatorial `R`-matrix using + the isomorphism method of digraphs:: sage: K1 = crystals.KirillovReshetikhin(['A',2,1],1,1) sage: K2 = crystals.KirillovReshetikhin(['A',2,1],2,1) sage: T1 = crystals.TensorProduct(K1,K2) sage: T2 = crystals.TensorProduct(K2,K1) - sage: T1.digraph().is_isomorphic(T2.digraph(), edge_labels = True, certificate = True) #todo: not implemented (see #10904 and #10549) + sage: T1.digraph().is_isomorphic(T2.digraph(), edge_labels=True, certificate=True) #todo: not implemented (see #10904 and #10549) (True, {[[[1]], [[2], [3]]]: [[[1], [3]], [[2]]], [[[3]], [[2], [3]]]: [[[2], [3]], [[3]]], [[[3]], [[1], [3]]]: [[[1], [3]], [[3]]], [[[1]], [[1], [3]]]: [[[1], [3]], [[1]]], [[[1]], [[1], [2]]]: [[[1], [2]], [[1]]], [[[2]], [[1], [2]]]: [[[1], [2]], [[2]]], [[[3]], @@ -695,7 +704,7 @@ def R_matrix(self, K): T2 = TensorProductOfCrystals(K, self) gen1 = T1( self.module_generator(), K.module_generator() ) gen2 = T2( K.module_generator(), self.module_generator() ) - g = { gen1 : gen2 } + g = {gen1: gen2} return T1.crystal_morphism(g, check=False) @cached_method @@ -941,16 +950,18 @@ def energy_function(self): class KirillovReshetikhinCrystalFromPromotion(KirillovReshetikhinGenericCrystal, AffineCrystalFromClassicalAndPromotion): r""" - This generic class assumes that the Kirillov-Reshetikhin crystal is constructed - from a classical crystal 'classical_decomposition' and an automorphism 'promotion' and its inverse - which corresponds to a Dynkin diagram automorphism 'dynkin_diagram_automorphism'. + This generic class assumes that the Kirillov-Reshetikhin crystal is + constructed from a classical crystal using the + ``classical_decomposition`` and an automorphism ``promotion`` + and its inverse, which corresponds to a Dynkin diagram automorphism + ``dynkin_diagram_automorphism``. Each instance using this class needs to implement the methods: - - classical_decomposition - - promotion - - promotion_inverse - - dynkin_diagram_automorphism + - ``classical_decomposition`` + - ``promotion`` + - ``promotion_inverse`` + - ``dynkin_diagram_automorphism`` """ def __init__(self, cartan_type, r, s): r""" @@ -962,8 +973,10 @@ def __init__(self, cartan_type, r, s): sage: TestSuite(K).run() """ KirillovReshetikhinGenericCrystal.__init__(self, cartan_type, r, s) - AffineCrystalFromClassicalAndPromotion.__init__(self, cartan_type, self.classical_decomposition(), - self.promotion(), self.promotion_inverse(), + AffineCrystalFromClassicalAndPromotion.__init__(self, cartan_type, + self.classical_decomposition(), + self.promotion(), + self.promotion_inverse(), self.dynkin_diagram_automorphism(0)) class KirillovReshetikhinCrystalFromPromotionElement(AffineCrystalFromClassicalAndPromotionElement, @@ -997,7 +1010,8 @@ def classical_decomposition(self): sage: K.classical_decomposition() The crystal of tableaux of type ['A', 3] and shape(s) [[2, 2]] """ - return CrystalOfTableaux(self.cartan_type().classical(), shape = [self.s() for i in range(1,self.r()+1)]) + return CrystalOfTableaux(self.cartan_type().classical(), + shape=[self.s()]*self.r()) @cached_method def promotion(self): @@ -1066,8 +1080,9 @@ def dynkin_diagram_automorphism(self, i): class KR_type_vertical(KirillovReshetikhinCrystalFromPromotion): r""" - Class of Kirillov-Reshetikhin crystals `B^{r,s}` of type `D_n^{(1)}` for `r\le n-2`, - `B_n^{(1)}` for `r0]) for r in b.to_tableau()]) outer = b.to_tableau().shape() @@ -1244,9 +1281,10 @@ def from_pm_diagram_to_highest_weight_vector(self, pm): sage: K.from_pm_diagram_to_highest_weight_vector(pm) [[2], [-2]] """ - u = [b for b in self.classical_decomposition().module_generators if b.to_tableau().shape() == pm.outer_shape()][0] + u = [b for b in self.classical_decomposition().module_generators + if b.to_tableau().shape() == pm.outer_shape()][0] ct = self.cartan_type() - rank = ct.rank()-1 + rank = ct.rank() - 1 ct_type = ct.classical().type() assert ct_type in ['B', 'C', 'D'] ulist = [] @@ -1254,11 +1292,11 @@ def from_pm_diagram_to_highest_weight_vector(self, pm): ulist += list(range(1, h + 1)) for h in pm.heights_of_minus(): if ct_type == 'D': - ulist += list(range(1,rank+1))+[rank-2-k for k in range(rank-1-h)] + ulist += list(range(1,rank+1)) + [rank-2-k for k in range(rank-1-h)] elif ct_type == 'B': - ulist += list(range(1,rank+1))+[rank-k for k in range(rank+1-h)] + ulist += list(range(1,rank+1)) + [rank-k for k in range(rank+1-h)] else: - ulist += list(range(1,rank+1))+[rank-1-k for k in range(rank-h)] + ulist += list(range(1,rank+1)) + [rank-1-k for k in range(rank-h)] for i in reversed(ulist): u = u.f(i) return u @@ -1331,19 +1369,22 @@ def classical_decomposition(self): """ La = self.cartan_type().classical().root_system().weight_lattice().fundamental_weights() if self.r() in [1,6]: - dw = [self.s()*La[self.r()]] + dw = [self.s() * La[self.r()]] elif self.r() == 2: - dw = sum( ([k*La[2]] for k in range(self.s()+1)), []) + dw = [k*La[2] for k in range(self.s()+1)] else: - raise ValueError - return DirectSumOfCrystals([HighestWeightCrystal(dominant_weight) for dominant_weight in dw], keepkey = False) + raise NotImplementedError + return DirectSumOfCrystals([HighestWeightCrystal(dominant_weight) + for dominant_weight in dw], + keepkey=False) def dynkin_diagram_automorphism(self, i): r""" - Specifies the Dynkin diagram automorphism underlying the promotion action on the crystal - elements. The automorphism needs to map node 0 to some other Dynkin node. + Specifies the Dynkin diagram automorphism underlying the promotion + action on the crystal elements. - Here we use the Dynkin diagram automorphism of order 3 which maps node 0 to node 1. + Here we use the Dynkin diagram automorphism of order 3 which maps + node 0 to node 1. EXAMPLES:: @@ -1356,41 +1397,44 @@ def dynkin_diagram_automorphism(self, i): def affine_weight(self, b): r""" - Returns the affine level zero weight corresponding to the element b of the classical - crystal underlying self. For the coefficients to calculate the level, see Kac pg. 48. + Return the affine level zero weight corresponding to the element + ``b`` of the classical crystal underlying ``self``. + + For the coefficients to calculate the level, see Kac pg. 48. EXAMPLES:: sage: K = crystals.KirillovReshetikhin(['E',6,1],2,1) - sage: [K.affine_weight(x.lift()) for x in K if all(x.epsilon(i) == 0 for i in [2,3,4,5])] + sage: [K.affine_weight(x.lift()) for x in K + ....: if all(x.epsilon(i) == 0 for i in [2,3,4,5])] [(0, 0, 0, 0, 0, 0, 0), - (-2, 0, 1, 0, 0, 0, 0), - (-1, -1, 0, 0, 0, 1, 0), - (0, 0, 0, 0, 0, 0, 0), - (0, 0, 0, 0, 0, 1, -2), - (0, -1, 1, 0, 0, 0, -1), - (-1, 0, 0, 1, 0, 0, -1), - (-1, -1, 0, 0, 1, 0, -1), - (0, 0, 0, 0, 0, 0, 0), - (0, -2, 0, 1, 0, 0, 0)] - """ - simple_roots = self.cartan_type().classical().root_system().ambient_space().simple_roots() - index_set = b.parent().index_set() - weight = [ Integer(b.weight().scalar( simple_roots[i] )) for i in index_set ] - E6_coeffs = [ 1, 2, 2, 3, 2, 1 ] - return tuple( [-sum([ weight[i-1] * E6_coeffs[i-1] for i in index_set ])] + weight ) - + (-2, 0, 1, 0, 0, 0, 0), + (-1, -1, 0, 0, 0, 1, 0), + (0, 0, 0, 0, 0, 0, 0), + (0, 0, 0, 0, 0, 1, -2), + (0, -1, 1, 0, 0, 0, -1), + (-1, 0, 0, 1, 0, 0, -1), + (-1, -1, 0, 0, 1, 0, -1), + (0, 0, 0, 0, 0, 0, 0), + (0, -2, 0, 1, 0, 0, 0)] + """ + cl = self.cartan_type().classical() + simple_roots = cl.root_system().ambient_space().simple_roots() + index_set = cl.index_set() + weight = [Integer(b.weight().scalar( simple_roots[i] )) for i in index_set] + E6_coeffs = [1, 2, 2, 3, 2, 1] + return tuple([-sum(weight[i] * coeff for i,coeff in enumerate(E6_coeffs))] + weight) @cached_method def hw_auxiliary(self): r""" - Returns the `{2,3,4,5}` highest weight elements of self. + Return the `{2,3,4,5}` highest weight elements of ``self``. EXAMPLES:: sage: K = crystals.KirillovReshetikhin(['E',6,1],2,1) sage: K.hw_auxiliary() - [[], [[(2, -1), (1,)]], + ([], [[(2, -1), (1,)]], [[(5, -3), (-1, 3)]], [[(6, -2), (-6, 2)]], [[(5, -2, -6), (-6, 2)]], @@ -1398,14 +1442,16 @@ def hw_auxiliary(self): [[(3, -1, -6), (1,)]], [[(4, -3, -6), (-1, 3)]], [[(1, -3), (-1, 3)]], - [[(-1,), (-1, 3)]]] + [[(-1,), (-1, 3)]]) """ - return [x for x in self.classical_decomposition() if all(x.epsilon(i) == 0 for i in [2,3,4,5])] + return tuple([x for x in self.classical_decomposition() + if all(x.epsilon(i) == 0 for i in [2,3,4,5])]) @cached_method def highest_weight_dict(self): r""" - Returns a dictionary between `{1,2,3,4,5}` highest weight elements, and a tuple of affine weights and its classical component. + Return a dictionary between `{1,2,3,4,5}` highest weight elements, + and a tuple of affine weights and its classical component. EXAMPLES:: @@ -1418,7 +1464,7 @@ def highest_weight_dict(self): []: ((0, 0, 0, 0, 0, 0, 0), 0)} """ hw = [x for x in self.hw_auxiliary() if x.epsilon(1) == 0] - dic = dict( ( x, tuple( [self.affine_weight(x), len(x)] ) ) for x in hw ) + dic = {x: (self.affine_weight(x), len(x)) for x in hw} assert len(hw) == len(dic) return dic @@ -1426,7 +1472,7 @@ def highest_weight_dict(self): def highest_weight_dict_inv(self): r""" Return a dictionary between a tuple of affine weights and a classical - component, and `{2,3,4,5,6}` highest weight elements. + component, and `\{2,3,4,5,6\}`-highest weight elements. EXAMPLES:: @@ -1439,19 +1485,20 @@ def highest_weight_dict_inv(self): ((0, 0, 0, 0, 0, 0, 0), 1): [[(1, -3), (-1, 3)]]} """ hw = [x for x in self.hw_auxiliary() if x.epsilon(6) == 0] - dic = dict( ( tuple( [self.affine_weight(x), len(x)] ), x ) for x in hw ) + dic = {(self.affine_weight(x), len(x)): x for x in hw} assert len(hw) == len(dic) return dic def automorphism_on_affine_weight(self, weight): r""" - Acts with the Dynkin diagram automorphism on affine weights + Act with the Dynkin diagram automorphism on affine weights as outputted by the ``affine_weight`` method. EXAMPLES:: sage: K = crystals.KirillovReshetikhin(['E',6,1],2,1) - sage: [[x[0], K.automorphism_on_affine_weight(x[0])] for x in K.highest_weight_dict().values()] + sage: [[x[0], K.automorphism_on_affine_weight(x[0])] + ....: for x in K.highest_weight_dict().values()] [[(0, 0, 0, 0, 0, 1, -2), (-2, 0, 1, 0, 0, 0, 0)], [(-1, 0, 0, 1, 0, 0, -1), (-1, -1, 0, 0, 0, 1, 0)], [(0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0)], @@ -1464,12 +1511,13 @@ def automorphism_on_affine_weight(self, weight): @cached_method def promotion_on_highest_weight_vectors(self): r""" - Gives a dictionary of the promotion map on `{1,2,3,4,5}` highest - weight elements to `{2,3,4,5,6}` elements in ``self``. + Return a dictionary of the promotion map on `\{1,2,3,4,5\}`-highest + weight elements to `\{2,3,4,5,6\}`-highest weight elements + in ``self``. EXAMPLES:: - sage: K = crystals.KirillovReshetikhin(['E',6,1],2,1) + sage: K = crystals.KirillovReshetikhin(['E',6,1], 2, 1) sage: dic = K.promotion_on_highest_weight_vectors() sage: dic {[[(2, -1), (1,)]]: [[(-1,), (-1, 3)]], @@ -1484,8 +1532,8 @@ def promotion_on_highest_weight_vectors(self): for (weight, i) in dic.values(): dic_weight[weight] = dic_weight.get(weight, []) + [i] map_index = lambda i_list: max(i_list[1]) + min(i_list[1]) - i_list[0] - map_element = lambda x : tuple([ self.automorphism_on_affine_weight(dic[x][0]), - map_index((dic[x][1], dic_weight[dic[x][0]])) ]) + map_element = lambda x: ( self.automorphism_on_affine_weight(dic[x][0]), + map_index((dic[x][1], dic_weight[dic[x][0]])) ) return {x: dic_inv[map_element(x)] for x in dic} @cached_method @@ -1496,12 +1544,12 @@ def promotion_on_highest_weight_vectors_function(self): EXAMPLES:: - sage: K = crystals.KirillovReshetikhin(['E',6,1], 2,1) + sage: K = crystals.KirillovReshetikhin(['E',6,1], 2, 1) sage: f = K.promotion_on_highest_weight_vectors_function() sage: f(K.module_generator().lift()) [[(-1,), (-1, 3)]] """ - return lambda x : self.promotion_on_highest_weight_vectors()[x] + return self.promotion_on_highest_weight_vectors().__getitem__ @cached_method def promotion(self): @@ -1523,7 +1571,7 @@ def promotion(self): T = self.classical_decomposition() ind = [1,2,3,4,5] return CrystalDiagramAutomorphism(T, self.promotion_on_highest_weight_vectors(), ind, - automorphism=self.dynkin_diagram_automorphism) + automorphism=self.dynkin_diagram_automorphism) @cached_method def promotion_inverse(self): @@ -1545,7 +1593,8 @@ def promotion_inverse(self): class KR_type_C(KirillovReshetikhinGenericCrystal): r""" - Class of Kirillov-Reshetikhin crystals `B^{r,s}` of type `C_n^{(1)}` for `r """ - def e0(self): r""" - Gives `e_0` on self by mapping self to the ambient crystal, calculating `e_1 e_0` there and - pulling the element back. + Return `e_0` on ``self`` by mapping ``self`` to the ambient crystal, + calculating `e_1 e_0` there and pulling the element back. EXAMPLES:: @@ -1730,8 +1788,8 @@ def e0(self): def f0(self): r""" - Gives `f_0` on self by mapping self to the ambient crystal, calculating `f_1 f_0` there and - pulling the element back. + Return `f_0` on ``self`` by mapping ``self`` to the ambient crystal, + calculating `f_1 f_0` there and pulling the element back. EXAMPLES:: @@ -1781,11 +1839,11 @@ def phi0(self): class KR_type_A2(KirillovReshetikhinGenericCrystal): r""" - Class of Kirillov-Reshetikhin crystals `B^{r,s}` of type `A_{2n}^{(2)}` for `1\le r \le n` - in the realization with classical subalgebra `B_n`. The Cartan type in this case is inputted as - the dual of `A_{2n}^{(2)}`. + Class of Kirillov-Reshetikhin crystals `B^{r,s}` of type `A_{2n}^{(2)}` + for `1 \leq r \leq n` in the realization with classical subalgebra `B_n`. + The Cartan type in this case is inputted as the dual of `A_{2n}^{(2)}`. - This is an alternative implementation to :class:`KR_type_box` which uses + This is an alternative implementation to :class:`KR_type_box` that uses the classical decomposition into type `C_n` crystals. EXAMPLES:: @@ -1799,8 +1857,9 @@ class KR_type_A2(KirillovReshetikhinGenericCrystal): [[1]] sage: b.e(0) - We can now check whether the two KR crystals of type `A_4^{(2)}` (namely the KR crystal and its dual - construction) are isomorphic up to relabelling of the edges:: + We can now check whether the two KR crystals of type `A_4^{(2)}` + (namely the KR crystal and its dual construction) are isomorphic + up to relabelling of the edges:: sage: C = CartanType(['A',4,2]) sage: K = crystals.KirillovReshetikhin(C,1,1) @@ -1815,13 +1874,15 @@ class KR_type_A2(KirillovReshetikhinGenericCrystal): def classical_decomposition(self): r""" - Specifies the classical crystal underlying the Kirillov-Reshetikhin crystal of type `A_{2n}^{(2)}` - with `B_n` as classical subdiagram. + Return the classical crystal underlying the Kirillov-Reshetikhin + crystal of type `A_{2n}^{(2)}` with `B_n` as classical subdiagram. - It is given by `B^{r,s} \cong \bigoplus_\Lambda B(\Lambda)` where `B(\Lambda)` is a highest weight crystal of type - `B_n` of highest weight `\Lambda`. The sum is over all weights `\Lambda` obtained from - a rectangle of width `s` and height `r` by removing horizontal dominoes. Here we identify the fundamental - weight `\Lambda_i` with a column of height `i`. + It is given by `B^{r,s} \cong \bigoplus_{\Lambda} B(\Lambda)`, + where `B(\Lambda)` is a highest weight crystal of type `B_n` + of highest weight `\Lambda`. The sum is over all weights `\Lambda` + obtained from a rectangle of width `s` and height `r` by removing + horizontal dominoes. Here we identify the fundamental weight + `\Lambda_i` with a column of height `i`. EXAMPLES:: @@ -1835,8 +1896,11 @@ def classical_decomposition(self): def ambient_crystal(self): r""" - Returns the ambient crystal `B^{r,s}` of type `B_{n+1}^{(1)}` associated to the Kirillov-Reshetikhin - crystal of type `A_{2n}^{(2)}` dual. This ambient crystal is used to construct the zero arrows. + Return the ambient crystal `B^{r,s}` of type `B_{n+1}^{(1)}` + associated to the Kirillov-Reshetikhin crystal of type + `A_{2n}^{(2)}` dual. + + This ambient crystal is used to construct the zero arrows. EXAMPLES:: @@ -1850,8 +1914,8 @@ def ambient_crystal(self): @cached_method def ambient_dict_pm_diagrams(self): r""" - Gives a dictionary of all self-dual `\pm` diagrams for the ambient crystal. - Their key is their inner shape. + Return a dictionary of all self-dual `\pm` diagrams for the + ambient crystal whose keys are their inner shape. EXAMPLES:: @@ -1871,18 +1935,20 @@ def ambient_dict_pm_diagrams(self): ulist = [] s = self.s() r = self.r() - m = s//2 + m = s // 2 for i in range(m+1): for la in IntegerVectors(m-i, min_length=r, max_length=r): ulist.append(PMDiagram([[j,j] for j in la]+[[s-2*m+2*i]])) - return dict( (x.inner_shape(), x) for x in ulist ) + return {x.inner_shape(): x for x in ulist} @cached_method def ambient_highest_weight_dict(self): r""" - Gives a dictionary of all `{2,...,n+1}`-highest weight vectors in the ambient crystal. - Their key is the inner shape of their corresponding `\pm` diagram, or equivalently, their - `{2,...,n+1}` weight. + Return a dictionary of all `\{2,\ldots,n+1\}`-highest weight vectors + in the ambient crystal. + + The key is the inner shape of their corresponding `\pm` diagram, + or equivalently, their `\{2,\ldots,n+1\}` weight. EXAMPLES:: @@ -1893,13 +1959,14 @@ def ambient_highest_weight_dict(self): """ A = self.ambient_dict_pm_diagrams() ambient = self.ambient_crystal() - return dict( (key, ambient.retract(ambient.from_pm_diagram_to_highest_weight_vector(A[key]))) for key in A ) + return {key: ambient.retract(ambient.from_pm_diagram_to_highest_weight_vector(A[key])) + for key in A} @cached_method def highest_weight_dict(self): r""" - Gives a dictionary of the classical highest weight vectors of self. - Their key is their shape. + Return a dictionary of the classical highest weight vectors + of ``self`` whose keys are their shape. EXAMPLES:: @@ -1908,13 +1975,13 @@ def highest_weight_dict(self): sage: K.highest_weight_dict() {[]: [], [2]: [[1, 1]]} """ - return dict( (x.lift().to_tableau().shape(),x) for x in self.module_generators ) + return {x.lift().to_tableau().shape(): x for x in self.module_generators} @cached_method def to_ambient_crystal(self): r""" - Provides a map from the Kirillov-Reshetikhin crystal of type `A_{2n}^{(2)}` to the - ambient crystal of type `B_{n+1}^{(1)}`. + Return a map from the Kirillov-Reshetikhin crystal of type + `A_{2n}^{(2)}` to the ambient crystal of type `B_{n+1}^{(1)}`. EXAMPLES:: @@ -1930,17 +1997,18 @@ def to_ambient_crystal(self): sage: K.to_ambient_crystal()(b).parent() Kirillov-Reshetikhin crystal of type ['B', 3, 1] with (r,s)=(2,2) """ - keys = self.highest_weight_dict() - pdict = dict( (self.highest_weight_dict()[key], self.ambient_highest_weight_dict()[key]) for key in keys ) + hwd = self.highest_weight_dict() + ahwd = self.ambient_highest_weight_dict() + pdict = {hwd[key]: ahwd[key] for key in hwd} classical = self.cartan_type().classical() - return self.crystal_morphism( pdict, index_set=classical.index_set(), - automorphism=lambda i: i+1, - cartan_type=classical, check=False ) + return self.crystal_morphism(pdict, index_set=classical.index_set(), + automorphism=lambda i: i+1, + cartan_type=classical, check=False) @cached_method def from_ambient_crystal(self): r""" - Provides a map from the ambient crystal of type `B_{n+1}^{(1)}` to + Return a map from the ambient crystal of type `B_{n+1}^{(1)}` to the Kirillov-Reshetikhin crystal of type `A_{2n}^{(2)}`. Note that this map is only well-defined on type `A_{2n}^{(2)}` @@ -1954,17 +2022,17 @@ def from_ambient_crystal(self): sage: K.from_ambient_crystal()(b) [[1, 1]] """ - keys = self.highest_weight_dict() - pdict_inv = dict( (self.ambient_highest_weight_dict()[key], self.highest_weight_dict()[key]) - for key in keys ) + hwd = self.highest_weight_dict() + ahwd = self.ambient_highest_weight_dict() + pdict_inv = {ahwd[key]: hwd[key] for key in hwd} ind = [j+1 for j in self.cartan_type().classical().index_set()] - return AmbientRetractMap( self, self.ambient_crystal(), pdict_inv, index_set=ind, - automorphism=lambda i : i-1 ) + return AmbientRetractMap(self, self.ambient_crystal(), pdict_inv, index_set=ind, + automorphism=lambda i: i-1) class KR_type_A2Element(KirillovReshetikhinGenericCrystalElement): r""" - Class for the elements in the Kirillov-Reshetikhin crystals `B^{r,s}` of type `A_{2n}^{(2)}` for `r """ def e0(self): r""" - Gives `e_0` on self by mapping self to the ambient crystal, calculating `e_0` there and - pulling the element back. + Return `e_0` on ``self`` by mapping ``self`` to the ambient crystal, + calculating `e_0` there and pulling the element back. EXAMPLES:: - sage: K=crystals.KirillovReshetikhin(['A',4,2],1,1) + sage: K = crystals.KirillovReshetikhin(['A',4,2],1,1) sage: b = K(rows=[]) sage: b.e(0) # indirect doctest [[-1]] @@ -2254,12 +2328,12 @@ def e0(self): def f0(self): r""" - Gives `f_0` on self by mapping self to the ambient crystal, calculating `f_0` there and - pulling the element back. + Return `f_0` on ``self`` by mapping ``self`` to the ambient crystal, + calculating `f_0` there and pulling the element back. EXAMPLES:: - sage: K=crystals.KirillovReshetikhin(['A',4,2],1,1) + sage: K = crystals.KirillovReshetikhin(['A',4,2],1,1) sage: b = K(rows=[]) sage: b.f(0) # indirect doctest [[1]] @@ -2271,13 +2345,13 @@ def f0(self): def epsilon0(self): r""" - Calculate `\varepsilon_0` of ``self`` by mapping the element + Return `\varepsilon_0` of ``self`` by mapping the element to the ambient crystal and calculating `\varepsilon_0` there. EXAMPLES:: sage: K = crystals.KirillovReshetikhin(['A',4,2], 1,1) - sage: b=K(rows=[[1]]) + sage: b = K(rows=[[1]]) sage: b.epsilon(0) # indirect doctest 2 """ @@ -2286,13 +2360,13 @@ def epsilon0(self): def phi0(self): r""" - Calculate `\varphi_0` of ``self`` by mapping the element to + Return `\varphi_0` of ``self`` by mapping the element to the ambient crystal and calculating `\varphi_0` there. EXAMPLES:: sage: K = crystals.KirillovReshetikhin(['D',3,2], 1,1) - sage: b=K(rows=[[-1]]) + sage: b = K(rows=[[-1]]) sage: b.phi(0) # indirect doctest 2 """ @@ -2358,12 +2432,15 @@ def _element_constructor_(self, *args, **options): def classical_decomposition(self): r""" - Specifies the classical crystal underlying the Kirillov-Reshetikhin crystal `B^{n,s}` of type `B_n^{(1)}`. + Return the classical crystal underlying the Kirillov-Reshetikhin + crystal `B^{n,s}` of type `B_n^{(1)}`. - It is the same as for `r0]) for r in b.to_tableau()]) - inter = Partition([len([i for i in r if i>=0]) for r in b.to_tableau()]) + inter1 = Partition([len([i for i in r if i > 0]) for r in b.to_tableau()]) + inter = Partition([len([i for i in r if i >= 0]) for r in b.to_tableau()]) if inter != inter1: inner[n-1] += 2 inner = Partition(inner) @@ -2902,9 +3004,10 @@ def from_highest_weight_vector_to_pm_diagram(self, b): return PMDiagram([n, s, outer, inter, inner], from_shapes=True) def from_pm_diagram_to_highest_weight_vector(self, pm): - """ - This gives the bijection between a `\pm` diagram and an element b in the classical - decomposition of the KR crystal that is {2,3,..,n}-highest weight. + r""" + This gives the bijection between a `\pm` diagram and an element + ``b`` in the classical decomposition of the KR crystal that is + `\{2,3,\ldots,n\}`-highest weight. EXAMPLES:: @@ -2931,7 +3034,8 @@ def from_pm_diagram_to_highest_weight_vector(self, pm): class KR_type_Dn_twistedElement(KirillovReshetikhinGenericCrystalElement): r""" - Class for the elements in the Kirillov-Reshetikhin crystals `B^{n,s}` of type `D_{n+1}^{(2)}`. + Class for the elements in the Kirillov-Reshetikhin crystals `B^{n,s}` + of type `D_{n+1}^{(2)}`. EXAMPLES:: @@ -2942,8 +3046,9 @@ class KR_type_Dn_twistedElement(KirillovReshetikhinGenericCrystalElement): def e0(self): r""" - Gives `e_0` on self by going to the `\pm`-diagram corresponding to the `{2,...,n}`-highest weight - vector in the component of `self`, then applying [Definition 6.2, 4], and pulling back from + Return `e_0` on ``self`` by going to the `\pm`-diagram corresponding + to the `\{2,\lots,n\}`-highest weight vector in the component of + ``self``, then applying [Definition 6.2, 4], and pulling back from `\pm`-diagrams. EXAMPLES:: @@ -2977,13 +3082,14 @@ def e0(self): def f0(self): r""" - Gives `e_0` on self by going to the `\pm`-diagram corresponding to the `{2,...,n}`-highest weight - vector in the component of `self`, then applying [Definition 6.2, 4], and pulling back from + Return `e_0` on ``self`` by going to the `\pm`-diagram corresponding + to the `\{2,\ldots,n\}`-highest weight vector in the component of + ``self``, then applying [Definition 6.2, 4], and pulling back from `\pm`-diagrams. EXAMPLES:: - sage: K=crystals.KirillovReshetikhin(['D',4,2],3,2) + sage: K = crystals.KirillovReshetikhin(['D',4,2],3,2) sage: b = K.module_generators[0] sage: b.f(0) # indirect doctest """ @@ -2993,7 +3099,7 @@ def f0(self): pm = self.parent().from_highest_weight_vector_to_pm_diagram(b) [l1,l2] = pm.pm_diagram[n-1] l3 = pm.pm_diagram[n-2][0] - if l1+l2+l3==s and l2==0: + if l1+l2+l3 == s and l2 == 0: return None if l1+l2+l3 0: - return (i,) + (self.e(i)).e_string_to_ground_state() + return (i,) + self.e(i).e_string_to_ground_state() if self.epsilon(0) > ell: - return (0,) + (self.e(0)).e_string_to_ground_state() + return (0,) + self.e(0).e_string_to_ground_state() return () CrystalOfWords.Element = TensorProductOfCrystalsElement @@ -1874,13 +1875,13 @@ def __classcall_private__(cls, cartan_type, shapes = None, shape = None): elif all(shape[-1]<0 for shape in spin_shapes): S = CrystalOfSpinsMinus(cartan_type) else: - raise ValueError("In type D spins should all be positive or negative") + raise ValueError("in type D spins should all be positive or negative") else: if any( i < 0 for shape in spin_shapes for i in shape): raise ValueError("shapes should all be partitions") S = CrystalOfSpins(cartan_type) - B = CrystalOfTableaux(cartan_type, shapes = shapes) - T = TensorProductOfCrystals(S,B, generators=[[S.module_generators[0],x] for x in B.module_generators]) + B = CrystalOfTableaux(cartan_type, shapes=shapes) + T = TensorProductOfCrystals(S, B, generators=[[S.module_generators[0],x] for x in B.module_generators]) T.rename("The crystal of tableaux of type %s and shape(s) %s"%(cartan_type, list(list(shape) for shape in spin_shapes))) T.shapes = spin_shapes return T @@ -1948,12 +1949,12 @@ def module_generator(self, shape): type = self.cartan_type() if type[0] == 'D' and len(shape) == type[1] and shape[type[1]-1] < 0: invert = True - shape = shape[:-1]+(-shape[type[1]-1],) + shape = shape[:-1] + (-shape[type[1]-1],) else: invert = False p = Partition(shape).conjugate() # The column canonical tableau, read by columns - module_generator = flatten([[p[j]-i for i in range(p[j])] for j in range(len(p))]) + module_generator = flatten([[val-i for i in range(val)] for val in p]) if invert: module_generator = [(-x if x == type[1] else x) for x in module_generator] return self(list=[self.letters(x) for x in module_generator]) @@ -1982,8 +1983,8 @@ class CrystalOfTableauxElement(TensorProductOfRegularCrystalsElement): def __init__(self, parent, *args, **options): """ There are several ways to input tableaux, by rows, - by columns, as the list of column elements, or as a sequence of numbers - in column reading. + by columns, as the list of column elements, or as a sequence + of numbers in column reading. EXAMPLES:: @@ -2151,7 +2152,7 @@ def _latex_(self): @cached_method def to_tableau(self): """ - Returns the Tableau object corresponding to self. + Return the :class:`Tableau` object corresponding to ``self``. EXAMPLES:: @@ -2186,10 +2187,9 @@ def to_tableau(self): def promotion(self): """ - Promotion for type A crystals of tableaux of rectangular shape - - Returns the result of applying promotion on this tableau. + Return the result of applying promotion on ``self``. + Promotion for type A crystals of tableaux of rectangular shape. This method only makes sense in type A with rectangular shapes. EXAMPLES:: @@ -2210,10 +2210,9 @@ def promotion(self): def promotion_inverse(self): """ - Inverse promotion for type A crystals of tableaux of rectangular shape - - Returns the result of applying inverse promotion on this tableau. + Return the result of applying inverse promotion on ``self``. + Inverse promotion for type A crystals of tableaux of rectangular shape. This method only makes sense in type A with rectangular shapes. EXAMPLES:: From d8b50b37a970983c146ed00fddb3c0d8a7d0cdac Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Fri, 24 Feb 2017 08:56:18 -0600 Subject: [PATCH 105/452] Fixed typo direclty -> directly. --- src/sage/combinat/crystals/kirillov_reshetikhin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/crystals/kirillov_reshetikhin.py b/src/sage/combinat/crystals/kirillov_reshetikhin.py index 9a58e382e1f..fa318a5089c 100644 --- a/src/sage/combinat/crystals/kirillov_reshetikhin.py +++ b/src/sage/combinat/crystals/kirillov_reshetikhin.py @@ -1228,13 +1228,13 @@ def promotion_on_highest_weight_vectors(self): sage: T = K.classical_decomposition() sage: hw = [ b for b in T if all(b.epsilon(i)==0 for i in [2,3,4]) ] sage: f = K.promotion_on_highest_weight_vectors() - doctest:...: DeprecationWarning: Call self.promotion_on_highest_weight_vector direclty + doctest:...: DeprecationWarning: Call self.promotion_on_highest_weight_vector directly See http://trac.sagemath.org/22429 for details. sage: f(hw[0]) [[1, 2], [-2, -1]] """ from sage.misc.superseded import deprecation - deprecation(22429, "Call self.promotion_on_highest_weight_vector direclty") + deprecation(22429, "Call self.promotion_on_highest_weight_vector directly") return self.promotion_on_highest_weight_vector def from_highest_weight_vector_to_pm_diagram(self, b): From c1836fcc1d774a70a8f5734f54124d79dfd656df Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 1 Mar 2017 09:26:39 -0600 Subject: [PATCH 106/452] Fixing some last tidbits. --- src/sage/combinat/crystals/direct_sum.py | 4 ++-- src/sage/combinat/crystals/kirillov_reshetikhin.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/combinat/crystals/direct_sum.py b/src/sage/combinat/crystals/direct_sum.py index 29356ff74af..59a9e2c49f6 100644 --- a/src/sage/combinat/crystals/direct_sum.py +++ b/src/sage/combinat/crystals/direct_sum.py @@ -53,7 +53,7 @@ class DirectSumOfCrystals(DisjointUnionEnumeratedSets): sage: [b.f(1) for b in B] [2, None, None, None, [[2], [3]], None] sage: B.module_generators - [1, [[1], [2]]] + (1, [[1], [2]]) :: @@ -61,7 +61,7 @@ class DirectSumOfCrystals(DisjointUnionEnumeratedSets): sage: B.list() [(0, 1), (0, 2), (0, 3), (1, 1), (1, 2), (1, 3)] sage: B.module_generators - [(0, 1), (1, 1)] + ((0, 1), (1, 1)) sage: b = B( tuple([0,C(1)]) ) sage: b (0, 1) diff --git a/src/sage/combinat/crystals/kirillov_reshetikhin.py b/src/sage/combinat/crystals/kirillov_reshetikhin.py index fa318a5089c..4510bd516f3 100644 --- a/src/sage/combinat/crystals/kirillov_reshetikhin.py +++ b/src/sage/combinat/crystals/kirillov_reshetikhin.py @@ -1450,7 +1450,7 @@ def hw_auxiliary(self): @cached_method def highest_weight_dict(self): r""" - Return a dictionary between `{1,2,3,4,5}` highest weight elements, + Return a dictionary between `\{1,2,3,4,5\}`-highest weight elements, and a tuple of affine weights and its classical component. EXAMPLES:: From e9186745d5df8cf7092e17103dee9c12b6b33ebf Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Fri, 17 Mar 2017 09:49:00 -0500 Subject: [PATCH 107/452] Moving CombinatorialFreeModuleElement to own (Cython) file. This involves renaming the class to IndexedFreeModuleElement. --- src/module_list.py | 3 + src/sage/algebras/free_algebra.py | 4 +- src/sage/algebras/free_algebra_element.py | 14 +- src/sage/algebras/iwahori_hecke_algebra.py | 4 +- .../algebras/steenrod/steenrod_algebra.py | 13 +- src/sage/algebras/weyl_algebra.py | 2 +- .../examples/filtered_modules_with_basis.py | 8 +- .../examples/graded_modules_with_basis.py | 8 +- src/sage/combinat/diagram_algebras.py | 5 +- src/sage/combinat/free_module.py | 828 +---------------- .../combinat/root_system/ambient_space.py | 4 +- src/sage/combinat/root_system/root_space.py | 4 +- src/sage/combinat/root_system/weight_space.py | 4 +- src/sage/homology/chains.py | 7 +- .../homology_vector_space_with_basis.py | 4 +- .../indexed_free_module_element.pxd | 10 + .../indexed_free_module_element.pyx | 878 ++++++++++++++++++ src/sage/quivers/algebra.py | 2 +- 18 files changed, 945 insertions(+), 857 deletions(-) create mode 100644 src/sage/modules/with_basis/indexed_free_module_element.pxd create mode 100644 src/sage/modules/with_basis/indexed_free_module_element.pyx diff --git a/src/module_list.py b/src/module_list.py index f5fcd79fe3a..caf896c51ef 100644 --- a/src/module_list.py +++ b/src/module_list.py @@ -1026,6 +1026,9 @@ def uname_specific(name, value, alternative): Extension('sage.modules.vector_real_double_dense', ['sage/modules/vector_real_double_dense.pyx']), + Extension('sage.modules.with_basis.indexed_free_module_element', + sources = ['sage/modules/with_basis/indexed_free_module_element.pyx']), + ################################ ## ## sage.numerical diff --git a/src/sage/algebras/free_algebra.py b/src/sage/algebras/free_algebra.py index a4c25868c12..cd8521cb854 100644 --- a/src/sage/algebras/free_algebra.py +++ b/src/sage/algebras/free_algebra.py @@ -145,7 +145,7 @@ from sage.rings.ring import Algebra from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular from sage.categories.algebras_with_basis import AlgebrasWithBasis -from sage.combinat.free_module import CombinatorialFreeModule, CombinatorialFreeModuleElement +from sage.combinat.free_module import CombinatorialFreeModule from sage.combinat.words.word import Word from sage.structure.category_object import normalize_names @@ -1336,7 +1336,7 @@ def expansion(self, t): return sum([i[1] * self._alg.lie_polynomial(i[0]) for i in list(t)], self._alg.zero()) - class Element(CombinatorialFreeModuleElement): + class Element(CombinatorialFreeModule.Element): def expand(self): """ Expand ``self`` in the monomials of the free algebra. diff --git a/src/sage/algebras/free_algebra_element.py b/src/sage/algebras/free_algebra_element.py index bb67ba568f5..42c5ad1e77d 100644 --- a/src/sage/algebras/free_algebra_element.py +++ b/src/sage/algebras/free_algebra_element.py @@ -36,7 +36,7 @@ from sage.misc.misc import repr_lincomb from sage.monoids.free_monoid_element import FreeMonoidElement -from sage.combinat.free_module import CombinatorialFreeModuleElement +from sage.modules.with_basis.indexed_free_module_element import IndexedFreeModuleElement from sage.structure.element import AlgebraElement from sage.structure.sage_object import richcmp @@ -45,7 +45,7 @@ # We need to have AlgebraElement first to avoid a segfault... -class FreeAlgebraElement(AlgebraElement, CombinatorialFreeModuleElement): +class FreeAlgebraElement(AlgebraElement, IndexedFreeModuleElement): """ A free algebra element. """ @@ -71,13 +71,13 @@ def __init__(self, A, x): else: raise TypeError("Argument x (= {}) is of the wrong type.".format(x)) - CombinatorialFreeModuleElement.__init__(self, A, x) + IndexedFreeModuleElement.__init__(self, A, x) # ...however AlgebraElement has a default error raising version of these - # so we must explicitly pull them from CombinatorialFreeModuleElement - _add_ = CombinatorialFreeModuleElement._add_ - _sub_ = CombinatorialFreeModuleElement._sub_ - _neg_ = CombinatorialFreeModuleElement._neg_ + # so we must explicitly pull them from IndexedFreeModuleElement + _add_ = IndexedFreeModuleElement._add_ + _sub_ = IndexedFreeModuleElement._sub_ + _neg_ = IndexedFreeModuleElement._neg_ def _repr_(self): """ diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 05bd7da97f1..fa70cb30520 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -33,7 +33,7 @@ from sage.arith.all import is_square from sage.combinat.root_system.weyl_group import WeylGroup from sage.combinat.family import Family -from sage.combinat.free_module import CombinatorialFreeModule, CombinatorialFreeModuleElement +from sage.combinat.free_module import CombinatorialFreeModule def normalized_laurent_polynomial(R, p): r""" @@ -1657,7 +1657,7 @@ def goldman_involution_on_basis(self, w): H = self.realization_of() return (-H._q_prod)**w.length() * self.monomial(w.inverse()).inverse() - class Element(CombinatorialFreeModuleElement): + class Element(CombinatorialFreeModule.Element): r""" A class for elements of an Iwahori-Hecke algebra in the `T` basis. diff --git a/src/sage/algebras/steenrod/steenrod_algebra.py b/src/sage/algebras/steenrod/steenrod_algebra.py index 4ce6f84b184..7189be1ad55 100644 --- a/src/sage/algebras/steenrod/steenrod_algebra.py +++ b/src/sage/algebras/steenrod/steenrod_algebra.py @@ -454,8 +454,7 @@ from __future__ import print_function from __future__ import absolute_import -from sage.combinat.free_module import CombinatorialFreeModule, \ - CombinatorialFreeModuleElement +from sage.combinat.free_module import CombinatorialFreeModule from sage.misc.lazy_attribute import lazy_attribute from sage.misc.cachefunc import cached_method from sage.categories.all import ModulesWithBasis, tensor, Hom @@ -3073,22 +3072,22 @@ def is_generic(self): # element class ###################################################### - class Element(CombinatorialFreeModuleElement): + class Element(CombinatorialFreeModule.Element): r""" Class for elements of the Steenrod algebra. Since the Steenrod algebra class is based on :class:`CombinatorialFreeModule `, this is - based on :class:`CombinatorialFreeModuleElement - `. + based on :class:`IndexedFreeModuleElement + `. It has new methods reflecting its role, like :meth:`degree` for computing the degree of an element. EXAMPLES: Since this class inherits from - :class:`CombinatorialFreeModuleElement - `, + :class:`IndexedFreeModuleElement + `, elements can be used as iterators, and there are other useful methods:: diff --git a/src/sage/algebras/weyl_algebra.py b/src/sage/algebras/weyl_algebra.py index 4104760a13a..39b41b3db3f 100644 --- a/src/sage/algebras/weyl_algebra.py +++ b/src/sage/algebras/weyl_algebra.py @@ -24,7 +24,7 @@ from sage.categories.algebras_with_basis import AlgebrasWithBasis from sage.sets.family import Family import sage.data_structures.blas_dict as blas -from sage.combinat.free_module import _divide_if_possible +from sage.modules.with_basis.indexed_free_module_element import _divide_if_possible from sage.rings.ring import Algebra from sage.rings.polynomial.polynomial_ring import PolynomialRing_general from sage.rings.polynomial.multi_polynomial_ring_generic import MPolynomialRing_generic diff --git a/src/sage/categories/examples/filtered_modules_with_basis.py b/src/sage/categories/examples/filtered_modules_with_basis.py index 9954d6a2ff5..ed00ac97b57 100644 --- a/src/sage/categories/examples/filtered_modules_with_basis.py +++ b/src/sage/categories/examples/filtered_modules_with_basis.py @@ -63,10 +63,10 @@ class FilteredPartitionModule(CombinatorialFreeModule): 'P[4, 3]' - There is a class for elements, which inherits from - :class:`CombinatorialFreeModuleElement - `. An - element is determined by a dictionary whose keys are partitions and whose - corresponding values are the coefficients. The class implements + :class:`IndexedFreeModuleElement + `. + An element is determined by a dictionary whose keys are partitions and + whose corresponding values are the coefficients. The class implements two things: an :meth:`is_homogeneous ` method and a :meth:`degree ` method. diff --git a/src/sage/categories/examples/graded_modules_with_basis.py b/src/sage/categories/examples/graded_modules_with_basis.py index e0f95880199..7af0ff2ed99 100644 --- a/src/sage/categories/examples/graded_modules_with_basis.py +++ b/src/sage/categories/examples/graded_modules_with_basis.py @@ -77,10 +77,10 @@ class GradedPartitionModule(CombinatorialFreeModule): 'P[4, 3]' - There is a class for elements, which inherits from - :class:`CombinatorialFreeModuleElement - `. An - element is determined by a dictionary whose keys are partitions and whose - corresponding values are the coefficients. The class implements + :class:`IndexedFreeModuleElement + `. + An element is determined by a dictionary whose keys are partitions and + whose corresponding values are the coefficients. The class implements two things: an :meth:`is_homogeneous ` method and a :meth:`degree ` method. diff --git a/src/sage/combinat/diagram_algebras.py b/src/sage/combinat/diagram_algebras.py index fd26541c4cd..eefd7dff136 100644 --- a/src/sage/combinat/diagram_algebras.py +++ b/src/sage/combinat/diagram_algebras.py @@ -26,8 +26,7 @@ from sage.categories.algebras import Algebras from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets from sage.structure.element import generic_power -from sage.combinat.free_module import (CombinatorialFreeModule, - CombinatorialFreeModuleElement) +from sage.combinat.free_module import CombinatorialFreeModule from sage.structure.parent import Parent from sage.structure.unique_representation import UniqueRepresentation from sage.combinat.combinat import bell_number, catalan_number @@ -1462,7 +1461,7 @@ def sgn(x): # The following subclass provides a few additional methods for # partition algebra elements. - class Element(CombinatorialFreeModuleElement): + class Element(CombinatorialFreeModule.Element): r""" An element of a diagram algebra. diff --git a/src/sage/combinat/free_module.py b/src/sage/combinat/free_module.py index 949b31f52e0..23183127f77 100644 --- a/src/sage/combinat/free_module.py +++ b/src/sage/combinat/free_module.py @@ -14,824 +14,25 @@ from six.moves import range from sage.structure.unique_representation import UniqueRepresentation -from sage.structure.element import Element, have_same_parent from sage.structure.parent import Parent from sage.structure.indexed_generators import IndexedGenerators -from sage.misc.misc import repr_lincomb from sage.modules.module import Module from sage.rings.all import Integer -import sage.structure.element +from sage.structure.element import parent +from sage.modules.with_basis.indexed_free_module_element import IndexedFreeModuleElement from sage.sets.finite_enumerated_set import FiniteEnumeratedSet from sage.combinat.cartesian_product import CartesianProduct_iters from sage.sets.disjoint_union_enumerated_sets import DisjointUnionEnumeratedSets from sage.misc.cachefunc import cached_method from sage.misc.lazy_attribute import lazy_attribute from sage.categories.all import Category, Sets, ModulesWithBasis +from sage.categories.tensor import tensor import sage.data_structures.blas_dict as blas -from sage.typeset.ascii_art import AsciiArt, empty_ascii_art -from sage.typeset.unicode_art import UnicodeArt, empty_unicode_art +from sage.typeset.ascii_art import AsciiArt +from sage.typeset.unicode_art import UnicodeArt import six - -# TODO: move the content of this class to CombinatorialFreeModule.Element and ModulesWithBasis.Element -class CombinatorialFreeModuleElement(Element): - def __init__(self, M, x): - """ - Create a combinatorial module element. This should never be - called directly, but only through the parent combinatorial - free module's :meth:`__call__` method. - - TESTS:: - - sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) - sage: B = F.basis() - sage: f = B['a'] + 3*B['c']; f - B['a'] + 3*B['c'] - sage: f == loads(dumps(f)) - True - """ - Element.__init__(self, M) - self._monomial_coefficients = x - - def __iter__(self): - """ - EXAMPLES:: - - sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) - sage: B = F.basis() - sage: f = B['a'] + 3*B['c'] - sage: [i for i in sorted(f)] - [('a', 1), ('c', 3)] - - :: - - sage: s = SymmetricFunctions(QQ).schur() - sage: a = s([2,1]) + s([3]) - sage: [i for i in sorted(a)] - [([2, 1], 1), ([3], 1)] - """ - return six.iteritems(self._monomial_coefficients) - - def __contains__(self, x): - """ - Returns whether or not a combinatorial object x indexing a basis - element is in the support of self. - - EXAMPLES:: - - sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) - sage: B = F.basis() - sage: f = B['a'] + 3*B['c'] - sage: 'a' in f - True - sage: 'b' in f - False - - :: - - sage: s = SymmetricFunctions(QQ).schur() - sage: a = s([2,1]) + s([3]) - sage: Partition([2,1]) in a - True - sage: Partition([1,1,1]) in a - False - """ - return x in self._monomial_coefficients and self._monomial_coefficients[x] != 0 - - @cached_method - def __hash__(self): - """ - Return the hash value for ``self``. - - The result is cached. - - EXAMPLES:: - - sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) - sage: B = F.basis() - sage: f = B['a'] + 3*B['c'] - sage: hash(f) - 6429418278783588506 # 64-bit - 726440090 # 32-bit - - sage: F = RootSystem(['A',2]).ambient_space() - sage: f = F.simple_root(0) - sage: hash(f) - 6920829894162680369 # 64-bit - -528971215 # 32-bit - - This uses the recipe that was proposed for frozendicts in `PEP - 0416 `_ (and adds - the hash of the parent). This recipe relies on the hash - function for frozensets which uses tricks to mix the hash - values of the items in case they are similar. - - .. TODO:: - - It would be desirable to make the hash value depend on the - hash value of the parent. See :trac:`15959`. - """ - return hash(frozenset(self._monomial_coefficients.items())) - - def monomial_coefficients(self, copy=True): - """ - Return the internal dictionary which has the combinatorial objects - indexing the basis as keys and their corresponding coefficients as - values. - - INPUT: - - - ``copy`` -- (default: ``True``) if ``self`` is internally - represented by a dictionary ``d``, then make a copy of ``d``; - if ``False``, then this can cause undesired behavior by - mutating ``d`` - - EXAMPLES:: - - sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) - sage: B = F.basis() - sage: f = B['a'] + 3*B['c'] - sage: d = f.monomial_coefficients() - sage: d['a'] - 1 - sage: d['c'] - 3 - - To run through the monomials of an element, it is better to - use the idiom:: - - sage: for (t,c) in f: - ....: print("{} {}".format(t,c)) - a 1 - c 3 - - :: - - sage: s = SymmetricFunctions(QQ).schur() - sage: a = s([2,1])+2*s([3,2]) - sage: d = a.monomial_coefficients() - sage: type(d) - <... 'dict'> - sage: d[ Partition([2,1]) ] - 1 - sage: d[ Partition([3,2]) ] - 2 - """ - if copy: - return dict(self._monomial_coefficients) - return self._monomial_coefficients - - def _sorted_items_for_printing(self): - """ - Returns the items (i.e terms) of ``self``, sorted for printing - - EXAMPLES:: - - sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) - sage: B = F.basis() - sage: f = B['a'] + 2*B['c'] + 3 * B['b'] - sage: f._sorted_items_for_printing() - [('a', 1), ('b', 3), ('c', 2)] - sage: F.print_options(sorting_reverse=True) - sage: f._sorted_items_for_printing() - [('c', 2), ('b', 3), ('a', 1)] - sage: F.print_options(sorting_reverse=False) #reset to original state - - .. SEEALSO:: :meth:`_repr_`, :meth:`_latex_`, :meth:`print_options` - """ - print_options = self.parent().print_options() - v = self._monomial_coefficients.items() - try: - v.sort(key=lambda monomial_coeff: - print_options['sorting_key'](monomial_coeff[0]), - reverse=print_options['sorting_reverse']) - except Exception: # Sorting the output is a plus, but if we can't, no big deal - pass - return v - - def _repr_(self): - """ - EXAMPLES:: - - sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'], prefix='F') - sage: e = F.basis() - sage: e['a'] + 2*e['b'] # indirect doctest - F['a'] + 2*F['b'] - sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'], prefix='') - sage: e = F.basis() - sage: e['a'] + 2*e['b'] # indirect doctest - ['a'] + 2*['b'] - sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'], prefix='', scalar_mult=' ', bracket=False) - sage: e = F.basis() - sage: e['a'] + 2*e['b'] # indirect doctest - 'a' + 2 'b' - - Controling the order of terms by providing a comparison - function on elements of the support:: - - sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'], - ....: sorting_reverse=True) - sage: e = F.basis() - sage: e['a'] + 3*e['b'] + 2*e['c'] - 2*B['c'] + 3*B['b'] + B['a'] - - sage: F = CombinatorialFreeModule(QQ, ['ac', 'ba', 'cb'], - ....: sorting_key=lambda x: x[1]) - sage: e = F.basis() - sage: e['ac'] + 3*e['ba'] + 2*e['cb'] - 3*B['ba'] + 2*B['cb'] + B['ac'] - """ - return repr_lincomb(self._sorted_items_for_printing(), - scalar_mult=self.parent()._print_options['scalar_mult'], - repr_monomial = self.parent()._repr_term, - strip_one = True) - - def _ascii_art_(self): - """ - TESTS:: - - sage: M = QuasiSymmetricFunctions(QQ).M() - sage: ascii_art(M[1,3]**2) # indirect doctest - 4*M + 2*M + 2*M + 2*M + 2*M + M - *** ****** *** *** *** ****** - *** * * **** *** ** - * * *** * ** - * * - sage: ascii_art(M.zero()) - 0 - """ - from sage.misc.misc import coeff_repr - terms = self._sorted_items_for_printing() - scalar_mult = self.parent()._print_options['scalar_mult'] - repr_monomial = self.parent()._ascii_art_term - strip_one = True - - if repr_monomial is None: - repr_monomial = str - - s = empty_ascii_art # "" - first = True - - if scalar_mult is None: - scalar_mult = "*" - - for (monomial,c) in terms: - b = repr_monomial(monomial) # PCR - if c != 0: - break_points = [] - coeff = coeff_repr(c, False) - if coeff != "0": - if coeff == "1": - coeff = "" - elif coeff == "-1": - coeff = "-" - elif b._l > 0: - if len(coeff) > 0 and monomial == 1 and strip_one: - b = empty_ascii_art # "" - else: - b = AsciiArt([scalar_mult]) + b - if not first: - if len(coeff) > 0 and coeff[0] == "-": - coeff = " - %s"%coeff[1:] - else: - coeff = " + %s"%coeff - break_points = [2] - else: - coeff = "%s"%coeff - s += AsciiArt([coeff], break_points) + b - first = False - if first: - return AsciiArt(["0"]) - elif s == empty_ascii_art: - return AsciiArt(["1"]) - else: - return s - - def _unicode_art_(self): - """ - TESTS:: - - sage: M = QuasiSymmetricFunctions(QQ).M() - sage: unicode_art(M[1,1]**2) # indirect doctest - 6*M + 2*M + 2*M + 2*M + M - ┌┐ ┌┬┐ ┌┐ ┌┐ ┌┬┐ - ├┤ ├┼┘ ┌┼┤ ├┤ ┌┼┼┘ - ├┤ ├┤ ├┼┘ ┌┼┤ └┴┘ - ├┤ └┘ └┘ └┴┘ - └┘ - """ - from sage.misc.misc import coeff_repr - terms = self._sorted_items_for_printing() - scalar_mult = self.parent()._print_options['scalar_mult'] - repr_monomial = self.parent()._unicode_art_term - strip_one = True - - if repr_monomial is None: - repr_monomial = str - - s = empty_unicode_art # "" - first = True - - if scalar_mult is None: - scalar_mult = "*" - - for (monomial, c) in terms: - b = repr_monomial(monomial) # PCR - if c != 0: - break_points = [] - coeff = coeff_repr(c, False) - if coeff != "0": - if coeff == "1": - coeff = "" - elif coeff == "-1": - coeff = "-" - elif b._l > 0: - if len(coeff) > 0 and monomial == 1 and strip_one: - b = empty_unicode_art # "" - else: - b = UnicodeArt([scalar_mult]) + b - if not first: - if len(coeff) > 0 and coeff[0] == "-": - coeff = " - %s" % coeff[1:] - else: - coeff = " + %s" % coeff - break_points = [2] - else: - coeff = "%s" % coeff - s += UnicodeArt([coeff], break_points) + b - first = False - if first: - return "0" - elif s == empty_unicode_art: - return UnicodeArt(["1"]) - else: - return s - - def _latex_(self): - r""" - EXAMPLES:: - - sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) - sage: B = F.basis() - sage: f = B['a'] + 3*B['c'] - sage: latex(f) - B_{a} + 3B_{c} - - :: - - sage: QS3 = SymmetricGroupAlgebra(QQ,3) - sage: a = 2 + QS3([2,1,3]) - sage: latex(a) #indirect doctest - 2[1, 2, 3] + [2, 1, 3] - - :: - - sage: F = CombinatorialFreeModule(QQ, ['a','b'], prefix='beta', latex_prefix='\\beta') - sage: x = F.an_element() - sage: x - 2*beta['a'] + 2*beta['b'] - sage: latex(x) - 2\beta_{a} + 2\beta_{b} - - Controling the order of terms by providing a comparison - function on elements of the support:: - - sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'], - ....: sorting_reverse=True) - sage: e = F.basis() - sage: latex(e['a'] + 3*e['b'] + 2*e['c']) - 2B_{c} + 3B_{b} + B_{a} - - sage: F = CombinatorialFreeModule(QQ, ['ac', 'ba', 'cb'], - ....: sorting_key=lambda x: x[1]) - sage: e = F.basis() - sage: latex(e['ac'] + 3*e['ba'] + 2*e['cb']) - 3B_{ba} + 2B_{cb} + B_{ac} - """ - return repr_lincomb(self._sorted_items_for_printing(), - scalar_mult = self.parent()._print_options['scalar_mult'], - latex_scalar_mult = self.parent()._print_options['latex_scalar_mult'], - repr_monomial = self.parent()._latex_term, - is_latex=True, strip_one = True) - - def __eq__(self, other): - """ - EXAMPLES:: - - sage: F1 = CombinatorialFreeModule(QQ, [1, 2, 3]) - sage: F2 = CombinatorialFreeModule(QQ, [1, 2, 3], prefix = "g") - sage: F1.zero() == F1.zero() - True - sage: F1.zero() == F1.an_element() - False - sage: F1.an_element() == F1.an_element() - True - sage: F1.an_element() is None - False - - .. TODO:: - - Currently, if ``self`` and ``other`` do not have the same parent, - seemingly equal elements do not evaluate equal, since conversions - between different modules have not been established. - - :: - - sage: F1.zero() == 0 - True - sage: F1(0) - 0 - - :: - - sage: F1.zero() == F2.zero() - False - sage: F1(F2.zero()) - Traceback (most recent call last): - ... - TypeError: do not know how to make x (= 0) an element of self (=Free module generated by {1, 2, 3} over Rational Field) - sage: F = AlgebrasWithBasis(QQ).example() - sage: F.one() == 1 - True - sage: 1 == F.one() - True - sage: 2 * F.one() == int(2) - True - sage: int(2) == 2 * F.one() - True - - sage: S = SymmetricFunctions(QQ); s = S.s(); p = S.p() - sage: p[2] == s[2] - s[1, 1] - True - sage: p[2] == s[2] - False - - This feature is disputable, in particular since it can make - equality testing costly. It may be removed at some point. - - Equality testing can be a bit tricky when the order of terms - can vary because their indices are incomparable with - ``cmp``. The following test did fail before :trac:`12489` :: - - sage: F = CombinatorialFreeModule(QQ, Subsets([1,2,3])) - sage: x = F.an_element() - sage: (x+F.zero()).terms() # random - [2*B[{1}], 3*B[{2}], B[{}]] - sage: x.terms() # random - [2*B[{1}], B[{}], 3*B[{2}]] - sage: x+F.zero() == x - True - - TESTS:: - - sage: TestSuite(F1).run() - sage: TestSuite(F).run() - """ - if have_same_parent(self, other): - return self._monomial_coefficients == other._monomial_coefficients - from sage.structure.element import get_coercion_model - import operator - try: - return get_coercion_model().bin_op(self, other, operator.eq) - except TypeError: - return False - - def __ne__(left, right): - """ - EXAMPLES:: - - sage: F1 = CombinatorialFreeModule(QQ, ['a','b','c']) - sage: F1.an_element() != F1.an_element() - False - sage: F1.an_element() != F1.zero() - True - """ - return not left == right - - def __cmp__(left, right): - """ - The ordering is the one on the underlying sorted list of - (monomial,coefficients) pairs. - - EXAMPLES:: - - sage: s = SymmetricFunctions(QQ).schur() - sage: a = s([2,1]) - sage: b = s([1,1,1]) - sage: cmp(a,b) #indirect doctest - 1 - """ - if have_same_parent(left, right) and left._monomial_coefficients == right._monomial_coefficients: - return 0 - v = sorted(mc for mc in left._monomial_coefficients.items() if mc[1] != 0) - w = sorted(mc for mc in right._monomial_coefficients.items() if mc[1] != 0) - return cmp(v, w) - - def _add_(self, other): - """ - EXAMPLES:: - - sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) - sage: B = F.basis() - sage: B['a'] + 3*B['c'] - B['a'] + 3*B['c'] - - :: - - sage: s = SymmetricFunctions(QQ).schur() - sage: s([2,1]) + s([5,4]) # indirect doctest - s[2, 1] + s[5, 4] - sage: a = s([2,1]) + 0 - sage: len(a.monomial_coefficients()) - 1 - """ - F = self.parent() - return F._from_dict(blas.add(self._monomial_coefficients, - other._monomial_coefficients), - remove_zeros=False) - - def _neg_(self): - """ - EXAMPLES:: - - sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) - sage: B = F.basis() - sage: f = B['a'] + 3*B['c'] - sage: -f - -B['a'] - 3*B['c'] - - :: - - sage: s = SymmetricFunctions(QQ).schur() - sage: -s([2,1]) # indirect doctest - -s[2, 1] - """ - F = self.parent() - return F._from_dict(blas.negate(self._monomial_coefficients), - remove_zeros=False) - - def _sub_(self, other): - """ - EXAMPLES:: - - sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) - sage: B = F.basis() - sage: B['a'] - 3*B['c'] - B['a'] - 3*B['c'] - - :: - - sage: s = SymmetricFunctions(QQ).schur() - sage: s([2,1]) - s([5,4]) # indirect doctest - s[2, 1] - s[5, 4] - """ - F = self.parent() - return F._from_dict(blas.axpy(-1, - other._monomial_coefficients, - self._monomial_coefficients), - remove_zeros=False) - - def _coefficient_fast(self, m): - """ - Return the coefficient of ``m`` in ``self``, where ``m`` is key in - ``self._monomial_coefficients``. - - EXAMPLES:: - - sage: p = Partition([2,1]) - sage: q = Partition([1,1,1]) - sage: s = SymmetricFunctions(QQ).schur() - sage: a = s(p) - sage: a._coefficient_fast([2,1]) - Traceback (most recent call last): - ... - TypeError: unhashable type: 'list' - - :: - - sage: a._coefficient_fast(p) - 1 - sage: a._coefficient_fast(q) - 0 - sage: a[p] - 1 - sage: a[q] - 0 - """ - return self._monomial_coefficients.get(m, self.base_ring().zero()) - - __getitem__ = _coefficient_fast - - def _vector_(self, new_base_ring=None): - """ - Returns ``self`` as a dense vector - - INPUT: - - - ``new_base_ring`` -- a ring (default: ``None``) - - OUTPUT: a dense :func:`FreeModule` vector - - .. WARNING:: This will crash/run forever if ``self`` is infinite dimensional! - - .. SEEALSO:: - - - :func:`vector` - - :meth:`CombinatorialFreeModule.get_order` - - :meth:`CombinatorialFreeModule.from_vector` - - :meth:`CombinatorialFreeModule._dense_free_module` - - EXAMPLES:: - - sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) - sage: B = F.basis() - sage: f = B['a'] - 3*B['c'] - sage: f._vector_() - (1, 0, -3) - - One can use equivalently:: - - sage: f.to_vector() - (1, 0, -3) - sage: vector(f) - (1, 0, -3) - - More examples:: - - sage: QS3 = SymmetricGroupAlgebra(QQ, 3) - sage: a = 2*QS3([1,2,3])+4*QS3([3,2,1]) - sage: a._vector_() - (2, 0, 0, 0, 0, 4) - sage: a.to_vector() - (2, 0, 0, 0, 0, 4) - sage: vector(a) - (2, 0, 0, 0, 0, 4) - sage: a == QS3.from_vector(a.to_vector()) - True - - If ``new_base_ring`` is specified, then a vector over - ``new_base_ring`` is returned:: - - sage: a._vector_(RDF) - (2.0, 0.0, 0.0, 0.0, 0.0, 4.0) - - .. NOTE:: - - :trac:`13406`: the current implementation has been optimized, at - the price of breaking the encapsulation for FreeModule - elements creation, with the following use case as metric, - on a 2008' Macbook Pro:: - - sage: F = CombinatorialFreeModule(QQ, range(10)) - sage: f = F.an_element() - sage: %timeit f._vector_() # not tested - 625 loops, best of 3: 17.5 micros per loop - - Other use cases may call for different or further - optimizations. - """ - parent = self.parent() - dense_free_module = parent._dense_free_module(new_base_ring) - d = self._monomial_coefficients - return dense_free_module.element_class(dense_free_module, - [d.get(m, 0) for m in parent.get_order()], - coerce=True, copy=False) - - to_vector = _vector_ - - def _acted_upon_(self, scalar, self_on_left=False): - """ - Return the action of ``scalar`` (an element of the base ring) on - ``self``. - - EXAMPLES:: - - sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) - sage: B = F.basis() - sage: B['a']*(1/2) # indirect doctest - 1/2*B['a'] - sage: B['a']/2 - 1/2*B['a'] - sage: B['a']*2 # indirect doctest - 2*B['a'] - sage: B['a']*int(2) # indirect doctest - 2*B['a'] - - sage: 1/2*B['a'] - 1/2*B['a'] - sage: 2*B['a'] # indirect doctest - 2*B['a'] - sage: int(2)*B['a'] # indirect doctest - 2*B['a'] - - TESTS:: - - sage: F.get_action(QQ, operator.mul, True) - Right action by Rational Field on Free module generated by {'a', 'b', 'c'} over Rational Field - sage: F.get_action(QQ, operator.mul, False) - Left action by Rational Field on Free module generated by {'a', 'b', 'c'} over Rational Field - sage: F.get_action(ZZ, operator.mul, True) - Right action by Integer Ring on Free module generated by {'a', 'b', 'c'} over Rational Field - sage: F.get_action(F, operator.mul, True) - sage: F.get_action(F, operator.mul, False) - - This also works when a coercion of the coefficient is needed, for - example with polynomials or fraction fields (:trac:`8832`):: - - sage: P. = QQ['q'] - sage: V = CombinatorialFreeModule(P, Permutations()) - sage: el = V(Permutation([3,1,2])) - sage: (3/2)*el - 3/2*B[[3, 1, 2]] - - sage: P. = QQ['q'] - sage: F = FractionField(P) - sage: V = CombinatorialFreeModule(F, Words()) - sage: w = Words()('abc') - sage: (1+q)*V(w) - (q+1)*B[word: abc] - sage: ((1+q)/q)*V(w) - ((q+1)/q)*B[word: abc] - - TODO: - - add non commutative tests - """ - # With the current design, the coercion model does not have - # enough information to detect a priori that this method only - # accepts scalars; so it tries on some elements(), and we need - # to make sure to report an error. - if isinstance(scalar, Element) and scalar.parent() is not self.base_ring(): - # Temporary needed by coercion (see Polynomial/FractionField tests). - if self.base_ring().has_coerce_map_from(scalar.parent()): - scalar = self.base_ring()( scalar ) - else: - return None - - F = self.parent() - D = self._monomial_coefficients - return F._from_dict(blas.scal(scalar, D, factor_on_left=not self_on_left), - remove_zeros=False) - - # For backward compatibility - _lmul_ = _acted_upon_ - _rmul_ = _acted_upon_ - - def __truediv__(self, x): - """ - Division by coefficients. - - EXAMPLES:: - - sage: F = CombinatorialFreeModule(QQ, [1,2,3]) - sage: x = F._from_dict({1:2, 2:3}) - sage: x/2 - B[1] + 3/2*B[2] - - :: - - sage: F = CombinatorialFreeModule(QQ, [1,2,3]) - sage: B = F.basis() - sage: f = 2*B[2] + 4*B[3] - sage: f/2 - B[2] + 2*B[3] - """ - if not self.base_ring().is_field(): - return self.map_coefficients(lambda c: _divide_if_possible(c, x)) - - F = self.parent() - x = self.base_ring()( x ) - x_inv = x**-1 - D = self._monomial_coefficients - return F._from_dict(blas.scal(x_inv, D), - remove_zeros=False) - - __div__ = __truediv__ - - -def _divide_if_possible(x, y): - """ - EXAMPLES:: - - sage: from sage.combinat.free_module import _divide_if_possible - sage: _divide_if_possible(4, 2) - 2 - sage: _.parent() - Integer Ring - - :: - - sage: _divide_if_possible(4, 3) - Traceback (most recent call last): - ... - ValueError: 4 is not divisible by 3 - """ - q, r = x.quo_rem(y) - if r != 0: - raise ValueError("%s is not divisible by %s"%(x, y)) - else: - return q - class CombinatorialFreeModule(UniqueRepresentation, Module, IndexedGenerators): r""" Class for free modules with a named basis @@ -846,7 +47,7 @@ class CombinatorialFreeModule(UniqueRepresentation, Module, IndexedGenerators): - ``element_class`` - the class of which elements of this module should be instances (optional, default None, in which case the elements are instances of - :class:`CombinatorialFreeModuleElement`) + :class:`~sage.modules.with_basis.indexed_free_module_element.IndexedFreeModuleElement`) - ``category`` - the category in which this module lies (optional, default None, in which case use the "category of modules with @@ -1084,7 +285,10 @@ def __classcall_private__(cls, base_ring, basis_keys, category = None, prefix="B keywords['latex_bracket'] = tuple(latex_bracket) return super(CombinatorialFreeModule, cls).__classcall__(cls, base_ring, basis_keys, category = category, prefix=prefix, **keywords) - Element = CombinatorialFreeModuleElement + # We make this explicitly a Python class so that the methods, + # specifically _mul_, from category framework still works -- TCS + class Element(IndexedFreeModuleElement): + pass def __init__(self, R, basis_keys, element_class = None, category = None, prefix="B", **kwds): r""" @@ -1199,7 +403,6 @@ def _ascii_art_term(self, m): sage: ascii_art(R.one()) # indirect doctest 1 """ - from sage.typeset.ascii_art import AsciiArt try: if m == self.one_basis(): return AsciiArt(["1"]) @@ -1291,7 +494,7 @@ def __contains__(self, x): sage: 5/3 in F False """ - return sage.structure.element.parent(x) == self # is self? + return parent(x) == self # is self? def _element_constructor_(self, x): """ @@ -1409,7 +612,7 @@ def _element_constructor_(self, x): elif ((hasattr(self._indices, 'element_class') and isinstance(self._indices.element_class, type) and isinstance(x, self._indices.element_class)) - or (sage.structure.element.parent(x) == self._indices)): + or (parent(x) == self._indices)): return self.monomial(x) elif x in self._indices: return self.monomial(self._indices(x)) @@ -1653,7 +856,7 @@ def from_vector(self, vector): True """ cc = self.get_order() - return self._from_dict(dict( (cc[index], coeff) for (index,coeff) in six.iteritems(vector))) + return self._from_dict({cc[index]: coeff for (index,coeff) in six.iteritems(vector)}) def __cmp__(self, other): """ @@ -2056,7 +1259,6 @@ def _ascii_art_(self, term): ## # ## """ - from sage.categories.tensor import tensor if hasattr(self, "_print_options"): symb = self._print_options['tensor_symbol'] if symb is None: @@ -2086,7 +1288,6 @@ def _unicode_art_(self, term): └┴┘ ├┼┐ └┴┘ """ - from sage.categories.tensor import tensor if hasattr(self, "_print_options"): symb = self._print_options['tensor_symbol'] if symb is None: @@ -2133,7 +1334,6 @@ def _repr_term(self, term): sage: tensor([f, g]) # indirect doctest 2*F[1] # G[3] + F[1] # G[4] + 4*F[2] # G[3] + 2*F[2] # G[4] """ - from sage.categories.tensor import tensor if hasattr(self, "_print_options"): symb = self._print_options['tensor_symbol'] if symb is None: @@ -2191,7 +1391,7 @@ def tensor_constructor(self, modules): 2*B[1] # B[3] # B[5] + 2*B[1] # B[3] # B[6] + B[1] # B[4] # B[5] + B[1] # B[4] # B[6] + 4*B[2] # B[3] # B[5] + 4*B[2] # B[3] # B[6] + 2*B[2] # B[4] # B[5] + 2*B[2] # B[4] # B[6] """ assert(module in ModulesWithBasis(self.base_ring()) for module in modules) - assert(sage.categories.tensor.tensor(modules) == self) + assert(tensor(modules) == self) # a list l such that l[i] is True if modules[i] is readily a tensor product is_tensor = [isinstance(module, CombinatorialFreeModule_Tensor) for module in modules] # the tensor_constructor, on basis elements diff --git a/src/sage/combinat/root_system/ambient_space.py b/src/sage/combinat/root_system/ambient_space.py index 9cc64aa8c28..c53ed162a3b 100644 --- a/src/sage/combinat/root_system/ambient_space.py +++ b/src/sage/combinat/root_system/ambient_space.py @@ -10,7 +10,7 @@ # http://www.gnu.org/licenses/ #***************************************************************************** from sage.misc.cachefunc import cached_method -from sage.combinat.free_module import CombinatorialFreeModule, CombinatorialFreeModuleElement +from sage.combinat.free_module import CombinatorialFreeModule from .weight_lattice_realizations import WeightLatticeRealizations from sage.rings.all import ZZ, QQ from sage.categories.homset import End @@ -360,7 +360,7 @@ def to_ambient_space_morphism(self): """ return End(self).identity() -class AmbientSpaceElement(CombinatorialFreeModuleElement): +class AmbientSpaceElement(CombinatorialFreeModule.Element): # For backward compatibility def _repr_(self): """ diff --git a/src/sage/combinat/root_system/root_space.py b/src/sage/combinat/root_system/root_space.py index 68da6897a80..ca295870afe 100644 --- a/src/sage/combinat/root_system/root_space.py +++ b/src/sage/combinat/root_system/root_space.py @@ -12,7 +12,7 @@ from sage.misc.cachefunc import cached_method, cached_in_parent_method from sage.rings.all import ZZ -from sage.combinat.free_module import CombinatorialFreeModule, CombinatorialFreeModuleElement +from sage.combinat.free_module import CombinatorialFreeModule from .root_lattice_realizations import RootLatticeRealizations from sage.misc.cachefunc import cached_in_parent_method import functools @@ -232,7 +232,7 @@ def basis_value(basis, i): return basis[i] return self.module_morphism(on_basis = functools.partial(basis_value, basis) , codomain=L) -class RootSpaceElement(CombinatorialFreeModuleElement): +class RootSpaceElement(CombinatorialFreeModule.Element): def scalar(self, lambdacheck): """ The scalar product between the root lattice and diff --git a/src/sage/combinat/root_system/weight_space.py b/src/sage/combinat/root_system/weight_space.py index 6dbacafab4e..9162fa3dc2e 100644 --- a/src/sage/combinat/root_system/weight_space.py +++ b/src/sage/combinat/root_system/weight_space.py @@ -11,7 +11,7 @@ from sage.misc.cachefunc import cached_method from sage.sets.family import Family -from sage.combinat.free_module import CombinatorialFreeModule, CombinatorialFreeModuleElement +from sage.combinat.free_module import CombinatorialFreeModule from .weight_lattice_realizations import WeightLatticeRealizations import functools @@ -449,7 +449,7 @@ def basis_value(basis, i): return basis[i] return self.module_morphism(on_basis = functools.partial(basis_value, basis), codomain=L) -class WeightSpaceElement(CombinatorialFreeModuleElement): +class WeightSpaceElement(CombinatorialFreeModule.Element): def scalar(self, lambdacheck): """ diff --git a/src/sage/homology/chains.py b/src/sage/homology/chains.py index 4d8241df647..a2c5ff751c1 100644 --- a/src/sage/homology/chains.py +++ b/src/sage/homology/chains.py @@ -21,8 +21,7 @@ from __future__ import absolute_import -from sage.combinat.free_module import CombinatorialFreeModule, \ - CombinatorialFreeModuleElement +from sage.combinat.free_module import CombinatorialFreeModule from sage.rings.integer_ring import ZZ from sage.structure.element import get_coercion_model @@ -216,7 +215,7 @@ def chain_complex(self): cochain=False, ) - class Element(CombinatorialFreeModuleElement): + class Element(CombinatorialFreeModule.Element): def to_complex(self): """ @@ -449,7 +448,7 @@ def cochain_complex(self): cochain=True, ) - class Element(CombinatorialFreeModuleElement): + class Element(CombinatorialFreeModule.Element): def to_complex(self): """ diff --git a/src/sage/homology/homology_vector_space_with_basis.py b/src/sage/homology/homology_vector_space_with_basis.py index 864523393d5..b1528aa8d48 100644 --- a/src/sage/homology/homology_vector_space_with_basis.py +++ b/src/sage/homology/homology_vector_space_with_basis.py @@ -30,7 +30,7 @@ from sage.misc.cachefunc import cached_method from sage.categories.algebras import Algebras from sage.categories.modules import Modules -from sage.combinat.free_module import CombinatorialFreeModule, CombinatorialFreeModuleElement +from sage.combinat.free_module import CombinatorialFreeModule from sage.sets.family import Family from .simplicial_complex import SimplicialComplex from .simplicial_set import SimplicialSet_arbitrary @@ -375,7 +375,7 @@ def _to_cycle_on_basis(self, i): cochains=self._cohomology) return chains.from_vector(vec) - class Element(CombinatorialFreeModuleElement): + class Element(CombinatorialFreeModule.Element): def to_cycle(self): r""" (Co)cycle representative of this homogeneous (co)homology class. diff --git a/src/sage/modules/with_basis/indexed_free_module_element.pxd b/src/sage/modules/with_basis/indexed_free_module_element.pxd new file mode 100644 index 00000000000..edac4cc368c --- /dev/null +++ b/src/sage/modules/with_basis/indexed_free_module_element.pxd @@ -0,0 +1,10 @@ +from sage.structure.element cimport Element + +cdef class IndexedFreeModuleElement(Element): + cdef public dict _monomial_coefficients + cdef long _hash + cdef bint _hash_set + + cpdef dict monomial_coefficients(self, bint copy=*) + cpdef _coefficient_fast(self, m) + diff --git a/src/sage/modules/with_basis/indexed_free_module_element.pyx b/src/sage/modules/with_basis/indexed_free_module_element.pyx new file mode 100644 index 00000000000..befd493dee7 --- /dev/null +++ b/src/sage/modules/with_basis/indexed_free_module_element.pyx @@ -0,0 +1,878 @@ +# -*- coding: utf-8 -*- +r""" +An element in an indexed free module. + +AUTHORS: + +- Travis Scrimshaw (03-2017): Moved code from :mod:`sage.combinat.free_module`. +""" + +#***************************************************************************** +# Copyright (C) 2017 Travis Scrimshaw +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# http://www.gnu.org/licenses/ +#***************************************************************************** + +from __future__ import print_function + +from sage.structure.element cimport have_same_parent +from sage.structure.sage_object cimport richcmp, richcmp_not_equal, rich_to_bool +from cpython.object cimport Py_NE, Py_EQ + +from sage.misc.misc import repr_lincomb +from sage.misc.cachefunc import cached_method +from sage.misc.lazy_attribute import lazy_attribute +from sage.typeset.ascii_art import AsciiArt, empty_ascii_art +from sage.typeset.unicode_art import UnicodeArt, empty_unicode_art +from sage.categories.all import Category, Sets, ModulesWithBasis +from sage.data_structures.blas_dict cimport add, negate, scal, axpy + +# TODO: move the content of this class to CombinatorialFreeModule.Element and ModulesWithBasis.Element +cdef class IndexedFreeModuleElement(Element): + def __init__(self, M, x): + """ + Create a combinatorial module element. This should never be + called directly, but only through the parent combinatorial + free module's :meth:`__call__` method. + + TESTS:: + + sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) + sage: B = F.basis() + sage: f = B['a'] + 3*B['c']; f + B['a'] + 3*B['c'] + sage: f == loads(dumps(f)) + True + """ + Element.__init__(self, M) + self._monomial_coefficients = x + self._hash_set = False + + def __iter__(self): + """ + EXAMPLES:: + + sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) + sage: B = F.basis() + sage: f = B['a'] + 3*B['c'] + sage: [i for i in sorted(f)] + [('a', 1), ('c', 3)] + + :: + + sage: s = SymmetricFunctions(QQ).schur() + sage: a = s([2,1]) + s([3]) + sage: [i for i in sorted(a)] + [([2, 1], 1), ([3], 1)] + """ + return self._monomial_coefficients.iteritems() + + def __contains__(self, x): + """ + Returns whether or not a combinatorial object x indexing a basis + element is in the support of self. + + EXAMPLES:: + + sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) + sage: B = F.basis() + sage: f = B['a'] + 3*B['c'] + sage: 'a' in f + True + sage: 'b' in f + False + + :: + + sage: s = SymmetricFunctions(QQ).schur() + sage: a = s([2,1]) + s([3]) + sage: Partition([2,1]) in a + True + sage: Partition([1,1,1]) in a + False + """ + return x in self._monomial_coefficients and self._monomial_coefficients[x] != 0 + + def __hash__(self): + """ + Return the hash value for ``self``. + + The result is cached. + + EXAMPLES:: + + sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) + sage: B = F.basis() + sage: f = B['a'] + 3*B['c'] + sage: hash(f) + 6429418278783588506 # 64-bit + 726440090 # 32-bit + + sage: F = RootSystem(['A',2]).ambient_space() + sage: f = F.simple_root(0) + sage: hash(f) + 6920829894162680369 # 64-bit + -528971215 # 32-bit + + This uses the recipe that was proposed for frozendicts in `PEP + 0416 `_ (and adds + the hash of the parent). This recipe relies on the hash + function for frozensets which uses tricks to mix the hash + values of the items in case they are similar. + + .. TODO:: + + It would be desirable to make the hash value depend on the + hash value of the parent. See :trac:`15959`. + """ + if not self._hash_set: + self._hash = hash(frozenset(self._monomial_coefficients.items())) + self._hash_set = True + return self._hash + + def __reduce__(self): + """ + For pickling. + + EXAMPLES:: + + sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) + sage: loads(dumps(F.an_element())) == F.an_element() + True + """ + return (_unpickle_element, (self.parent(), self._monomial_coefficients)) + + cpdef dict monomial_coefficients(self, bint copy=True): + """ + Return the internal dictionary which has the combinatorial objects + indexing the basis as keys and their corresponding coefficients as + values. + + INPUT: + + - ``copy`` -- (default: ``True``) if ``self`` is internally + represented by a dictionary ``d``, then make a copy of ``d``; + if ``False``, then this can cause undesired behavior by + mutating ``d`` + + EXAMPLES:: + + sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) + sage: B = F.basis() + sage: f = B['a'] + 3*B['c'] + sage: d = f.monomial_coefficients() + sage: d['a'] + 1 + sage: d['c'] + 3 + + To run through the monomials of an element, it is better to + use the idiom:: + + sage: for (t,c) in f: + ....: print("{} {}".format(t,c)) + a 1 + c 3 + + :: + + sage: s = SymmetricFunctions(QQ).schur() + sage: a = s([2,1])+2*s([3,2]) + sage: d = a.monomial_coefficients() + sage: type(d) + <... 'dict'> + sage: d[ Partition([2,1]) ] + 1 + sage: d[ Partition([3,2]) ] + 2 + """ + if copy: + return dict(self._monomial_coefficients) + return self._monomial_coefficients + + def _sorted_items_for_printing(self): + """ + Returns the items (i.e terms) of ``self``, sorted for printing + + EXAMPLES:: + + sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) + sage: B = F.basis() + sage: f = B['a'] + 2*B['c'] + 3 * B['b'] + sage: f._sorted_items_for_printing() + [('a', 1), ('b', 3), ('c', 2)] + sage: F.print_options(sorting_reverse=True) + sage: f._sorted_items_for_printing() + [('c', 2), ('b', 3), ('a', 1)] + sage: F.print_options(sorting_reverse=False) #reset to original state + + .. SEEALSO:: :meth:`_repr_`, :meth:`_latex_`, :meth:`print_options` + """ + print_options = self.parent().print_options() + v = self._monomial_coefficients.items() + try: + v.sort(key=lambda monomial_coeff: + print_options['sorting_key'](monomial_coeff[0]), + reverse=print_options['sorting_reverse']) + except Exception: # Sorting the output is a plus, but if we can't, no big deal + pass + return v + + def _repr_(self): + """ + EXAMPLES:: + + sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'], prefix='F') + sage: e = F.basis() + sage: e['a'] + 2*e['b'] # indirect doctest + F['a'] + 2*F['b'] + sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'], prefix='') + sage: e = F.basis() + sage: e['a'] + 2*e['b'] # indirect doctest + ['a'] + 2*['b'] + sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'], prefix='', scalar_mult=' ', bracket=False) + sage: e = F.basis() + sage: e['a'] + 2*e['b'] # indirect doctest + 'a' + 2 'b' + + Controling the order of terms by providing a comparison + function on elements of the support:: + + sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'], + ....: sorting_reverse=True) + sage: e = F.basis() + sage: e['a'] + 3*e['b'] + 2*e['c'] + 2*B['c'] + 3*B['b'] + B['a'] + + sage: F = CombinatorialFreeModule(QQ, ['ac', 'ba', 'cb'], + ....: sorting_key=lambda x: x[1]) + sage: e = F.basis() + sage: e['ac'] + 3*e['ba'] + 2*e['cb'] + 3*B['ba'] + 2*B['cb'] + B['ac'] + """ + return repr_lincomb(self._sorted_items_for_printing(), + scalar_mult=self.parent()._print_options['scalar_mult'], + repr_monomial = self.parent()._repr_term, + strip_one = True) + + def _ascii_art_(self): + """ + TESTS:: + + sage: M = QuasiSymmetricFunctions(QQ).M() + sage: ascii_art(M[1,3]**2) # indirect doctest + 4*M + 2*M + 2*M + 2*M + 2*M + M + *** ****** *** *** *** ****** + *** * * **** *** ** + * * *** * ** + * * + sage: ascii_art(M.zero()) + 0 + """ + from sage.misc.misc import coeff_repr + terms = self._sorted_items_for_printing() + scalar_mult = self.parent()._print_options['scalar_mult'] + repr_monomial = self.parent()._ascii_art_term + strip_one = True + + if repr_monomial is None: + repr_monomial = str + + s = empty_ascii_art # "" + first = True + + if scalar_mult is None: + scalar_mult = "*" + + for (monomial,c) in terms: + b = repr_monomial(monomial) # PCR + if c != 0: + break_points = [] + coeff = coeff_repr(c, False) + if coeff != "0": + if coeff == "1": + coeff = "" + elif coeff == "-1": + coeff = "-" + elif b._l > 0: + if len(coeff) > 0 and monomial == 1 and strip_one: + b = empty_ascii_art # "" + else: + b = AsciiArt([scalar_mult]) + b + if not first: + if len(coeff) > 0 and coeff[0] == "-": + coeff = " - %s"%coeff[1:] + else: + coeff = " + %s"%coeff + break_points = [2] + else: + coeff = "%s"%coeff + s += AsciiArt([coeff], break_points) + b + first = False + if first: + return AsciiArt(["0"]) + elif s == empty_ascii_art: + return AsciiArt(["1"]) + else: + return s + + def _unicode_art_(self): + """ + TESTS:: + + sage: M = QuasiSymmetricFunctions(QQ).M() + sage: unicode_art(M[1,1]**2) # indirect doctest + 6*M + 2*M + 2*M + 2*M + M + ┌┐ ┌┬┐ ┌┐ ┌┐ ┌┬┐ + ├┤ ├┼┘ ┌┼┤ ├┤ ┌┼┼┘ + ├┤ ├┤ ├┼┘ ┌┼┤ └┴┘ + ├┤ └┘ └┘ └┴┘ + └┘ + """ + from sage.misc.misc import coeff_repr + terms = self._sorted_items_for_printing() + scalar_mult = self.parent()._print_options['scalar_mult'] + repr_monomial = self.parent()._unicode_art_term + strip_one = True + + if repr_monomial is None: + repr_monomial = str + + s = empty_unicode_art # "" + first = True + + if scalar_mult is None: + scalar_mult = "*" + + for (monomial, c) in terms: + b = repr_monomial(monomial) # PCR + if c != 0: + break_points = [] + coeff = coeff_repr(c, False) + if coeff != "0": + if coeff == "1": + coeff = "" + elif coeff == "-1": + coeff = "-" + elif b._l > 0: + if len(coeff) > 0 and monomial == 1 and strip_one: + b = empty_unicode_art # "" + else: + b = UnicodeArt([scalar_mult]) + b + if not first: + if len(coeff) > 0 and coeff[0] == "-": + coeff = " - %s" % coeff[1:] + else: + coeff = " + %s" % coeff + break_points = [2] + else: + coeff = "%s" % coeff + s += UnicodeArt([coeff], break_points) + b + first = False + if first: + return "0" + elif s == empty_unicode_art: + return UnicodeArt(["1"]) + else: + return s + + def _latex_(self): + r""" + EXAMPLES:: + + sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) + sage: B = F.basis() + sage: f = B['a'] + 3*B['c'] + sage: latex(f) + B_{a} + 3B_{c} + + :: + + sage: QS3 = SymmetricGroupAlgebra(QQ,3) + sage: a = 2 + QS3([2,1,3]) + sage: latex(a) #indirect doctest + 2[1, 2, 3] + [2, 1, 3] + + :: + + sage: F = CombinatorialFreeModule(QQ, ['a','b'], prefix='beta', latex_prefix='\\beta') + sage: x = F.an_element() + sage: x + 2*beta['a'] + 2*beta['b'] + sage: latex(x) + 2\beta_{a} + 2\beta_{b} + + Controling the order of terms by providing a comparison + function on elements of the support:: + + sage: F = CombinatorialFreeModule(QQ, ['a', 'b', 'c'], + ....: sorting_reverse=True) + sage: e = F.basis() + sage: latex(e['a'] + 3*e['b'] + 2*e['c']) + 2B_{c} + 3B_{b} + B_{a} + + sage: F = CombinatorialFreeModule(QQ, ['ac', 'ba', 'cb'], + ....: sorting_key=lambda x: x[1]) + sage: e = F.basis() + sage: latex(e['ac'] + 3*e['ba'] + 2*e['cb']) + 3B_{ba} + 2B_{cb} + B_{ac} + """ + return repr_lincomb(self._sorted_items_for_printing(), + scalar_mult = self.parent()._print_options['scalar_mult'], + latex_scalar_mult = self.parent()._print_options['latex_scalar_mult'], + repr_monomial = self.parent()._latex_term, + is_latex=True, strip_one=True) + + cpdef _richcmp_(self, other, int op): + """ + Rich comparison for equal parents. + + EXAMPLES:: + + sage: F1 = CombinatorialFreeModule(QQ, [1, 2, 3]) + sage: F2 = CombinatorialFreeModule(QQ, [1, 2, 3], prefix = "g") + sage: F1.zero() == F1.zero() + True + sage: F1.zero() == F1.an_element() + False + sage: F1.an_element() == F1.an_element() + True + sage: F1.an_element() is None + False + + :: + + sage: F3 = CombinatorialFreeModule(QQ, ['a','b','c']) + sage: F3.an_element() != F3.an_element() + False + sage: F3.an_element() != F3.zero() + True + + :: + + sage: s = SymmetricFunctions(QQ).schur() + sage: a = s([2,1]) + sage: b = s([1,1,1]) + sage: cmp(a,b) #indirect doctest + 1 + + .. TODO:: + + Currently, if ``self`` and ``other`` do not have the same parent, + seemingly equal elements do not evaluate equal, since conversions + between different modules have not been established. + + :: + + sage: F1.zero() == 0 + True + sage: F1(0) + 0 + + :: + + sage: F1.zero() == F2.zero() + False + sage: F1(F2.zero()) + Traceback (most recent call last): + ... + TypeError: do not know how to make x (= 0) an element of self (=Free module generated by {1, 2, 3} over Rational Field) + sage: F = AlgebrasWithBasis(QQ).example() + sage: F.one() == 1 + True + sage: 1 == F.one() + True + sage: 2 * F.one() == int(2) + True + sage: int(2) == 2 * F.one() + True + + sage: S = SymmetricFunctions(QQ); s = S.s(); p = S.p() + sage: p[2] == s[2] - s[1, 1] + True + sage: p[2] == s[2] + False + + This feature is disputable, in particular since it can make + equality testing costly. It may be removed at some point. + + Equality testing can be a bit tricky when the order of terms + can vary because their indices are incomparable with + ``cmp``. The following test did fail before :trac:`12489` :: + + sage: F = CombinatorialFreeModule(QQ, Subsets([1,2,3])) + sage: x = F.an_element() + sage: (x+F.zero()).terms() # random + [2*B[{1}], 3*B[{2}], B[{}]] + sage: x.terms() # random + [2*B[{1}], B[{}], 3*B[{2}]] + sage: x+F.zero() == x + True + + TESTS:: + + sage: TestSuite(F1).run() + sage: TestSuite(F).run() + """ + if op in [Py_EQ, Py_NE]: + return richcmp(self._monomial_coefficients, other._monomial_coefficients, op) + + if self._monomial_coefficients == other._monomial_coefficients: + return rich_to_bool(op, 0) + + v = sorted(self._monomial_coefficients.items()) + w = sorted(other._monomial_coefficients.items()) + return richcmp_not_equal(v, w, op) + + cpdef _add_(self, other): + """ + EXAMPLES:: + + sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) + sage: B = F.basis() + sage: B['a'] + 3*B['c'] + B['a'] + 3*B['c'] + + :: + + sage: s = SymmetricFunctions(QQ).schur() + sage: s([2,1]) + s([5,4]) # indirect doctest + s[2, 1] + s[5, 4] + sage: a = s([2,1]) + 0 + sage: len(a.monomial_coefficients()) + 1 + """ + F = self.parent() + return F._from_dict(add(self._monomial_coefficients, + other._monomial_coefficients), + remove_zeros=False) + + cpdef _neg_(self): + """ + EXAMPLES:: + + sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) + sage: B = F.basis() + sage: f = B['a'] + 3*B['c'] + sage: -f + -B['a'] - 3*B['c'] + + :: + + sage: s = SymmetricFunctions(QQ).schur() + sage: -s([2,1]) # indirect doctest + -s[2, 1] + """ + F = self.parent() + return F._from_dict(negate(self._monomial_coefficients), + remove_zeros=False) + + cpdef _sub_(self, other): + """ + EXAMPLES:: + + sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) + sage: B = F.basis() + sage: B['a'] - 3*B['c'] + B['a'] - 3*B['c'] + + :: + + sage: s = SymmetricFunctions(QQ).schur() + sage: s([2,1]) - s([5,4]) # indirect doctest + s[2, 1] - s[5, 4] + """ + F = self.parent() + return F._from_dict(axpy(-1, + other._monomial_coefficients, + self._monomial_coefficients), + remove_zeros=False) + + cpdef _coefficient_fast(self, m): + """ + Return the coefficient of ``m`` in ``self``, where ``m`` is key in + ``self._monomial_coefficients``. + + EXAMPLES:: + + sage: p = Partition([2,1]) + sage: q = Partition([1,1,1]) + sage: s = SymmetricFunctions(QQ).schur() + sage: a = s(p) + sage: a._coefficient_fast([2,1]) + Traceback (most recent call last): + ... + TypeError: unhashable type: 'list' + + :: + + sage: a._coefficient_fast(p) + 1 + sage: a._coefficient_fast(q) + 0 + """ + return self._monomial_coefficients.get(m, self.base_ring().zero()) + + def __getitem__(self, m): + """ + EXAMPLES:: + + sage: s = SymmetricFunctions(QQ).schur() + sage: p = Partition([2,1]) + sage: q = Partition([1,1,1]) + sage: a = s(p) + sage: a[p] + 1 + sage: a[q] + 0 + """ + return self._coefficient_fast(m) + + def _vector_(self, new_base_ring=None): + """ + Returns ``self`` as a dense vector + + INPUT: + + - ``new_base_ring`` -- a ring (default: ``None``) + + OUTPUT: a dense :func:`FreeModule` vector + + .. WARNING:: This will crash/run forever if ``self`` is infinite dimensional! + + .. SEEALSO:: + + - :func:`vector` + - :meth:`CombinatorialFreeModule.get_order` + - :meth:`CombinatorialFreeModule.from_vector` + - :meth:`CombinatorialFreeModule._dense_free_module` + + EXAMPLES:: + + sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) + sage: B = F.basis() + sage: f = B['a'] - 3*B['c'] + sage: f._vector_() + (1, 0, -3) + + One can use equivalently:: + + sage: f.to_vector() + (1, 0, -3) + sage: vector(f) + (1, 0, -3) + + More examples:: + + sage: QS3 = SymmetricGroupAlgebra(QQ, 3) + sage: a = 2*QS3([1,2,3]) + 4*QS3([3,2,1]) + sage: a._vector_() + (2, 0, 0, 0, 0, 4) + sage: a.to_vector() + (2, 0, 0, 0, 0, 4) + sage: vector(a) + (2, 0, 0, 0, 0, 4) + sage: a == QS3.from_vector(a.to_vector()) + True + + If ``new_base_ring`` is specified, then a vector over + ``new_base_ring`` is returned:: + + sage: a._vector_(RDF) + (2.0, 0.0, 0.0, 0.0, 0.0, 4.0) + + .. NOTE:: + + :trac:`13406`: the current implementation has been optimized, at + the price of breaking the encapsulation for FreeModule + elements creation, with the following use case as metric, + on a 2008' Macbook Pro:: + + sage: F = CombinatorialFreeModule(QQ, range(10)) + sage: f = F.an_element() + sage: %timeit f._vector_() # not tested + 625 loops, best of 3: 17.5 micros per loop + + Other use cases may call for different or further + optimizations. + """ + parent = self.parent() + dense_free_module = parent._dense_free_module(new_base_ring) + d = self._monomial_coefficients + zero = dense_free_module.base_ring().zero() + return dense_free_module.element_class(dense_free_module, + [d.get(m, zero) for m in parent.get_order()], + coerce=True, copy=False) + + to_vector = _vector_ + + cpdef _acted_upon_(self, scalar, bint self_on_left): + """ + Return the action of ``scalar`` (an element of the base ring) on + ``self``. + + EXAMPLES:: + + sage: F = CombinatorialFreeModule(QQ, ['a','b','c']) + sage: B = F.basis() + sage: B['a']*(1/2) # indirect doctest + 1/2*B['a'] + sage: B['a']/2 + 1/2*B['a'] + sage: B['a']*2 # indirect doctest + 2*B['a'] + sage: B['a']*int(2) # indirect doctest + 2*B['a'] + + sage: 1/2*B['a'] + 1/2*B['a'] + sage: 2*B['a'] # indirect doctest + 2*B['a'] + sage: int(2)*B['a'] # indirect doctest + 2*B['a'] + + TESTS:: + + sage: F.get_action(QQ, operator.mul, True) + Right action by Rational Field on Free module generated by {'a', 'b', 'c'} over Rational Field + sage: F.get_action(QQ, operator.mul, False) + Left action by Rational Field on Free module generated by {'a', 'b', 'c'} over Rational Field + sage: F.get_action(ZZ, operator.mul, True) + Right action by Integer Ring on Free module generated by {'a', 'b', 'c'} over Rational Field + sage: F.get_action(F, operator.mul, True) + sage: F.get_action(F, operator.mul, False) + + This also works when a coercion of the coefficient is needed, for + example with polynomials or fraction fields (:trac:`8832`):: + + sage: P. = QQ['q'] + sage: V = CombinatorialFreeModule(P, Permutations()) + sage: el = V(Permutation([3,1,2])) + sage: (3/2)*el + 3/2*B[[3, 1, 2]] + + sage: P. = QQ['q'] + sage: F = FractionField(P) + sage: V = CombinatorialFreeModule(F, Words()) + sage: w = Words()('abc') + sage: (1+q)*V(w) + (q+1)*B[word: abc] + sage: ((1+q)/q)*V(w) + ((q+1)/q)*B[word: abc] + + .. TODO:: + + Add non commutative tests. + """ + # With the current design, the coercion model does not have + # enough information to detect a priori that this method only + # accepts scalars; so it tries on some elements(), and we need + # to make sure to report an error. + if isinstance(scalar, Element) and scalar.parent() is not self.base_ring(): + # Temporary needed by coercion (see Polynomial/FractionField tests). + if self.base_ring().has_coerce_map_from(scalar.parent()): + scalar = self.base_ring()( scalar ) + else: + return None + + F = self.parent() + D = self._monomial_coefficients + return F._from_dict(scal(scalar, D, factor_on_left=not self_on_left), + remove_zeros=False) + + def _lmul_(self, other): + """ + For backward compatibility. + + EXAMPLES:: + + sage: C = CombinatorialFreeModule(QQ, [1,2,3]) + sage: C.an_element()._lmul_(2) + 4*B[1] + 4*B[2] + 6*B[3] + """ + return self._acted_upon_(other, True) + + def _rmul_(self, other): + """ + For backward compatibility. + + EXAMPLES:: + + sage: C = CombinatorialFreeModule(QQ, [1,2,3]) + sage: C.an_element()._rmul_(2) + 4*B[1] + 4*B[2] + 6*B[3] + """ + return self._acted_upon_(other, False) + + def __truediv__(self, x): + """ + Division by coefficients. + + EXAMPLES:: + + sage: F = CombinatorialFreeModule(QQ, [1,2,3]) + sage: x = F._from_dict({1:2, 2:3}) + sage: x/2 + B[1] + 3/2*B[2] + + :: + + sage: F = CombinatorialFreeModule(QQ, [1,2,3]) + sage: B = F.basis() + sage: f = 2*B[2] + 4*B[3] + sage: f/2 + B[2] + 2*B[3] + """ + if not self.base_ring().is_field(): + return self.map_coefficients(lambda c: _divide_if_possible(c, x)) + + F = self.parent() + x = self.base_ring()( x ) + x_inv = x ** -1 + D = self._monomial_coefficients + return F._from_dict(scal(x_inv, D), + remove_zeros=False) + + __div__ = __truediv__ + + +def _divide_if_possible(x, y): + """ + EXAMPLES:: + + sage: from sage.modules.with_basis.indexed_free_module_element import _divide_if_possible + sage: _divide_if_possible(4, 2) + 2 + sage: _.parent() + Integer Ring + + :: + + sage: _divide_if_possible(4, 3) + Traceback (most recent call last): + ... + ValueError: 4 is not divisible by 3 + """ + q, r = x.quo_rem(y) + if r != 0: + raise ValueError("%s is not divisible by %s"%(x, y)) + else: + return q + +def _unpickle_element(C, d): + """ + Unpickle an element in ``C`` given by ``d``. + + EXAMPLES:: + + sage: from sage.modules.with_basis.indexed_free_module_element import _unpickle_element + sage: C = CombinatorialFreeModule(QQ, [1,2,3]) + sage: _unpickle_element(C, {1: -2, 3: -12}) + -2*B[1] - 12*B[3] + """ + return C._from_dict(d, coerce=False, remove_zeros=False) + diff --git a/src/sage/quivers/algebra.py b/src/sage/quivers/algebra.py index 5d9b9e07b72..4d6345cebfd 100644 --- a/src/sage/quivers/algebra.py +++ b/src/sage/quivers/algebra.py @@ -22,7 +22,7 @@ import six from sage.misc.cachefunc import cached_method -from sage.combinat.free_module import CombinatorialFreeModule, CombinatorialFreeModuleElement +from sage.combinat.free_module import CombinatorialFreeModule from .algebra_elements import PathAlgebraElement class PathAlgebra(CombinatorialFreeModule): From 6b9d88b14b162c5d7ea88c3339896c3adc6e79da Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Fri, 17 Mar 2017 11:35:23 -0500 Subject: [PATCH 108/452] Doing some additional tweaks. --- .../indexed_free_module_element.pyx | 68 +++++++++---------- 1 file changed, 32 insertions(+), 36 deletions(-) diff --git a/src/sage/modules/with_basis/indexed_free_module_element.pyx b/src/sage/modules/with_basis/indexed_free_module_element.pyx index befd493dee7..810a8d9980a 100644 --- a/src/sage/modules/with_basis/indexed_free_module_element.pyx +++ b/src/sage/modules/with_basis/indexed_free_module_element.pyx @@ -19,7 +19,7 @@ AUTHORS: from __future__ import print_function -from sage.structure.element cimport have_same_parent +from sage.structure.element cimport parent from sage.structure.sage_object cimport richcmp, richcmp_not_equal, rich_to_bool from cpython.object cimport Py_NE, Py_EQ @@ -144,7 +144,7 @@ cdef class IndexedFreeModuleElement(Element): sage: loads(dumps(F.an_element())) == F.an_element() True """ - return (_unpickle_element, (self.parent(), self._monomial_coefficients)) + return (_unpickle_element, (self._parent, self._monomial_coefficients)) cpdef dict monomial_coefficients(self, bint copy=True): """ @@ -212,7 +212,7 @@ cdef class IndexedFreeModuleElement(Element): .. SEEALSO:: :meth:`_repr_`, :meth:`_latex_`, :meth:`print_options` """ - print_options = self.parent().print_options() + print_options = self._parent.print_options() v = self._monomial_coefficients.items() try: v.sort(key=lambda monomial_coeff: @@ -255,8 +255,8 @@ cdef class IndexedFreeModuleElement(Element): 3*B['ba'] + 2*B['cb'] + B['ac'] """ return repr_lincomb(self._sorted_items_for_printing(), - scalar_mult=self.parent()._print_options['scalar_mult'], - repr_monomial = self.parent()._repr_term, + scalar_mult=self._parent._print_options['scalar_mult'], + repr_monomial = self._parent._repr_term, strip_one = True) def _ascii_art_(self): @@ -275,8 +275,8 @@ cdef class IndexedFreeModuleElement(Element): """ from sage.misc.misc import coeff_repr terms = self._sorted_items_for_printing() - scalar_mult = self.parent()._print_options['scalar_mult'] - repr_monomial = self.parent()._ascii_art_term + scalar_mult = self._parent._print_options['scalar_mult'] + repr_monomial = self._parent._ascii_art_term strip_one = True if repr_monomial is None: @@ -335,8 +335,8 @@ cdef class IndexedFreeModuleElement(Element): """ from sage.misc.misc import coeff_repr terms = self._sorted_items_for_printing() - scalar_mult = self.parent()._print_options['scalar_mult'] - repr_monomial = self.parent()._unicode_art_term + scalar_mult = self._parent._print_options['scalar_mult'] + repr_monomial = self._parent._unicode_art_term strip_one = True if repr_monomial is None: @@ -422,9 +422,9 @@ cdef class IndexedFreeModuleElement(Element): 3B_{ba} + 2B_{cb} + B_{ac} """ return repr_lincomb(self._sorted_items_for_printing(), - scalar_mult = self.parent()._print_options['scalar_mult'], - latex_scalar_mult = self.parent()._print_options['latex_scalar_mult'], - repr_monomial = self.parent()._latex_term, + scalar_mult = self._parent._print_options['scalar_mult'], + latex_scalar_mult = self._parent._print_options['latex_scalar_mult'], + repr_monomial = self._parent._latex_term, is_latex=True, strip_one=True) cpdef _richcmp_(self, other, int op): @@ -518,14 +518,15 @@ cdef class IndexedFreeModuleElement(Element): sage: TestSuite(F1).run() sage: TestSuite(F).run() """ + cdef IndexedFreeModuleElement elt = other if op in [Py_EQ, Py_NE]: - return richcmp(self._monomial_coefficients, other._monomial_coefficients, op) + return richcmp(self._monomial_coefficients, elt._monomial_coefficients, op) - if self._monomial_coefficients == other._monomial_coefficients: + if self._monomial_coefficients == elt._monomial_coefficients: return rich_to_bool(op, 0) v = sorted(self._monomial_coefficients.items()) - w = sorted(other._monomial_coefficients.items()) + w = sorted(elt._monomial_coefficients.items()) return richcmp_not_equal(v, w, op) cpdef _add_(self, other): @@ -546,10 +547,9 @@ cdef class IndexedFreeModuleElement(Element): sage: len(a.monomial_coefficients()) 1 """ - F = self.parent() - return F._from_dict(add(self._monomial_coefficients, - other._monomial_coefficients), - remove_zeros=False) + return self._parent._from_dict(add(self._monomial_coefficients, + (other)._monomial_coefficients), + remove_zeros=False) cpdef _neg_(self): """ @@ -567,9 +567,8 @@ cdef class IndexedFreeModuleElement(Element): sage: -s([2,1]) # indirect doctest -s[2, 1] """ - F = self.parent() - return F._from_dict(negate(self._monomial_coefficients), - remove_zeros=False) + return self._parent._from_dict(negate(self._monomial_coefficients), + remove_zeros=False) cpdef _sub_(self, other): """ @@ -586,11 +585,10 @@ cdef class IndexedFreeModuleElement(Element): sage: s([2,1]) - s([5,4]) # indirect doctest s[2, 1] - s[5, 4] """ - F = self.parent() - return F._from_dict(axpy(-1, - other._monomial_coefficients, - self._monomial_coefficients), - remove_zeros=False) + return self._parent._from_dict(axpy(-1, + (other)._monomial_coefficients, + self._monomial_coefficients), + remove_zeros=False) cpdef _coefficient_fast(self, m): """ @@ -700,12 +698,11 @@ cdef class IndexedFreeModuleElement(Element): Other use cases may call for different or further optimizations. """ - parent = self.parent() - dense_free_module = parent._dense_free_module(new_base_ring) + dense_free_module = self._parent._dense_free_module(new_base_ring) d = self._monomial_coefficients zero = dense_free_module.base_ring().zero() return dense_free_module.element_class(dense_free_module, - [d.get(m, zero) for m in parent.get_order()], + [d.get(m, zero) for m in self._parent.get_order()], coerce=True, copy=False) to_vector = _vector_ @@ -772,17 +769,16 @@ cdef class IndexedFreeModuleElement(Element): # enough information to detect a priori that this method only # accepts scalars; so it tries on some elements(), and we need # to make sure to report an error. - if isinstance(scalar, Element) and scalar.parent() is not self.base_ring(): + if isinstance(scalar, Element) and parent(scalar) is not self.base_ring(): # Temporary needed by coercion (see Polynomial/FractionField tests). - if self.base_ring().has_coerce_map_from(scalar.parent()): + if self.base_ring().has_coerce_map_from(parent(scalar)): scalar = self.base_ring()( scalar ) else: return None - F = self.parent() D = self._monomial_coefficients - return F._from_dict(scal(scalar, D, factor_on_left=not self_on_left), - remove_zeros=False) + return self._parent._from_dict(scal(scalar, D, factor_on_left=not self_on_left), + remove_zeros=False) def _lmul_(self, other): """ @@ -830,7 +826,7 @@ cdef class IndexedFreeModuleElement(Element): if not self.base_ring().is_field(): return self.map_coefficients(lambda c: _divide_if_possible(c, x)) - F = self.parent() + F = parent(self) x = self.base_ring()( x ) x_inv = x ** -1 D = self._monomial_coefficients From f1fcdd97670b9450f31e1230250dba8cde53c790 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Fri, 17 Mar 2017 12:01:44 -0500 Subject: [PATCH 109/452] Do not go through _from_dict but directly create an element. --- .../indexed_free_module_element.pyx | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/sage/modules/with_basis/indexed_free_module_element.pyx b/src/sage/modules/with_basis/indexed_free_module_element.pyx index 810a8d9980a..df727ea7fe9 100644 --- a/src/sage/modules/with_basis/indexed_free_module_element.pyx +++ b/src/sage/modules/with_basis/indexed_free_module_element.pyx @@ -547,9 +547,9 @@ cdef class IndexedFreeModuleElement(Element): sage: len(a.monomial_coefficients()) 1 """ - return self._parent._from_dict(add(self._monomial_coefficients, - (other)._monomial_coefficients), - remove_zeros=False) + return type(self)(self._parent, + add(self._monomial_coefficients, + (other)._monomial_coefficients)) cpdef _neg_(self): """ @@ -567,8 +567,7 @@ cdef class IndexedFreeModuleElement(Element): sage: -s([2,1]) # indirect doctest -s[2, 1] """ - return self._parent._from_dict(negate(self._monomial_coefficients), - remove_zeros=False) + return type(self)(self._parent, negate(self._monomial_coefficients)) cpdef _sub_(self, other): """ @@ -585,10 +584,10 @@ cdef class IndexedFreeModuleElement(Element): sage: s([2,1]) - s([5,4]) # indirect doctest s[2, 1] - s[5, 4] """ - return self._parent._from_dict(axpy(-1, - (other)._monomial_coefficients, - self._monomial_coefficients), - remove_zeros=False) + return type(self)(self._parent, + axpy(-1, + (other)._monomial_coefficients, + self._monomial_coefficients)) cpdef _coefficient_fast(self, m): """ @@ -777,8 +776,8 @@ cdef class IndexedFreeModuleElement(Element): return None D = self._monomial_coefficients - return self._parent._from_dict(scal(scalar, D, factor_on_left=not self_on_left), - remove_zeros=False) + return type(self)(self._parent, + scal(scalar, D, factor_on_left=not self_on_left)) def _lmul_(self, other): """ @@ -830,8 +829,7 @@ cdef class IndexedFreeModuleElement(Element): x = self.base_ring()( x ) x_inv = x ** -1 D = self._monomial_coefficients - return F._from_dict(scal(x_inv, D), - remove_zeros=False) + return type(self)(parent(self), scal(x_inv, D)) __div__ = __truediv__ From 2e171a4682256be81bc6a0513ad62abc39bde9ac Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sat, 18 Mar 2017 19:00:34 -0500 Subject: [PATCH 110/452] Cythonizing tensor product of crystals element. --- src/sage/combinat/crystals/affinization.py | 9 +- .../combinat/crystals/infinity_crystals.py | 164 +- .../combinat/crystals/kirillov_reshetikhin.py | 28 +- .../combinat/crystals/kyoto_path_model.py | 30 +- .../crystals/polyhedral_realization.py | 16 +- src/sage/combinat/crystals/subcrystal.py | 6 +- src/sage/combinat/crystals/tensor_product.py | 1254 +--------------- .../crystals/tensor_product_element.pxd | 20 + .../crystals/tensor_product_element.pyx | 1331 +++++++++++++++++ .../tensor_product_kr_tableaux.py | 4 +- 10 files changed, 1411 insertions(+), 1451 deletions(-) create mode 100644 src/sage/combinat/crystals/tensor_product_element.pxd create mode 100644 src/sage/combinat/crystals/tensor_product_element.pyx diff --git a/src/sage/combinat/crystals/affinization.py b/src/sage/combinat/crystals/affinization.py index 8cced3900d1..df9e4a1c61a 100644 --- a/src/sage/combinat/crystals/affinization.py +++ b/src/sage/combinat/crystals/affinization.py @@ -92,8 +92,8 @@ def __init__(self, B): self._B = B self._cartan_type = B.cartan_type() Parent.__init__(self, category=(RegularCrystals(), InfiniteEnumeratedSets())) - mg_elt = lambda b: self.element_class(self, b, 0) - self.module_generators = tuple(map(mg_elt, B.module_generators)) + self.module_generators = tuple([self.element_class(self, b, 0) + for b in B.module_generators]) def _repr_(self): """ @@ -195,9 +195,8 @@ def __hash__(self): sage: A = crystals.KirillovReshetikhin(['A',2,1], 2, 2).affinization() sage: mg = A.module_generators[0] - sage: hash(mg) - -6948036233304877976 # 64-bit - -1420700568 # 32-bit + sage: hash(mg) == hash(mg._b) ^^ hash(mg._m) + True """ return hash(self._b) ^ hash(self._m) diff --git a/src/sage/combinat/crystals/infinity_crystals.py b/src/sage/combinat/crystals/infinity_crystals.py index 48360942d4e..ecbf2d444ac 100644 --- a/src/sage/combinat/crystals/infinity_crystals.py +++ b/src/sage/combinat/crystals/infinity_crystals.py @@ -37,7 +37,9 @@ from sage.combinat.partition import Partition from sage.combinat.root_system.cartan_type import CartanType from sage.combinat.crystals.letters import CrystalOfLetters -from sage.combinat.crystals.tensor_product import CrystalOfWords, CrystalOfTableauxElement +from sage.combinat.crystals.tensor_product import CrystalOfWords +from sage.combinat.crystals.tensor_product_element import (CrystalOfTableauxElement, + InfinityCrystalOfTableauxElement, InfinityCrystalOfTableauxElementTypeD) class InfinityCrystalOfTableaux(CrystalOfWords): @@ -298,94 +300,10 @@ def _coerce_map_from_(self, P): return FromRCIsomorphism(Hom(P, self)) return super(InfinityCrystalOfTableaux, self)._coerce_map_from_(P) - class Element(CrystalOfTableauxElement): + class Element(InfinityCrystalOfTableauxElement): r""" Elements in `\mathcal{B}(\infty)` crystal of tableaux. """ - - def e(self,i): - r""" - Return the action of `\widetilde{e}_i` on ``self``. - - INPUT: - - - ``i`` -- An element of the index set - - EXAMPLES:: - - sage: B = crystals.infinity.Tableaux(['B',3]) - sage: b = B(rows=[[1,1,1,1,1,1,1,2,0,-3,-1,-1,-1,-1],[2,2,2,2,-2,-2],[3,-3,-3]]) - sage: b.e(3).pp() - 1 1 1 1 1 1 1 2 0 -3 -1 -1 -1 -1 - 2 2 2 2 -2 -2 - 3 0 -3 - sage: b.e(1).pp() - 1 1 1 1 1 1 1 0 -3 -1 -1 -1 -1 - 2 2 2 2 -2 -2 - 3 -3 -3 - """ - if i not in self.index_set(): - raise ValueError('i is not in the index set.') - position = self.positions_of_unmatched_plus(i) - if position == []: - return None - k = position[0] - ret = self.set_index(k, self[k].e(i)) - if k+i > len(self): - return ret - for j in reversed(range(1, i+1)): - if ret[k+i-j].value != j: - return ret - # We've found a column, so we need to remove it - for j in range(i): - ret._list.pop(k) - return ret - - def f(self, i): - r""" - Return the action of `\widetilde{f}_i` on ``self``. - - INPUT: - - - ``i`` -- An element of the index set - - EXAMPLES:: - - sage: B = crystals.infinity.Tableaux(['C',4]) - sage: b = B.highest_weight_vector() - sage: b.f(1).pp() - 1 1 1 1 2 - 2 2 2 - 3 3 - 4 - sage: b.f(3).pp() - 1 1 1 1 1 - 2 2 2 2 - 3 3 4 - 4 - sage: b.f(3).f(4).pp() - 1 1 1 1 1 - 2 2 2 2 - 3 3 -4 - 4 - """ - if i not in self.index_set(): - raise ValueError('i is not in the index set.') - position = self.positions_of_unmatched_minus(i) - if position == []: - return None - k = position[len(position)-1] - ret = self.set_index(k, self[k].f(i)) - if k+i > len(self): - return ret - for j in reversed(range(1,i+1)): - if self[k+i-j].value != j: - return ret - # We've found a full column, so we'll need to add a new column - for j in range(i): - ret._list.insert(k,self.parent().letters(j+1)) - return ret - def phi(self,i): r""" Return `\varphi_i` of ``self``. @@ -766,79 +684,9 @@ def module_generator(self): module_generator = flatten([[p[j]-i for i in range(p[j])] for j in range(n-1)]) return self(list=[self.letters(x) for x in module_generator]) - class Element(InfinityCrystalOfTableaux.Element): + class Element(InfinityCrystalOfTableauxElementTypeD, InfinityCrystalOfTableaux.Element): r""" Elements in `\mathcal{B}(\infty)` crystal of tableaux for type `D_n`. """ - def e(self, i): - r""" - Return the action of `\widetilde{e}_i` on ``self``. - - INPUT: - - - ``i`` -- An element of the index set - - EXAMPLES:: - - sage: B = crystals.infinity.Tableaux(['D',4]) - sage: b = B.highest_weight_vector().f_string([1,4,3,1,2]); b.pp() - 1 1 1 1 2 3 - 2 2 2 - 3 -3 - sage: b.e(2).pp() - 1 1 1 1 2 2 - 2 2 2 - 3 -3 - """ - if i not in self.index_set(): - raise ValueError('i is not in the index set.') - position = self.positions_of_unmatched_plus(i) - if position == []: - return None - k = position[0] - ret = self.set_index(k, self[k].e(i)) - if i == self.cartan_type().rank(): - i -= 1 - if k+i > len(self): - return ret - for j in reversed(range(1, i+1)): - if ret[k+i-j].value != j: - return ret - # We've found a column, so we need to remove it - for j in range(i): - ret._list.pop(k) - return ret - - def f(self, i): - r""" - Return the action of `\widetilde{f}_i` on ``self``. - - INPUT: + pass - - ``i`` -- An element of the index set - - EXAMPLES:: - - sage: B = crystals.infinity.Tableaux(['D',5]) - sage: b = B.highest_weight_vector().f_string([1,4,3,1,5]); b.pp() - 1 1 1 1 1 1 2 2 - 2 2 2 2 2 - 3 3 3 -5 - 4 5 - sage: b.f(1).pp() - 1 1 1 1 1 1 2 2 2 - 2 2 2 2 2 - 3 3 3 -5 - 4 5 - sage: b.f(5).pp() - 1 1 1 1 1 1 2 2 - 2 2 2 2 2 - 3 3 3 -5 - 4 -4 - """ - ret = InfinityCrystalOfTableaux.Element.f(self, i) - if ret._list[0].value == -self.cartan_type().rank(): - # Exceptional case for f_n where we need to add a new column - for j in range(i-1): - ret._list.insert(0,self.parent().letters(j+1)) - return ret diff --git a/src/sage/combinat/crystals/kirillov_reshetikhin.py b/src/sage/combinat/crystals/kirillov_reshetikhin.py index 8eac1105507..f8e82f6cf88 100644 --- a/src/sage/combinat/crystals/kirillov_reshetikhin.py +++ b/src/sage/combinat/crystals/kirillov_reshetikhin.py @@ -1411,11 +1411,11 @@ def highest_weight_dict(self): sage: K = crystals.KirillovReshetikhin(['E',6,1],2,1) sage: K.highest_weight_dict() - {[[(2, -1), (1,)]]: ((-2, 0, 1, 0, 0, 0, 0), 1), - [[(3, -1, -6), (1,)]]: ((-1, 0, 0, 1, 0, 0, -1), 1), + {[]: ((0, 0, 0, 0, 0, 0, 0), 0), + [[(2, -1), (1,)]]: ((-2, 0, 1, 0, 0, 0, 0), 1), [[(6, -2), (-6, 2)]]: ((0, 0, 0, 0, 0, 0, 0), 1), - [[(5, -2, -6), (-6, 2)]]: ((0, 0, 0, 0, 0, 1, -2), 1), - []: ((0, 0, 0, 0, 0, 0, 0), 0)} + [[(3, -1, -6), (1,)]]: ((-1, 0, 0, 1, 0, 0, -1), 1), + [[(5, -2, -6), (-6, 2)]]: ((0, 0, 0, 0, 0, 1, -2), 1)} """ hw = [x for x in self.hw_auxiliary() if x.epsilon(1) == 0] dic = dict( ( x, tuple( [self.affine_weight(x), len(x)] ) ) for x in hw ) @@ -1452,11 +1452,11 @@ def automorphism_on_affine_weight(self, weight): sage: K = crystals.KirillovReshetikhin(['E',6,1],2,1) sage: [[x[0], K.automorphism_on_affine_weight(x[0])] for x in K.highest_weight_dict().values()] - [[(0, 0, 0, 0, 0, 1, -2), (-2, 0, 1, 0, 0, 0, 0)], - [(-1, 0, 0, 1, 0, 0, -1), (-1, -1, 0, 0, 0, 1, 0)], + [[(0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0)], [(0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0)], [(-2, 0, 1, 0, 0, 0, 0), (0, -2, 0, 1, 0, 0, 0)], - [(0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0)]] + [(-1, 0, 0, 1, 0, 0, -1), (-1, -1, 0, 0, 0, 1, 0)], + [(0, 0, 0, 0, 0, 1, -2), (-2, 0, 1, 0, 0, 0, 0)]] """ f = self.dynkin_diagram_automorphism return tuple( [weight[f(f(i))] for i in self.index_set()] ) @@ -1472,11 +1472,11 @@ def promotion_on_highest_weight_vectors(self): sage: K = crystals.KirillovReshetikhin(['E',6,1],2,1) sage: dic = K.promotion_on_highest_weight_vectors() sage: dic - {[[(2, -1), (1,)]]: [[(-1,), (-1, 3)]], - [[(3, -1, -6), (1,)]]: [[(5, -3), (-1, 3)]], + {[]: [[(1, -3), (-1, 3)]], + [[(2, -1), (1,)]]: [[(-1,), (-1, 3)]], [[(6, -2), (-6, 2)]]: [], - [[(5, -2, -6), (-6, 2)]]: [[(2, -1), (1,)]], - []: [[(1, -3), (-1, 3)]]} + [[(3, -1, -6), (1,)]]: [[(5, -3), (-1, 3)]], + [[(5, -2, -6), (-6, 2)]]: [[(2, -1), (1,)]]} """ dic = self.highest_weight_dict() dic_inv = self.highest_weight_dict_inv() @@ -3231,9 +3231,9 @@ def promotion_on_highest_weight_vectors(self): sage: HW = [t for t in T if t.is_highest_weight([2,3,4])] sage: for t in HW: ....: print("{} {}".format(t, prom[t])) - [4, 3, 2, 1] [-1, 4, 3, 2] - [4, -4, 3, 2] [-4, 4, 3, 2] - [-1, -4, 3, 2] [-4, 3, 2, 1] + [[1], [2], [3], [4]] [[2], [3], [4], [-1]] + [[2], [3], [-4], [4]] [[2], [3], [4], [-4]] + [[2], [3], [-4], [-1]] [[1], [2], [3], [-4]] sage: KR = crystals.KirillovReshetikhin(['D',4,1],4,1) sage: prom = KR.promotion_on_highest_weight_vectors() diff --git a/src/sage/combinat/crystals/kyoto_path_model.py b/src/sage/combinat/crystals/kyoto_path_model.py index 6ce66b6ce2a..a8d9409ff44 100644 --- a/src/sage/combinat/crystals/kyoto_path_model.py +++ b/src/sage/combinat/crystals/kyoto_path_model.py @@ -397,18 +397,17 @@ def e(self, i): sage: mg.f(0).e(0) == mg True """ - position = self.positions_of_unmatched_plus(i) - if not position: + k = self.position_of_first_unmatched_plus(i) + if k is None: return None - k = position[0] if k == len(self)-1: return None crystal = self[k].e(i) - if k == len(self)-2 and crystal.Epsilon() == self._list[-1].Phi(): - l = self._list[:-1] + if k == len(self)-2 and crystal.Epsilon() == self[-1].Phi(): + l = self[:-1] l[-1] = crystal return self.__class__(self.parent(), l) - return self.set_index(k, crystal) + return self._set_index(k, crystal) def f(self, i): """ @@ -426,17 +425,16 @@ def f(self, i): sage: mg.f_string([0,1,2]) [[[2]], [[3]], [[1]]] """ - position = self.positions_of_unmatched_minus(i) - if not position: + k = self.position_of_last_unmatched_minus(i) + if k is None: return None - k = position[len(position)-1] if k == len(self)-1: - l = self._list[:] + l = list(self) k = len(l) % len(self.parent().crystals) l.append(self.parent()._phi_dicts[k][ l[-1].Epsilon() ]) l[-2] = l[-2].f(i) return self.__class__(self.parent(), l) - return self.set_index(k, self[k].f(i)) + return self._set_index(k, self[k].f(i)) def weight(self): """ @@ -455,7 +453,7 @@ def weight(self): Lambda[0] - delta """ wt = TensorProductOfRegularCrystalsElement.weight(self) - return wt + self._list[-1].Epsilon() + return wt + self[-1].Epsilon() def truncate(self, k=None): r""" @@ -488,13 +486,13 @@ def truncate(self, k=None): [[2]], [[1]], [[2], [3]], [[1]], [[3]]] """ if k is None: - k = len(self._list) + k = len(self) P = self.parent().finite_tensor_product(k) - if k <= len(self._list): - l = self._list[:k] + if k <= len(self): + l = self[:k] else: - l = self._list[:] + l = list(self) N = len(self.parent().crystals) while len(l) < k: i = len(l) % N diff --git a/src/sage/combinat/crystals/polyhedral_realization.py b/src/sage/combinat/crystals/polyhedral_realization.py index 4707a0b7a1b..27775dd9926 100644 --- a/src/sage/combinat/crystals/polyhedral_realization.py +++ b/src/sage/combinat/crystals/polyhedral_realization.py @@ -266,7 +266,7 @@ def phi(self, i): sage: [elt.phi(i) for i in B.index_set()] [1, 1, 0] """ - P = self[-1].parent().weight_lattice_realization() + P = self.parent().weight_lattice_realization() h = P.simple_coroots() omega = P(self.weight()).scalar(h[i]) return self.epsilon(i) + omega @@ -297,7 +297,7 @@ def e(self, i): if pos is None or pos <= nf: return None - l = self._list[:] + l = list(self) l[-pos] = crystal if pos <= 2*nf and all(b._m == 0 for b in l[-2*nf:-nf]): return self.__class__(self.parent(), l[:-nf]) @@ -327,10 +327,10 @@ def f(self, i): nf = len(self.parent()._factors) if pos <= nf: - l = self._list[:] + l = list(self) l[-pos] = l[-pos].f(i) return self.__class__(self.parent(), l + self.parent()._tp) - return self.set_index(-pos, crystal) + return self._set_index(-pos, crystal) def truncate(self, k=None): r""" @@ -359,13 +359,13 @@ def truncate(self, k=None): [-1, -2, -1, 0, 0, 0, 0, 0, 0, 0] """ if k is None: - k = len(self._list) + k = len(self) P = self.parent().finite_tensor_product(k) - if k <= len(self._list): - l = self._list[:k] + if k <= len(self): + l = self[:k] else: - l = self._list[:] + l = list(self) N = len(self.parent()._tp) while len(l) < k: i = len(l) % N diff --git a/src/sage/combinat/crystals/subcrystal.py b/src/sage/combinat/crystals/subcrystal.py index 15f43642ad1..6bedd570fca 100644 --- a/src/sage/combinat/crystals/subcrystal.py +++ b/src/sage/combinat/crystals/subcrystal.py @@ -82,8 +82,8 @@ class Subcrystal(UniqueRepresentation, Parent): 8 sage: list(T) [[[1, 1], [3]], - [[1, 2], [3]], [[1, 1], [2]], + [[1, 2], [3]], [[1, 2], [2]], [[2, 2], [3]], [[2, 3], [3]], @@ -321,10 +321,10 @@ def _richcmp_(self, other, op): [[1, 2]](0), [[1, -2]](0), [[2, 2]](0), - [[2, -1]](1), - [[-1, -1]](1), [](1), + [[2, -1]](1), [[-2, -1]](1), + [[-1, -1]](1), [[-1, -1]](2)] For != operator:: diff --git a/src/sage/combinat/crystals/tensor_product.py b/src/sage/combinat/crystals/tensor_product.py index 4aef2ec48f4..089168b2790 100644 --- a/src/sage/combinat/crystals/tensor_product.py +++ b/src/sage/combinat/crystals/tensor_product.py @@ -32,10 +32,9 @@ from __future__ import absolute_import import operator -from sage.misc.latex import latex -from sage.misc.cachefunc import cached_method, cached_in_parent_method +from sage.misc.cachefunc import cached_method from sage.structure.parent import Parent -from sage.structure.element import parent +from sage.structure.unique_representation import UniqueRepresentation from sage.structure.global_options import GlobalOptions from sage.categories.category import Category from sage.categories.cartesian_product import cartesian_product @@ -44,11 +43,11 @@ from sage.categories.sets_cat import Sets from sage.categories.map import Map from sage.combinat.root_system.cartan_type import CartanType -from sage.combinat.combinat import CombinatorialElement from sage.combinat.partition import Partition -from sage.combinat.tableau import Tableau from .letters import CrystalOfLetters from .spins import CrystalOfSpins, CrystalOfSpinsMinus, CrystalOfSpinsPlus +from sage.combinat.crystals.tensor_product_element import (TensorProductOfCrystalsElement, + TensorProductOfRegularCrystalsElement, CrystalOfTableauxElement) from sage.misc.flatten import flatten from sage.structure.element import get_coercion_model from sage.rings.all import ZZ @@ -78,222 +77,6 @@ def trunc(i): # Support classes ############################################################################## -from sage.structure.unique_representation import UniqueRepresentation - -class TestParent(UniqueRepresentation, Parent): - """ - A parent for tests. - """ - def _repr_(self): - """ - EXAMPLES:: - - sage: from sage.combinat.crystals.tensor_product import TestParent - sage: TestParent() - A parent for tests - """ - return "A parent for tests" - -class ImmutableListWithParent(CombinatorialElement): - r""" - A class for lists having a parent - - Specification: any subclass ``C`` should implement ``__init__`` which - accepts the following form ``C(parent, list = list)`` - - EXAMPLES: - - We create an immutable list whose parent is the class list:: - - sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent, TestParent - sage: l = ImmutableListWithParent(TestParent(), [1,2,3]) - sage: l._list - [1, 2, 3] - sage: l.parent() - A parent for tests - sage: l.sibling([2,1]) == ImmutableListWithParent(TestParent(), [2,1]) - True - sage: l.reversed() - [3, 2, 1] - sage: l.set_index(1,4) - [1, 4, 3] - - TESTS:: - - sage: TestSuite(l).run(skip = "_test_category") - """ - def _repr_(self): - """ - EXAMPLES:: - - sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent, TestParent - sage: l = ImmutableListWithParent(TestParent(), [1,2,3]) - sage: l._repr_() - '[1, 2, 3]' - """ - return repr(self._list) - - def __eq__(self, other): - """ - EXAMPLES:: - - sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent, TestParent - sage: l = ImmutableListWithParent(TestParent(), [1,2,3]) - sage: m = ImmutableListWithParent(ZZ, [1,2,3]) - sage: n = ImmutableListWithParent(ZZ, [2,3,4]) - sage: l == l - True - sage: l == m - False - sage: m == n - False - """ - return self.__class__ is other.__class__ and \ - self.parent() == other.parent() and \ - self._list == other._list - - def __ne__(self, other): - """ - EXAMPLES:: - - sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent, TestParent - sage: l = ImmutableListWithParent(TestParent(), [1,2,3]) - sage: m = ImmutableListWithParent(ZZ, [1,2,3]) - sage: n = ImmutableListWithParent(ZZ, [2,3,4]) - sage: l != l - False - sage: l != m - True - sage: m != n - True - """ - return not self == other - - def __lt__(self, other): - """ - EXAMPLES:: - - sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent, TestParent - sage: l = ImmutableListWithParent(TestParent(), [1,2,3]) - sage: m = ImmutableListWithParent(ZZ, [1,2,3]) - sage: n = ImmutableListWithParent(ZZ, [2,3,4]) - sage: l < l - False - sage: l < m - False - sage: m < n - True - """ - if parent(self) is not parent(other): - return NotImplemented - return self._list.__lt__(other._list) - - def __le__(self, other): - """ - EXAMPLES:: - - sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent, TestParent - sage: l = ImmutableListWithParent(TestParent(), [1,2,3]) - sage: m = ImmutableListWithParent(ZZ, [1,2,3]) - sage: n = ImmutableListWithParent(ZZ, [2,3,4]) - sage: l <= l - True - sage: l <= m - True - sage: m <= n - True - """ - return self == other or self.__lt__(other) - - def __gt__(self, other): - """ - EXAMPLES:: - - sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent, TestParent - sage: l = ImmutableListWithParent(TestParent(), [1,2,3]) - sage: m = ImmutableListWithParent(ZZ, [1,2,3]) - sage: n = ImmutableListWithParent(ZZ, [2,3,4]) - sage: l > l - False - sage: l > m - False - sage: m > n - False - """ - if parent(self) is not parent(other): - return NotImplemented - return other.__lt__(self) - - def __ge__(self, other): - """ - EXAMPLES:: - - sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent, TestParent - sage: l = ImmutableListWithParent(TestParent(), [1,2,3]) - sage: m = ImmutableListWithParent(ZZ, [1,2,3]) - sage: n = ImmutableListWithParent(ZZ, [2,3,4]) - sage: l >= l - True - sage: l >= m - True - sage: m >= n - False - """ - return self == other or self.__gt__(other) - - def sibling(self, l): - """ - Returns an :class:`ImmutableListWithParent` object whose list is - ``l`` and whose parent is the same as the parent of ``self``. - - Note that the implementation of this function makes an assumption - about the constructor for subclasses. - - EXAMPLES:: - - sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent, TestParent - sage: l = ImmutableListWithParent(TestParent(), [1,2,3]) - sage: m = l.sibling([2,3,4]); m - [2, 3, 4] - sage: m.parent() - A parent for tests - """ - return self.__class__(self.parent(), list=l) - - def reversed(self): - """ - Returns the sibling of ``self`` which is obtained by reversing the - elements of`` self``. - - EXAMPLES:: - - sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent, TestParent - sage: l = ImmutableListWithParent(TestParent(), [1,2,3]) - sage: l.reversed() - [3, 2, 1] - """ - return self.sibling([ i for i in reversed(self._list)]) - - def set_index(self, k, value): - """ - Returns the sibling of ``self`` obtained by setting the - `k^{th}` entry of self to value. - - EXAMPLES:: - - sage: from sage.combinat.crystals.tensor_product import ImmutableListWithParent, TestParent - sage: l = ImmutableListWithParent(TestParent(), [1,2,3]) - sage: l.set_index(0,2) - [2, 2, 3] - sage: l.set_index(1,4) - [1, 4, 3] - sage: _.parent() - A parent for tests - """ - l = [i for i in self._list] - l[k] = value - return self.sibling(l) - class CrystalOfWords(UniqueRepresentation, Parent): """ Auxiliary class to provide a call method to create tensor product elements. @@ -890,766 +673,6 @@ def weight_lattice_realization(self): return cm.common_parent(*[crystal.weight_lattice_realization() for crystal in self.crystals]) -class TensorProductOfCrystalsElement(ImmutableListWithParent): - r""" - A class for elements of tensor products of crystals. - """ - def _repr_(self): - """ - Return a string representation of ``self``. - - EXAMPLES:: - - sage: C = crystals.Letters(['A',3]) - sage: T = crystals.TensorProduct(C,C) - sage: T(C(1),C(2)) - [1, 2] - """ - if self.parent().options.convention == "Kashiwara": - return repr(list(reversed(self._list))) - return repr(self._list) - - def _latex_(self): - r""" - Return latex code for ``self``. - - EXAMPLES:: - - sage: C = crystals.Letters(["A",2]) - sage: D = crystals.Tableaux(["A",2], shape=[2]) - sage: E = crystals.TensorProduct(C,D) - sage: latex(E.module_generators[0]) - 1 \otimes {\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}} - \raisebox{-.6ex}{$\begin{array}[b]{*{2}c}\cline{1-2} - \lr{1}&\lr{1}\\\cline{1-2} - \end{array}$} - } - """ - return ' \otimes '.join(latex(c) for c in self) - - def _ascii_art_(self): - """ - Return an ASCII art representation of ``self``. - - EXAMPLES:: - - sage: KT = crystals.TensorProductOfKirillovReshetikhinTableaux(['D',4,1],[[3,3],[2,1],[1,2]]) - sage: ascii_art(KT.module_generators[0]) - 1 1 1 - 2 2 2 # 1 # 1 1 - 3 3 3 2 - -4 -4 -4 - """ - from sage.typeset.ascii_art import ascii_art, AsciiArt - s = ascii_art(self[0]) - s._baseline = s._h // 2 - ret = s - for tableau in self[1:]: - s = ascii_art(tableau) - s._baseline = s._h // 2 - ret += AsciiArt([" # "]) + s - return ret - - def __lt__(self, other): - """ - Non elements of the crystal are incomparable with elements of the crystal - (or should it return NotImplemented?). - - Comparison of two elements of this crystal: - - - different length: incomparable - - otherwise lexicographically, considering ``self[i]`` and ``other[i]`` - as incomparable if ``self[i] < other[i]`` returns NotImplemented - """ - if parent(self) is not parent(other): - return False - if len(self) != len(other): - return False - for i in range(len(self)): - if (self[i] < other[i]): - return True - if (other[i] < self[i]): - return False - return False - - def _repr_diagram(self): - r""" - Return a string representation of ``self`` as a diagram. - - EXAMPLES:: - - sage: C = crystals.Tableaux(['A',3], shape=[3,1]) - sage: D = crystals.Tableaux(['A',3], shape=[1]) - sage: E = crystals.Tableaux(['A',3], shape=[2,2,2]) - sage: T = crystals.TensorProduct(C,D,E) - sage: print(T.module_generators[0]._repr_diagram()) - 1 1 1 (X) 1 (X) 1 1 - 2 2 2 - 3 3 - """ - pplist = [] - max_widths = [] - num_cols = len(self) - for c in self: - try: - pplist.append(c._repr_diagram().split('\n')) - except AttributeError: - pplist.append(c._repr_().split('\n')) - max_widths.append(max(map(len, pplist[-1]))) - num_rows = max(map(len, pplist)) - ret = "" - for i in range(num_rows): - if i > 0: - ret += '\n' - for j in range(num_cols): - if j > 0: - if i == 0: - ret += ' (X) ' - else: - ret += ' ' - if i < len(pplist[j]): - ret += pplist[j][i] - ret += ' '*(max_widths[j] - len(pplist[j][i])) - else: - ret += ' '*max_widths[j] - return ret - - def pp(self): - """ - Pretty print ``self``. - - EXAMPLES:: - - sage: C = crystals.Tableaux(['A',3], shape=[3,1]) - sage: D = crystals.Tableaux(['A',3], shape=[1]) - sage: E = crystals.Tableaux(['A',3], shape=[2,2,2]) - sage: T = crystals.TensorProduct(C,D,E) - sage: T.module_generators[0].pp() - 1 1 1 (X) 1 (X) 1 1 - 2 2 2 - 3 3 - """ - print(self._repr_diagram()) - - def weight(self): - r""" - Return the weight of ``self``. - - EXAMPLES:: - - sage: B = crystals.infinity.Tableaux("A3") - sage: T = crystals.TensorProduct(B,B) - sage: b1 = B.highest_weight_vector().f_string([2,1,3]) - sage: b2 = B.highest_weight_vector().f(1) - sage: t = T(b2, b1) - sage: t - [[[1, 1, 1, 2], [2, 2], [3]], [[1, 1, 1, 1, 2], [2, 2, 4], [3]]] - sage: t.weight() - (-2, 1, 0, 1) - """ - return sum(self[i].weight() for i in range(len(self))) - - def epsilon(self, i): - r""" - Return `\varepsilon_i` of ``self``. - - INPUT: - - - ``i`` -- An element of the index set - - EXAMPLES:: - - sage: B = crystals.infinity.Tableaux("G2") - sage: T = crystals.TensorProduct(B,B) - sage: b1 = B.highest_weight_vector().f(2) - sage: b2 = B.highest_weight_vector().f_string([2,2,1]) - sage: t = T(b2, b1) - sage: [t.epsilon(i) for i in B.index_set()] - [0, 3] - """ - return max(self._sig(i, k) for k in range(1, len(self)+1)) - - def phi(self, i): - r""" - Return `\varphi_i` of ``self``. - - INPUT: - - - ``i`` -- An element of the index set - - EXAMPLES:: - - sage: La = RootSystem(['A',2,1]).weight_lattice(extended=True).fundamental_weights() - sage: B = crystals.GeneralizedYoungWalls(2,La[0]+La[1]) - sage: T = crystals.TensorProduct(B,B) - sage: b1 = B.highest_weight_vector().f_string([1,0]) - sage: b2 = B.highest_weight_vector().f_string([0,1]) - sage: t = T(b2, b1) - sage: [t.phi(i) for i in B.index_set()] - [1, 1, 4] - - TESTS: - - Check that :trac:`15462` is fixed:: - - sage: B = crystals.Tableaux(['A',2], shape=[2,1]) - sage: La = RootSystem(['A',2]).ambient_space().fundamental_weights() - sage: T = crystals.TensorProduct(crystals.elementary.T(['A',2], La[1]+La[2]), B) - sage: t = T.an_element() - sage: t.phi(1) - 2 - sage: t.phi(2) - 2 - """ - P = self[-1].parent().weight_lattice_realization() - h = P.simple_coroots() - omega = P(self.weight()).scalar(h[i]) - return max([omega + self._sig(i, k) for k in range(1, len(self)+1)]) - - @cached_in_parent_method - def _sig(self,i,k): - r""" - Return `a_i(k)` of ``self``. - - The value `a_i(k)` of a crystal `b = b_N \otimes \cdots \otimes b_1` - is defined as: - - .. MATH:: - - a_i(k) = \varepsilon_i(b_k) - \sum_{j=1}^{k-1} \langle h_i, - \mathrm{wt}(b_j) \rangle - - where `\mathrm{wt}` is the :meth:`weight` of `b_j`. - - INPUT: - - - ``i`` -- An element of the index set - - - ``k`` -- The (1-based) index of the tensor factor of ``self`` - - EXAMPLES:: - - sage: B = crystals.infinity.GeneralizedYoungWalls(3) - sage: T = crystals.TensorProduct(B,B) - sage: b1 = B.highest_weight_vector().f_string([0,3,1]) - sage: b2 = B.highest_weight_vector().f_string([3,2,1,0,2,3]) - sage: t = T(b1, b2) - sage: [[t._sig(i,k) for k in range(1,len(t)+1)] for i in B.index_set()] - [[0, -1], [0, 0], [0, 1], [1, 2]] - - TESTS: - - Check that :trac:`18469` is fixed:: - - sage: E1 = crystals.elementary.B(['A',2], 1) - sage: E2 = crystals.elementary.B(['A',2], 2) - sage: T = crystals.TensorProduct(E1, E2) - sage: x = T(E1.module_generators[0], E2.module_generators[0]); x - [0, 0] - sage: [[x._sig(i,k) for k in range(1,3)] for i in T.index_set()] - [[-inf, 0], [0, -inf]] - sage: x.f(1) - [-1, 0] - sage: x.e(1) - [1, 0] - """ - if k == 1: - return self[-1].epsilon(i) - ep = self[-k].epsilon(i) - if ep == float("-inf"): - return ep - - P = self[-1].parent().weight_lattice_realization() - h = P.simple_coroots() - wt = sum(P(self[-j].weight()) for j in range(1, k)) - return ep - P(wt).scalar(h[i]) - - def e(self,i): - r""" - Return the action of `e_i` on ``self``. - - INPUT: - - - ``i`` -- An element of the index set - - EXAMPLES:: - - sage: B = crystals.infinity.Tableaux("D4") - sage: T = crystals.TensorProduct(B,B) - sage: b1 = B.highest_weight_vector().f_string([1,4,3]) - sage: b2 = B.highest_weight_vector().f_string([2,2,3,1,4]) - sage: t = T(b2, b1) - sage: t.e(1) - [[[1, 1, 1, 1, 1], [2, 2, 3, -3], [3]], [[1, 1, 1, 1, 2], [2, 2, 2], [3, -3]]] - sage: t.e(2) - sage: t.e(3) - [[[1, 1, 1, 1, 1, 2], [2, 2, 3, -4], [3]], [[1, 1, 1, 1, 2], [2, 2, 2], [3, -3]]] - sage: t.e(4) - [[[1, 1, 1, 1, 1, 2], [2, 2, 3, 4], [3]], [[1, 1, 1, 1, 2], [2, 2, 2], [3, -3]]] - """ - N = len(self) + 1 - for k in range(1, N): - if all(self._sig(i,k) > self._sig(i,j) for j in range(1, k)) and \ - all(self._sig(i,k) >= self._sig(i,j) for j in range(k+1, N)): - crystal = self[-k].e(i) - if crystal is None: - return None - return self.set_index(-k, crystal) - return None - - def f(self,i): - r""" - Return the action of `f_i` on ``self``. - - INPUT: - - - ``i`` -- An element of the index set - - EXAMPLES:: - - sage: La = RootSystem(['A',3,1]).weight_lattice(extended=True).fundamental_weights() - sage: B = crystals.GeneralizedYoungWalls(3,La[0]) - sage: T = crystals.TensorProduct(B,B,B) - sage: b1 = B.highest_weight_vector().f_string([0,3]) - sage: b2 = B.highest_weight_vector().f_string([0]) - sage: b3 = B.highest_weight_vector() - sage: t = T(b3, b2, b1) - sage: t.f(0) - [[[0]], [[0]], [[0, 3]]] - sage: t.f(1) - [[], [[0]], [[0, 3], [1]]] - sage: t.f(2) - [[], [[0]], [[0, 3, 2]]] - sage: t.f(3) - [[], [[0, 3]], [[0, 3]]] - """ - N = len(self) + 1 - for k in range(1, N): - if all(self._sig(i,k) >= self._sig(i,j) for j in range(1, k)) and \ - all(self._sig(i,k) > self._sig(i,j) for j in range(k+1, N)): - crystal = self[-k].f(i) - if crystal is None: - return None - return self.set_index(-k, crystal) - return None - -class TensorProductOfRegularCrystalsElement(TensorProductOfCrystalsElement): - """ - Element class for a tensor product of regular crystals. - - TESTS:: - - sage: C = crystals.Letters(['A',2]) - sage: T = crystals.TensorProduct(C, C) - sage: elt = T(C(1), C(2)) - sage: from sage.combinat.crystals.tensor_product import TensorProductOfRegularCrystalsElement - sage: isinstance(elt, TensorProductOfRegularCrystalsElement) - True - """ - def e(self, i): - """ - Return the action of `e_i` on ``self``. - - EXAMPLES:: - - sage: C = crystals.Letters(['A',5]) - sage: T = crystals.TensorProduct(C,C) - sage: T(C(1),C(2)).e(1) == T(C(1),C(1)) - True - sage: T(C(2),C(1)).e(1) is None - True - sage: T(C(2),C(2)).e(1) == T(C(1),C(2)) - True - """ - if i not in self.index_set(): - raise ValueError("i must be in the index set") - position = self.positions_of_unmatched_plus(i) - if position == []: - return None - k = position[0] - return self.set_index(k, self[k].e(i)) - - def weight(self): - """ - Return the weight of ``self``. - - EXAMPLES:: - - sage: C = crystals.Letters(['A',3]) - sage: T = crystals.TensorProduct(C,C) - sage: T(C(1),C(2)).weight() - (1, 1, 0, 0) - sage: T = crystals.Tableaux(['D',4],shape=[]) - sage: T.list()[0].weight() - (0, 0, 0, 0) - """ - return sum((self[j].weight() for j in range(len(self))), self.parent().weight_lattice_realization().zero()) - - def f(self, i): - """ - Return the action of `f_i` on ``self``. - - EXAMPLES:: - - sage: C = crystals.Letters(['A',5]) - sage: T = crystals.TensorProduct(C,C) - sage: T(C(1),C(1)).f(1) - [1, 2] - sage: T(C(1),C(2)).f(1) - [2, 2] - sage: T(C(2),C(1)).f(1) is None - True - """ - if i not in self.index_set(): - raise ValueError("i must be in the index set") - position = self.positions_of_unmatched_minus(i) - if position == []: - return None - k = position[len(position)-1] - return self.set_index(k, self[k].f(i)) - - def phi(self, i): - r""" - Return `\varphi_i` of ``self``. - - EXAMPLES:: - - sage: C = crystals.Letters(['A',5]) - sage: T = crystals.TensorProduct(C,C) - sage: T(C(1),C(1)).phi(1) - 2 - sage: T(C(1),C(2)).phi(1) - 1 - sage: T(C(2),C(1)).phi(1) - 0 - """ - self = self.reversed() - height = 0 - for j in range(len(self)): - plus = self[j].epsilon(i) - minus = self[j].phi(i) - if height-plus < 0: - height = minus - else: - height = height - plus + minus - return height - - def epsilon(self, i): - r""" - Return `\varepsilon_i` of ``self``. - - EXAMPLES:: - - sage: C = crystals.Letters(['A',5]) - sage: T = crystals.TensorProduct(C,C) - sage: T(C(1),C(1)).epsilon(1) - 0 - sage: T(C(1),C(2)).epsilon(1) - 1 - sage: T(C(2),C(1)).epsilon(1) - 0 - """ - height = 0 - for j in range(len(self)): - minus = self[j].phi(i) - plus = self[j].epsilon(i) - if height-minus < 0: - height = plus - else: - height = height - minus + plus - return height - - def positions_of_unmatched_minus(self, i, dual=False, reverse=False): - """ - EXAMPLES:: - - sage: C = crystals.Letters(['A',5]) - sage: T = crystals.TensorProduct(C,C) - sage: T(C(2),C(1)).positions_of_unmatched_minus(1) - [] - sage: T(C(1),C(2)).positions_of_unmatched_minus(1) - [0] - """ - unmatched_plus = [] - height = 0 - if reverse: - self = self.reversed() - if not dual: - for j in range(len(self)): - minus = self[j].phi(i) - plus = self[j].epsilon(i) - if height-minus < 0: - unmatched_plus.append(j) - height = plus - else: - height = height - minus + plus - else: - for j in range(len(self)): - plus = self[j].epsilon(i) - minus = self[j].phi(i) - if height-plus < 0: - unmatched_plus.append(j) - height = minus - else: - height = height - plus + minus - return unmatched_plus - - def positions_of_unmatched_plus(self, i): - """ - EXAMPLES:: - - sage: C = crystals.Letters(['A',5]) - sage: T = crystals.TensorProduct(C,C) - sage: T(C(2),C(1)).positions_of_unmatched_plus(1) - [] - sage: T(C(1),C(2)).positions_of_unmatched_plus(1) - [1] - """ - l = self.positions_of_unmatched_minus(i, dual=True, reverse=True) - l.reverse() - return [len(self)-1-l[j] for j in range(len(l))] - - def energy_function(self, algorithm=None): - r""" - Return the energy function of ``self``. - - ALGORITHM: - - .. RUBRIC:: definition - - Let `T` be a tensor product of Kirillov-Reshetikhin - crystals. Let `R_i` and `H_i` be the combinatorial - `R`-matrix and local energy functions, respectively, acting - on the `i` and `i+1` factors. Let `D_B` be the energy - function of a single Kirillov-Reshetikhin crystal. The - *energy function* is given by - - .. MATH:: - - D = \sum_{j > i} H_i R_{i+1} R_{i+2} \cdots R_{j-1} - + \sum_j D_B R_1 R_2 \cdots R_{j-1}, - - where `D_B` acts on the rightmost factor. - - .. RUBRIC:: grading - - If ``self`` is an element of `T`, a tensor product of - perfect crystals of the same level, then use the affine - grading to determine the energy. Specifically, let `g` - denote the affine grading of ``self`` and `d` the affine - grading of the maximal vector in `T`. Then the energy - of ``self`` is given by `d - g`. - - For more details, see Theorem 7.5 in [SchillingTingley2011]_. - - INPUT: - - - ``algorithm`` -- (default: ``None``) use one of the - following algorithms to determine the energy function: - - * ``'definition'`` - use the definition of the energy - function; - * ``'grading'`` - use the affine grading; - - if not specified, then this uses ``'grading'`` if all - factors are perfect of the same level and otherwise - this uses ``'definition'`` - - OUTPUT: an integer - - REFERENCES: - - .. [SchillingTingley2011] \A. Schilling, P. Tingley. - *Demazure crystals, Kirillov-Reshetikhin crystals, and - the energy function*. - Electronic Journal of Combinatorics. **19(2)**. 2012. - :arXiv:`1104.2359` - - EXAMPLES:: - - sage: K = crystals.KirillovReshetikhin(['A',2,1], 1, 1) - sage: T = crystals.TensorProduct(K,K,K) - sage: hw = sorted([x for x in T if x.is_highest_weight([1,2])]) - sage: for b in hw: - ....: print("{} {}".format(b, b.energy_function())) - [[[1]], [[1]], [[1]]] 0 - [[[1]], [[2]], [[1]]] 2 - [[[2]], [[1]], [[1]]] 1 - [[[3]], [[2]], [[1]]] 3 - - sage: K = crystals.KirillovReshetikhin(['C',2,1], 1, 2) - sage: T = crystals.TensorProduct(K,K) - sage: hw = [x for x in T if x.is_highest_weight([1,2])] - sage: for b in hw: - ....: print("{} {}".format(b, b.energy_function())) - [[], []] 4 - [[], [[1, 1]]] 1 - [[[1, 1]], []] 3 - [[[1, 1]], [[1, 1]]] 0 - [[[1, 2]], [[1, 1]]] 1 - [[[2, 2]], [[1, 1]]] 2 - [[[-1, -1]], [[1, 1]]] 2 - [[[1, -1]], [[1, 1]]] 2 - [[[2, -1]], [[1, 1]]] 2 - - sage: K = crystals.KirillovReshetikhin(['C',2,1], 1, 1) - sage: T = crystals.TensorProduct(K) - sage: t = T.module_generators[0] - sage: t.energy_function('grading') - Traceback (most recent call last): - ... - NotImplementedError: all crystals in the tensor product need to be perfect of the same level - - TESTS:: - - sage: K = crystals.KirillovReshetikhin(['C',2,1], 1, 2) - sage: K2 = crystals.KirillovReshetikhin(['C',2,1], 2, 2) - sage: T = tensor([K, K2]) - sage: hw = [x for x in T if x.is_highest_weight([1,2])] - sage: all(b.energy_function() == b.energy_function(algorithm='definition') - ....: for b in hw) - True - """ - C = self.parent().crystals[0] - ell = ceil(C.s()/C.cartan_type().c()[C.r()]) - is_perfect = all(ell == K.s()/K.cartan_type().c()[K.r()] - for K in self.parent().crystals) - if algorithm is None: - if is_perfect: - algorithm = 'grading' - else: - algorithm = 'definition' - - if algorithm == 'grading': - if not is_perfect: - raise NotImplementedError("all crystals in the tensor product need to be perfect of the same level") - t = self.parent()(*[K.module_generator() for K in self.parent().crystals]) - d = t.affine_grading() - return d - self.affine_grading() - - if algorithm == 'definition': - # Setup - energy = ZZ.zero() - R_mats = [[K.R_matrix(Kp) for Kp in self.parent().crystals[i+1:]] - for i,K in enumerate(self.parent().crystals)] - H_funcs = [[K.local_energy_function(Kp) for Kp in self.parent().crystals[i+1:]] - for i,K in enumerate(self.parent().crystals)] - - for i,b in enumerate(self): - for j,R in enumerate(R_mats[i]): - H = H_funcs[i][j] - bp = self[i+j+1] - T = R.domain() - t = T(b, bp) - energy += H(t) - b = R(t)[1] - energy += b.energy_function() # D contribution - return energy - else: - raise ValueError("invalid algorithm") - - def affine_grading(self): - r""" - Returns the affine grading of `self`. - - The affine grading is only defined when ``self`` is an element of a - tensor product of affine Kirillov-Reshetikhin crystals. It is - calculated by finding a path from ``self`` to a ground state path - using the helper method :meth:`e_string_to_ground_state` and counting - the number of affine Kashiwara operators `e_0` applied on the way. - - INPUT: - - - ``self`` -- an element of a tensor product of Kirillov-Reshetikhin - crystals - - OUTPUT: an integer - - EXAMPLES:: - - sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) - sage: T = crystals.TensorProduct(K,K) - sage: t = T.module_generators[0] - sage: t.affine_grading() - 1 - - sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) - sage: T = crystals.TensorProduct(K,K,K) - sage: hw = [b for b in T if all(b.epsilon(i)==0 for i in [1,2])] - sage: for b in hw: - ....: print("{} {}".format(b, b.affine_grading())) - [[[1]], [[1]], [[1]]] 3 - [[[1]], [[2]], [[1]]] 1 - [[[2]], [[1]], [[1]]] 2 - [[[3]], [[2]], [[1]]] 0 - - sage: K = crystals.KirillovReshetikhin(['C',2,1],1,1) - sage: T = crystals.TensorProduct(K,K,K) - sage: hw = [b for b in T if all(b.epsilon(i)==0 for i in [1,2])] - sage: for b in hw: - ....: print("{} {}".format(b, b.affine_grading())) - [[[1]], [[1]], [[1]]] 2 - [[[1]], [[2]], [[1]]] 1 - [[[1]], [[-1]], [[1]]] 0 - [[[2]], [[1]], [[1]]] 1 - [[[-2]], [[2]], [[1]]] 0 - [[[-1]], [[1]], [[1]]] 1 - """ - return self.e_string_to_ground_state().count(0) - - @cached_method - def e_string_to_ground_state(self): - r""" - Returns a string of integers in the index set `(i_1,\ldots,i_k)` such - that `e_{i_k} \cdots e_{i_1}` of ``self`` is the ground state. - - This method is only defined when ``self`` is an element of a tensor - product of affine Kirillov-Reshetikhin crystals. It calculates a path - from ``self`` to a ground state path using Demazure arrows as defined - in Lemma 7.3 in [SchillingTingley2011]_. - - INPUT: - - - ``self`` -- an element of a tensor product of Kirillov-Reshetikhin - crystals - - OUTPUT: a tuple of integers `(i_1,\ldots,i_k)` - - EXAMPLES:: - - sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) - sage: T = crystals.TensorProduct(K,K) - sage: t = T.module_generators[0] - sage: t.e_string_to_ground_state() - (0, 2) - - sage: K = crystals.KirillovReshetikhin(['C',2,1],1,1) - sage: T = crystals.TensorProduct(K,K) - sage: t = T.module_generators[0]; t - [[[1]], [[1]]] - sage: t.e_string_to_ground_state() - (0,) - sage: x=t.e(0) - sage: x.e_string_to_ground_state() - () - sage: y=t.f_string([1,2,1,1,0]); y - [[[2]], [[1]]] - sage: y.e_string_to_ground_state() - () - """ - from sage.combinat.rigged_configurations.kr_tableaux import KirillovReshetikhinTableaux - if self.parent().crystals[0].__module__ != 'sage.combinat.crystals.kirillov_reshetikhin' and \ - not isinstance(self.parent().crystals[0], KirillovReshetikhinTableaux): - raise ValueError("All crystals in the tensor product need to be Kirillov-Reshetikhin crystals") - I = self.cartan_type().classical().index_set() - ell = max(ceil(K.s()/K.cartan_type().c()[K.r()]) for K in self.parent().crystals) - for i in I: - if self.epsilon(i) > 0: - return (i,) + (self.e(i)).e_string_to_ground_state() - if self.epsilon(0) > ell: - return (0,) + (self.e(0)).e_string_to_ground_state() - return () - CrystalOfWords.Element = TensorProductOfCrystalsElement class FullTensorProductOfRegularCrystals(FullTensorProductOfCrystals): @@ -1729,7 +752,7 @@ class CrystalOfTableaux(CrystalOfWords): sage: T = crystals.Tableaux(['A',2], shape = [3,2]) sage: T.module_generators[0] [[1, 1, 1], [2, 2]] - sage: T.module_generators[0]._list + sage: list(T.module_generators[0]) [2, 1, 2, 1, 1] To create a tableau, one can use:: @@ -1805,18 +828,18 @@ class CrystalOfTableaux(CrystalOfWords): sage: T = crystals.Tableaux(['A',3], shape = [2,2]) sage: C = T.letters - sage: Tab(rows = [[1,2],[3,4]])._list == [C(3),C(1),C(4),C(2)] + sage: list(Tab(rows = [[1,2],[3,4]])) == [C(3),C(1),C(4),C(2)] True - sage: Tab(columns = [[3,1],[4,2]])._list == [C(3),C(1),C(4),C(2)] + sage: list(Tab(columns = [[3,1],[4,2]])) == [C(3),C(1),C(4),C(2)] True For compatibility with :func:`~sage.combinat.crystals.tensor_product.TensorProductOfCrystals` we need to accept as input the internal list or sequence of elements:: - sage: Tab(list = [3,1,4,2])._list == [C(3),C(1),C(4),C(2)] + sage: list(Tab(list = [3,1,4,2])) == [C(3),C(1),C(4),C(2)] True - sage: Tab(3,1,4,2)._list == [C(3),C(1),C(4),C(2)] + sage: list(Tab(3,1,4,2)) == [C(3),C(1),C(4),C(2)] True The next example checks whether a given tableau is in fact a valid @@ -1973,265 +996,6 @@ def _element_constructor_(self, *args, **options): """ return self.element_class(self, *args, **options) - - -class CrystalOfTableauxElement(TensorProductOfRegularCrystalsElement): - """ - Element in a crystal of tableaux. - """ - def __init__(self, parent, *args, **options): - """ - There are several ways to input tableaux, by rows, - by columns, as the list of column elements, or as a sequence of numbers - in column reading. - - EXAMPLES:: - - sage: T = crystals.Tableaux(['A',3], shape = [2,2]) - sage: t = T(rows=[[1,2],[3,4]]) - sage: t - [[1, 2], [3, 4]] - sage: TestSuite(t).run() - - sage: t = T(columns=[[3,1],[4,2]]) - sage: t - [[1, 2], [3, 4]] - sage: TestSuite(t).run() - - sage: t = T(list=[3,1,4,2]) - sage: t - [[1, 2], [3, 4]] - - sage: t = T(3,1,4,2) - sage: t - [[1, 2], [3, 4]] - - Currently inputting the empty tableau as an empty sequence is - broken due to a bug in the generic __call__ method (see :trac:`8648`). - - EXAMPLES:: - - sage: T = crystals.Tableaux(['A',3], shape=[]) - sage: t = T() - sage: t._list - [0] - - TESTS: - - Integer types that are not a Sage ``Integer`` (such as a Python ``int`` - and typically arise from compiled code) were not converted into a - letter. This caused certain functions to fail. This is fixed in - :trac:`13204`:: - - sage: T = crystals.Tableaux(['A',3], shape = [2,2]) - sage: t = T(list=[int(3),1,4,2]) - sage: type(t[0]) - - sage: t = T(list=[3,int(1),4,2]) - sage: type(t[1]) - - sage: C = crystals.KirillovReshetikhin(['A',int(3),1], 1,1) - sage: C[0].e(0) - [[4]] - """ - if len(args) == 1: - if isinstance(args[0], Tableau): - options['rows'] = args[0] - if 'list' in options: - the_list = options['list'] - elif 'rows' in options: - rows = options['rows'] -# the_list=Tableau(rows).to_word_by_column() - rows = Tableau(rows).conjugate() - the_list = [] - for col in rows: - the_list += reversed(col) - elif 'columns' in options: - columns = options['columns'] - the_list = [] - for col in columns: - the_list += col - else: - the_list = [i for i in args] - TensorProductOfRegularCrystalsElement.__init__(self, parent, [parent.letters(_) for _ in the_list]) - - def _repr_(self): - """ - EXAMPLES:: - - sage: T = crystals.Tableaux(['A',3], shape = [2,2]) - sage: t = T(rows=[[1,2],[3,4]]) - sage: t._repr_() - '[[1, 2], [3, 4]]' - """ - return repr(self.to_tableau()) - - def _repr_diagram(self): - """ - Return a string representation of ``self`` as a diagram. - - EXAMPLES:: - - sage: C = crystals.Tableaux(['A', 4], shape=[4,2,1]) - sage: elt = C(rows=[[1,1,1,2], [2,3], [4]]) - sage: print(elt._repr_diagram()) - 1 1 1 2 - 2 3 - 4 - """ - return self.to_tableau()._repr_diagram() - - def pp(self): - """ - EXAMPLES:: - - sage: T = crystals.Tableaux(['A',3], shape = [2,2]) - sage: t = T(rows=[[1,2],[3,4]]) - sage: t.pp() - 1 2 - 3 4 - """ - return self.to_tableau().pp() - - def _ascii_art_(self): - """ - Return an ascii art version of ``self``. - - EXAMPLES: - - We check that :trac:`16486` is fixed:: - - sage: T = crystals.Tableaux(['B',6], shape=[1]*5) - sage: ascii_art(T.module_generators[0]) - 1 - 2 - 3 - 4 - 5 - sage: T = crystals.Tableaux(['D',4], shape=[2,1]) - sage: t = T.module_generators[0].f_string([1,2,3,4,2,2,3,4]) - sage: ascii_art(t) - 1 -2 - -3 - """ - return self.to_tableau()._ascii_art_() - - def _latex_(self): - r""" - EXAMPLES:: - - sage: T = crystals.Tableaux(['A',3], shape = [4,2]) - sage: t = T(rows=[[1,1,2,3],[2,3]]) - sage: latex(t) # indirect doctest - {\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}} - \raisebox{-.6ex}{$\begin{array}[b]{*{4}c}\cline{1-4} - \lr{1}&\lr{1}&\lr{2}&\lr{3}\\\cline{1-4} - \lr{2}&\lr{3}\\\cline{1-2} - \end{array}$} - } - """ - from sage.combinat.output import tex_from_array - # Modified version of to_tableau() to have the entries be letters - # rather than their values - if self._list == []: - return "{\\emptyset}" - - tab = [ [self[0]] ] - for i in range(1,len(self)): - if self[i-1] < self[i] or (self[i-1].value != 0 and self[i-1] == self[i]): - tab.append([self[i]]) - else: - l = len(tab)-1 - tab[l].append(self[i]) - for x in tab: - x.reverse() - T = Tableau(tab).conjugate() - return tex_from_array([[letter._latex_() for letter in row] for row in T]) - - @cached_method - def to_tableau(self): - """ - Returns the Tableau object corresponding to self. - - EXAMPLES:: - - sage: T = crystals.Tableaux(['A',3], shape = [2,2]) - sage: t = T(rows=[[1,2],[3,4]]).to_tableau(); t - [[1, 2], [3, 4]] - sage: type(t) - - sage: type(t[0][0]) - <... 'int'> - sage: T = crystals.Tableaux(['D',3], shape = [1,1]) - sage: t=T(rows=[[-3],[3]]).to_tableau(); t - [[-3], [3]] - sage: t=T(rows=[[3],[-3]]).to_tableau(); t - [[3], [-3]] - sage: T = crystals.Tableaux(['B',2], shape = [1,1]) - sage: t = T(rows=[[0],[0]]).to_tableau(); t - [[0], [0]] - """ - if self._list == []: - return Tableau([]) - tab = [ [self[0].value] ] - for i in range(1,len(self)): - if self[i-1] < self[i] or (self[i-1].value != 0 and self[i-1] == self[i]): - tab.append([self[i].value]) - else: - l = len(tab)-1 - tab[l].append(self[i].value) - for x in tab: - x.reverse() - return Tableau(tab).conjugate() - - def promotion(self): - """ - Promotion for type A crystals of tableaux of rectangular shape - - Returns the result of applying promotion on this tableau. - - This method only makes sense in type A with rectangular shapes. - - EXAMPLES:: - - sage: C = crystals.Tableaux(["A",3], shape = [3,3,3]) - sage: t = C(Tableau([[1,1,1],[2,2,3],[3,4,4]])) - sage: t - [[1, 1, 1], [2, 2, 3], [3, 4, 4]] - sage: t.promotion() - [[1, 1, 2], [2, 2, 3], [3, 4, 4]] - sage: t.promotion().parent() - The crystal of tableaux of type ['A', 3] and shape(s) [[3, 3, 3]] - """ - crystal = self.parent() - cartan_type = crystal.cartan_type() - assert cartan_type.type() == 'A' - return crystal(self.to_tableau().promotion(cartan_type.rank())) - - def promotion_inverse(self): - """ - Inverse promotion for type A crystals of tableaux of rectangular shape - - Returns the result of applying inverse promotion on this tableau. - - This method only makes sense in type A with rectangular shapes. - - EXAMPLES:: - - sage: C = crystals.Tableaux(["A",3], shape = [3,3,3]) - sage: t = C(Tableau([[1,1,1],[2,2,3],[3,4,4]])) - sage: t - [[1, 1, 1], [2, 2, 3], [3, 4, 4]] - sage: t.promotion_inverse() - [[1, 1, 2], [2, 3, 3], [4, 4, 4]] - sage: t.promotion_inverse().parent() - The crystal of tableaux of type ['A', 3] and shape(s) [[3, 3, 3]] - """ - crystal = self.parent() - cartan_type = crystal.cartan_type() - assert cartan_type.type() == 'A' - return crystal(self.to_tableau().promotion_inverse(cartan_type.rank())) - CrystalOfTableaux.Element = CrystalOfTableauxElement ##################################################################### diff --git a/src/sage/combinat/crystals/tensor_product_element.pxd b/src/sage/combinat/crystals/tensor_product_element.pxd new file mode 100644 index 00000000000..df44135819f --- /dev/null +++ b/src/sage/combinat/crystals/tensor_product_element.pxd @@ -0,0 +1,20 @@ +from sage.structure.list_clone cimport ClonableArray + +cdef class ImmutableListWithParent(ClonableArray): + cpdef _set_index(self, k, value) + +cdef class TensorProductOfCrystalsElement(ImmutableListWithParent): + pass + +cdef class TensorProductOfRegularCrystalsElement(TensorProductOfCrystalsElement): + cpdef position_of_last_unmatched_minus(self, i) + cpdef position_of_first_unmatched_plus(self, i) + +cdef class CrystalOfTableauxElement(TensorProductOfRegularCrystalsElement): + pass + +cdef class InfinityCrystalOfTableauxElement(CrystalOfTableauxElement): + pass + +cdef class InfinityCrystalOfTableauxElementTypeD(InfinityCrystalOfTableauxElement): + pass diff --git a/src/sage/combinat/crystals/tensor_product_element.pyx b/src/sage/combinat/crystals/tensor_product_element.pyx new file mode 100644 index 00000000000..c9f93c0baf8 --- /dev/null +++ b/src/sage/combinat/crystals/tensor_product_element.pyx @@ -0,0 +1,1331 @@ +""" +Tensor Products of Crystals Elements + +AUTHORS: + +- Anne Schilling, Nicolas Thiery (2007): Initial version +- Ben Salisbury, Travis Scrimshaw (2013): Refactored tensor products to handle + non-regular crystals and created new subclass to take advantage of + the regularity +- Travis Scrimshaw (2017): Cythonized element classes +""" +#***************************************************************************** +# Copyright (C) 2007 Anne Schilling +# Nicolas Thiery +# 2017 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: +# +# http://www.gnu.org/licenses/ +#**************************************************************************** +from __future__ import print_function, absolute_import + +from cpython.object cimport Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT, Py_GE +from sage.structure.parent cimport Parent + +from sage.misc.cachefunc import cached_method, cached_in_parent_method +from sage.functions.other import ceil +from sage.combinat.tableau import Tableau +from sage.rings.all import ZZ + +############################################################################## +# Support classes +############################################################################## + +cdef class ImmutableListWithParent(ClonableArray): + r""" + A class for lists having a parent + + Specification: any subclass ``C`` should implement ``__init__`` which + accepts the following form ``C(parent, list=list)`` + """ + def __init__(self, Parent parent, list): + """ + Initialize ``self``. + + TESTS:: + + sage: b = crystals.Tableaux(['A',2], shape=[2,1]).module_generators[0] + sage: TestSuite(b).run() + """ + ClonableArray.__init__(self, parent, list, check=False) + + def reversed(self): + """ + Return a copy of ``self`` but in the reversed order. + + EXAMPLES:: + + sage: b = crystals.Tableaux(['A',2], shape=[2,1]).module_generators[0] + sage: list(b) + [2, 1, 1] + sage: list(b.reversed()) + doctest:warning + ... + DeprecationWarning: reversed() is deprecated; use reversed(self) instead + See http://trac.sagemath.org/22642 for details. + [1, 1, 2] + """ + from sage.misc.superseded import deprecation + deprecation(22642, 'reversed() is deprecated; use reversed(self) instead') + return type(self)(self._parent, list=list(reversed(self._list))) + + def set_index(self, k, value): + """ + Return a sibling of ``self`` obtained by setting the + `k^{th}` entry of self to value. + + EXAMPLES:: + + sage: b = crystals.Tableaux(['A',2], shape=[3]).module_generators[0] + sage: list(b.set_index(0, 2)) + doctest:warning + ... + DeprecationWarning: set_index is deprecated; use _set_index instead + See http://trac.sagemath.org/22642 for details. + [2, 1, 1] + """ + from sage.misc.superseded import deprecation + deprecation(22642, 'set_index is deprecated; use _set_index instead') + return self._set_index(int(k), value) + + cpdef _set_index(self, k, value): + r""" + Return a sibling of ``self`` obtained by setting the + `k^{th}` entry of self to value. + + EXAMPLES:: + + sage: b = crystals.Tableaux(['A',2], shape=[3]).module_generators[0] + sage: list(b._set_index(0, 2)) + [2, 1, 1] + sage: list(b._set_index(1, 4)) + [1, 4, 1] + """ + cdef list l = list(self._list) # Make a (shallow) copy + l[k] = value + return type(self)(self._parent, list=l) + +############################################################################## +# Primary classes +############################################################################## + +cdef class TensorProductOfCrystalsElement(ImmutableListWithParent): + r""" + A class for elements of tensor products of crystals. + """ + def _repr_(self): + """ + Return a string representation of ``self``. + + EXAMPLES:: + + sage: C = crystals.Letters(['A',3]) + sage: T = crystals.TensorProduct(C,C) + sage: T(C(1),C(2)) + [1, 2] + """ + if self._parent.options.convention == "Kashiwara": + return repr(list(reversed(self._list))) + return repr(self._list) + + def _latex_(self): + r""" + Return latex code for ``self``. + + EXAMPLES:: + + sage: C = crystals.Letters(["A",2]) + sage: D = crystals.Tableaux(["A",2], shape=[2]) + sage: E = crystals.TensorProduct(C,D) + sage: latex(E.module_generators[0]) + 1 \otimes {\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}} + \raisebox{-.6ex}{$\begin{array}[b]{*{2}c}\cline{1-2} + \lr{1}&\lr{1}\\\cline{1-2} + \end{array}$} + } + """ + from sage.misc.latex import latex + if self._parent.options.convention == "Kashiwara": + return ' \otimes '.join(latex(c) for c in reversed(self)) + return ' \otimes '.join(latex(c) for c in self) + + def _ascii_art_(self): + """ + Return an ASCII art representation of ``self``. + + EXAMPLES:: + + sage: KT = crystals.TensorProductOfKirillovReshetikhinTableaux(['D',4,1],[[3,3],[2,1],[1,2]]) + sage: ascii_art(KT.module_generators[0]) + 1 1 1 + 2 2 2 # 1 # 1 1 + 3 3 3 2 + -4 -4 -4 + """ + if self._parent.options.convention == "Kashiwara": + lst = list(reversed(self)) + else: + lst = self + from sage.typeset.ascii_art import ascii_art, AsciiArt + s = ascii_art(lst[0]) + s._baseline = s._h // 2 + ret = s + for tableau in lst[1:]: + s = ascii_art(tableau) + s._baseline = s._h // 2 + ret += AsciiArt([" # "]) + s + return ret + + def _repr_diagram(self): + r""" + Return a string representation of ``self`` as a diagram. + + EXAMPLES:: + + sage: C = crystals.Tableaux(['A',3], shape=[3,1]) + sage: D = crystals.Tableaux(['A',3], shape=[1]) + sage: E = crystals.Tableaux(['A',3], shape=[2,2,2]) + sage: T = crystals.TensorProduct(C,D,E) + sage: print(T.module_generators[0]._repr_diagram()) + 1 1 1 (X) 1 (X) 1 1 + 2 2 2 + 3 3 + """ + pplist = [] + max_widths = [] + num_cols = len(self._list) + for c in self: + try: + pplist.append(c._repr_diagram().split('\n')) + except AttributeError: + pplist.append(c._repr_().split('\n')) + max_widths.append(max(map(len, pplist[-1]))) + num_rows = max(map(len, pplist)) + ret = "" + for i in range(num_rows): + if i > 0: + ret += '\n' + for j in range(num_cols): + if j > 0: + if i == 0: + ret += ' (X) ' + else: + ret += ' ' + if i < len(pplist[j]): + ret += pplist[j][i] + ret += ' '*(max_widths[j] - len(pplist[j][i])) + else: + ret += ' '*max_widths[j] + return ret + + def pp(self): + """ + Pretty print ``self``. + + EXAMPLES:: + + sage: C = crystals.Tableaux(['A',3], shape=[3,1]) + sage: D = crystals.Tableaux(['A',3], shape=[1]) + sage: E = crystals.Tableaux(['A',3], shape=[2,2,2]) + sage: T = crystals.TensorProduct(C,D,E) + sage: T.module_generators[0].pp() + 1 1 1 (X) 1 (X) 1 1 + 2 2 2 + 3 3 + """ + print(self._repr_diagram()) + + def weight(self): + r""" + Return the weight of ``self``. + + EXAMPLES:: + + sage: B = crystals.infinity.Tableaux("A3") + sage: T = crystals.TensorProduct(B,B) + sage: b1 = B.highest_weight_vector().f_string([2,1,3]) + sage: b2 = B.highest_weight_vector().f(1) + sage: t = T(b2, b1) + sage: t + [[[1, 1, 1, 2], [2, 2], [3]], [[1, 1, 1, 1, 2], [2, 2, 4], [3]]] + sage: t.weight() + (-2, 1, 0, 1) + + :: + + sage: C = crystals.Letters(['A',3]) + sage: T = crystals.TensorProduct(C,C) + sage: T(C(1),C(2)).weight() + (1, 1, 0, 0) + sage: T = crystals.Tableaux(['D',4],shape=[]) + sage: T.list()[0].weight() + (0, 0, 0, 0) + """ + WLR = self._parent.weight_lattice_realization() + return WLR(sum(elt.weight() for elt in self)) + + def epsilon(self, i): + r""" + Return `\varepsilon_i` of ``self``. + + INPUT: + + - ``i`` -- An element of the index set + + EXAMPLES:: + + sage: B = crystals.infinity.Tableaux("G2") + sage: T = crystals.TensorProduct(B,B) + sage: b1 = B.highest_weight_vector().f(2) + sage: b2 = B.highest_weight_vector().f_string([2,2,1]) + sage: t = T(b2, b1) + sage: [t.epsilon(i) for i in B.index_set()] + [0, 3] + """ + return max(self._sig(i, k) for k in range(1, len(self._list)+1)) + + def phi(self, i): + r""" + Return `\varphi_i` of ``self``. + + INPUT: + + - ``i`` -- An element of the index set + + EXAMPLES:: + + sage: La = RootSystem(['A',2,1]).weight_lattice(extended=True).fundamental_weights() + sage: B = crystals.GeneralizedYoungWalls(2,La[0]+La[1]) + sage: T = crystals.TensorProduct(B,B) + sage: b1 = B.highest_weight_vector().f_string([1,0]) + sage: b2 = B.highest_weight_vector().f_string([0,1]) + sage: t = T(b2, b1) + sage: [t.phi(i) for i in B.index_set()] + [1, 1, 4] + + TESTS: + + Check that :trac:`15462` is fixed:: + + sage: B = crystals.Tableaux(['A',2], shape=[2,1]) + sage: La = RootSystem(['A',2]).ambient_space().fundamental_weights() + sage: T = crystals.TensorProduct(crystals.elementary.T(['A',2], La[1]+La[2]), B) + sage: t = T.an_element() + sage: t.phi(1) + 2 + sage: t.phi(2) + 2 + """ + P = self._list[-1].parent().weight_lattice_realization() + h = P.simple_coroots() + omega = P(self.weight()).scalar(h[i]) + return max(omega + self._sig(i, k) for k in range(1, len(self._list)+1)) + + @cached_in_parent_method + def _sig(self, i, k): + r""" + Return `a_i(k)` of ``self``. + + The value `a_i(k)` of a crystal `b = b_N \otimes \cdots \otimes b_1` + is defined as: + + .. MATH:: + + a_i(k) = \varepsilon_i(b_k) - \sum_{j=1}^{k-1} \langle h_i, + \mathrm{wt}(b_j) \rangle + + where `\mathrm{wt}` is the :meth:`weight` of `b_j`. + + INPUT: + + - ``i`` -- An element of the index set + + - ``k`` -- The (1-based) index of the tensor factor of ``self`` + + EXAMPLES:: + + sage: B = crystals.infinity.GeneralizedYoungWalls(3) + sage: T = crystals.TensorProduct(B,B) + sage: b1 = B.highest_weight_vector().f_string([0,3,1]) + sage: b2 = B.highest_weight_vector().f_string([3,2,1,0,2,3]) + sage: t = T(b1, b2) + sage: [[t._sig(i,k) for k in range(1,len(t)+1)] for i in B.index_set()] + [[0, -1], [0, 0], [0, 1], [1, 2]] + + TESTS: + + Check that :trac:`18469` is fixed:: + + sage: E1 = crystals.elementary.B(['A',2], 1) + sage: E2 = crystals.elementary.B(['A',2], 2) + sage: T = crystals.TensorProduct(E1, E2) + sage: x = T(E1.module_generators[0], E2.module_generators[0]); x + [0, 0] + sage: [[x._sig(i,k) for k in range(1,3)] for i in T.index_set()] + [[-inf, 0], [0, -inf]] + sage: x.f(1) + [-1, 0] + sage: x.e(1) + [1, 0] + """ + if k == 1: + return self._list[-1].epsilon(i) + ep = self._list[-k].epsilon(i) + if ep == float("-inf"): + return ep + + P = self._list[-1].parent().weight_lattice_realization() + h = P.simple_coroots() + wt = P.sum(P(self._list[-j].weight()) for j in range(1, k)) + return ep - wt.scalar(h[i]) + + def e(self, i): + r""" + Return the action of `e_i` on ``self``. + + INPUT: + + - ``i`` -- An element of the index set + + EXAMPLES:: + + sage: B = crystals.infinity.Tableaux("D4") + sage: T = crystals.TensorProduct(B,B) + sage: b1 = B.highest_weight_vector().f_string([1,4,3]) + sage: b2 = B.highest_weight_vector().f_string([2,2,3,1,4]) + sage: t = T(b2, b1) + sage: t.e(1) + [[[1, 1, 1, 1, 1], [2, 2, 3, -3], [3]], [[1, 1, 1, 1, 2], [2, 2, 2], [3, -3]]] + sage: t.e(2) + sage: t.e(3) + [[[1, 1, 1, 1, 1, 2], [2, 2, 3, -4], [3]], [[1, 1, 1, 1, 2], [2, 2, 2], [3, -3]]] + sage: t.e(4) + [[[1, 1, 1, 1, 1, 2], [2, 2, 3, 4], [3]], [[1, 1, 1, 1, 2], [2, 2, 2], [3, -3]]] + """ + N = len(self._list) + 1 + for k in range(1, N): + if all(self._sig(i,k) > self._sig(i,j) for j in range(1, k)) and \ + all(self._sig(i,k) >= self._sig(i,j) for j in range(k+1, N)): + crystal = self._list[-k].e(i) + if crystal is None: + return None + return self._set_index(-k, crystal) + return None + + def f(self, i): + r""" + Return the action of `f_i` on ``self``. + + INPUT: + + - ``i`` -- An element of the index set + + EXAMPLES:: + + sage: La = RootSystem(['A',3,1]).weight_lattice(extended=True).fundamental_weights() + sage: B = crystals.GeneralizedYoungWalls(3,La[0]) + sage: T = crystals.TensorProduct(B,B,B) + sage: b1 = B.highest_weight_vector().f_string([0,3]) + sage: b2 = B.highest_weight_vector().f_string([0]) + sage: b3 = B.highest_weight_vector() + sage: t = T(b3, b2, b1) + sage: t.f(0) + [[[0]], [[0]], [[0, 3]]] + sage: t.f(1) + [[], [[0]], [[0, 3], [1]]] + sage: t.f(2) + [[], [[0]], [[0, 3, 2]]] + sage: t.f(3) + [[], [[0, 3]], [[0, 3]]] + """ + N = len(self._list) + 1 + for k in range(1, N): + if all(self._sig(i,k) >= self._sig(i,j) for j in range(1, k)) and \ + all(self._sig(i,k) > self._sig(i,j) for j in range(k+1, N)): + crystal = self._list[-k].f(i) + if crystal is None: + return None + return self._set_index(-k, crystal) + return None + +cdef class TensorProductOfRegularCrystalsElement(TensorProductOfCrystalsElement): + """ + Element class for a tensor product of regular crystals. + + TESTS:: + + sage: C = crystals.Letters(['A',2]) + sage: T = crystals.TensorProduct(C, C) + sage: elt = T(C(1), C(2)) + sage: from sage.combinat.crystals.tensor_product import TensorProductOfRegularCrystalsElement + sage: isinstance(elt, TensorProductOfRegularCrystalsElement) + True + """ + def e(self, i): + """ + Return the action of `e_i` on ``self``. + + EXAMPLES:: + + sage: C = crystals.Letters(['A',5]) + sage: T = crystals.TensorProduct(C,C) + sage: T(C(1),C(2)).e(1) == T(C(1),C(1)) + True + sage: T(C(2),C(1)).e(1) is None + True + sage: T(C(2),C(2)).e(1) == T(C(1),C(2)) + True + """ + if i not in self.index_set(): + raise ValueError("i must be in the index set") + k = self.position_of_first_unmatched_plus(i) + if k is None: + return None + return self._set_index(k, self._list[k].e(i)) + + def f(self, i): + """ + Return the action of `f_i` on ``self``. + + EXAMPLES:: + + sage: C = crystals.Letters(['A',5]) + sage: T = crystals.TensorProduct(C,C) + sage: T(C(1),C(1)).f(1) + [1, 2] + sage: T(C(1),C(2)).f(1) + [2, 2] + sage: T(C(2),C(1)).f(1) is None + True + """ + if i not in self.index_set(): + raise ValueError("i must be in the index set") + k = self.position_of_last_unmatched_minus(i) + if k is None: + return None + return self._set_index(k, self._list[k].f(i)) + + def phi(self, i): + r""" + Return `\varphi_i` of ``self``. + + EXAMPLES:: + + sage: C = crystals.Letters(['A',5]) + sage: T = crystals.TensorProduct(C,C) + sage: T(C(1),C(1)).phi(1) + 2 + sage: T(C(1),C(2)).phi(1) + 1 + sage: T(C(2),C(1)).phi(1) + 0 + """ + height = 0 + for elt in reversed(self._list): + plus = elt.epsilon(i) + minus = elt.phi(i) + if height - plus < 0: + height = minus + else: + height = height - plus + minus + return height + + def epsilon(self, i): + r""" + Return `\varepsilon_i` of ``self``. + + EXAMPLES:: + + sage: C = crystals.Letters(['A',5]) + sage: T = crystals.TensorProduct(C,C) + sage: T(C(1),C(1)).epsilon(1) + 0 + sage: T(C(1),C(2)).epsilon(1) + 1 + sage: T(C(2),C(1)).epsilon(1) + 0 + """ + height = 0 + for elt in self: + minus = elt.phi(i) + plus = elt.epsilon(i) + if height - minus < 0: + height = plus + else: + height = height - minus + plus + return height + + cpdef position_of_last_unmatched_minus(self, i): + """ + Return the position of the last unmatched `-` or ``None`` if + there is no unmatched `-`. + + EXAMPLES:: + + sage: C = crystals.Letters(['A',5]) + sage: T = crystals.TensorProduct(C,C) + sage: T(C(2),C(1)).position_of_last_unmatched_minus(1) + sage: T(C(1),C(2)).position_of_last_unmatched_minus(1) + 0 + """ + unmatched_minus = None + height = 0 + cdef int j + for j,elt in enumerate(self): + plus = elt.epsilon(i) + minus = elt.phi(i) + if height - minus < 0: + unmatched_minus = j + height = plus + else: + height = height - minus + plus + return unmatched_minus + + cpdef position_of_first_unmatched_plus(self, i): + """ + Return the position of the first unmatched `+` or ``None`` if + there is no unmatched `+`. + + EXAMPLES:: + + sage: C = crystals.Letters(['A',5]) + sage: T = crystals.TensorProduct(C,C) + sage: T(C(2),C(1)).position_of_first_unmatched_plus(1) + sage: T(C(1),C(2)).position_of_first_unmatched_plus(1) + 1 + """ + unmatched_plus = None + height = 0 + cdef int N = len(self._list) - 1 + cdef int j + for j, elt in enumerate(reversed(self._list)): + plus = elt.epsilon(i) + minus = elt.phi(i) + if height - plus < 0: + unmatched_plus = N - j + height = minus + else: + height = height - plus + minus + return unmatched_plus + + # Legacy function + def positions_of_unmatched_minus(self, i, dual=False, reverse=False): + """ + EXAMPLES:: + + sage: C = crystals.Letters(['A',5]) + sage: T = crystals.TensorProduct(C,C) + sage: T(C(2),C(1)).positions_of_unmatched_minus(1) + [] + sage: T(C(1),C(2)).positions_of_unmatched_minus(1) + [0] + """ + cdef list unmatched_plus = [] + cdef int j + height = 0 + if reverse: + self = type(self)(self._parent, list(reversed(self._list))) + if not dual: + for j,elt in enumerate(self): + minus = elt.phi(i) + plus = elt.epsilon(i) + if height-minus < 0: + unmatched_plus.append(j) + height = plus + else: + height = height - minus + plus + else: + for j,elt in enumerate(self): + plus = elt.epsilon(i) + minus = elt.phi(i) + if height-plus < 0: + unmatched_plus.append(j) + height = minus + else: + height = height - plus + minus + return unmatched_plus + + # Legacy function + def positions_of_unmatched_plus(self, i): + """ + EXAMPLES:: + + sage: C = crystals.Letters(['A',5]) + sage: T = crystals.TensorProduct(C,C) + sage: T(C(2),C(1)).positions_of_unmatched_plus(1) + [] + sage: T(C(1),C(2)).positions_of_unmatched_plus(1) + [1] + """ + cdef list L = self.positions_of_unmatched_minus(i, dual=True, reverse=True) + L.reverse() + cdef int N = len(self._list) - 1 + return [N - val for val in L] + + def energy_function(self, algorithm=None): + r""" + Return the energy function of ``self``. + + ALGORITHM: + + .. RUBRIC:: definition + + Let `T` be a tensor product of Kirillov-Reshetikhin + crystals. Let `R_i` and `H_i` be the combinatorial + `R`-matrix and local energy functions, respectively, acting + on the `i` and `i+1` factors. Let `D_B` be the energy + function of a single Kirillov-Reshetikhin crystal. The + *energy function* is given by + + .. MATH:: + + D = \sum_{j > i} H_i R_{i+1} R_{i+2} \cdots R_{j-1} + + \sum_j D_B R_1 R_2 \cdots R_{j-1}, + + where `D_B` acts on the rightmost factor. + + .. RUBRIC:: grading + + If ``self`` is an element of `T`, a tensor product of + perfect crystals of the same level, then use the affine + grading to determine the energy. Specifically, let `g` + denote the affine grading of ``self`` and `d` the affine + grading of the maximal vector in `T`. Then the energy + of ``self`` is given by `d - g`. + + For more details, see Theorem 7.5 in [SchillingTingley2011]_. + + INPUT: + + - ``algorithm`` -- (default: ``None``) use one of the + following algorithms to determine the energy function: + + * ``'definition'`` - use the definition of the energy + function; + * ``'grading'`` - use the affine grading; + + if not specified, then this uses ``'grading'`` if all + factors are perfect of the same level and otherwise + this uses ``'definition'`` + + OUTPUT: an integer + + REFERENCES: + + .. [SchillingTingley2011] \A. Schilling, P. Tingley. + *Demazure crystals, Kirillov-Reshetikhin crystals, and + the energy function*. + Electronic Journal of Combinatorics. **19(2)**. 2012. + :arXiv:`1104.2359` + + EXAMPLES:: + + sage: K = crystals.KirillovReshetikhin(['A',2,1], 1, 1) + sage: T = crystals.TensorProduct(K,K,K) + sage: hw = sorted([x for x in T if x.is_highest_weight([1,2])]) + sage: for b in hw: + ....: print("{} {}".format(b, b.energy_function())) + [[[1]], [[1]], [[1]]] 0 + [[[1]], [[2]], [[1]]] 2 + [[[2]], [[1]], [[1]]] 1 + [[[3]], [[2]], [[1]]] 3 + + sage: K = crystals.KirillovReshetikhin(['C',2,1], 1, 2) + sage: T = crystals.TensorProduct(K,K) + sage: hw = [x for x in T if x.is_highest_weight([1,2])] + sage: for b in hw: + ....: print("{} {}".format(b, b.energy_function())) + [[], []] 4 + [[], [[1, 1]]] 1 + [[[1, 1]], []] 3 + [[[1, 1]], [[1, 1]]] 0 + [[[1, 2]], [[1, 1]]] 1 + [[[2, 2]], [[1, 1]]] 2 + [[[-1, -1]], [[1, 1]]] 2 + [[[1, -1]], [[1, 1]]] 2 + [[[2, -1]], [[1, 1]]] 2 + + sage: K = crystals.KirillovReshetikhin(['C',2,1], 1, 1) + sage: T = crystals.TensorProduct(K) + sage: t = T.module_generators[0] + sage: t.energy_function('grading') + Traceback (most recent call last): + ... + NotImplementedError: all crystals in the tensor product need to be perfect of the same level + + TESTS:: + + sage: K = crystals.KirillovReshetikhin(['C',2,1], 1, 2) + sage: K2 = crystals.KirillovReshetikhin(['C',2,1], 2, 2) + sage: T = tensor([K, K2]) + sage: hw = [x for x in T if x.is_highest_weight([1,2])] + sage: all(b.energy_function() == b.energy_function(algorithm='definition') + ....: for b in hw) + True + """ + C = self._parent.crystals[0] + ell = ceil(C.s() / C.cartan_type().c()[C.r()]) + is_perfect = all(ell == K.s() / K.cartan_type().c()[K.r()] + for K in self._parent.crystals) + if algorithm is None: + if is_perfect: + algorithm = 'grading' + else: + algorithm = 'definition' + + if algorithm == 'grading': + if not is_perfect: + raise NotImplementedError("all crystals in the tensor product need to be perfect of the same level") + t = self._parent(*[K.module_generator() for K in self._parent.crystals]) + d = t.affine_grading() + return d - self.affine_grading() + + if algorithm == 'definition': + # Setup + energy = ZZ.zero() + R_mats = [[K.R_matrix(Kp) for Kp in self._parent.crystals[i+1:]] + for i,K in enumerate(self._parent.crystals)] + H_funcs = [[K.local_energy_function(Kp) for Kp in self._parent.crystals[i+1:]] + for i,K in enumerate(self._parent.crystals)] + + for i,b in enumerate(self): + for j,R in enumerate(R_mats[i]): + H = H_funcs[i][j] + bp = self._list[i+j+1] + T = R.domain() + t = T(b, bp) + energy += H(t) + b = R(t)[1] + energy += b.energy_function() # D contribution + return energy + else: + raise ValueError("invalid algorithm") + + def affine_grading(self): + r""" + Returns the affine grading of ``self``. + + The affine grading is only defined when ``self`` is an element of a + tensor product of affine Kirillov-Reshetikhin crystals. It is + calculated by finding a path from ``self`` to a ground state path + using the helper method :meth:`e_string_to_ground_state` and counting + the number of affine Kashiwara operators `e_0` applied on the way. + + INPUT: + + - ``self`` -- an element of a tensor product of Kirillov-Reshetikhin + crystals + + OUTPUT: an integer + + EXAMPLES:: + + sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) + sage: T = crystals.TensorProduct(K,K) + sage: t = T.module_generators[0] + sage: t.affine_grading() + 1 + + sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) + sage: T = crystals.TensorProduct(K,K,K) + sage: hw = [b for b in T if all(b.epsilon(i)==0 for i in [1,2])] + sage: for b in hw: + ....: print("{} {}".format(b, b.affine_grading())) + [[[1]], [[1]], [[1]]] 3 + [[[1]], [[2]], [[1]]] 1 + [[[2]], [[1]], [[1]]] 2 + [[[3]], [[2]], [[1]]] 0 + + sage: K = crystals.KirillovReshetikhin(['C',2,1],1,1) + sage: T = crystals.TensorProduct(K,K,K) + sage: hw = [b for b in T if all(b.epsilon(i)==0 for i in [1,2])] + sage: for b in hw: + ....: print("{} {}".format(b, b.affine_grading())) + [[[1]], [[1]], [[1]]] 2 + [[[1]], [[2]], [[1]]] 1 + [[[1]], [[-1]], [[1]]] 0 + [[[2]], [[1]], [[1]]] 1 + [[[-2]], [[2]], [[1]]] 0 + [[[-1]], [[1]], [[1]]] 1 + """ + return self.e_string_to_ground_state().count(0) + + @cached_method + def e_string_to_ground_state(self): + r""" + Returns a string of integers in the index set `(i_1,\ldots,i_k)` such + that `e_{i_k} \cdots e_{i_1}` of ``self`` is the ground state. + + This method is only defined when ``self`` is an element of a tensor + product of affine Kirillov-Reshetikhin crystals. It calculates a path + from ``self`` to a ground state path using Demazure arrows as defined + in Lemma 7.3 in [SchillingTingley2011]_. + + INPUT: + + - ``self`` -- an element of a tensor product of Kirillov-Reshetikhin + crystals + + OUTPUT: a tuple of integers `(i_1,\ldots,i_k)` + + EXAMPLES:: + + sage: K = crystals.KirillovReshetikhin(['A',2,1],1,1) + sage: T = crystals.TensorProduct(K,K) + sage: t = T.module_generators[0] + sage: t.e_string_to_ground_state() + (0, 2) + + sage: K = crystals.KirillovReshetikhin(['C',2,1],1,1) + sage: T = crystals.TensorProduct(K,K) + sage: t = T.module_generators[0]; t + [[[1]], [[1]]] + sage: t.e_string_to_ground_state() + (0,) + sage: x=t.e(0) + sage: x.e_string_to_ground_state() + () + sage: y=t.f_string([1,2,1,1,0]); y + [[[2]], [[1]]] + sage: y.e_string_to_ground_state() + () + """ + from sage.combinat.rigged_configurations.kr_tableaux import KirillovReshetikhinTableaux + if self._parent.crystals[0].__module__ != 'sage.combinat.crystals.kirillov_reshetikhin' and \ + not isinstance(self._parent.crystals[0], KirillovReshetikhinTableaux): + raise ValueError("all crystals in the tensor product need to be Kirillov-Reshetikhin crystals") + I = self.cartan_type().classical().index_set() + ell = max(ceil(K.s() / K.cartan_type().c()[K.r()]) for K in self._parent.crystals) + for i in I: + if self.epsilon(i) > 0: + return (i,) + (self.e(i)).e_string_to_ground_state() + if self.epsilon(0) > ell: + return (0,) + (self.e(0)).e_string_to_ground_state() + return () + + +cdef class CrystalOfTableauxElement(TensorProductOfRegularCrystalsElement): + """ + Element in a crystal of tableaux. + """ + def __init__(self, parent, *args, **options): + """ + There are several ways to input tableaux, by rows, by columns, + as the list of column elements, or as a sequence of numbers + in column reading. + + EXAMPLES:: + + sage: T = crystals.Tableaux(['A',3], shape = [2,2]) + sage: t = T(rows=[[1,2],[3,4]]) + sage: t + [[1, 2], [3, 4]] + sage: TestSuite(t).run() + + sage: t = T(columns=[[3,1],[4,2]]) + sage: t + [[1, 2], [3, 4]] + sage: TestSuite(t).run() + + sage: t = T(list=[3,1,4,2]) + sage: t + [[1, 2], [3, 4]] + + sage: t = T(3,1,4,2) + sage: t + [[1, 2], [3, 4]] + + Currently inputting the empty tableau as an empty sequence is + broken due to a bug in the generic __call__ method (see :trac:`8648`). + + EXAMPLES:: + + sage: T = crystals.Tableaux(['A',3], shape=[]) + sage: t = T() + sage: list(t) + [0] + + TESTS: + + Integer types that are not a Sage ``Integer`` (such as a Python ``int`` + and typically arise from compiled code) were not converted into a + letter. This caused certain functions to fail. This is fixed in + :trac:`13204`:: + + sage: T = crystals.Tableaux(['A',3], shape = [2,2]) + sage: t = T(list=[int(3),1,4,2]) + sage: type(t[0]) + + sage: t = T(list=[3,int(1),4,2]) + sage: type(t[1]) + + sage: C = crystals.KirillovReshetikhin(['A',int(3),1], 1,1) + sage: C[0].e(0) + [[4]] + """ + if len(args) == 1: + if isinstance(args[0], Tableau): + options['rows'] = args[0] + if 'list' in options: + the_list = options['list'] + elif 'rows' in options: + rows = options['rows'] +# the_list=Tableau(rows).to_word_by_column() + rows = Tableau(rows).conjugate() + the_list = [] + for col in rows: + the_list += reversed(col) + elif 'columns' in options: + columns = options['columns'] + the_list = [] + for col in columns: + the_list += col + else: + the_list = [i for i in args] + TensorProductOfRegularCrystalsElement.__init__(self, parent, [parent.letters(_) for _ in the_list]) + + def _repr_(self): + """ + EXAMPLES:: + + sage: T = crystals.Tableaux(['A',3], shape = [2,2]) + sage: t = T(rows=[[1,2],[3,4]]) + sage: t._repr_() + '[[1, 2], [3, 4]]' + """ + return repr(self.to_tableau()) + + def _repr_diagram(self): + """ + Return a string representation of ``self`` as a diagram. + + EXAMPLES:: + + sage: C = crystals.Tableaux(['A', 4], shape=[4,2,1]) + sage: elt = C(rows=[[1,1,1,2], [2,3], [4]]) + sage: print(elt._repr_diagram()) + 1 1 1 2 + 2 3 + 4 + """ + return self.to_tableau()._repr_diagram() + + def pp(self): + """ + EXAMPLES:: + + sage: T = crystals.Tableaux(['A',3], shape = [2,2]) + sage: t = T(rows=[[1,2],[3,4]]) + sage: t.pp() + 1 2 + 3 4 + """ + return self.to_tableau().pp() + + def _ascii_art_(self): + """ + Return an ascii art version of ``self``. + + EXAMPLES: + + We check that :trac:`16486` is fixed:: + + sage: T = crystals.Tableaux(['B',6], shape=[1]*5) + sage: ascii_art(T.module_generators[0]) + 1 + 2 + 3 + 4 + 5 + sage: T = crystals.Tableaux(['D',4], shape=[2,1]) + sage: t = T.module_generators[0].f_string([1,2,3,4,2,2,3,4]) + sage: ascii_art(t) + 1 -2 + -3 + """ + return self.to_tableau()._ascii_art_() + + def _latex_(self): + r""" + EXAMPLES:: + + sage: T = crystals.Tableaux(['A',3], shape = [4,2]) + sage: t = T(rows=[[1,1,2,3],[2,3]]) + sage: latex(t) # indirect doctest + {\def\lr#1{\multicolumn{1}{|@{\hspace{.6ex}}c@{\hspace{.6ex}}|}{\raisebox{-.3ex}{$#1$}}} + \raisebox{-.6ex}{$\begin{array}[b]{*{4}c}\cline{1-4} + \lr{1}&\lr{1}&\lr{2}&\lr{3}\\\cline{1-4} + \lr{2}&\lr{3}\\\cline{1-2} + \end{array}$} + } + """ + from sage.combinat.output import tex_from_array + # Modified version of to_tableau() to have the entries be letters + # rather than their values + if not self._list: + return "{\\emptyset}" + + tab = [ [self[0]] ] + for i in range(1,len(self)): + if self[i-1] < self[i] or (self[i-1].value != 0 and self[i-1] == self[i]): + tab.append([self[i]]) + else: + l = len(tab)-1 + tab[l].append(self[i]) + for x in tab: + x.reverse() + T = Tableau(tab).conjugate() + return tex_from_array([[letter._latex_() for letter in row] for row in T]) + + @cached_method + def to_tableau(self): + """ + Returns the Tableau object corresponding to self. + + EXAMPLES:: + + sage: T = crystals.Tableaux(['A',3], shape = [2,2]) + sage: t = T(rows=[[1,2],[3,4]]).to_tableau(); t + [[1, 2], [3, 4]] + sage: type(t) + + sage: type(t[0][0]) + <... 'int'> + sage: T = crystals.Tableaux(['D',3], shape = [1,1]) + sage: t=T(rows=[[-3],[3]]).to_tableau(); t + [[-3], [3]] + sage: t=T(rows=[[3],[-3]]).to_tableau(); t + [[3], [-3]] + sage: T = crystals.Tableaux(['B',2], shape = [1,1]) + sage: t = T(rows=[[0],[0]]).to_tableau(); t + [[0], [0]] + """ + if not self._list: + return Tableau([]) + cdef list lst = self._list + cdef list tab = [ [lst[0].value] ] + cdef int i + for i in range(1,len(self)): + if lst[i-1] < lst[i] or (lst[i-1].value != 0 and lst[i-1] == lst[i]): + tab.append([lst[i].value]) + else: + tab[len(tab)-1].append(lst[i].value) + for x in tab: + x.reverse() + return Tableau(tab).conjugate() + + def promotion(self): + """ + Promotion for type A crystals of tableaux of rectangular shape. + + Returns the result of applying promotion on this tableau. + + This method only makes sense in type A with rectangular shapes. + + EXAMPLES:: + + sage: C = crystals.Tableaux(["A",3], shape = [3,3,3]) + sage: t = C(Tableau([[1,1,1],[2,2,3],[3,4,4]])) + sage: t + [[1, 1, 1], [2, 2, 3], [3, 4, 4]] + sage: t.promotion() + [[1, 1, 2], [2, 2, 3], [3, 4, 4]] + sage: t.promotion().parent() + The crystal of tableaux of type ['A', 3] and shape(s) [[3, 3, 3]] + """ + crystal = self._parent + cartan_type = crystal.cartan_type() + assert cartan_type.type() == 'A' + return crystal(self.to_tableau().promotion(cartan_type.rank())) + + def promotion_inverse(self): + """ + Inverse promotion for type A crystals of tableaux of rectangular shape. + + Returns the result of applying inverse promotion on this tableau. + + This method only makes sense in type A with rectangular shapes. + + EXAMPLES:: + + sage: C = crystals.Tableaux(["A",3], shape = [3,3,3]) + sage: t = C(Tableau([[1,1,1],[2,2,3],[3,4,4]])) + sage: t + [[1, 1, 1], [2, 2, 3], [3, 4, 4]] + sage: t.promotion_inverse() + [[1, 1, 2], [2, 3, 3], [4, 4, 4]] + sage: t.promotion_inverse().parent() + The crystal of tableaux of type ['A', 3] and shape(s) [[3, 3, 3]] + """ + crystal = self._parent + cartan_type = crystal.cartan_type() + assert cartan_type.type() == 'A' + return crystal(self.to_tableau().promotion_inverse(cartan_type.rank())) + +cdef class InfinityCrystalOfTableauxElement(CrystalOfTableauxElement): + def e(self,i): + r""" + Return the action of `\widetilde{e}_i` on ``self``. + + INPUT: + + - ``i`` -- An element of the index set + + EXAMPLES:: + + sage: B = crystals.infinity.Tableaux(['B',3]) + sage: b = B(rows=[[1,1,1,1,1,1,1,2,0,-3,-1,-1,-1,-1],[2,2,2,2,-2,-2],[3,-3,-3]]) + sage: b.e(3).pp() + 1 1 1 1 1 1 1 2 0 -3 -1 -1 -1 -1 + 2 2 2 2 -2 -2 + 3 0 -3 + sage: b.e(1).pp() + 1 1 1 1 1 1 1 0 -3 -1 -1 -1 -1 + 2 2 2 2 -2 -2 + 3 -3 -3 + """ + if i not in self.index_set(): + raise ValueError('i is not in the index set') + k = self.position_of_first_unmatched_plus(i) + if k is None: + return None + cdef InfinityCrystalOfTableauxElement ret + ret = (self._set_index(k, self._list[k].e(i))) + if k+i > len(self._list): + return ret + for j in reversed(range(1, i+1)): + if ret._list[k+i-j].value != j: + return ret + # We've found a column, so we need to remove it + for j in range(i): + ret._list.pop(k) + return ret + + def f(self, i): + r""" + Return the action of `\widetilde{f}_i` on ``self``. + + INPUT: + + - ``i`` -- An element of the index set + + EXAMPLES:: + + sage: B = crystals.infinity.Tableaux(['C',4]) + sage: b = B.highest_weight_vector() + sage: b.f(1).pp() + 1 1 1 1 2 + 2 2 2 + 3 3 + 4 + sage: b.f(3).pp() + 1 1 1 1 1 + 2 2 2 2 + 3 3 4 + 4 + sage: b.f(3).f(4).pp() + 1 1 1 1 1 + 2 2 2 2 + 3 3 -4 + 4 + """ + if i not in self.index_set(): + raise ValueError('i is not in the index set') + k = self.position_of_last_unmatched_minus(i) + if k is None: + return None + cdef InfinityCrystalOfTableauxElement ret + ret = (self._set_index(k, self._list[k].f(i))) + if k+i > len(self._list): + return ret + for j in reversed(range(1,i+1)): + if self._list[k+i-j].value != j: + return ret + # We've found a full column, so we'll need to add a new column + for j in range(i): + ret._list.insert(k, self._parent.letters(j+1)) + return ret + +cdef class InfinityCrystalOfTableauxElementTypeD(InfinityCrystalOfTableauxElement): + def e(self, i): + r""" + Return the action of `\widetilde{e}_i` on ``self``. + + INPUT: + + - ``i`` -- An element of the index set + + EXAMPLES:: + + sage: B = crystals.infinity.Tableaux(['D',4]) + sage: b = B.highest_weight_vector().f_string([1,4,3,1,2]); b.pp() + 1 1 1 1 2 3 + 2 2 2 + 3 -3 + sage: b.e(2).pp() + 1 1 1 1 2 2 + 2 2 2 + 3 -3 + """ + if i not in self.index_set(): + raise ValueError('i is not in the index set') + k = self.position_of_first_unmatched_plus(i) + if k is None: + return None + cdef InfinityCrystalOfTableauxElementTypeD ret + ret = (self._set_index(k, self._list[k].e(i))) + if i == self.cartan_type().rank(): + i -= 1 + if k+i > len(self._list): + return ret + for j in reversed(range(1, i+1)): + if ret._list[k+i-j].value != j: + return ret + # We've found a column, so we need to remove it + for j in range(i): + ret._list.pop(k) + return ret + + def f(self, i): + r""" + Return the action of `\widetilde{f}_i` on ``self``. + + INPUT: + + - ``i`` -- An element of the index set + + EXAMPLES:: + + sage: B = crystals.infinity.Tableaux(['D',5]) + sage: b = B.highest_weight_vector().f_string([1,4,3,1,5]); b.pp() + 1 1 1 1 1 1 2 2 + 2 2 2 2 2 + 3 3 3 -5 + 4 5 + sage: b.f(1).pp() + 1 1 1 1 1 1 2 2 2 + 2 2 2 2 2 + 3 3 3 -5 + 4 5 + sage: b.f(5).pp() + 1 1 1 1 1 1 2 2 + 2 2 2 2 2 + 3 3 3 -5 + 4 -4 + """ + cdef InfinityCrystalOfTableauxElementTypeD ret + ret = (InfinityCrystalOfTableauxElement.f(self, i)) + if ret._list[0].value == -self._parent.cartan_type().rank(): + # Exceptional case for f_n where we need to add a new column + for j in range(i-1): + ret._list.insert(0, self._parent.letters(j+1)) + return ret + diff --git a/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py b/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py index 5b4ac01976a..ec300a227c5 100644 --- a/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py +++ b/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py @@ -330,9 +330,9 @@ def __iter__(self): sage: KRT = crystals.TensorProductOfKirillovReshetikhinTableaux(['A', 3, 1], [[2,1], [1,1]]) sage: g = KRT.__iter__() sage: next(g) - [[2], [3]] (X) [[1]] + [[1], [2]] (X) [[1]] sage: next(g) - [[2], [4]] (X) [[1]] + [[1], [2]] (X) [[2]] """ index_set = self._cartan_type.classical().index_set() from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet From dd578067b6b53ec399cb8f903c119716e0165260 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sun, 19 Mar 2017 03:00:36 -0500 Subject: [PATCH 111/452] Use _richcmp_ instead of __eq__/__ne__. --- src/sage/homology/hochschild_complex.py | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/src/sage/homology/hochschild_complex.py b/src/sage/homology/hochschild_complex.py index 99500b98aec..cbbe859b392 100644 --- a/src/sage/homology/hochschild_complex.py +++ b/src/sage/homology/hochschild_complex.py @@ -16,6 +16,7 @@ from sage.structure.unique_representation import UniqueRepresentation from sage.structure.parent import Parent from sage.structure.element import ModuleElement +from sage.structure.sage_object import richcmp from sage.categories.category_types import ChainComplexes from sage.categories.tensor import tensor from sage.combinat.free_module import CombinatorialFreeModule @@ -676,9 +677,9 @@ def _lmul_(self, scalar): vectors[d] = vec return self.__class__(self.parent(), vectors) - def __eq__(self, other): + def _richcmp_(self, other, op): """ - Return ``True`` if ``self`` is equal to ``other``. + Rich comparison of ``self`` to ``other``. EXAMPLES:: @@ -693,22 +694,7 @@ def __eq__(self, other): True sage: a == H.zero() False - """ - return (type(self) == type(other) - and self.parent() is other.parent() - and self._vec == other._vec) - - def __ne__(self, other): - """ - Return ``True`` if ``self`` is not equal to ``other``. - - EXAMPLES:: - sage: F. = FreeAlgebra(ZZ) - sage: H = F.hochschild_complex(F) - sage: a = H({0: x - y, - ....: 1: H.free_module(1).basis().an_element(), - ....: 2: H.free_module(2).basis().an_element()}) sage: a != 3*a True sage: a + a != 2*a @@ -716,5 +702,5 @@ def __ne__(self, other): sage: a != H.zero() True """ - return not self == other + return richcmp(self._vec, other._vec, op) From 70735593e6a41dd11a0fbff0d7eabc6d110ebfa8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jori=20M=C3=A4ntysalo?= Date: Thu, 23 Mar 2017 11:28:13 +0200 Subject: [PATCH 112/452] Add irreducibles_poset(). --- src/sage/categories/finite_lattice_posets.py | 40 ++++++++++++++++++++ src/sage/combinat/posets/posets.py | 4 ++ 2 files changed, 44 insertions(+) diff --git a/src/sage/categories/finite_lattice_posets.py b/src/sage/categories/finite_lattice_posets.py index a70997e6eca..681cd0ab169 100644 --- a/src/sage/categories/finite_lattice_posets.py +++ b/src/sage/categories/finite_lattice_posets.py @@ -119,6 +119,46 @@ def meet_irreducibles_poset(self): """ return self.subposet(self.meet_irreducibles()) + def irreducibles_poset(self): + """ + Return the poset of meet- or join-irreducibles of the lattice. + + A *join-irreducible* element of a lattice is an element with + exactly one lower cover. Dually a *meet-irreducible* element + has exactly one upper cover. + + This is the smallest poset with completion by cuts being + isomorphic to the lattice. (Due to implementation detail + in Sage, actually isomorphic to the dual of the lattice.) + As a special case this returns one-element poset from one-element + lattice. + + .. SEEALSO:: + + :meth:`~sage.combinat.posets.posets.FinitePoset.completion_by_cuts`. + + EXAMPLES:: + + sage: L = LatticePoset({1: [2, 3, 4], 2: [5, 6], 3: [5], + ....: 4: [6], 5: [9, 7], 6: [9, 8], 7: [10], + ....: 8: [10], 9: [10], 10: [11]}) + sage: L_ = L.irreducibles_poset() + sage: sorted(L_) + [2, 3, 4, 7, 8, 9, 10, 11] + sage: L_.completion_by_cuts().is_isomorphic(L.dual()) + True + + TESTS:: + + sage: LatticePoset().irreducibles_poset() + Finite poset containing 0 elements + sage: Posets.ChainPoset(1).irreducibles_poset() + Finite poset containing 1 elements + """ + if self.cardinality() == 1: + from sage.combinat.posets.posets import Poset + return Poset({self[0]: []}) + return self.subposet(self.join_irreducibles()+self.meet_irreducibles()) ########################################################################## # Lattice morphisms diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index dc39754282e..515eef92db1 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -6856,6 +6856,10 @@ def completion_by_cuts(self): - a finite lattice + .. SEEALSO:: + + :meth:`~sage.categories.finite_lattice_posets.FiniteLatticePosets.ParentMethods.irreducibles_poset` + EXAMPLES:: sage: P = Posets.PentagonPoset() From 1d4aa1c1ae110e7318dca183c7ed8be0dbf0ba32 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sat, 25 Mar 2017 11:53:13 -0500 Subject: [PATCH 113/452] Fixing unpickling issues. --- src/sage/combinat/free_module.py | 44 ++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/free_module.py b/src/sage/combinat/free_module.py index 23183127f77..5beb1f9f603 100644 --- a/src/sage/combinat/free_module.py +++ b/src/sage/combinat/free_module.py @@ -286,9 +286,44 @@ def __classcall_private__(cls, base_ring, basis_keys, category = None, prefix="B return super(CombinatorialFreeModule, cls).__classcall__(cls, base_ring, basis_keys, category = category, prefix=prefix, **keywords) # We make this explicitly a Python class so that the methods, - # specifically _mul_, from category framework still works -- TCS + # specifically _mul_, from category framework still works. -- TCS + # We also need to deal with the old pickles too. -- TCS class Element(IndexedFreeModuleElement): - pass + def __setstate__(self, state): + r""" + For unpickling. + + EXAMPLES:: + + sage: loads('x\x9c\x95R\xcbn\x131\x14\xd5\x00\r\x89KK\xcb\xa3' + ....: '\xbc\xa1\xbc\xd3\xcd,\xe0\x0f\n\xad\xc4\xa2Y\x0c\xb2XZ' + ....: '\x8e\xe7N\xe6\x8a\xb1\xa7\xd7\x0f\x91,F\x82E&\xe2\xafq3' + ....: '\x13\xa4"X\xb0\xb1}\xae}\xce=\xf7\xc8\xdf\xaf(\'g\x90:o' + ....: '\x83\xf2\xc1B\x9a/\x8c\xd4\xa8\x84\xaa\xa4s\xec2\xa2d' + ....: '\xcc\xdf\x7f\xa8\xf5\x14\x8d\xf4\xb5EY\x9dZ\x80\xb3:' + ....: '\x0f\x15\x88o\xe8K\xa1\xa4\x87Ym\x17)T\xa0\xc1\xf8\x8eH}' + ....: '\x17\xd5S\xd3"\xd2\x84^\xf3\xd8?\xf4N:\x01FW\x95\x10\xd3' + ....: '\x80\x95G#\x04\x9b\x81\x97\xde[F\xd7:I\x8dN\xad\x17\xa6dU' + ....: '\t\r\xbe\xacsF[\xe5\xd6\x9f\x83\x05\x83\x14@X8\xb7\xe0' + ....: '\xa2\xb2\xf4X\x1b\x16\x8c\x85<(`4\xe8=v\x13 \xb8\xb43' + ....: '\xe8\xd8Y\xbf\xd3\xf5\xee\x89E3s)\x9a\xf8\x10\xac\xb8@' + ....: '\xecS\x07\xb2\x8b3\r\x8f2\x1a-\x1bb|\x98\xa3;\x97^\x95' + ....: '\xb4\xfd\xd3\xad\xe8FF;|\xbbKJ\xce\xb1\xd6\xb4\xcbG_":' + ....: '\x96\x0e\x1d\xdd\\e\xb4W\xee\xf2\xfdS4\xe8\xe1#\xc6\x00' + ....: '\\4)+\xda\x8fW\xb7\xf8\xce\xe5To\xb7\x19\xddi\xe9\xeed2' + ....: '\xf1\x19\x1d\x1c\xfd\xa0{\xe5\xe0\xff\x93ft\xbf\x1cm\x88' + ....: '\x0e\xbcK\x8bu\x7f\x01&h\xb01\x8f\\\xc42\xeb\\\x9d\xfc.~' + ....: '\x8e5z\xc0\x939O\x16-=\\6+z\x94\xd1\xe3\xb6\xa1\'c>\xdc' + ....: '\xfc\x04zZ\xee\xf1A\xcc\xbc\xc09=\xe3\xc9qX\xd1aF\xcf' + ....: '\x1bz\xc1\x0f\xa23S\xeb\xe8F\xa8\x1a\x8a\x02\x15\xc6\xe9' + ....: '\x1c\xbdl\xe8\xd58\xaa\xfe%n\xa6\xe5W\x10\x1b@\xafy\xf2n' + ....: '\x99\xd1\x9b\xe8\xa2\xec\xcfo\x83k\xa7\xe9/\xc1\xe1\t\x17') + 2*B['x'] + 2*B['y'] + """ + self._set_parent(state[0]) + d = state[1] + self._monomial_coefficients = d.pop('_monomial_coefficients') + self.__dict__ = d def __init__(self, R, basis_keys, element_class = None, category = None, prefix="B", **kwds): r""" @@ -1731,3 +1766,8 @@ class Element(CombinatorialFreeModule.Element): # TODO: get rid of this inherita CombinatorialFreeModule.CartesianProduct = CombinatorialFreeModule_CartesianProduct +from sage.structure.sage_object import register_unpickle_override +register_unpickle_override("sage.combinat.free_module", + "CombinatorialFreeModuleElement", + CombinatorialFreeModule.Element) + From 4ee3313767ce3b3be2f7b5a8f5938d0d6c3e0edc Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sat, 25 Mar 2017 13:03:36 -0500 Subject: [PATCH 114/452] Fixing Cython not inheriting _rmul_ and _lmul_ from different signatures. --- src/sage/algebras/free_algebra.py | 2 +- src/sage/algebras/free_algebra_element.py | 31 +++++++++---------- .../indexed_free_module_element.pxd | 4 ++- .../indexed_free_module_element.pyx | 18 +++++------ 4 files changed, 27 insertions(+), 28 deletions(-) diff --git a/src/sage/algebras/free_algebra.py b/src/sage/algebras/free_algebra.py index cd8521cb854..b45a88805a4 100644 --- a/src/sage/algebras/free_algebra.py +++ b/src/sage/algebras/free_algebra.py @@ -613,7 +613,7 @@ def exp_to_monomial(T): if T[i]: out.append((i%ngens,T[i])) return M(out) - return self.element_class(self, dict([(exp_to_monomial(T),c) for T,c in six.iteritems(x.letterplace_polynomial().dict())])) + return self.element_class(self, {exp_to_monomial(T):c for T,c in six.iteritems(x.letterplace_polynomial().dict())}) # ok, not a free algebra element (or should not be viewed as one). if isinstance(x, six.string_types): from sage.all import sage_eval diff --git a/src/sage/algebras/free_algebra_element.py b/src/sage/algebras/free_algebra_element.py index 42c5ad1e77d..8b63d6ce61e 100644 --- a/src/sage/algebras/free_algebra_element.py +++ b/src/sage/algebras/free_algebra_element.py @@ -37,6 +37,7 @@ from sage.misc.misc import repr_lincomb from sage.monoids.free_monoid_element import FreeMonoidElement from sage.modules.with_basis.indexed_free_module_element import IndexedFreeModuleElement +from sage.combinat.free_module import CombinatorialFreeModule from sage.structure.element import AlgebraElement from sage.structure.sage_object import richcmp @@ -44,8 +45,7 @@ import six -# We need to have AlgebraElement first to avoid a segfault... -class FreeAlgebraElement(AlgebraElement, IndexedFreeModuleElement): +class FreeAlgebraElement(IndexedFreeModuleElement, AlgebraElement): """ A free algebra element. """ @@ -60,32 +60,28 @@ def __init__(self, A, x): sage: TestSuite(elt).run() """ if isinstance(x, FreeAlgebraElement): + # We should have an input for when we know we don't need to + # convert the keys/values x = x._monomial_coefficients R = A.base_ring() if isinstance(x, AlgebraElement): #and x.parent() == A.base_ring(): - x = { A.monoid()(1):R(x) } + x = {A.monoid()(1): R(x)} elif isinstance(x, FreeMonoidElement): - x = { x:R(1) } + x = {x: R(1)} elif True: - x = dict([ (A.monoid()(e1),R(e2)) for e1,e2 in x.items()]) + x = {A.monoid()(e1): R(e2) for e1,e2 in x.items()} else: raise TypeError("Argument x (= {}) is of the wrong type.".format(x)) IndexedFreeModuleElement.__init__(self, A, x) - # ...however AlgebraElement has a default error raising version of these - # so we must explicitly pull them from IndexedFreeModuleElement - _add_ = IndexedFreeModuleElement._add_ - _sub_ = IndexedFreeModuleElement._sub_ - _neg_ = IndexedFreeModuleElement._neg_ - def _repr_(self): """ Return string representation of self. EXAMPLES:: - sage: A.=FreeAlgebra(ZZ,3) + sage: A. = FreeAlgebra(ZZ,3) sage: repr(-x+3*y*z) # indirect doctest '-x + 3*y*z' @@ -142,10 +138,10 @@ def __call__(self, *x, **kwds): - Joel B. Mohler (2007-10-27) """ - if len(kwds)>0 and len(x)>0: + if kwds and x: raise ValueError("must not specify both a keyword and positional argument") - if len(kwds)>0: + if kwds: p = self.parent() def extract_from(kwds,g): for x in g: @@ -156,14 +152,14 @@ def extract_from(kwds,g): return None x = [extract_from(kwds,(p.gen(i),p.variable_name(i))) for i in range(p.ngens())] - elif isinstance(x[0],tuple): + elif isinstance(x[0], tuple): x = x[0] if len(x) != self.parent().ngens(): raise ValueError("must specify as many values as generators in parent") # I don't start with 0, because I don't want to preclude evaluation with - #arbitrary objects (e.g. matrices) because of funny coercion. + # arbitrary objects (e.g. matrices) because of funny coercion. result = None for m, c in six.iteritems(self._monomial_coefficients): if result is None: @@ -241,7 +237,8 @@ def _acted_upon_(self, scalar, self_on_left=False): if self_on_left: return Factorization([(self, 1)]) * scalar return scalar * Factorization([(self, 1)]) - return super(FreeAlgebraElement, self)._acted_upon_(scalar, self_on_left) + ret = super(FreeAlgebraElement, self)._acted_upon_(scalar, self_on_left) + return ret # For backward compatibility #_lmul_ = _acted_upon_ diff --git a/src/sage/modules/with_basis/indexed_free_module_element.pxd b/src/sage/modules/with_basis/indexed_free_module_element.pxd index edac4cc368c..c29caa26d62 100644 --- a/src/sage/modules/with_basis/indexed_free_module_element.pxd +++ b/src/sage/modules/with_basis/indexed_free_module_element.pxd @@ -1,4 +1,4 @@ -from sage.structure.element cimport Element +from sage.structure.element cimport Element, RingElement cdef class IndexedFreeModuleElement(Element): cdef public dict _monomial_coefficients @@ -7,4 +7,6 @@ cdef class IndexedFreeModuleElement(Element): cpdef dict monomial_coefficients(self, bint copy=*) cpdef _coefficient_fast(self, m) + cpdef _lmul_(self, RingElement right) + cpdef _rmul_(self, RingElement left) diff --git a/src/sage/modules/with_basis/indexed_free_module_element.pyx b/src/sage/modules/with_basis/indexed_free_module_element.pyx index df727ea7fe9..356f0692374 100644 --- a/src/sage/modules/with_basis/indexed_free_module_element.pyx +++ b/src/sage/modules/with_basis/indexed_free_module_element.pyx @@ -529,7 +529,7 @@ cdef class IndexedFreeModuleElement(Element): w = sorted(elt._monomial_coefficients.items()) return richcmp_not_equal(v, w, op) - cpdef _add_(self, other): + cdef _add_(self, other): """ EXAMPLES:: @@ -551,7 +551,7 @@ cdef class IndexedFreeModuleElement(Element): add(self._monomial_coefficients, (other)._monomial_coefficients)) - cpdef _neg_(self): + cdef _neg_(self): """ EXAMPLES:: @@ -569,7 +569,7 @@ cdef class IndexedFreeModuleElement(Element): """ return type(self)(self._parent, negate(self._monomial_coefficients)) - cpdef _sub_(self, other): + cdef _sub_(self, other): """ EXAMPLES:: @@ -775,11 +775,11 @@ cdef class IndexedFreeModuleElement(Element): else: return None - D = self._monomial_coefficients return type(self)(self._parent, - scal(scalar, D, factor_on_left=not self_on_left)) + scal(scalar, self._monomial_coefficients, + factor_on_left=not self_on_left)) - def _lmul_(self, other): + cpdef _lmul_(self, RingElement right): """ For backward compatibility. @@ -789,9 +789,9 @@ cdef class IndexedFreeModuleElement(Element): sage: C.an_element()._lmul_(2) 4*B[1] + 4*B[2] + 6*B[3] """ - return self._acted_upon_(other, True) + return self._acted_upon_(right, True) - def _rmul_(self, other): + cpdef _rmul_(self, RingElement left): """ For backward compatibility. @@ -801,7 +801,7 @@ cdef class IndexedFreeModuleElement(Element): sage: C.an_element()._rmul_(2) 4*B[1] + 4*B[2] + 6*B[3] """ - return self._acted_upon_(other, False) + return self._acted_upon_(left, False) def __truediv__(self, x): """ From d87735db11bdeab38d4932ca3b46abba8d4ba185 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 28 Mar 2017 00:29:24 -0500 Subject: [PATCH 115/452] Fixed trivial doctest failure. --- src/doc/en/thematic_tutorials/tutorial-objects-and-classes.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 3f964bf172c..749ab5fd1da 100644 --- a/src/doc/en/thematic_tutorials/tutorial-objects-and-classes.rst +++ b/src/doc/en/thematic_tutorials/tutorial-objects-and-classes.rst @@ -285,8 +285,7 @@ Some particular actions modify the data structure of ``el``:: sage: el.__class__ sage: el.__dict__ - {'__custom_name': 'foo', - '_monomial_coefficients': {[1, 2, 3]: 1, [1, 3, 2]: 3}} + {'__custom_name': 'foo'} Lots of Sage objects are not Python objects but compiled Cython objects. Python sees them as builtin objects and you don't have access to From 7774636bccb7975aca5659acabdd2a20bf332240 Mon Sep 17 00:00:00 2001 From: Marc Masdeu Date: Fri, 31 Mar 2017 18:05:14 +0200 Subject: [PATCH 116/452] Exposed intermediate data computed in some functions which is useful in other applications. --- .../modular/overconvergent/hecke_series.py | 28 ++++++++++++++----- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/sage/modular/overconvergent/hecke_series.py b/src/sage/modular/overconvergent/hecke_series.py index acec842a31f..caea3fac014 100644 --- a/src/sage/modular/overconvergent/hecke_series.py +++ b/src/sage/modular/overconvergent/hecke_series.py @@ -670,7 +670,7 @@ def hecke_series_degree_bound(p,N,k,m): # Returns matrix A modulo p^m from Step 6 of Algorithm 2. -def higher_level_UpGj(p,N,klist,m,modformsring,bound): +def higher_level_UpGj(p,N,klist,m,modformsring,bound,extra_data=False): r""" Returns a list ``[A_k]`` of square matrices over ``IntegerRing(p^m)`` parameterised by the weights k in ``klist``. The matrix `A_k` is the finite @@ -687,10 +687,12 @@ def higher_level_UpGj(p,N,klist,m,modformsring,bound): - ``m`` -- positive integer. - ``modformsring`` -- True or False. - ``bound`` -- (even) positive integer. + - ``extra_data`` -- (default: False) True or False. OUTPUT: - - list of square matrices. + - list of square matrices. If extra_data is True, return also extra intermediate + data, namely the matrix E in [Lau2011] and the integers elldash and mdash. EXAMPLES:: @@ -704,7 +706,8 @@ def higher_level_UpGj(p,N,klist,m,modformsring,bound): [ 0 7 20 0 20 0] [ 0 1 24 0 20 0] ] - + sage: len(higher_level_UpGj(5,3,[4],2,true,6,extra_data=True)) + 4 """ t = cputime() # Step 1 @@ -769,7 +772,10 @@ def higher_level_UpGj(p,N,klist,m,modformsring,bound): Alist.append(MatrixSpace(Zmod(p**m),ell,ell)(A)) verbose("done step 6", t) - return Alist + if extra_data == True: + return Alist, e, elldash, mdash + else: + return Alist # *** LEVEL 1 CODE *** @@ -915,7 +921,7 @@ def katz_expansions(k0,p,ellp,mdash,n): # *** MAIN FUNCTION FOR LEVEL 1 *** -def level1_UpGj(p,klist,m): +def level1_UpGj(p,klist,m,extra_data=False): r""" Returns a list `[A_k]` of square matrices over ``IntegerRing(p^m)`` parameterised by the weights k in ``klist``. The matrix `A_k` is the finite @@ -929,10 +935,12 @@ def level1_UpGj(p,klist,m): - ``p`` -- prime at least 5. - ``klist`` -- list of integers congruent modulo `(p-1)` (the weights). - ``m`` -- positive integer. + - ``extra_data`` -- (default: False) True or False. OUTPUT: - - list of square matrices. + - list of square matrices. If extra_data is True, return also extra intermediate + data, namely the matrix E in [Lau2011] and the integers elldash and mdash. EXAMPLES:: @@ -945,6 +953,9 @@ def level1_UpGj(p,klist,m): [ 0 1995 4802 0 0] [ 0 9212 14406 0 0] ] + sage: len(level1_UpGj(7,[100],5,extra_data=True)) + 4 + """ # Step 1 t = cputime() @@ -1012,7 +1023,10 @@ def level1_UpGj(p,klist,m): Alist.append(MatrixSpace(Zmod(p**m),ell,ell)(A)) verbose("done step 6", t) - return Alist + if extra_data == True: + return Alist, e, ell, mdash + else: + return Alist # *** CODE FOR GENERAL LEVEL *** From 9a829255a356e0edb2959fd197f2a8f64f088e83 Mon Sep 17 00:00:00 2001 From: Matthias Goerner Date: Sat, 1 Apr 2017 03:10:48 -0700 Subject: [PATCH 117/452] Mac install dmg: scaling background image to 72dpi and exporting png from InkScape such that the bars have a gradient as intended. --- src/mac-app/sage-dmg-background.png | Bin 25592 -> 16958 bytes src/mac-app/sage-dmg-background.svg | 58 +++++++++++++++------------- 2 files changed, 31 insertions(+), 27 deletions(-) diff --git a/src/mac-app/sage-dmg-background.png b/src/mac-app/sage-dmg-background.png index a2600b9b83ec419c2571494bd74e69ed895426f5..2348b2fe65d7a011434d5c7c42410442f7479421 100644 GIT binary patch literal 16958 zcmeIaWmg zbQ6_Pe+wLbZ_Oisa};N39XAjN4g0?z+|)|I6L68xT|(Pk&B@Z;)5O&R zW@h4S!R+K}m3hKX1Oj~o$%u=nd;L0I@%}|(ktKAdq;b9CWbJ@g2EJ0!SP_`M-rv0!94~m<-xov>2M*?<)CW)ma9nh= ziUH@<{r|7S4&4<7I;D4riQ*S|P8Zr)r6~6Pkux$lkJe5_>?)$N z9gz~GKi%vorWqjX`*WS0#~~aa7YP#OA0fgEYc$2~PrJi%$OoQ~P`vn2sph3~O=>^o zo4Rqr2*QF_4cA*e4DA=UB&d40n|F!|EYKJ#9sjtAQkmYV+Ry&9cnc=3s7JCk72d}6I;qYpo1{;r&Sw}!B* zb+ zK%ec+_p`&7^7qBCp}M-Yvc|ihVPP?Gq%^H`Hgts1(JnD4dR|EhD?$M-(%o)gDiMwX zg05b$QULZm6#B7^GN1p*?qah9)B5*A2J_4uF)%@Sxu^<{b7BPQz_5fO#! zuNY3#+!Cn)IToZ}LK&O^LT3x(vRcYo_-BVk2(Pz+U9(kVxFCiocQ*g?=&5H;4|?a# zn66zR%&Y5dsDJ*@NgsZR@j`t|uBObVT13JRNH_@%uC|w4=m?N%vu7Wp?%nuF&i#wl zJJa<&72{LG^%5bZW_uS$sw5MTfWXBiO8^}IHLi0%VVBUe+Rh0*#jt`=4t`B1kuWD; zgg6C;!CW`ED{|0AC#T**2Oc3(96po#9?eS{+kEvkV7-7mC1g49)zf$YV>jF^ytnIq zSI&8%5#{%zhCw97?-!IFB%?4%AyjH#~y5F@N70u9Kd|2L|4cbR~Z7;)c>aKEtf2 z_TH-mK-%DWeAJ~FKbRb%W8sNoaB-;KEiLH${tg$^(xDI{u7v4)ScT2FGlrDy$KG;m zozd8yZq)rz+29>4zb2!!5?Z=ZuMcjeBj)-abn@N2yrezFpg zAnNK?F8Oq@|5|)Hxg0u%DGt4_xVbMX65x)}kMt)`oWjmiF&4l91=E`UqFjcX&%2E|-e7={PE84a^P`BA$ z_>FZ}^9qkang~g67*Bot_D$A6K_Lbg-YBqx(Q;vpCD?LDe*HUnGM2_TKjo4KLynT} zFI&5++)`Qs-GB3_cHfxQaB~X~<~w}17>Bz**1DI;Yo^zTi$X{Sb-pqt=Ha>B*e~SVFE0ta*q>N2?@q2_aB`*G+-lARi}Qcc2ieD1o35Z^Z96Tq znsx4@2l8^FnmoAM1P|@_+dC^$*Bu@r`1o$GRaJE*P`Zj9?tx;-)6Np42b-0?Du}8` zy*ZmVQw^M6W^^i_E*^4_9~WY|eVzypLP9Ha+-+Vm7aAQ^g}RLkO#O9#;yGKii{(d> zuu>Ggi}jTDa(f`jrxo_(b{-(@LSxZR(^3aa)(?l!N6M;%s%(Y(D*u2cI&3Squ&iOHi8rhI~9*XfOMP z{W#hBcG__k@!GB6dU-`*{IX2md*}Tk)!QbAOpkltRZ6ID-v{*JwV{Ub;WcF&0%>$4 z!b`CP69PtfY6>ZHArsid0!7Za+TXwIqI=oCg%z9s!izMh3|MJb-um81&yD50q8}~O zrM<(DMGGn)M!7hsut>kQ5@Kk$6@1}28&Z;eztGCzHtA?)X6rdnQ8S$Rz zi-X(!WhQWSeOQEN+zn6oZ)=O@-n6X3?d4CFjE^-6;;(n?)EX(mY8okz{uLD#Vf&&2 zP5-qEp?*z{CFMiLlG85g(mpoI z{)^m~#rQk3fuP=Sj+S!shd+)4QwOsX#-RoMlKW)suP;Y>R{Ui9h8gUAkfVuDHZjqC zg-xv9ulro0LveB{=3gtcN|3*3q&QaAp`(L{zkr-NQdV574Pm6*zGnTsUJ|@m1Og|8kZ+b5?ct+WjYRWB~iC=J$hq!LMgaY#HVWAPJ#NI7=u*jg_x zZBu#PuDD)6wy<>!9@C)iO1Ds*(##|1E3wxWR+-1S*A_#LM;Xkg`21;Ksp}TX0>x=% zZKH!eSup(6{|0uqv-sNjZ-_?D`HRCM)zaZ!ZIoqF%m>TFxcx9EnYk&aK(zJ? z)U$t>dMm;yDeRA@6*ZQt# z?ln?L6u9=ZJv!2%cHZdfT&xe#SR@Qv&&;Z6aPHIWcZ=}eWPOeHC8?^yhF@AbUI~2m zLHV6?_v6X;Kz;r6)zI=M84JOW-lR__c!K;^kBPxUb~qAnzDgeiD>%CT*&c*@nCj0aFV^#nlu3_Mc&HnP|y zAnuN>pWQ}Ax`O;H?0_9i>9@Dvcxda15-JwiyE$j zqvSQ5hU-u7<5TPFP#X>p%s+o?&?qjE5_SKiD<#V`9d&9C{*)hCZd_8YkZC?xS&d-y zl+U=F{<80J@4A1$LDXkuF0RAw@5C{RMBnyW#1Zi9eCIJ z&I5Wv!5qi^shRvWvw_01g&`f65jw`?{JxloQgu`^%ZCT{9PwTgLd&J4%td$vY3;N7 zEwxLB78wE5k2KNI%!!{?Tf^Q+By5;*z#5w@xF6`q(saQkIjMm;-o;!hYp+jnh#5#| zvK)j&G9Ue)To{tmdmobU$u)4nYW*b7xY0w(C;C#Vtun>NeL-U4I2zrntNdg(b$h4d zPy3!@BxO!K?zByR`%lvraXGAyRu~KfEZ0?V_nEz3AKfw|Mt9|oP5FE{AF&vppV@!j zO?*NT(=w!6F=T-kw}0`yv;;$~ zDHuvLDJb$q8LUU-KeGCaz?NI5vKl=qJiv1d*Ie9djKTf-3cj0?C^(iPb#n|kjV!HH zkKD(`%97MzL+{Tm%wf%6)(?%+z#;yEbcT-B@!qzOHj5LSmeGBc@(jX~rbg-K=zAYq zBIgy4sS7QYPfXrBn@7hfdGk1Rd)zt?hkPoAb`<&Ys6>{cpLo5^QQtLK4mrS>se~cH ztJlnS`Ryaj4XZ(OHEEL)#m?HZ(tM}wN3pxfYL%^a8|N^w`hm-b!+KmXDhiq*rvSC) zCbMvUGB@}x*AyG}-;u5%z9+3Srt5vtpa1ClR&ilbeiS<}^6tBTuCP5}G77b)%apER z!kY9#HRRyX<({T189ZCux|ihRtK>CvH=x$ySUY`MyN*f ziuod^=QA@l)^>q$(vCNO0X`^mx~ipl7^Qz^nX$JqjwIpVm=b@24^$lfZq#Wj=HdA? z?WFj?*5=ba%*y;FL!O>qb*_xp3$Wt196GJocWbXHI#zR)aLm7jb*&(6!DuYW4>7JO z0oYm^bg2&Z?v7I}V~TXCU!(}|rpL0_!K<&2ftn-Y7bwp_AT$1VER8Wi=2H^B(5RNi z-$4mZLdOW}eEL1~F2kB1;H#v)nX;+!dZ!#1vi-v$G?ikh?S#l*b4^=bFnDfOHZ8e) zc$uYTmEMSniSkrUD~%62n92kWkBXC;rm9^Igp%C$gw~$|rtL75IVJM>0=&{ZzcZRt zO;GY@^J1C*vC?e`rb+SXnib!G)74$aw@rRaJGP3QLDPH=lFssf)qimmQJPjpD46q$ z?1W7Az2}a+4%&WRc)wA0ZVl#LT42J4-t@uWu3bT^slebof?{te#`&9P@Rw z3VNqIy1CiTX)-gnE9-i|GQh8oLhIo|jf%g>FrDwW>kq#1GCNI7bDT?^gQnP%UwpZB zk2UGQ|9TV|OsXFqrN$Z+#5q-Pk2p*$irRHba`-jy(uIuRflwQp9Z&<_`=2e+#t^ds zD#YhKsabY}Q}4LO>}8KMdk$RLsrY1WEy`3NaK-m1K+pY}(k9~F8GB+>DrtfV| zlCn+tPAL^+SDm0s&T;m6E|qF7-5kRI?4ywMP=v-zJGx0Yy7s&>DC|2a!G52&@=;G3 zh~5J+!Lw?vA=M-83frCKU$GJlkkB~r@Gbx? zOWRs>J{pv1sc5WsoTe~`hLa^OM(Q+FEulBou2s5s#*z!sz zqCiE*t$cY8QhB#Bv$g!i&Niqd+qKz?i+nem!Gvk$XhD@TV9meJ24zSBKncQyk{@Uz zB9<$1nK&Sh9z*HvhBn}ZT9KX+p_c+iG-JZOXZ1b=?yZ~av4T?EuLw(6e7q$A_G-ZE5bl4d+$6<64>u@Wu;?*z+8xMJmS%Kj0vV+rPJY1Xv7 z9i0Orb=oo@JJbvj2K_#lEW=}MlLWN0Wi>GePeRd0Fb9_^#|21Cm~<%Ms5=e^kJ#<( zl6p3emx>H&$kHOOY;CF3pYI0PTUX8Ln;FA(aV6khcAP3dGoT~ft(=-$96JT-1#lP3 z!wEj9=rGQdk6m!!kEio&-UfoVyeP!L7I6t4&ZZnGM@9^qAhCcH9lR5#x= zn7uhmgYw*JFBi_3NKR7?%4b>{-2B18Hb)nuo@#rrz3+I7NOk16Y+dtySthCMIyRy- z9`GHY{T;SYQB5|-Kq#(&cTgPP?#0FMbxiCBBDa&mTJc%x`z(K1uLm= zcMnot3K5F|jMmDEk%JKJI?=E|r7U{NG%|m6M+E7Qx^0@VB6Gn5oG&6OF2|C

XS9tL3I2!PBk+bZ@>F%+YNh3^S;u!SgtSye@_ksw5B) zx`1%HuPY_x!uNJze7N@IisD*SMu-|}q#HHtP|Aaqumtdo3jditYNn2=qB7a?#s2zA z`%_VqhM>pom2?m*i=Bf4X`bszYyDO*;ZJliTU}SMRbi6`YO+&@#s_mwB}om9E{n9G z@#Eud4ynOLo7V6jTN*>tEX1ci5($$=Zo50pUd?%hKY$?LG+WP4;B`lsz?vaDUcy}`>3JH@v{OkZ|{C2&XmLS0$pBi zi&lW6V=DLEj%BMLSz3~us~pTLMC1_hen#!W<~fGjHLySvw^iw4=&5nKayE!2C)tdp zX?tW_+|YhUMi8G26G*A#Dh!IZnfnt-?D?~2G~2861`O9#=YrpmBWhOF>;7eKMfBSJ z$`Rgt^<4B?d5AsOdDFB^_MMI-^`u&Ljsy&Yb~r4_`csLEx6(=mI71*L@?CQ1 z0$asCZLKWOHS9Ys)8-UXV(kiI*%F=Iw2a)wV(`YUv>iK)@Y{f&0>Cnw8r$iCk4sZ= zJ8(fsO3XPrUegw~C~6wJkPHx5Y%lmtzmtcZO+rSQlmEyfbmf6mp#h@SF!?v-{=&5^ zO9nGsT-;HmHk5kPWgi~${7pxBigoLU+ga|frxN*up3(cuB8mQ?;$vlL2pELI7LKv7 zmYQD};3{~nPPlDOFomkj%<)W(y?u_dR%szS3!vT^`JIAv4=cZ2o|cHh(Axr^T&x0i zUCTTdYV-KhT3Ic8fO5uiuCZ8y!ay8?(R~!`)b(OWHK*32g7Iyu^QW^IC+T(XZM@x^ zR(tTzAovTRVA`m^c=@!NlNVh_B)pm|#tzA2l z1**_1?m)A57Tk7f8!iiBIyL!+nl0H29qIZbi7$B3aBbgY@J*X(HmucStu`gW#|w^V zDiog{M`tg`0VF(flL~nrz`Q>T%DQ=DbA7F2ip6Q}~gzGDshXQfWj8SrdxTs{j zz_WW<+#l@dp}}U;)5}|E8Vd!5t710+5VZ!9cW1^B)x-6TV* zUlkBOx(OsI`@-=>yYPh+=LHM)oT2qx#w_9FN_|_S2mnyc4o=YyCP|=3b%VzR1F5RH z0LcEoUTo_g6CDpoiXc16 zs-OX~%wKZ&@3F8_3i87Vg(dM<+>>Ue{H_YvX-2a=Wph!&EkYoefjqbOa^)2k5Fgnz;!0e*(!W1V8Tbdz#x8->DP+Kk)7M2Pxy-YfsxkDkbQ*w2QQlM@s z=iRWDIYCWp{rUCW?gwiif*qPbN6>~E>RK^Fq>I~g1P#J8jC>s&3$*yj2t6#uTpwrD zDCeF(0m;&sT0+NOu9$vrsj0-4)h-aTlCv`mpt+1j3Y80k_xwtBQgDZ9R~|f5vUaHx_ygM?v0;R;9jL2A=VERaDIL63Vcp; zM?v~t-}8-@iZX|u-rW1gXSu>!tvQRgH~lf19WXT|xXdp)k6s6KItzT>&9lv4YzQBE z$<4{9i)BV8bgYKzy!fYd)%5IEO6paa<0MJ_Q3s1~B?8E8Z7bIVh8f>G8*6{Unxu6_ zea=Yw1O>sV8@iIKJa?FGos_3M%A`B8KuDy1;V}V1V4i2ig?bZp6V?TQ9sa1Wj zPTE#Kuj%O(Rai4-P&aYxX3^jrRT*Y^(|S=P@I|fxMJ|}0Sf9)NcGudALs?u1$XNE6 zP54}l(1%=Qo<>R>W4OvfQbWZcD`<^ej7l|q+k@K)x!D0hvnnxg?yroes#8s4E>O>W zx*M2^nx3I*(SfK#B0%e*_>#yN5(y7!e=CYSc7M58L3nUOm06~LL6OJDXwE_{j}t$LAL6?hmu zxJJ@Onm;hcOAsW5`$!dZy*$^~-#lDnYx8|o!!LdUvNz4lZjox*qc27Jd3@L|mUJvl6LF4y|68G3>pSQE$28O?%LZ^U1j4$y**>zC zNS$Y*bj^rC{gUeyMo2H$M!|05DYyNznz@~Zs9svt$*m@d;U0&O<>FSI4^4i@T;MLJ zN-Wv)yS?i#>Z{paqM{BT<9+V6cPFn7(R(3`OOJh~>=&cxvq|9bxoBQDPmyW*Jn#1Z zsf&@mIRBXi!0eEVl9I=MQoEMaeW1nQ|Mmhn5Fon?1Zy*f1P2?sdwK%6etE6MNTMkT zC8*4RcN_OVj1m$B!%=6ntlBO-qzoU#z<^&_Vc)RnMYb8@buYbw+cqOl8iEH(904IE zk#_r2R&0UYSn3+H`NhR#f4S7KP&K-DFU6+$m6H=kmt@3oqybDl3RU5{>+srSyKI!l zwGjFE_&Suo(&x=38zzNtweowotS z&!ZQ3bM2-<AktU*H~wAg$7`r#kukM~g$Z2mr9XZ6o$ z+8>5_d0b2_^J3k8cI}!)mL4%E!}}LTfSg-S#7~Cl*ZC2?o51v(7CVw>_2uRoD7Ud;kn-W3dxa71 zq2^Y-yZeV3UC%&4^nGADPN%`BzcS3>%*X%i@%vk31}qE>3WB%2z@iVY>ome5P$^nu zE^$AXdGv=1fBXrQn|mir2#`~=8i^Y$kA>ByWgDBB#rVkx0t>{qbPb)z4-UD_W-DXP z?%loo;Sirheu!$k4X=2Qszv#}GH4v%xB{pH%a5Tczz-`Q{=^S6>0)&!6#S9rNZa&g zBn=uX5&aSpJGRd=$&2&+>=7Z!K;W1tUNBX^bv^8(B)&Z!G{EsT2TGi0Ok7^RD(Z2K zWi5t)z@PmQU`9wc>W|+4hyeoEb&C1RJxaFNi7Qp83$E*lcEfXNJIN19m!iU10OQa$VYOi5oy?t4#QmzcI)F18L??Hs%Gmi+%qx z^PDV=`1udjMsF2+uL&~2iz2Wq=$|b|el9fG``h$-a9Y}-e+Q_Gt(qW9>z)Xw7#Gme ztBYmij`9)eR8FC@qqB*h6c)NOWj3)6t&K8&Mkb`7{~*=#la6bKfEE3I%QB3R<4>(b z*kG0_f~;+=NyMjoRToZJI*j{^M8Z17sRKHzI8HR4E`f1GX)-FdWulIgt6u{p1qH>f z%f=gEaODDkxc?pghXv#LeXAG>5)NgUKY)%aTCK3)Qd5F{K@gg(KPwQ{ihsGP&x{2A zqaR}u_P@jb4_Gj|ITMC1*2xfc-QbZ0C!rDs;I_mF!Veyk#CtD41!TUM8lt!ML9 z&6^f-K|xTM_t#6~M6yH^0_9xvHR|c((WRdOkA*Z|e~wKq2_*TiXUB&!ho4l_@Z#Q_ zy*XMlnhOqwTWLk0fX}r-g@^ME6iJ8(mi|NV8ipe?MV!R`q?vkg^2I&t{^jcx2l~f- z2bSruu$H98(XFKD*3o}%a6kWf%C=(6j!Op^$@?N`Bqy86tXl32aJw=L?Y8HQ7D4SW z$=x2zWLI}0cIo!Lr3G`ZmSVoCN((6!51;WDwNuZ2nI_Lkxv1xZ22yGc zyt?{4G*C{C#KFPE3iBs5mjoOU@iXAoU7l5Z;JfMXm zVF3iskit`$M`CY-sphF_VxJOui2RT7 z;UPKYF_Z=#PhvCG3lcQVEF14&+u%}sXEdlc1OcN{LWR`B#YkI|s}b71fhJ3z9T@fZ z#3Yb>^@n)F;Eon>n*JW_Uefb8G?9~yQ~9P5A0{hD9M*F#QcE@~&#$El3^CF7u|7;% z`J#vZ-1U1yGZ!rxob{Dzem<}Kf^P9N$D9U}zEr%YYb*=v&t@w$R7<^-$D?Tcy!bBC zv^~j6^{W?FoSA8Jp~Yiq6n;6oS$ZByUJd?y+tSN(har+&+C$#XxppAC00%jLHpaPe-pbdGWpmtLlFqL<@l!2@Z}b{kIsMk|IR>HF3Bj_L6h zGhBmFXJfa-#8q7>F82BH`1(6@`f1I)F@n`+7xmd<6T(E!yQNZZxRT`(ISdCjz_S|P!)dU`7rWKMT}9Q?LjZagQu!kBO6AHnbSo&qF+DNA=k}7TPv-$@K28m))RP@}E`MU_7TrN5l2<%lt&95!vrgA;)mxJt8@F`muEX$PFU86Qtwvf=D?=4W9$OtRA$7l zG_#cQ*9HIShl8zsa}rw3Mp~F#!s8^+_c(S(U}>#ty@=-Sxd45Ifyv}^1Sf^wsnwD4 z;Wh~L?9ZtAzg616Qe2>&mG1)I=wghZ^LUeN3qsidmZJiqzlem6vAEX%bWie6d~B(W z+tl~R^nS^k^-IM{;mtoX4f+R~7e-Jzs8xYF2b@*ng??epk0VeRVFu?08{xm?^|v(i zl#z(FZdQns)+bI!-MJwe6;H}E$6vi)qRIK1pst#=&S{&hm!e@XnMWGoq-kNHT3>wo zsuTom%3nNdZ+Pj5Qa&wxljKnV=Wi4yX-}sNY11gtSiv`Qml?TypG-g1_O9m7zNhZ< z_e1C4-2b(=1&|c-_vg#VI2yg;@lAbmxue*aQ7y{IuS~?-B0c{OpO;^x$cGv2FJCXK zSd!``*8054<84j#EUOcl(7U9D#U&gb*FURoOZp{&5L#zCMNu&uiQmI&`D)MtS@PE( z2a>5hPr4fto_m3u(6^ibRh#3rH}2bPJvRO5vCb5`9oL%Z$HzC4JXQRC;ZdlaRV5>~ zmWGs@ahq#SB-^tY>M&mC{>2OrlCh&W=ryMeA#$y+)eGe>TiZLEd70;DWHR4MatDVm z3{7ZTU@PQWvv97-mHrr&_B&HDD8HGtZB%Xx_boh8oYbuI#XYq!xpgeZWh}RFF^TTy zVH0q$eQd!py!My>c0PI_IBRLUjWh}#(0wu1y{DY1)eg2wgC)KvkL{EJm*Xaf-G zUjLAM`|?9;os39sSLV#@I`ZTn9^8S-O9zk7%)%S5J7;*{`u9#j-+}wbwOg}G%L+80 zvkkei z{C%^C>UZkf^m{wi)^8ob1o1olNoO0H=dug@x!1ms80pv4E{<{ZkCrtvWuwvb^bFdWTpH=FD{^2Sc97rRNg5LOTl zP0;tp;CnOxUq96XS{uoiS}+$eBnrT6V!inivpEN!(-2+y2?L(i-xzp3ox|z7NW2A2 zEdLTV$^p`z_W5R}u+&r@MWL1OGBvKNTjKdnfw0(E#PW*&OsIsz@!&W+DJh>}pa7~u z5}_p?63}N6o5H{mw|a0e<+2{cY3H!?A#|;#YgcSo`5(fYjroqR$O>w;ey#W%mRqY# zEe?9<9G0bTku}xD_}>4E|tdj9^%Uz}odTjqp6=9*4YU|Nn&O-!2^uL<&w z9WR-cmdkc+0u{I0cWX`qv9x@AS8O>sriX{qb)HU$fRAwNbQ1giMxX;3gT$HE0+J3V zO!yGkjTSO}qs!lVIzHxRa{T#qz>2`xUY)iVeKJ1v!^iiCmas<8*I`*aH2jB&8FMGN zZv9G~%>gwf?>fgUJj<6yXi>4*FfN{gf{VIVMQN2r-eFgX;9sCwU!b&1WpXj2D-ws# z@pm4o-K;jv5cg`tMs*uRStT#O)38qr^LoR<>2hdo0+!8M^4rjQqFFuq|tB*Ewv zf|-FV56=IWs^`awzP{?)cK&qvJ^kz4cWd0=x2rtWoe=mmgAYX4by+-ln>R~JK#N{_ z2p&T_D99=B5phg_J7~@@I=^03#Iq%K)ewPuO+QAXf-0VqtIuW0A?t0p1}CTW-pQ=X zo-&Ehy$tE%l1HT;&A@%z+I8L#IRV?@JBeTJVL?ASFcJ`uNXjrnYK)8-BO0_W+T$e2;p<--)iDF+FGv6^Lg3ci> zgK_jGL?jo|zxsT5D6n@rH#ue6@RkNhrG3xm&7Sv8x!)7%7FfN$@Mu=P1s>ZrxBOzr z%DAgb;C9AjmeHnf!edArdFl!Kb1B*O0qv@QG8+NNL{-HGDylOc_cqWGOh zlbVtB4yPFUZBgRgjd?VI0R63V8Hvs*>@Y4IW;}ryE3$Q*ENr4XT2TToy*bv z{mY7DEbZ^RNj+zb|A}I5xFD?E^`r1#NUu4kdv8Pr0CL@@1=ZzvvZ-lMladGx0R-Rg zX%p}F^9>GwWtXdHSvBpcYuN#K#o@$+v49ZJ2gnj|kwo^(L(^M6-fK%59kA_XYHq$G zsaT2uPunRXS69Cad`GjF$I^9jy4;qHs&|jisjt-}@8^DBV33_eCl)zLeWs@j`^15W zxuY`2>*?qs$paR1PLk?Cgh#DzrRLXvDx;l(XR}L1Hb`?UoSj7+< z4q05t_VW|%`99j{OY{bdFxr?oG%r`DN%G>uuqqYW z)`P<&96efde`@d-1yYx(sDXD+8~Fa(EsmhbAHl-Hgw=;OPIGKdWX?z0B;`^6W>Kb( z7H-5ACJRt1wG(uI9Gugpa}1c-6{`AFDM*AyX~Tf%kMg~8-8YA~YfqN=)os=9MpEx< zeVQ=wjYtSuZa$N7pRIrI@H%M~*@Gn1-)QRTnf{ijnBi2YBbBDWDqxK2J0@I^T~}`t z+4(?}sn@bVq6*=eDBco5OkSGM%Z zSG`x_XA1&obse{8nJuu>Z3zVM2ge1r`~TMH1v<C7Kq$qCImO0-MN^MYKBdc@W zww#@Z5wQTG^?W;La=Akb7`KhMz@q`Pxa)t_ZMJMyV|&3{bpsD|CSr(2uRiaHh&z;V zbBjL5D*2c9o|`(hspDDOH_k!WS&i3Y6t+2%p+~&BuL&!pu2ngN{uSFs?)tPxmJ~$! zv|Uq@bnwlG>)o_`U(t;0@B4{W+V3sV@eO%iXw$O37HGFl#U&}$OHv&#B=Pn1@h>>7 zW&3zPKsnfYl^%v%`_acEp3yOg07EXAk2FXZ92C+pcCoohUh@a~V#lPevGX0SuXQ<^*VCgOAfyMJk=OF$ z+^j9&HNs9DWrzVY1t_Y~u)_z&GvmMXK4E$U`Z!rFxhYMZxvKC70;6wK$s7#GVGx)JLX=iK5#ihbiN*9;j{V^ptu`I8d z%cbo)tdW|Wv&w}U#Wqwc_MNPp|JyBT<&6bwKPepht*Z+kd zy7b|h*suDT-res5p5w2E3DDBtv3XQ?W^2a<%XX*r|-Q^)Bg$5YuYG2^{I5 z#rn2GnBD&DL4wQFs%oeH78R7yVJI}*2&4iD?D-}i@D_>b4q%LXOz{5IdaQMeAkZl8 zrGHT%t}d~0Pyk+>;td1L@pN$vy26f2|7QQ$^<-&qhp$-lyup6d94Z{e-z%rzkAtJ_ovX4kmz#Ka)Q4kO~i>STuV37T!#8p)`VxhTX z(lfoAZBbmGlKcMq;UEf|d}V9nl1{sh!nk6+1<>98Ib;L1v&`ixl|5FoRm-bf1P1Bf zUtl2ArVCU;3$G8Av?~ z8;w6H8#uhaNX7NL9BF&MTk{ZAh>6M|LQYo&a|~qG&xkgoBh1(TT}AK4iGFVIyb!n~ z%4h6&0mo4ctgFDTGk>W^^%Hm6O%_hGGC&jL3=B|6`1fKrWL@JRd_cSI0jn-=bX z0jnz=alxBNn1Ql4p&5c%_D{4#mMBu)pKLEF!{B=>)W`qHWy`?uuq+^oLO|fVIf{fh z%uuAXI&1gkOKd6yr4Rk1bRps6tkXqt6ZDR~zD*xkv*nei(5jSqzTk~@-3v2K&y%4f zNF)q6?iA|VME-Uh_1i0km|iLX8e%c>)Es8)>3%R@XGYP8T^!qt$o`9;^toZg!R-EY zaqvv-#uZaz`;kneloG&aWV$y~xY9T?-I~CZX~=IzZWTh7rKZhCi_SG~#tLhc2B@oB zIq6GYR7dhWs5Q>p3Sa`MYi=ec02-jA@p*9Tt7}=Cujvex^1XKZd`|s=ce5!Qf>S$| z2;-N!9*>6tx^N5RexcZncH~w;{7}Af*LVMAn*W&e(bY8<{{zkJMPv2zr!u(5qv_O+ zV)Pf=d80aCBJs>6)fSViTyi$gC7F3&_2+&4HpvD`Gr3T2lGyrxnTAW{%dUW3k-T5cxnX<`rcGOh?@+N<0 z;oNo>p+Zv3DxcIf%e8B}tPVThVD_KS>ftn{I3Ec$_Q1k3GoM0!AjEwvSvUFVlZ7+B zJ-D0S=#&iH|0%Q=crEef)G1b9mMYzRkQd;4ksLtU)=tTI?j(}cbtv1l?630{k9}hp zm686_F2$ut%7`62Ac%-tmonWo8FPb0Z>5+M3OE&p?6#(MM(sbtUbgnvaZ)tS2AvCf zQo_4*Era9%T6v}P6Ti{V7BU0TLA8N_xGO6pr?O)zxW?zEImZcdHPG(+n0|K6Vgm1i zx|$Ko?0-GTkw-?mqA*zIp_9%@(gWVkZTf!@m_&4N6u%@hDKEB|-Jy7uOs*=Jd)&(R zKjl=pQc6sa>pf!TP!`{wVOKp^i*@y41`_X{bPoLVjDf)-AZuLpiKa{&)R`{!W;F}z z;PP)djmS4kjL{zsbE8r697X&k!wU;GBbC}W{SPdA>!D^r&};wz7&j*|Jf6bhpz`vg zIQ_-Ik72#xGTfijZBe;x zC1zd9>*>M!-pH?N_Sh@BZ{~DG3vf8uXmyO8YL3~{m0UNH1V9KZ2mgjiF)utR%z7Bl zRlm)jRK4Y!7T-9h<=HO;@nR@I{6DjRGv>!6@VSA4|Go?G|9tcR-thmO%smI@ YM=+S55q&HKzV!f-kx&$`7Bvp}Kgi&hF8}}l literal 25592 zcmeEt^;272_-Ak}?%Lq)?(XjH?i6=uap%P;?k>eW6l*E&uEo7*(Y^id>_4!-?aU4n zF3DubIp;p|ktZ=~DzYDtiI71c&kcdI!)`ac9UhWGUA1kfRS$ZO^Ogi7#)o=WVtpuvt2K5k6JLk&p4K56!f3?q*Fm_3 zU3Skg1qsUCAehl=Pr+ToWr;6%41n17xC}%2`%oISobEr%`S1U??ui^xQb!+>6`kn9 z6}qO`{?l)L_FJVE?SG>iZnU%y54l2*tzAkL{ZkmBdchM$G6(RCZcm8KCF7)oantQ=~GYp~MdrEC~Te+v8gU zuS>soKCg^`8iC{L`jdL%U{jHz8kdd3O^?aCu0x-K8==GKt&J^uaYS%9#(!!(DJ&r1 z4~ZXYg<1cua>Ygemsff1Kie7#uu#)m=&(>2k(9<8Ct?bP^=Jgb2HV@>F>k?Q(J3sr z;L(wr`TiWDyD8}_MI}T+@ED6tY1+{dhVKPGx#N=ma(m`v0bfuMggO)PN;!%E8D@()S3QsmKVX}}>h|!*UdOUa4{9!c~ z0)rx1*r{(ePghv-WsoCWi+HU);Bnw#&i95Nilv7wPAm3vBnC$ys{S}^*pTam;!d_L z19mVrEQJ3Mk;(X^s8!o+t{kI%1J7a|!_>h5$wK_^}`C2ifKKW!GaKB~Q!YDqBV;pz40!EuWGEgc&8GPv>*P7>m@ zb+JP$D!=FY-bU`_*y)1dL(gj8VXKZELT^OxD#iQhgAgG^(;vA5uNlRZ@!^-rwfjG z6gdh|$1PYw5}>|@wxz}D{$nmRO-eOQ7%rabS4T&I!nHXeUGK(WJ*-nU zIcCNWK@f|E&pLX2M@2JkCoweO z$^7Xe;82?FTy**s{cRD!>4kRelx0J!tz_Pp)n_m4D@={PO^_&&wC_hVVgUisu0f1L z8O&G+XqDiymv2y^Xnaz?U5lKvQKzRrx~*743f@Ty>s8E-XK_~7nmZm$kR*Og|FD96 zyRE=s=^lSGqqjo@@0U|a|CvusCp8(f3By*wcs!B~YH5`hx|Ry{I;G-qN?vYPjlmPf zu6kAtun638VNB~R-E;V+Z}#GgGzCNEkN9}sE(zQ!BM)U{+gz~H*#~f`XMPAvM4!l8 zGO&dbI$#S@x|w4-l{n%crEH3;lq6riW2!L0OVlQ7l*ZuRF`YjOe63`W8eWYid5rZK zdTryf${!ldpc*|YhLVDDiaQBAcHq%zb3b;#!hj{IQZe-&Vxz|~nEs}TA<|PyD}LGN zW@NO=`3hIxyEwRF8=%)j0bvaxw0Q9iTQb!pl!MuTX&t3TbXxomk9pN`ZW&Q2kHKx# z9-90y6ymj1#^#zIdI;qj@HMIbFEKi!Ze+*ZBB}gG&XHDYH2x5>-@mc3`3!Ag+X_=qCoHn z>8CNr__Wvpeow^5sdvh0!zSZ|h&+u*ky$4pU42#Vp>PfzbHt}n znGdqWX(d8~(mafGHoyu>?ASHyzXlUj&!7HcxnXlJKF|6rwmqvDM5&@df7j5dk9rbG z0?S}h-fdXiZ5WdQ?3U?!Ul3N3D4E3sQOwQcjoTzYS)gh9@Xfs1yw{T7qv<;%WM>ev zSf?-@xX&n3-^~(1D)>#Wl_BRTkL$BotF5uI^$A9#n2%5JAt9`S&*Ai(+tmOCgdZ|E~4NaFPO?0!!n_QH6~#CX=(G zPJaKvhalW{EZHqsuVh!-ilMhxtZp9|1T?yxZz26d^~Mfal~qW3jbhvLn!-KzIYS;( zaK2CWts$!DK#>%_KUn|^2!?q~UIWjfm<_3d|6p_1-oD&mZM_GFhCEf^h+HF)o4#0t zp07~{hVZd!`XNG_T^NNu^eqkM@>8^bYkD<`e)(lM&I1k|jQW>=ji1VL3e}q3iXhLM zhvvIOMU0UjK_(%_yG2nFLU;4iJ=V_7kp0X6-?^_n-;6Zr!@eMd(H5XyZGV{^GLWx| z6ld*#3`*nsbxISYD>tDdu3p%QN^j7JgPb-P+}~fpCjRn?ZfxCBLN1XQ5@Q2}LrR_B zFgy)B9U0w*amiSE=Q*#LS%9W{e{Sw#8isF*+7#4{MG*zPHiC+I9RE#!J5ew#i~pP}%+LkN{YcG|{il;o zkoW5yy;4>o>|~oW*!xUP_3U&}-qVu~zdQKP!oyTH=K^%b(<=(AoYN-i`X|LuVppZ2 zGPuX*{)Z+@+0a%;>Zj+hHCJ?YYvij*pQnxkq8LLLbrcPn{d}gfKROcytjNeeKFzMz zMyB4XDGGd0DqtC7AUHV-Ir6nYJ_cxgLgA%t+JyVYj*($~lSQd&X`* zxwHtclrPk=GyCa31t?A%kh3%N>Czmh1S0=iWmXmv^qth^D#P>~rMf0%qh}Q)U~{je zlMsMFFifUoyR(YIMqcSj#@$pjDq7i!B{EQ%Ce@!^+MP9PEKcLgfZ~aSt;I73ltuGJ zrUi8_UKpP((%sE~g=9^hnlW`cwcFdd1wRlsSF7_^gTvz(S}K=b?l@u>IrA}`Fk+Xh ztA=+XvrCihADG(#TPW<-vDJf#q!8hUaKypih&fscsEYbt@sT1+Gd*I$!ovwhPa^S; zS3%rPZNN&=L-f|&=Hdw%G?mE}6}GR;vkhZjk49rcGE{0VZ37KGnjKu3%kOIEiRiTh zXNn}h)k6KKO2exE@S#n~-^K|z0J5s+EF?+p{$H}9Cp+Vu!k(U$i8l96VIPPkUPeR0 z0SFp1sY0#r8T7a^1>JLM%-~&A4$rrb6UK()`*$B>uHxCw4&#RnH5$1Nqdhqv2q^Q> z^qN9IGi|ht;u?iT_K|r)@*98_TrU#l%ddc4-tbXW`if_EtU>-Sa7)PHT)ODROv$G= z(f$D_))0N>)<&NOqS)DN?S(|+__lZl~h4@%k(vv$An=IF}idaBc=^9f5-oG&z z27^V+6Q0F8#hIUqgbf?~=7Ib0-_K>Hj6RXOzjLaJ0Na%7 zd2&d<#gi>ki@JxvfcyR`pW`Jv{QvIHgIJLH_a)vebvSJ3 zIRC=xxTIjoiJ?*Lo4u&B|8{vPYf{~MNRK|=-cM?As1mbk@NW}*ha}xszbTXCYV|P9 zR=L8GLe@uh`*tlidrnM8=}~W@I86eS{hB=k?(Z2?rK{fk1CsLc=9UnIo+@)@^jV+u z$NPbfv-Kilap&Mw>`BCTqlAucv`u=qu2H@7qyI&b`Ww`p@l(UQhGb0H$1>&NMdHEhYz~LlQT1w+RFWdiUN&1W4VQX z>-_v#fhy=S0II7i6o6-{f!{~Rv%in8&1}}+lL{NuT?vQ0%|vNe<73)SeR>hZV`%Mb ziMhO0(+}uI##(|dZq@d)U0szb#a@!DiiDoxm)!>V1EoztAjeRuD%u34Hl21a!J2~l z(J~Gsn|3`s z9bL3)V79_Ru4|&tcVorIYe&C;{jxjEV{#CIuaz+`_OgSH^(zzMhfNs22W)-6iSW#G zA4AE7ToOr&?|JK(khN}3iozT-6<;hkRb4VZNu(O>_cH^H;|hl>iU~4 zy4zu%`GEY}*nnAoX8K1KoL|D0902CU#yuVrQvCqu>0K>0bs5AuRINQbBzshGs;R0i z$$5Uxc1k8+^;zij1UC3O4is>|?7U=hYI&@Y9;4+%ixJ7d?0us3mFRg^(V;#^V)Ty? zbyx7y90s~5iG%`>`@%*6by1!MekpCvnvz@y=+!$!p`;^jJANlbOr|VNJ`E1fk?`E3 z)5X%?t(xsmPC|Y9*9Kqyo3Hpph*O|;bE%l>apS#*Nh4eqw_K`gw zod4^%6xqj`8-VDVo);B?Pv`}AV7YIaCJolQv@M2XQ}Qv}In;h&NNn0^IVFoTD}J2b z$P;yyC8%!wZzK`-=t%8&F-J+pOYZqz-qQ=}VT;xMv@UGL_SSA&v*3^WL3VK^0q&MA z_Q)}~Jm{H<$5o__clbej`+BLL%xp`9diEde%QQaNX&R*>3o*(ew2#Bpv$8`hk~)sX z1uxdO4nX4YYgWp1*LFc`!J&be|UyTuQ*e zGoGdZb$16Xo49QKfy+Tdc>hkX-y|mQquQX#`^yx4Zg3am@8PrWQnyy1Qb>Q!^Zo#W z_I)e{q*fog;3+MNkTY>ZT(OGg@GH;6$SFReXR>)H-GW@*|Pz1MMFCW-~1g>;Ltd~H7fqK^Bq#{P7 zUaG4P5f~EHDX}rxIYhY0D{I7e<8t<#s)6Lo{af|zTsH9vP0D5S{qm{d+0cF6#E+9c z&_aK$>}ae7&$-awZ&gKTR7LzNFkl^!zC8Kg^;IDF-Yx8MI0&fgfOR2P zy z2)Vw+37IRMbM>QIXJ^e56AGy3E0pZ!pCP92tx0PxDARK#W1qHy#0NqT9roinVO4~+ z3;X+pB&`6MBf!URiHHbQqk1L#vX^%#O0<^6(>U+X{jonOU*Y21m{qmo-x&3h`Pw0D znzTb-2F>Zg+vCw|J|b{9pVnDMy&y{OQOTP6;t~wN56-s8EvCp?m4{~#0ih!B!UGD( z+2u~o6J-G6d0g@KVQ$Bn-YSb-!r}Wa_nYp%znOB|$_XuZl)(W)h2T(&y=L?m1jU*q zIDEvH`*tXk5Yoq8d`&xNIF|l(Nz;O%-C?qkc%()T+cE<$JDfk`J;%yqE}g@YG@4{S z8mt+Vu z_HvmRLehro{D(@V5?OLmy&s_as+(+Es=n8ACINx@djMxhk}K@&#@)~^2;OO#?6{xU!oDa(g}p2mk%`kpt%+5emF5siv$eUnb1^$(gKc!I#NdNhJ=d zHD+w`sv$i@mNa`0j!7V9JWMB4*br{`Gw|c}m7$p}rdbPH;zv{EGUrL9IvaLc=cCB< zVtIaIyNmX&1pvxDrf>lm{vB%1#Hgjv@6kNwdJiV>%u+-qNk_GP$@Fp$5(Y{VwxN}p z^MHT=@cENy|&$f&cKGrTdxLIh1@`Hx=)ltqVIiVY+yV7^$qDXU> ze&L~iEaujZv28t3ue~=|G+9mkQv0d5K7hNBW)j<`%-gu)zy_dPux(CN^@Jg1T5%Qi z2Dlbaw_{d=*3FQcDaD?r6S<`fAT%V0T}~4csx94hu`)D}LRXsM{Qao}1kyS>F9gyt zTWk_YT1KT*vwWV_C}BbcThyoNRb;I(uX?S8EC}gvX#G5-JkK_^WP#* zXjF&njn?=%0B>-Ay@R$bsMF~Enj>X$n56<^Il9WB6ITc|Ka17A!Q&?M%M6cp{!&}4 z1rqWSm9)|<+xMUU=boB+EIXIBeN2hEU$<`$0gnamoRv9_#hhDhPAMJNBV#d4dCa(x z3%s}TfcRMW*+OQxvcr*FzDkG((Ae~1-Fq?QQ2Ex`Z| z)+n&aKtJHgGmJHOX7v7i7FOr}9-6h^=}-b-zeB6jg<}hg@JuF5jb>q3Vw^V7pPNvl z(C8axS6jg*zT&&pHEFiR{p7wc*BJee($Tu6b@||OzI}fI0AV&X2z>rBlAtO6+n|y} z2ocaVpf;a$&;c?uF>!K}X{u9oyTGx88UYUuM@;}aPb9q8mqiPixWtv_1ro0FbI8_9 zLR3Y*MjRg=aq{V|pTk9_YcMAyiyiWHt5%?8I8KVclIe6yQ=r>AL@FFa7*{rPi%a59LrpFm(;XVie&09BXNf%Mp^= zAVa6Go;^cuj}`QUu0rz&8gSMpJ-0-*x89hCbo&|HMhGb`e|9%vKE50-jC6Vkb5b@c z5o`C!lV>uZVspT`x@(A{p`=UKC_Z9+pOpk)k7oaS@7Sb&2_oTyTpWPD zvpK^adZ&2zSGw_Sw9nERfkKGpeo{q7M7$8JDoScLm4A}$0f<(>+N8$AiwxKW5$ANXc`XqyFw7(nDeBh#{e9JduR3hqqOHT~dGI^Fqb;pM?xUx~Y3a6cYA4epLm+;~qK8*)n+IKSH0ax}o^Psw$}ZE`@Ew zt?I-bb_qnVWXT!eFHzIcD5-76W#BFReR!y8*{9dkx}Oq$fc1Uz6GTY(%KzK1`U{b; zK}_+8%w1orcAcKE-?yi=*Ez0?qRH+(EYhi=}`ooYd7-{fOYbM z&-Atj$?vZsSSwpwVtZZoe`t9`nbzzF+{oNAVM+W4>;Skk(l;$xfb&-;n5qI(QE&my z(;1Z5da*(F@*189te(^5B;@{je6azDz?2WVyFW0~2maBpoe1cVJKbQZd042c<^ni? zAMEbik;*Z^^*mJ%^}h$;y+0<2xO7Uxy;tiegekJ(5(w&${=?+Ax2U80L|P#s{da-x+A;^bSgYPFj85~|J$;yvz+fYfP6{8^Wz+v`oVA3e0aPj` z;08qjR5=L9(X{9OSHqZsH?DEw#rOhV5%laqZEX|pTwe(NKz@}PF|?i~rZ*rg5iRER`JaeI_TNS~ zwfDJ(g!PsPE?4ePy)bN8Zw)rmnwtxsn#AUAV!dXXAwZn-Ju2GODCc!j8^lu;tveV< z(I^8sHjI}mJCtvwaxRDs-eQHIc2wCc`HP^*=d)Qz=W4y4R!{&QC(FIQmFAbipj4}F7aEkyz zDQQcK0qgDeLD<7fpswCgfcaC%LX(5TJi|J=Fb<&2TFIM~1F|S<2!F)nWRdkvdK|YS z6(BuvZ$RWS0Rj+PbY?-54xJyUu^UPJtz#QH3_Vy)*@{-G<;(E}JXxSxU1G0KgTjJ{ zr=0Nd{hj>nZRI3wYEu*D1rg81#NtCqp1CPG;8HnMDkyB1fBp72;hKgId5AmZa&T}u zgrnQ>9DpOEQPnwKe%Qb_+v-a>kN&3L%J3-qR#K3qQduO9^c{tjY3iDT(Cp43CW?%R z4_-#WY!q!6$B0xdT~>`{a!}IZRqJ`)Pk*|mOqbg zYGuX+rqb7<`YMlTw#E}f{-y>X>6nn0Q5*xqbhVk!BM%Fy=YZPi>9qned?3h2X#R6; zHnYNfm|OBK-ups}P+`T%zJ~gg!@fbvgA?#1#~7O(GlvGzlLBkw(;R-38Q72{nvTA` zjZM0sR9?;kc3)w$$M(FhuvEvVvLQfF(`$1&vJ{jc35b?MmnRjf6iWK=LE9|_-mG-) z4Cu``3_Mfuc(e~2v?&ud*T_e9n*vHgwW(~jY%=s|0MJ#fKmwTvcb}* z;sN4QEAoRP>rXJL;b>%d(Md88wPDz*T9Rl$E=1qoE3}%qTMM~~y*fIPtbDtDU`#ng z&be?&Kfen@f3)Fte<(=gcjsJP->GAZufIR5|B4F>sW*n?`M~?`L|C$Feheo{e7a83 zHkzoa@TZl4$fYBUM;0cZQ)9=wJGj?DI11Hp0EdkFVRX@BO035b2}&NofABk+q&8b7LKOQ{M| z&&*mxm=jR^m(%dDAj$L8ipNr4sdcGMl1la;iPQLh7z&`EyBaVNk;ME$x;IprR(^() z&V;c?%S~0x3sv8<@&3eDA^p~rZn9;$W}k*wOv>=&QgwB97(MZ33+ZT}=2(*7xc{Vf zIC=kg)npcCK){xc^|;s$?X)4#vJ$FE&kZ(ZDEl1A>rCWN>bW>}T!E7NDK^LVd;kH) zY0HGVSFJwYCHYfRnqo3iQN4IzC4H*;iqse3B{4=X^cL5q6|t^BV`E4PWtpk0@z%g% z1wfVW_3fp`I*VG{$el#edp z@tFTybx!@w;%#X0kVDG##A0*FJ;}@WSEws1ood*49iH8C&1AU>+Wtu^S!?((V$>Ci zA%R%M6WJ=b_<0wR5BLg>jZx}Jqw>h|x{GvA$-dduUL&_CUA zexZu%@~}Xc9m(SmIq)|n8B4#>1hdAt!c>06Sm5=rLudG=3AfeamS`@sEHI3d97b?2 zjwGD$>fB!C^q*t>wflK1LrE2&`yWxD(-xfV+!Ww<9Mg0M&oxCtf79nS{qgeG0sL!} z937Z(7<#;hB=A0E@v2&XOdw1hu4^BYn`Q{@d2sO?O+q*rS8pB>dC1MtiU+m=UKog$ z(z8qY#TtxRT#xq8q9gwsjm2e-2pD??gU9{vKIA}r1N*lgxN}_3wogZpsk@{KH@MjT zjsiEyCpmFn9Tg5xZdo4U!d}wl9)0Vq+lN6^*#MpIIVQJI~OmweAduLxi=KCT}I2Ht#yBJ&&a zw`=(^?XkkeTa&Gr$)e3jfe>bp`{#G6_IiB26zf;Gi+)il$uE%qsG;$VOKplbnk0Ak zGpSeC7EWKE(>vrV!Xi)>r~*Na=8|4a#$wfRDF)m^_P%7e+zxKQ@Yn9 zS%zQ7V~jz8yVwvw$AjF2GS*+Q1FnXx=xIqk3j_wea;K=tav^pN0EJ9Objbky8bM^z zD>MpPN0M|$?Hx5y$XWC$k|(Ms?Vr74x} zxLa>Okra$Zx~u8?A3-9&QMj51#_-Y?iVUq-$>#9nG4+-#dnblV<)1fNJ-;6M8zQqd zA4JFjmX-5l92W`jovA>Y2+k?g!uLtUet9plR}pWgAT9rN+5KNC7i3~`A* z)pd2_!&nl`IsA?p5Yv~4Kk)y3Z)vN}#()dq3r|K?Ysn&?P>nCP-?%rEJ)c2% zOo1VhXbD6RHccdmD%RNiQO`FYiTDe z^95lcSxpfI7}kkeHQiZOL>dAQM(8E7HQ9!jJ)B~)2!izvvZI<4d8hT!$}<1yb8?O_N?xLZOV?2q#u33E zJy;SV;mw|IG1l5M>9Ljv9>SJPQUOB*1cWBEH?0yzmWVL{x_prEl}||K_eypBmzP7V zZf_{sJgV{OIm@JoqvIw?(8PoT0kEd+3D{Ne{)7!FQe3V!xA8D2VE-*~8UE4h0!`W;bP}!hslKU3iDsTmueGR=d*TB>RYhPs#KLQ%Wis9JH z0azw5CXhb$K**R1d-gq1A$)P^5CK~EkAMPF&zk^X>zivcNeRp{3AG}$wtglfl#m;y zv(L{?RY7KRw+IC$h$!vCLHB1V7|?(RzYDlWS5czjdR_B_08KG4NL$(ml65=_%;ua! z#Bg#33s{zeE%wlw<#ejbJT!9l5XM53yGw~obJIVeel$O3R)0_7TXipj-`;+roE zmPD)~px$ta_!ls{JvUF+SA(sCn$v0iyFt51G1@iX{`CSt`?B1Xde+LFsFuH6tWVc# zmf2mg)xNqal05O4(xix~!RvS5ZYATlnK&8Fw!MSgID8C8_;`|C)bVd3%8E^M zyT_VA7JgZ=?I$A48J--g@r}|bAtc~2uIyE=j7q1jnz&8kxo=Fu0GRyx{gYlP7tzzF zX8t&VctJoVHz7Sa#e6JHgsJ-v=;Tz`H{W!cQ4-LetmI0bBoH6_q7+$wna!3mkp(tF zWshI2H)_yt16GPjh;SSsXXw56ezrU9FUoLKTC6xc(t*GDB;v{m=vxi!`Pm)GMUBAL zQj3R_ii&6;Uk;(-@DQ?upE2GZ)ksbB4Go(hX82Q@Rdc6HHDEe4T1*ZOrR>=#>O<1+ z^HpFWR=6!y>2Op_YhX;SwA9ZA8Hs2M!N4GlvHoaaZEG_D-&D?WFw)>`%TzyNARbdf zCNeS-jh8*W6ywQ0#FGinQiFdl>w$}< zWAj91Pza`)2l{Y0!jpF_en3Io#Y@_%&YwK!sRK=OmSTC^lEGBj%fl3{h3XbIW|$=p zw7_gA`|s$~j>4HWBlVKxl-JE86GDmqf#6XHd&VwsSUXCm+@ zzAQH5|9nDmZKqg757&h)VEw_r^kPdyrhcR4LH}I_cv3O>?#jDPd?-w3h>Qb#Q2zsX~)55uVc|N4J%4hcucNWbOqKmUVvrCQ->|5*Tf z86r3)Vo(V@&`fs#)ex_w;cK1P#?^?ymj zkic=zEh!N1#RyHC>F@N&Ui!jV#hgjcmN*M?poKDDU2xu#GwdFf4BI0sQyLW#D}|0Y zy=)8VQKpdfRy7b0n1Z2Eg&+D@KP7gynl8@6sMtnZim^8ePvDo8_QdDXVZTi&4}1c)ibZ;Crfzx zL@jqT@%kqbQ>D@_nN6M%c{TgMiiGw&=LEdRt_OHL*sjir5Z)7Dm5q)gn!oc)$s%aU zmIaUVyPH2LKbsDj_I?|5Rn=DwsfLyr)^e` zT3b0|F^cKf3Ezl6a{_-eRo88J5a#l^I{G_T%qs6Ya@KtuPl2Y}@4nF4tb+wniVo?P zO@r{PC&3DGn`h>)fPl_qJgtY=f86#`k^ows5aM2)}P)N>s&M{3epAsJ8v@9 zzqymQ)Uyz{fK@}?OBVUEmkfuAbk@UKOx?)1BRx~)omQ2msce-6Fa&@oNzz!ykckd+ zM+S?Gb=cK$@R?n*QDR_IPH|ch;5!pF`64(gSh;>kR%NG=lq((6|#uBf;rAC4!q zZ)tg?Uc=Ui&J*NZZl=|2$-{uIV5ybV)Vv*NDx_WMWgWekncbwaQ+=*(l|62E0a2rI zN()>>SAUaan_Yq5lgDTrl!8mkZJY8#^ju?zzG5Vz(aOHI>rv%a_cfCEH)&UsWwmV6DPCL|Y2vYs+CWy36pw0e8dv;@Y;qkCU~ zX@k7`ULxcopRv8cg*ZTkkiQ|$)5lvX{NAXN;b*k2gw%a{IgJ7ko$ta-?MPd`oiFf4)NL>fC z%!N(o-)lRI!YZJEGM?l`3{X$&8uQ{~bbluJ&?PC>mSE1n5V%8)4t~sq`3gp$CE&db ztp>SN9E?n5bq!6rcBvh&)}Y6Oex26{YV$@IkOP39oIbc`pjPmERe$_qKg2p3N4V`P zp7zXB_j4y)j4|>dv>m#qe(2eU({p!r4rEYW_K&`UgUS;_?T z>Eay)V(hyM4=?V)iI&%JXLRCi!^gNn%UCO?5Jtqh_HkVHMOJHJQ5S(W?@;M=<9fu| zC6P}9rJ4q-EykV-WMCW$bX-YkWAER6hK0-F*=R z`RjZX(BcWr3j) zsQuhG>)(j=Vpu7YBCHuQm)NXfdzjNEcpcBbNqFu*@84s$jnC?gtd5RPNHeS1U~_72 zGn}H*kkXOdnb{K`^MuTkty)rzU+LXKLyWfU?#f z*%*!uU&^0PS7xEkYYO9TIjJ&+hAu2<$5a|PCrr62RQc)>0js(N!jVJMn$2bBCmSNN zaj;m=oA7vv#D$6axa_yM6Erc3?p$`13`b`Wsz)`q4by z*njh)pQ)U@i-2xA8cdgl2Xe|!w3eDa(vVKi-aJ5EArOt8v7VWM8>OVE^MqLk6GI)k zmWDP~_z0Z*P>c648RE%a@`g9TA^PV2M%1A6yRysp(|us9x_syGeJ%!dwnpAaapL$hS2dxqvVauaqDVQg%UY!?q8AQ$%&z-92UP|W&qjbL9*`^$G<({`x1l=v8pFePwn$z&g3eBoQ zuX0-!TdwOVi}`$8{RJLRZCj(26^S~{ZQ2FhC-Hx4;@OXDO=WN7JVf>gmetQ8C|Gx| zn;UuY+6%3H7|9>S+tRL0L?31jjfR($7HOX-{3>dIP@}be!0VNK0kw`iw8~IjOZxTb zV%nX%JRURe$Rs(X{qh`cv6lifvh3BsGg4DonLnQ#QC$uR7&9=4)O4peUwkZ&>i?BBr$P@jgstVK`imgJnF zlau*J&h_|>yHV^*Tl3weaq-RqSU|;C&yoD|u4RtCiO_h7^{5>D)6vjp1_-*@MzU4PmZ1nB^f5o?qO$obOW+Gr`kfxMSl zHIwi86m9D#TC7)K%G_5pjiIsXVO^#-*hRfHM?y+tpU?Dt^8(-bMAxy7;#@fzJ+m#O zq-*n__z%mY7ep6d%AunRHhgVs1xI@mXa2~ps*b$b2WS<%F4kd@{#&p6o&%c~0}$AL z{GN2cz)+br-$Z`i$Zz_pqtu2LcOOtK!p5=LdeEI~6d!!HonQ?Se&(bwn-1wta&HObFU)ko1J5D<{pe!NlU`~J7sl3m6hUiAysR> zg;V*@8_zNqZ-<+v<3aT8!k1+70jucUuhYSTWeA{CXhL)IJ)7dskQCBRl~Ln(c8++8 z_2AL^J=jA!On2~}2|{}o`@nuQOmh-{(uS;5z`*i~homyaC(tS3k2pd1seQ5AWl)@F`V)h;0hz17SfHfErVz znuCApWQyi`gxeQ^Xs@UYLY}AU0!-pn2mDu9!!Zozf15(_e*I}LQnCFb2&(QEUBlb= zR{R-%M@;jR%Ul391MWh(a+xSv=^Vr0&yp{ZX(=D+ga@mtevaB#EY$GUJ8lI<#|h&~ z4qd1d0fi##JW4_y3NoTxs!+~Dc`xLOli8>`OB1@3$D;bcbq|u^L%a*a}zY z$p3M?NAYtN9}8)9qD+|WhgaZt`dt2?aY;2fEyA7DnlCKPb5`Z`Z9N=1A)^%-jLnl) zvs)40302$BI5u}i8IpOiEr-^^WG_zY(wFlW8aclX9;+^O^?cR1*k1cnj_qLlvulceVWdh%+s4GZviqBY2Uq^p{i4 zGJW$Mg*Y0T^p*b!7|T|cI~hAyXwhdakvdoP2!DSAAqp+N(ew-fSQdD-=fLpcc3-qu(8x z^kmJPjGYff5zO-*MlUtBEL z4o}G0OB?h>V^+4ATDL&)FmJ*>*-{UWslqa=*yl6e+DyO}Ei7tkF`b{UvcJ6zUv6)B z+@64vulm+vyc{0#?nXJyI)v+@ivUXfL1aN6Tj9}X&81_ zE7_m4wYNYFz}Y_l6sMYszhJL*rF=*U-r;kM7x)s2;~&rDfS({pC}wnIBHvx#GL8|E zGmwHjIYB%1%Y5DR{)IvZs)QgSG?{|J?iMD5ijvNj92cSMt^C-`GxONj`uF#)CeDZx zy1cg7pr}vhmQ$_{)a$RM!XdT$>nLWzW{c05RiS&=(eR*S8>Pq~0+6F=3g0$?mRN$AvLcbKu?U%Ht`FkU=5j)MyQjs9;fVQvh>d@q1FrSD z&=m2Z+d~?NzY2uaxaLMH(%N2aZ$w=`?&&*;6esdO)ZKO5OEPC|9vM9=iC(-8KrxwC zjrCs@tMmCN!9Tp|Z<2I_-Vt5_$8fL8ieI>Tpm z)61f=vW~UZL!{hbf8qSVYGPqwIH|1X7AK;uAXjn{6adm^t^o)_Xe!=&=Bvbjw(X(^ zxaDv}=-LpBoy|_r6#UcI?2~NUo`8ZLVt3L4<2~kjf_Mx9lcQ-A_$@>$?F(n)D{U3L+(RNJ0SV z(u)F8rGrQSLq`HA2nbT7_ujjNP5`OWLhn^jLPxq%zwvYKnfac%b7$@!aDLi*_I}sw zHG9?fd7kyYi&A9z^U}Wo@BCGMg=@2PzIWoH&9rzQfj)P&(UiTpo@hDj&J4oKif6BX zooLh`DRyw~OyqVxjPG`Q#E))orNsyU=4VdUi6vPSdF}?scwdEH{#wWX;$W)tzO1UU zPYF|0?dTy}&n)8$!k>}h9Q;6n+T0g>*!A?~VJ`T0n>*qFv{+<|;kHCDUa$c3sG`O* z&k|}_=UwtoQrel$b#o#)w%kjbYpajN@?WK(NdD$m<6jrN%3?XG7*K(cPv%naq{V%;R#sV6ga0i_xCKU2;8YGO0-z`p}-ap_=QU|4Ojc@CH zWhmv>O8mfMgsYta4P|)E4u9rSIv_PjX#DRj)=UGV133-@YA9SPTQy{3$i&ttQ0lx8lBAC z+2tATaNa}ix`eZxR}Q~~oeTsdT=x0;5u?;6iNC!u3wbzsH^tNp=jUr=0lU3rRe0Em z4&&=wZoJuHAntw~RPf2*B{Hhh!p!r51?ph4XOlSoNdQ-Zk<|z(K-1CGv;Nchg9ZmN zL6`Xm8c6NtXI#zqZ<%&*M!hXL(F{dBEge5VEWaAzR6F+q5m!IzyQB_w!5V3)%5m!t z`ApGY>$Js3XLxFS;J}TMD&V~5Vk7m&&{ON?Zfv#NI38gBgiSp&vF(8`{E&GoUVpmZ zQKL*LpG@YLDgMn3_rr3A1?eG%qV6E|$0Pu(XnM^){H=NfmaLV4;R?;Dyyq+p`85ir z=qN*7a zzg>wWrS`Fnx5GbY>#sSNUj3opnrrsw?20l?@;s-k>Uv6FqP#y_Xm5y_ z%H%3h`qW0=1jp3xY%^G{6M%k5GfT7(YW)j?SfLj2ZF5aBNkxbz$w75 z>3c)YQq4a10Nh12uC1viN(ABdtWg&%#`dLJM|ABn?{u>EB(#VTloG;Z^V{2FXv_B0v3M%I8U}GsrSX6Tf~vY9rPL}!!rtPF- zrq>F0-Utg?1(GumL{{Qgm*7h-aaZr|iq&5o3L(y_FZ3LEhJN?tx%o`UlzUfG-6GrR z4!}KKtcdB*jKc5txD(RaZU5ZPMc;T8#-a(*J#`XIFVZI{;4xMDg-0NR9la}QM|^jt{#J^fmFz_8?VnBcC4cI zi3XnqOfITxp+e{6=j;Qg#l#rN{Dati=<+q;Smqf`Ei3NBz9B{K?pTqvQb|r8t(+wu zD@nWFv(;}6US}Sm(UbO`r18muL1ix&g&`ih4tDSyzqdYo~sXgOd)mD8Iqp(8Z9oN7^>8E`1OkRrS$HZo&-P=G-|6Eat=3&Rd1Jb6S zr%ww7K3mJWQ40B}ZOIm+(SS6G1jwpk0!G!3mJGR20UuFaUsF&0wGlU=C82|+qGY6x z)qC0BXZ-8Pp3Lg!M_9S}7)eLhm*}X@h?SiW8MTe~4sOv#VmGUR#HyiH`?A20r0C9{ zn?2_Ss!YQ(&meV#S*T{#2L6%N{VZD?@8t8Sv1F+hyp^l_zgQ(tU;Y`!AHErs5vLuD z61h`Fj(ZBw;Uj7TI>a5-IFP!obom=ySEESbBQ6~t2c?i#Ap8lLkO8(}KR3LueN-1T_AV=Ov^bIVTOUEq|U-&#f zEJdYN6dm)ddm%PXAa`|3vk9M4c+AKC2y)OV3HHW}FM_6xY#rpao@D_I;J`b=DC*-st z_i?rYg@hrYF~{hXV@THX8h>YIp#a2|JU0Q?bj41^EA~5&$TanxG|{m-jpZi$D-kB< zXVts!e39SyS(++{`5-~{=MsthHUK$a7UMpW5mSM2Du-8UIVGym{V(V3r6_Q*eBH(8 zU=0h4Fihr-uDmkqkk6~AV1n+yayY&|{mCMf{LnS5m@P(YF&w$Z zB~t#~`yNuCO{UfQ`Fl;q#HQte41P4ND7ZC$$r#3ILTDGtQm)P~A`=wG1n&u|Xryp} zsWm`a@0H+E?|H;k`m{;8%}@7iE2?yN{NeZtiq===r3gQEn;HB4&F%=&t?GsmZW?P zFZtag^j>bQ3FAAufPcI`bI$*L8JK>V8@9x$w9BH6h54fW$1KhX6tcvC9~MYb<;qk5>Df@x@odX(S5s-mQO^dt2NOHE{n{_{&wpX8C1bT&zA{;gDzHT5FBi&b-?| zJQb1FqQ+aw26>MLt6`eQA@iz=3p1va3k(uz>i)FQ_^>Imruu~X%nSHlzuN$-n`Y0c z-K3d8-Py4=rf2$rK=9;+$p^dQq~udF*?wD*q>e03>cmReLGo zbbcgrJ*S|~oxRq}gDPoVOJ&(HhH8Fyf%P z-HpO0!(IW~5P8=+St)9%_S_f2JEf1ePJ}(vSO!KjiXi-y(Wo)((a(aQyybhal0e?1j3CeqF6=tPw}c1krv)i}nEtA_G9Y2TL6g=Y&9pgYYxn-+ z_GdUgU04txA-!p`jqkl?nrN(_=~X7K1F#9z$A*Z;a$_pr5XD^@JrVSKU=h4Y1sWj* z1~g14qfGBn;jw3^)f-6nhr8vd(X18>B`mPa4;_U6CcmYYlVdT|f1`#%cX8g-Ew2 ziqc|-IXsF{B(s*ZCOGSs6jA?>)>GaFnXIZ;htj? z3t0LWda@G)HfKMwzc29#U!Zl;!m!(@J^u8n(M^3Ght|!ji9^-m@*7^97HW;Bl+;f) zsVQEK1~y{NUVs(x_GxcWmat&8F+H1O1@?lc=bT6RR)1lL3bPB2BjRuw0WA8<3A5M+ zs_Od2XNfM0>-2sqNu~c-BR<9_-f~uHS}jbb>k^jer)PW+;*7tQF8kPK&2hvPZQFOA zPAR2*;)zIC#T%Mv|Fls3Zg5h|j|%BOv}ihsYg>==^^f5TwKN|Z%_pJOoJ$+g^9p{E z?uiMJW`N`!#)>v%zzMJBH78y%gCEYz<)_$~d<78E2Irl=ukZhFW!kVb6}cN!ykW*{!Zy41lqpxXpVf_4|gUUg?V`m;}tk z*|rn-1nF-iHzRe6!s&Y{vEDm0pu2^Fo&ibxCUyPW=ATa?@%3WOxCZbIv#?h+Sx}Yi zf`Su^flMepvVk=qMcu~6(fL%^-?t=1{d%^JZ)cH{y7$igA6^{$an*AnXUHm+f4Rv% z;6#cidFnLJ?R?WjZLF`@l#`TH@R_2+kmDq-p|9_zx5wgkW-f0Pb1DdP$fk&$K#Jkskp-(jPIKAbXx^U@}$9q_RnA6v0`f>I9Al4nWxHdc->7;ITnp=o+nDH*Vs3 z0^GdWoR&SENb0>nr{lsm@<@{)BNL^BI%}#WW^iS1yl^hn60yjeGl2?)LDTI$k{X1+ zcBWT+Ob#~csT$f8>@C!hI)xf5S_$&>L<|Dxr+OKYz?pKA^I+`T!^Lf z;?}X5A7Sy+O#tV8jmHhuojjEKxQ5bm4@sZ-Z6#AZfKY`6V;ecC`!E=^Ppc10^W4AR zL$CuH+YxCxySOU6sq{C$HlwgZQN|``85J>*yiSZIU7qcF@qBS|CB5IbKYwY1spGMo z`i z-%yTQ7W;Y}y!`;|zRqKo?D6;dY*M@;XSq-7CSQ zJc#KKcUEgYLt5}6=75RstWjW5dHM{-Y;`;1Uo6<*K&FG32ibq{c1M#zE&8`c3&aiC=!@rtHynCGWrNDS%jZFH+Vs8~dfH@WBKfUY zDk`F|a7{Gn%ZqSK=7ExOC~PY$?6;EY}Sy#{O&&9B>>%($FQYGEx`qg8&NMUq#p@SlEn93s5iqU#zwDfHR+!d76H= zS~jpvx4BtEIG1DE_w6Kc1Bytjy#%mkADVJURmwJ@J_`1SbC1XR776{ZVh%_S_#$U! zwj~>d#mL<@$wiY?eNw=6_ttw85}QuO)lr+$Op0Iv$$hz7yR}2&ah7g`7FO3#fF)Ed z3IxQqniJj};1o%VG*=0hm$gM^yIq*0oVpj8xhX3Jt3TO>gz)*EY!O%W*f3C6VmkLw zmNLRyww`f^L{0cYyy%+x@y8r8tq(P{%Sq!UODuwp`W7DfG836UZiHVYON?{$5vWt& z$kSU|`@4utBSMCI!e&Q6f1L#EzQoD!UW=#j-@#a8t)C38Lk<;?FkaNyyO8^AU*Ks=nM`p1hOjWV@!Z$2J5n3H z5X<>KB8rLZ*cxUE5Ne;zHh*Y4?whofu~D-jmluGUiW&%i`@5T{+Tl*}Z$_2ko)9A> zktde^duM~ZuAm#N07Nz-2fYVWnOEnfstRg{ii1ix3!(MIZi6Ch?2y8hSB(T(O$VAn@xshFNrag^?eP>h#Fg!Fe@pL2(Q zt3^pfe-h~u7~(b_f8C54C%F`GIHlG<{iu@F2G!!{BrEj5OIr6-*wec&T)XI!>33D*d5!LQ}jJ-R;oq5*5~K@SDoeW?TC# zkPKQ|v>s~P@8bGr)>FuL5RTI#o}9rDZ5rT?$@E|IA1RUm?bh#uK=|Y}nZurAo-O;| zp7YS2KWaRa+VG6Ez_EAHot^htF9a=I?D%s)wq=aXjEu-44;fM}OpewOHpuYx(@6|- z^^4q(<<}CEJbhKm2E~Z)IcD9zbRQnwZk|f%RU{5VpXBzhA&6!T|qG zbOEq-@PIk7d0E2Q>|8uxHl@d=f>;~sf7|@ck|Aj2=x$+S>+0?Rkm3zN=wRQ|{KtE1 zm)9GV+SbC^*4@Fy1|W0^!H>k6vHXXbm!pll z1HXf + sodipodi:docname="sage-dmg-background.svg" + inkscape:export-filename="/Users/matthias/Desktop/shared/sage_src/sage/src/mac-app/sage-dmg-background.png" + inkscape:export-xdpi="71.982414" + inkscape:export-ydpi="71.982414"> + gradientTransform="matrix(0.69346635,0,0,0.69346635,333.67367,116.84807)" /> + gradientTransform="matrix(0.69346635,0,0,0.69346635,333.67367,116.84807)" /> + transform="translate(-384.98959,-335.08768)"> + + style="opacity:0.45899999;fill:#000000;fill-opacity:1;stroke:none;stroke-width:12.5;stroke-linecap:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:12;stroke-opacity:1;filter:url(#filter5453)" + transform="matrix(0.69346635,0,0,0.69346635,333.67367,102.71565)" /> + transform="matrix(0.69346635,0,0,0.69346635,333.67367,73.567542)" /> @@ -236,7 +247,7 @@ xml:space="preserve" id="flowRoot5540" style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:27.5px;line-height:125%;font-family:sans-serif;-inkscape-font-specification:'sans-serif, Normal';text-align:start;letter-spacing:0px;word-spacing:0px;writing-mode:lr-tb;text-anchor:start;fill:#1818df;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" - transform="translate(76.459086,-181.94754)"> - From c1062b631b529c2755abcce53924db472ee5360b Mon Sep 17 00:00:00 2001 From: Volker Braun Date: Sat, 1 Apr 2017 17:32:19 +0200 Subject: [PATCH 118/452] Disable garbage collection while testing ipdb --- src/sage/misc/trace.py | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/sage/misc/trace.py b/src/sage/misc/trace.py index efcaa33cc5f..5d4d8bc293c 100644 --- a/src/sage/misc/trace.py +++ b/src/sage/misc/trace.py @@ -46,10 +46,13 @@ def trace(code, preparse=True): TESTS: - The only real way to test this is via pexpect spawning a - sage subprocess that uses IPython. + For tests we disable garbage collection, see :trac:`21258` :: - :: + sage: import gc + sage: gc.disable() + + The only real way to test this is via pexpect spawning a + sage subprocess that uses IPython:: sage: import pexpect sage: s = pexpect.spawn('sage') @@ -59,9 +62,7 @@ def trace(code, preparse=True): sage: _ = s.expect('100', timeout=90) Seeing the ipdb prompt and the 2 \* 5 in the output below is a - strong indication that the trace command worked correctly. - - :: + strong indication that the trace command worked correctly:: sage: print(s.before[s.before.find('--'):]) --... @@ -75,6 +76,10 @@ def trace(code, preparse=True): Traceback (most recent call last): ... NotImplementedError: the trace command is not implemented in the Sage notebook; you must use the command line. + + Re-enable garbage collection:: + + sage: gc.enable() """ from sage.plot.plot import EMBEDDED_MODE if EMBEDDED_MODE: From db0460e04ff4bce8becc26804c8b2449673850b5 Mon Sep 17 00:00:00 2001 From: Matthias Goerner Date: Sat, 1 Apr 2017 09:48:40 -0700 Subject: [PATCH 119/452] Using AppleScript to set background image of the .app.dmg (for Mac installations) instead of the ds_store python package by Alastair Houghton. Mac OS 10.12 (Sierra) changed the proprietary .DS_Store file format (which contains the information where the background image is and how to position the icons) so the ds_store package broke. The advantage of AppleScript is that we are isolated from the details of the .DS_Store file and that the AppleScript API is hopefully more stable and reliable than trying to create the .DS_Store file itself which is proprietary and undocumented. The disadvantage is that this requires that we first produce a read-writable disk image and can compress it to a readable image only after we have mounted the disk image to run AppleScript to set the background image. This means that the build time is slightly longer and that we create a intermediate file several Gb in size. --- src/mac-app/Makefile | 56 ++++++++++++++++++++-------- src/mac-app/arrangeIcons.applescript | 38 +++++++++++++++++++ 2 files changed, 79 insertions(+), 15 deletions(-) create mode 100644 src/mac-app/arrangeIcons.applescript diff --git a/src/mac-app/Makefile b/src/mac-app/Makefile index 7aa1a6007bb..430121647aa 100644 --- a/src/mac-app/Makefile +++ b/src/mac-app/Makefile @@ -81,17 +81,18 @@ $(APP)/Contents/Resources/sage: $(APP) @# because $(APP) is newer than (the rsync preserves time) test -d $@ && touch $@ -# .DS_Store tells finder the icon position and background image to use -# when opening the dmg. -$(TARGET)/.DS_Store: tools/createDSStore/createDSStore.py - @# On some old Mac OS X, createDSStore fails when there already - @# is an existing file - rm -f $(TARGET)/.DS_Store - tools/createDSStore/createDSStore.py $(TARGET) $(TARGET) $(APP_NAME) - -$(TARGET)/.background.png: sage-dmg-background.png - cp sage-dmg-background.png $(TARGET)/.background.png +# The background image for the DMG. +# It contains the arrow pointing from the .app to the Applications +# folder. +# +# The background image should be at 72dpi. if a different resolution is +# set in the metadata, Finder produces weird results. +# +$(TARGET)/.background/sage.png: sage-dmg-background.png + mkdir -p $(TARGET)/.background + cp sage-dmg-background.png $(TARGET)/.background/sage.png +# Link to Applications $(TARGET)/Applications: rm -f $(TARGET)/Applications ln -s /Applications/ $(TARGET)/Applications @@ -100,19 +101,44 @@ $(TARGET)/Applications: $(TARGET)/README.txt: $(SAGE_ROOT)/src/bin/sage-README-osx.txt cp $^ $@ -non_app_files: $(TARGET)/README.txt $(TARGET)/.DS_Store $(TARGET)/.background.png $(TARGET)/Applications +non_app_files: $(TARGET)/README.txt $(TARGET)/.background/sage.png $(TARGET)/Applications sage_symlink: $(APP)/Contents/Resources/sage/sage rm -f $(APP)/sage ln -s Contents/Resources/sage/sage $(APP)/sage -# Compress the built directory into a DMG +# The arrangement of the icons and the "alias" for the background +# image are stored in a .DS_Store file. The .DS_Store file does +# not store the background image by relative path, but by "alias" +# which contains the volume name as well - so we cannot just +# generate one .DS_Store and copy it from version to version since +# the volume name contains the version. +# +# It would be nice if we could generate the .DS_Store directly +# instead of mounting the image before compressing it. +# Unfortunately, the .DS_Store format is proprietary and changed +# in Mac OS 10.12, so trying this with the ds_store python package +# did not work out (https://bitbucket.org/al45tair/ds_store/issues/7). +# Also see Ticket 20119 and 22739. + # Dependencies need to be in that order because non_app_files # needs the directory created by $(APP)/Contents/Resources/sage -$(DMG): $(APP)/Contents/Resources/sage sage_symlink non_app_files - hdiutil create -srcfolder $(TARGET) -volname $(TARGET) -format UDBZ $(DMG) +tmp-$(DMG): $(APP)/Contents/Resources/sage sage_symlink non_app_files + @# Create initial DMG + hdiutil create -srcfolder $(TARGET) -volname $(TARGET) -format UDRW tmp-$(DMG) + + @# Mount it so that we can run the Apple Script file on it + @# to arrange the icons and set the background image + mkdir -p mnt + hdiutil attach tmp-$(DMG) -mountpoint mnt + osascript arrangeIcons.applescript mnt $(APP_NAME) + hdiutil detach mnt + +# Compress the built directory into a DMG +$(DMG): tmp-$(DMG) + hdiutil convert -format UDBZ -o $(DMG) tmp-$(DMG) .PHONY: clean default debug app non_app_files clean: - rm -rf $(APP) build $(DMG) + rm -rf $(TARGET) build $(DMG) tmp-$(DMG) mnt diff --git a/src/mac-app/arrangeIcons.applescript b/src/mac-app/arrangeIcons.applescript new file mode 100644 index 00000000000..157b4d5a0f1 --- /dev/null +++ b/src/mac-app/arrangeIcons.applescript @@ -0,0 +1,38 @@ +on run (volname, appname) + + tell application "Finder" + tell disk (volname as string) + open + set opts to the icon view options of container window + tell opts + set arrangement to not arranged + set icon size to 88 + end tell + + # Path .background/sage.png needs to be converted + # .background:sage.png + set background picture of opts to file ".background:sage.png" + + tell container window + set current view to icon view + set toolbar visible to false + set statusbar visible to false + # The size of the window should match that of the image + set the bounds to {0, 0, 563, 348} + + set position of item "README.txt" to {462, 52} + set position of item "Applications" to {462, 212} + set position of item (appname as string) to {104, 212} + end tell + + # Some people report that the above settings are not applied + # unless we wait for a couple of seconds in some versions of + # Mac OS X. + update without registering applications + delay 3 + + close + end tell + end tell + +end run \ No newline at end of file From 8e10f56bfd47b651ebc1481de1c6cf05eeeb9396 Mon Sep 17 00:00:00 2001 From: Matthias Goerner Date: Sat, 1 Apr 2017 09:50:04 -0700 Subject: [PATCH 120/452] Deleting old code trying to directly create the .DS_Store file since we are now using AppleScript. --- src/mac-app/tools/createDSStore/README.txt | 10 - .../tools/createDSStore/biplist/__init__.py | 871 ------------ .../tools/createDSStore/createDSStore.py | 148 -- .../tools/createDSStore/ds_store/__init__.py | 3 - .../tools/createDSStore/ds_store/buddy.py | 456 ------- .../tools/createDSStore/ds_store/store.py | 1201 ----------------- .../tools/createDSStore/mac_alias/__init__.py | 14 - .../tools/createDSStore/mac_alias/alias.py | 587 -------- .../tools/createDSStore/mac_alias/osx.py | 823 ----------- .../tools/createDSStore/mac_alias/utils.py | 17 - src/mac-app/tools/createDSStore/six.py | 868 ------------ 11 files changed, 4998 deletions(-) delete mode 100644 src/mac-app/tools/createDSStore/README.txt delete mode 100644 src/mac-app/tools/createDSStore/biplist/__init__.py delete mode 100755 src/mac-app/tools/createDSStore/createDSStore.py delete mode 100644 src/mac-app/tools/createDSStore/ds_store/__init__.py delete mode 100644 src/mac-app/tools/createDSStore/ds_store/buddy.py delete mode 100644 src/mac-app/tools/createDSStore/ds_store/store.py delete mode 100644 src/mac-app/tools/createDSStore/mac_alias/__init__.py delete mode 100644 src/mac-app/tools/createDSStore/mac_alias/alias.py delete mode 100644 src/mac-app/tools/createDSStore/mac_alias/osx.py delete mode 100644 src/mac-app/tools/createDSStore/mac_alias/utils.py delete mode 100644 src/mac-app/tools/createDSStore/six.py diff --git a/src/mac-app/tools/createDSStore/README.txt b/src/mac-app/tools/createDSStore/README.txt deleted file mode 100644 index eca2dd2a659..00000000000 --- a/src/mac-app/tools/createDSStore/README.txt +++ /dev/null @@ -1,10 +0,0 @@ -All dependencies of createDSStore are available on http://pypi.python.org/ and -are included here in the following versions and under the following licenses: - -six 1.10.0 MIT -mac_alias 1.1.0 MIT -biplist 1.0.1 BSD -ds_store 1.0.1 MIT - -There are no dependencies on Mac OS X specific libraries so the code can -be run from Linux as well. diff --git a/src/mac-app/tools/createDSStore/biplist/__init__.py b/src/mac-app/tools/createDSStore/biplist/__init__.py deleted file mode 100644 index c2b93079ffc..00000000000 --- a/src/mac-app/tools/createDSStore/biplist/__init__.py +++ /dev/null @@ -1,871 +0,0 @@ -"""biplist -- a library for reading and writing binary property list files. - -Binary Property List (plist) files provide a faster and smaller serialization -format for property lists on OS X. This is a library for generating binary -plists which can be read by OS X, iOS, or other clients. - -The API models the plistlib API, and will call through to plistlib when -XML serialization or deserialization is required. - -To generate plists with UID values, wrap the values with the Uid object. The -value must be an int. - -To generate plists with NSData/CFData values, wrap the values with the -Data object. The value must be a string. - -Date values can only be datetime.datetime objects. - -The exceptions InvalidPlistException and NotBinaryPlistException may be -thrown to indicate that the data cannot be serialized or deserialized as -a binary plist. - -Plist generation example: - - from biplist import * - from datetime import datetime - plist = {'aKey':'aValue', - '0':1.322, - 'now':datetime.now(), - 'list':[1,2,3], - 'tuple':('a','b','c') - } - try: - writePlist(plist, "example.plist") - except (InvalidPlistException, NotBinaryPlistException), e: - print "Something bad happened:", e - -Plist parsing example: - - from biplist import * - try: - plist = readPlist("example.plist") - print plist - except (InvalidPlistException, NotBinaryPlistException), e: - print "Not a plist:", e -""" - -from collections import namedtuple -import datetime -import io -import math -import plistlib -from struct import pack, unpack, unpack_from -from struct import error as struct_error -import sys -import time - -try: - unicode - unicodeEmpty = r'' -except NameError: - unicode = str - unicodeEmpty = '' -try: - long -except NameError: - long = int -try: - {}.iteritems - iteritems = lambda x: x.iteritems() -except AttributeError: - iteritems = lambda x: x.items() - -__all__ = [ - 'Uid', 'Data', 'readPlist', 'writePlist', 'readPlistFromString', - 'writePlistToString', 'InvalidPlistException', 'NotBinaryPlistException' -] - -# Apple uses Jan 1, 2001 as a base for all plist date/times. -apple_reference_date = datetime.datetime.utcfromtimestamp(978307200) - -class Uid(object): - """Wrapper around integers for representing UID values. This - is used in keyed archiving.""" - integer = 0 - def __init__(self, integer): - self.integer = integer - - def __repr__(self): - return "Uid(%d)" % self.integer - - def __eq__(self, other): - if isinstance(self, Uid) and isinstance(other, Uid): - return self.integer == other.integer - return False - - def __cmp__(self, other): - return self.integer - other.integer - - def __lt__(self, other): - return self.integer < other.integer - - def __hash__(self): - return self.integer - - def __int__(self): - return int(self.integer) - -class Data(bytes): - """Wrapper around bytes to distinguish Data values.""" - -class InvalidPlistException(Exception): - """Raised when the plist is incorrectly formatted.""" - -class NotBinaryPlistException(Exception): - """Raised when a binary plist was expected but not encountered.""" - -def readPlist(pathOrFile): - """Raises NotBinaryPlistException, InvalidPlistException""" - didOpen = False - result = None - if isinstance(pathOrFile, (bytes, unicode)): - pathOrFile = open(pathOrFile, 'rb') - didOpen = True - try: - reader = PlistReader(pathOrFile) - result = reader.parse() - except NotBinaryPlistException as e: - try: - pathOrFile.seek(0) - result = None - if hasattr(plistlib, 'loads'): - contents = None - if isinstance(pathOrFile, (bytes, unicode)): - with open(pathOrFile, 'rb') as f: - contents = f.read() - else: - contents = pathOrFile.read() - result = plistlib.loads(contents) - else: - result = plistlib.readPlist(pathOrFile) - result = wrapDataObject(result, for_binary=True) - except Exception as e: - raise InvalidPlistException(e) - finally: - if didOpen: - pathOrFile.close() - return result - -def wrapDataObject(o, for_binary=False): - if isinstance(o, Data) and not for_binary: - v = sys.version_info - if not (v[0] >= 3 and v[1] >= 4): - o = plistlib.Data(o) - elif isinstance(o, (bytes, plistlib.Data)) and for_binary: - if hasattr(o, 'data'): - o = Data(o.data) - elif isinstance(o, tuple): - o = wrapDataObject(list(o), for_binary) - o = tuple(o) - elif isinstance(o, list): - for i in range(len(o)): - o[i] = wrapDataObject(o[i], for_binary) - elif isinstance(o, dict): - for k in o: - o[k] = wrapDataObject(o[k], for_binary) - return o - -def writePlist(rootObject, pathOrFile, binary=True): - if not binary: - rootObject = wrapDataObject(rootObject, binary) - if hasattr(plistlib, "dump"): - if isinstance(pathOrFile, (bytes, unicode)): - with open(pathOrFile, 'wb') as f: - return plistlib.dump(rootObject, f) - else: - return plistlib.dump(rootObject, pathOrFile) - else: - return plistlib.writePlist(rootObject, pathOrFile) - else: - didOpen = False - if isinstance(pathOrFile, (bytes, unicode)): - pathOrFile = open(pathOrFile, 'wb') - didOpen = True - writer = PlistWriter(pathOrFile) - result = writer.writeRoot(rootObject) - if didOpen: - pathOrFile.close() - return result - -def readPlistFromString(data): - return readPlist(io.BytesIO(data)) - -def writePlistToString(rootObject, binary=True): - if not binary: - rootObject = wrapDataObject(rootObject, binary) - if hasattr(plistlib, "dumps"): - return plistlib.dumps(rootObject) - elif hasattr(plistlib, "writePlistToBytes"): - return plistlib.writePlistToBytes(rootObject) - else: - return plistlib.writePlistToString(rootObject) - else: - ioObject = io.BytesIO() - writer = PlistWriter(ioObject) - writer.writeRoot(rootObject) - return ioObject.getvalue() - -def is_stream_binary_plist(stream): - stream.seek(0) - header = stream.read(7) - if header == b'bplist0': - return True - else: - return False - -PlistTrailer = namedtuple('PlistTrailer', 'offsetSize, objectRefSize, offsetCount, topLevelObjectNumber, offsetTableOffset') -PlistByteCounts = namedtuple('PlistByteCounts', 'nullBytes, boolBytes, intBytes, realBytes, dateBytes, dataBytes, stringBytes, uidBytes, arrayBytes, setBytes, dictBytes') - -class PlistReader(object): - file = None - contents = '' - offsets = None - trailer = None - currentOffset = 0 - - def __init__(self, fileOrStream): - """Raises NotBinaryPlistException.""" - self.reset() - self.file = fileOrStream - - def parse(self): - return self.readRoot() - - def reset(self): - self.trailer = None - self.contents = '' - self.offsets = [] - self.currentOffset = 0 - - def readRoot(self): - result = None - self.reset() - # Get the header, make sure it's a valid file. - if not is_stream_binary_plist(self.file): - raise NotBinaryPlistException() - self.file.seek(0) - self.contents = self.file.read() - if len(self.contents) < 32: - raise InvalidPlistException("File is too short.") - trailerContents = self.contents[-32:] - try: - self.trailer = PlistTrailer._make(unpack("!xxxxxxBBQQQ", trailerContents)) - offset_size = self.trailer.offsetSize * self.trailer.offsetCount - offset = self.trailer.offsetTableOffset - offset_contents = self.contents[offset:offset+offset_size] - offset_i = 0 - while offset_i < self.trailer.offsetCount: - begin = self.trailer.offsetSize*offset_i - tmp_contents = offset_contents[begin:begin+self.trailer.offsetSize] - tmp_sized = self.getSizedInteger(tmp_contents, self.trailer.offsetSize) - self.offsets.append(tmp_sized) - offset_i += 1 - self.setCurrentOffsetToObjectNumber(self.trailer.topLevelObjectNumber) - result = self.readObject() - except TypeError as e: - raise InvalidPlistException(e) - return result - - def setCurrentOffsetToObjectNumber(self, objectNumber): - self.currentOffset = self.offsets[objectNumber] - - def readObject(self): - result = None - tmp_byte = self.contents[self.currentOffset:self.currentOffset+1] - marker_byte = unpack("!B", tmp_byte)[0] - format = (marker_byte >> 4) & 0x0f - extra = marker_byte & 0x0f - self.currentOffset += 1 - - def proc_extra(extra): - if extra == 0b1111: - #self.currentOffset += 1 - extra = self.readObject() - return extra - - # bool, null, or fill byte - if format == 0b0000: - if extra == 0b0000: - result = None - elif extra == 0b1000: - result = False - elif extra == 0b1001: - result = True - elif extra == 0b1111: - pass # fill byte - else: - raise InvalidPlistException("Invalid object found at offset: %d" % (self.currentOffset - 1)) - # int - elif format == 0b0001: - extra = proc_extra(extra) - result = self.readInteger(pow(2, extra)) - # real - elif format == 0b0010: - extra = proc_extra(extra) - result = self.readReal(extra) - # date - elif format == 0b0011 and extra == 0b0011: - result = self.readDate() - # data - elif format == 0b0100: - extra = proc_extra(extra) - result = self.readData(extra) - # ascii string - elif format == 0b0101: - extra = proc_extra(extra) - result = self.readAsciiString(extra) - # Unicode string - elif format == 0b0110: - extra = proc_extra(extra) - result = self.readUnicode(extra) - # uid - elif format == 0b1000: - result = self.readUid(extra) - # array - elif format == 0b1010: - extra = proc_extra(extra) - result = self.readArray(extra) - # set - elif format == 0b1100: - extra = proc_extra(extra) - result = set(self.readArray(extra)) - # dict - elif format == 0b1101: - extra = proc_extra(extra) - result = self.readDict(extra) - else: - raise InvalidPlistException("Invalid object found: {format: %s, extra: %s}" % (bin(format), bin(extra))) - return result - - def readInteger(self, byteSize): - result = 0 - original_offset = self.currentOffset - data = self.contents[self.currentOffset:self.currentOffset + byteSize] - result = self.getSizedInteger(data, byteSize, as_number=True) - self.currentOffset = original_offset + byteSize - return result - - def readReal(self, length): - result = 0.0 - to_read = pow(2, length) - data = self.contents[self.currentOffset:self.currentOffset+to_read] - if length == 2: # 4 bytes - result = unpack('>f', data)[0] - elif length == 3: # 8 bytes - result = unpack('>d', data)[0] - else: - raise InvalidPlistException("Unknown real of length %d bytes" % to_read) - return result - - def readRefs(self, count): - refs = [] - i = 0 - while i < count: - fragment = self.contents[self.currentOffset:self.currentOffset+self.trailer.objectRefSize] - ref = self.getSizedInteger(fragment, len(fragment)) - refs.append(ref) - self.currentOffset += self.trailer.objectRefSize - i += 1 - return refs - - def readArray(self, count): - result = [] - values = self.readRefs(count) - i = 0 - while i < len(values): - self.setCurrentOffsetToObjectNumber(values[i]) - value = self.readObject() - result.append(value) - i += 1 - return result - - def readDict(self, count): - result = {} - keys = self.readRefs(count) - values = self.readRefs(count) - i = 0 - while i < len(keys): - self.setCurrentOffsetToObjectNumber(keys[i]) - key = self.readObject() - self.setCurrentOffsetToObjectNumber(values[i]) - value = self.readObject() - result[key] = value - i += 1 - return result - - def readAsciiString(self, length): - result = unpack("!%ds" % length, self.contents[self.currentOffset:self.currentOffset+length])[0] - self.currentOffset += length - return str(result.decode('ascii')) - - def readUnicode(self, length): - actual_length = length*2 - data = self.contents[self.currentOffset:self.currentOffset+actual_length] - # unpack not needed?!! data = unpack(">%ds" % (actual_length), data)[0] - self.currentOffset += actual_length - return data.decode('utf_16_be') - - def readDate(self): - result = unpack(">d", self.contents[self.currentOffset:self.currentOffset+8])[0] - # Use timedelta to workaround time_t size limitation on 32-bit python. - result = datetime.timedelta(seconds=result) + apple_reference_date - self.currentOffset += 8 - return result - - def readData(self, length): - result = self.contents[self.currentOffset:self.currentOffset+length] - self.currentOffset += length - return Data(result) - - def readUid(self, length): - return Uid(self.readInteger(length+1)) - - def getSizedInteger(self, data, byteSize, as_number=False): - """Numbers of 8 bytes are signed integers when they refer to numbers, but unsigned otherwise.""" - result = 0 - # 1, 2, and 4 byte integers are unsigned - if byteSize == 1: - result = unpack('>B', data)[0] - elif byteSize == 2: - result = unpack('>H', data)[0] - elif byteSize == 4: - result = unpack('>L', data)[0] - elif byteSize == 8: - if as_number: - result = unpack('>q', data)[0] - else: - result = unpack('>Q', data)[0] - elif byteSize <= 16: - # Handle odd-sized or integers larger than 8 bytes - # Don't naively go over 16 bytes, in order to prevent infinite loops. - result = 0 - if hasattr(int, 'from_bytes'): - result = int.from_bytes(data, 'big') - else: - for byte in data: - if not isinstance(byte, int): # Python3.0-3.1.x return ints, 2.x return str - byte = unpack_from('>B', byte)[0] - result = (result << 8) | byte - else: - raise InvalidPlistException("Encountered integer longer than 16 bytes.") - return result - -class HashableWrapper(object): - def __init__(self, value): - self.value = value - def __repr__(self): - return "" % [self.value] - -class BoolWrapper(object): - def __init__(self, value): - self.value = value - def __repr__(self): - return "" % self.value - -class FloatWrapper(object): - _instances = {} - def __new__(klass, value): - # Ensure FloatWrapper(x) for a given float x is always the same object - wrapper = klass._instances.get(value) - if wrapper is None: - wrapper = object.__new__(klass) - wrapper.value = value - klass._instances[value] = wrapper - return wrapper - def __repr__(self): - return "" % self.value - -class StringWrapper(object): - __instances = {} - - encodedValue = None - encoding = None - - def __new__(cls, value): - '''Ensure we only have a only one instance for any string, - and that we encode ascii as 1-byte-per character when possible''' - - encodedValue = None - - for encoding in ('ascii', 'utf_16_be'): - try: - encodedValue = value.encode(encoding) - except Exception: - pass - if encodedValue is not None: - if encodedValue not in cls.__instances: - cls.__instances[encodedValue] = super(StringWrapper, cls).__new__(cls) - cls.__instances[encodedValue].encodedValue = encodedValue - cls.__instances[encodedValue].encoding = encoding - return cls.__instances[encodedValue] - - raise ValueError('Unable to get ascii or utf_16_be encoding for %s' % repr(value)) - - def __len__(self): - '''Return roughly the number of characters in this string (half the byte length)''' - if self.encoding == 'ascii': - return len(self.encodedValue) - else: - return len(self.encodedValue)//2 - - @property - def encodingMarker(self): - if self.encoding == 'ascii': - return 0b0101 - else: - return 0b0110 - - def __repr__(self): - return '' % (self.encoding, self.encodedValue) - -class PlistWriter(object): - header = b'bplist00bybiplist1.0' - file = None - byteCounts = None - trailer = None - computedUniques = None - writtenReferences = None - referencePositions = None - wrappedTrue = None - wrappedFalse = None - - def __init__(self, file): - self.reset() - self.file = file - self.wrappedTrue = BoolWrapper(True) - self.wrappedFalse = BoolWrapper(False) - - def reset(self): - self.byteCounts = PlistByteCounts(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) - self.trailer = PlistTrailer(0, 0, 0, 0, 0) - - # A set of all the uniques which have been computed. - self.computedUniques = set() - # A list of all the uniques which have been written. - self.writtenReferences = {} - # A dict of the positions of the written uniques. - self.referencePositions = {} - - def positionOfObjectReference(self, obj): - """If the given object has been written already, return its - position in the offset table. Otherwise, return None.""" - return self.writtenReferences.get(obj) - - def writeRoot(self, root): - """ - Strategy is: - - write header - - wrap root object so everything is hashable - - compute size of objects which will be written - - need to do this in order to know how large the object refs - will be in the list/dict/set reference lists - - write objects - - keep objects in writtenReferences - - keep positions of object references in referencePositions - - write object references with the length computed previously - - computer object reference length - - write object reference positions - - write trailer - """ - output = self.header - wrapped_root = self.wrapRoot(root) - self.computeOffsets(wrapped_root, asReference=True, isRoot=True) - self.trailer = self.trailer._replace(**{'objectRefSize':self.intSize(len(self.computedUniques))}) - self.writeObjectReference(wrapped_root, output) - output = self.writeObject(wrapped_root, output, setReferencePosition=True) - - # output size at this point is an upper bound on how big the - # object reference offsets need to be. - self.trailer = self.trailer._replace(**{ - 'offsetSize':self.intSize(len(output)), - 'offsetCount':len(self.computedUniques), - 'offsetTableOffset':len(output), - 'topLevelObjectNumber':0 - }) - - output = self.writeOffsetTable(output) - output += pack('!xxxxxxBBQQQ', *self.trailer) - self.file.write(output) - - def wrapRoot(self, root): - if isinstance(root, bool): - if root is True: - return self.wrappedTrue - else: - return self.wrappedFalse - elif isinstance(root, float): - return FloatWrapper(root) - elif isinstance(root, set): - n = set() - for value in root: - n.add(self.wrapRoot(value)) - return HashableWrapper(n) - elif isinstance(root, dict): - n = {} - for key, value in iteritems(root): - n[self.wrapRoot(key)] = self.wrapRoot(value) - return HashableWrapper(n) - elif isinstance(root, list): - n = [] - for value in root: - n.append(self.wrapRoot(value)) - return HashableWrapper(n) - elif isinstance(root, tuple): - n = tuple([self.wrapRoot(value) for value in root]) - return HashableWrapper(n) - elif isinstance(root, (str, unicode)) and not isinstance(root, Data): - return StringWrapper(root) - elif isinstance(root, bytes): - return Data(root) - else: - return root - - def incrementByteCount(self, field, incr=1): - self.byteCounts = self.byteCounts._replace(**{field:self.byteCounts.__getattribute__(field) + incr}) - - def computeOffsets(self, obj, asReference=False, isRoot=False): - def check_key(key): - if key is None: - raise InvalidPlistException('Dictionary keys cannot be null in plists.') - elif isinstance(key, Data): - raise InvalidPlistException('Data cannot be dictionary keys in plists.') - elif not isinstance(key, StringWrapper): - raise InvalidPlistException('Keys must be strings.') - - def proc_size(size): - if size > 0b1110: - size += self.intSize(size) - return size - # If this should be a reference, then we keep a record of it in the - # uniques table. - if asReference: - if obj in self.computedUniques: - return - else: - self.computedUniques.add(obj) - - if obj is None: - self.incrementByteCount('nullBytes') - elif isinstance(obj, BoolWrapper): - self.incrementByteCount('boolBytes') - elif isinstance(obj, Uid): - size = self.intSize(obj.integer) - self.incrementByteCount('uidBytes', incr=1+size) - elif isinstance(obj, (int, long)): - size = self.intSize(obj) - self.incrementByteCount('intBytes', incr=1+size) - elif isinstance(obj, FloatWrapper): - size = self.realSize(obj) - self.incrementByteCount('realBytes', incr=1+size) - elif isinstance(obj, datetime.datetime): - self.incrementByteCount('dateBytes', incr=2) - elif isinstance(obj, Data): - size = proc_size(len(obj)) - self.incrementByteCount('dataBytes', incr=1+size) - elif isinstance(obj, StringWrapper): - size = proc_size(len(obj)) - self.incrementByteCount('stringBytes', incr=1+size) - elif isinstance(obj, HashableWrapper): - obj = obj.value - if isinstance(obj, set): - size = proc_size(len(obj)) - self.incrementByteCount('setBytes', incr=1+size) - for value in obj: - self.computeOffsets(value, asReference=True) - elif isinstance(obj, (list, tuple)): - size = proc_size(len(obj)) - self.incrementByteCount('arrayBytes', incr=1+size) - for value in obj: - asRef = True - self.computeOffsets(value, asReference=True) - elif isinstance(obj, dict): - size = proc_size(len(obj)) - self.incrementByteCount('dictBytes', incr=1+size) - for key, value in iteritems(obj): - check_key(key) - self.computeOffsets(key, asReference=True) - self.computeOffsets(value, asReference=True) - else: - raise InvalidPlistException("Unknown object type: %s (%s)" % (type(obj).__name__, repr(obj))) - - def writeObjectReference(self, obj, output): - """Tries to write an object reference, adding it to the references - table. Does not write the actual object bytes or set the reference - position. Returns a tuple of whether the object was a new reference - (True if it was, False if it already was in the reference table) - and the new output. - """ - position = self.positionOfObjectReference(obj) - if position is None: - self.writtenReferences[obj] = len(self.writtenReferences) - output += self.binaryInt(len(self.writtenReferences) - 1, byteSize=self.trailer.objectRefSize) - return (True, output) - else: - output += self.binaryInt(position, byteSize=self.trailer.objectRefSize) - return (False, output) - - def writeObject(self, obj, output, setReferencePosition=False): - """Serializes the given object to the output. Returns output. - If setReferencePosition is True, will set the position the - object was written. - """ - def proc_variable_length(format, length): - result = b'' - if length > 0b1110: - result += pack('!B', (format << 4) | 0b1111) - result = self.writeObject(length, result) - else: - result += pack('!B', (format << 4) | length) - return result - - def timedelta_total_seconds(td): - # Shim for Python 2.6 compatibility, which doesn't have total_seconds. - # Make one argument a float to ensure the right calculation. - return (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10.0**6) / 10.0**6 - - if setReferencePosition: - self.referencePositions[obj] = len(output) - - if obj is None: - output += pack('!B', 0b00000000) - elif isinstance(obj, BoolWrapper): - if obj.value is False: - output += pack('!B', 0b00001000) - else: - output += pack('!B', 0b00001001) - elif isinstance(obj, Uid): - size = self.intSize(obj.integer) - output += pack('!B', (0b1000 << 4) | size - 1) - output += self.binaryInt(obj.integer) - elif isinstance(obj, (int, long)): - byteSize = self.intSize(obj) - root = math.log(byteSize, 2) - output += pack('!B', (0b0001 << 4) | int(root)) - output += self.binaryInt(obj, as_number=True) - elif isinstance(obj, FloatWrapper): - # just use doubles - output += pack('!B', (0b0010 << 4) | 3) - output += self.binaryReal(obj) - elif isinstance(obj, datetime.datetime): - try: - timestamp = (obj - apple_reference_date).total_seconds() - except AttributeError: - timestamp = timedelta_total_seconds(obj - apple_reference_date) - output += pack('!B', 0b00110011) - output += pack('!d', float(timestamp)) - elif isinstance(obj, Data): - output += proc_variable_length(0b0100, len(obj)) - output += obj - elif isinstance(obj, StringWrapper): - output += proc_variable_length(obj.encodingMarker, len(obj)) - output += obj.encodedValue - elif isinstance(obj, bytes): - output += proc_variable_length(0b0101, len(obj)) - output += obj - elif isinstance(obj, HashableWrapper): - obj = obj.value - if isinstance(obj, (set, list, tuple)): - if isinstance(obj, set): - output += proc_variable_length(0b1100, len(obj)) - else: - output += proc_variable_length(0b1010, len(obj)) - - objectsToWrite = [] - for objRef in obj: - (isNew, output) = self.writeObjectReference(objRef, output) - if isNew: - objectsToWrite.append(objRef) - for objRef in objectsToWrite: - output = self.writeObject(objRef, output, setReferencePosition=True) - elif isinstance(obj, dict): - output += proc_variable_length(0b1101, len(obj)) - keys = [] - values = [] - objectsToWrite = [] - for key, value in iteritems(obj): - keys.append(key) - values.append(value) - for key in keys: - (isNew, output) = self.writeObjectReference(key, output) - if isNew: - objectsToWrite.append(key) - for value in values: - (isNew, output) = self.writeObjectReference(value, output) - if isNew: - objectsToWrite.append(value) - for objRef in objectsToWrite: - output = self.writeObject(objRef, output, setReferencePosition=True) - return output - - def writeOffsetTable(self, output): - """Writes all of the object reference offsets.""" - all_positions = [] - writtenReferences = list(self.writtenReferences.items()) - writtenReferences.sort(key=lambda x: x[1]) - for obj,order in writtenReferences: - # Porting note: Elsewhere we deliberately replace empty unicdoe strings - # with empty binary strings, but the empty unicode string - # goes into writtenReferences. This isn't an issue in Py2 - # because u'' and b'' have the same hash; but it is in - # Py3, where they don't. - if bytes != str and obj == unicodeEmpty: - obj = b'' - position = self.referencePositions.get(obj) - if position is None: - raise InvalidPlistException("Error while writing offsets table. Object not found. %s" % obj) - output += self.binaryInt(position, self.trailer.offsetSize) - all_positions.append(position) - return output - - def binaryReal(self, obj): - # just use doubles - result = pack('>d', obj.value) - return result - - def binaryInt(self, obj, byteSize=None, as_number=False): - result = b'' - if byteSize is None: - byteSize = self.intSize(obj) - if byteSize == 1: - result += pack('>B', obj) - elif byteSize == 2: - result += pack('>H', obj) - elif byteSize == 4: - result += pack('>L', obj) - elif byteSize == 8: - if as_number: - result += pack('>q', obj) - else: - result += pack('>Q', obj) - elif byteSize <= 16: - try: - result = pack('>Q', 0) + pack('>Q', obj) - except struct_error as e: - raise InvalidPlistException("Unable to pack integer %d: %s" % (obj, e)) - else: - raise InvalidPlistException("Core Foundation can't handle integers with size greater than 16 bytes.") - return result - - def intSize(self, obj): - """Returns the number of bytes necessary to store the given integer.""" - # SIGNED - if obj < 0: # Signed integer, always 8 bytes - return 8 - # UNSIGNED - elif obj <= 0xFF: # 1 byte - return 1 - elif obj <= 0xFFFF: # 2 bytes - return 2 - elif obj <= 0xFFFFFFFF: # 4 bytes - return 4 - # SIGNED - # 0x7FFFFFFFFFFFFFFF is the max. - elif obj <= 0x7FFFFFFFFFFFFFFF: # 8 bytes signed - return 8 - elif obj <= 0xffffffffffffffff: # 8 bytes unsigned - return 16 - else: - raise InvalidPlistException("Core Foundation can't handle integers with size greater than 8 bytes.") - - def realSize(self, obj): - return 8 diff --git a/src/mac-app/tools/createDSStore/createDSStore.py b/src/mac-app/tools/createDSStore/createDSStore.py deleted file mode 100755 index c935837360e..00000000000 --- a/src/mac-app/tools/createDSStore/createDSStore.py +++ /dev/null @@ -1,148 +0,0 @@ -#!/usr/bin/python - -""" -Creates a .DS_Store file that instructs Mac OS X's finder to use icon view with -a certain background image, and places the icons. - -This file is intended to be placed into the directory from which a dmg is -created for packaging an application. It needs as additional information the -name of the volume that will be used when creating the dmg and the name of the -application, including the .app, e.g., Sage-6.9.app. - -We could just always use the same .DS_Store that if the volume name and -application name were not changing. - -Most of the other values set in the .DS_Store have been taken from dmgbuild -(on pypi). However, dmgbuild requires the creation of a writable dmg, then -puts the .DS_Store file into it, and converts it to a read-only dmg. We avoid -this by using the volume name of the dmg instead. -See getBackgroundImage_alias. -""" -from __future__ import print_function - -import ds_store, mac_alias, biplist -import datetime, sys, os - -# Hard-coded data for finder -# The .background.png's dpi should be set to 72, otherwise, we get weird -# behavior (especially on Retina displays). This can be fixed with -# convert -density 72 -units pixelsperinch file.png file.png -backgroundImageSize = (563, 348) -backgroundImageName = '.background.png' -iconPositions = { - 'README.txt' : (497, 52), - 'Applications' : (462, 212), - 'app' : (104, 212) -} - -def getWindowData_bwsp(): - global backgroundImageSize - - return { - 'ShowTabView': False, - 'ShowStatusBar': False, - 'WindowBounds': '{{100, 100}, {%d, %d}}' % backgroundImageSize, - 'PreviewPaneVisibility': False, - 'ContainerShowSidebar': False, - 'ShowToolbar': False, - 'ShowPathbar': False, - 'SidebarWidth': 180, - 'ShowSidebar': False - } - -def getSomeTime(): - class UTC(datetime.tzinfo): - def utcoffset(self, dt): - return datetime.timedelta(0) - def tzname(self, dt): - return "UTC" - def dst(self, dt): - return datetime.timedelta(0) - - return datetime.datetime(2000, 1, 1, tzinfo = UTC()) - -def getBackgroundImage_alias(volume_name): - """ - The location of the background image is stored as "Alias" which consists - of the volume name and an absolute path with respect to that volume. - - Currently, we only support having the background image at the root of the - volume. - """ - - # Also see Alias.for_file which only works after the volume is mounted - - global backgroundImageName - - carbon_path = '%s:%s' % (volume_name, backgroundImageName) - - volume = mac_alias.VolumeInfo(volume_name, - getSomeTime(), - 'H+', - 0, - 0, - '\x00\x00') - - target = mac_alias.TargetInfo(0, - backgroundImageName, - 0, 0, - getSomeTime(), - '\x00\x00\x00\x00', - '\x00\x00\x00\x00', - folder_name = volume_name, - carbon_path = carbon_path) - - return mac_alias.Alias(volume = volume, target = target) - -def getBackgroundImage_icvp(volume_name): - return { - 'gridSpacing': 100.0, - 'textSize': 16.0, - 'viewOptionsVersion': 1, - 'backgroundColorBlue': 1.0, - 'scrollPositionX': 0.0, - 'iconSize': 88.0, - 'backgroundColorGreen': 1.0, - 'arrangeBy': 'none', - 'showIconPreview': False, - 'gridOffsetX': 0.0, - 'gridOffsetY': 0.0, - 'showItemInfo': False, - 'labelOnBottom': True, - 'backgroundType': 2, - 'scrollPositionY': 0.0, - 'backgroundColorRed': 1.0, - 'backgroundImageAlias': biplist.Data( - getBackgroundImage_alias(volume_name).to_bytes()) - } - -def createDSStore(target_dir, volume_name, app_name): - global iconPositions - - filePath = os.path.join(target_dir, '.DS_Store') - - with ds_store.DSStore.open(filePath, 'w+') as d: - d['.']['vSrn'] = ('long', 1) - d['.']['icvl'] = ('type', 'icnv') - d['.']['bwsp'] = getWindowData_bwsp() - d['.']['icvp'] = getBackgroundImage_icvp(volume_name) - - for key, iconPosition in iconPositions.items(): - if key == 'app': - name = app_name - else: - name = key - d[name]['Iloc'] = iconPosition - -if __name__ == '__main__': - if len(sys.argv) != 4: - print( - "Usage: %s TARGET_DIR VOLUME_NAME APP_NAME.app" % sys.argv[0], - file=sys.stderr) - print(" creates .DS_Store", file=sys.stderr) - sys.exit(1) - - createDSStore( - target_dir = sys.argv[1], - volume_name = sys.argv[2], - app_name = sys.argv[3]) diff --git a/src/mac-app/tools/createDSStore/ds_store/__init__.py b/src/mac-app/tools/createDSStore/ds_store/__init__.py deleted file mode 100644 index a6b81210495..00000000000 --- a/src/mac-app/tools/createDSStore/ds_store/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -from .store import DSStore, DSStoreEntry - -__all__ = ['DSStore', 'DSStoreEntry'] diff --git a/src/mac-app/tools/createDSStore/ds_store/buddy.py b/src/mac-app/tools/createDSStore/ds_store/buddy.py deleted file mode 100644 index 8811ffc6981..00000000000 --- a/src/mac-app/tools/createDSStore/ds_store/buddy.py +++ /dev/null @@ -1,456 +0,0 @@ -# -*- coding: utf-8 -*- -import os -import bisect -import struct -import binascii -import six - -class BuddyError (Exception): - pass - -class Block(object): - def __init__(self, allocator, offset, size): - self._allocator = allocator - self._offset = offset - self._size = size - self._value = bytearray(allocator.read (offset, size)) - self._pos = 0 - self._dirty = False - - def __len__(self): - return self._size - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, traceback): - self.close() - - def close(self): - if self._dirty: - self.flush() - - def flush(self): - if self._dirty: - self._dirty = False - self._allocator.write (self._offset, self._value) - - def invalidate(self): - self._dirty = False - - def zero_fill(self): - len = self._size - self._pos - zeroes = '\0' * len - self._value[self._pos:self._size] = zeroes - self._dirty = True - - def tell(self): - return self._pos - - def seek(self, pos, whence=os.SEEK_SET): - if whence == os.SEEK_CUR: - pos += self._pos - elif whence == os.SEEK_END: - pos = self._size - pos - - if pos < 0 or pos > self._size: - raise ValueError('Seek out of range in Block instance') - - self._pos = pos - - def read(self, size_or_format): - if isinstance(size_or_format, basestring): - size = struct.calcsize (size_or_format) - fmt = size_or_format - else: - size = size_or_format - fmt = None - - if self._size - self._pos < size: - raise BuddyError('Unable to read %lu bytes in block' % size) - - data = self._value[self._pos:self._pos + size] - self._pos += size - - if fmt is not None: - return struct.unpack (size_or_format, data) - else: - return data - - def write(self, data_or_format, *args): - if len(args): - data = struct.pack (data_or_format, *args) - else: - data = data_or_format - - if self._pos + len(data) > self._size: - raise ValueError('Attempt to write past end of Block') - - self._value[self._pos:self._pos + len(data)] = data - self._pos += len(data) - - self._dirty = True - - def insert(self, data_or_format, *args): - if len(args): - data = struct.pack (data_or_format, *args) - else: - data = data_or_format - - del self._value[-len(data):] - self._value[self._pos:self._pos] = data - self._pos += len(data) - - self._dirty = True - - def delete(self, size): - if self._pos + size > self._size: - raise ValueError('Attempt to delete past end of Block') - del self._value[self._pos:self._pos + size] - self._value += b'\0' * size - self._dirty = True - - def __str__(self): - return binascii.b2a_hex(self._value) - -class Allocator (object): - def __init__(self, the_file): - self._file = the_file - self._dirty = False - - self._file.seek(0) - - # Read the header - magic1, magic2, offset, size, offset2, self._unknown1 \ - = self.read (-4, '>I4sIII16s') - - if magic2 != 'Bud1' or magic1 != 1: - raise BuddyError('Not a buddy file') - - if offset != offset2: - raise BuddyError('Root addresses differ') - - self._root = Block(self, offset, size) - - # Read the block offsets - count, self._unknown2 = self._root.read('>II') - self._offsets = [] - c = (count + 255) & ~255 - while c: - self._offsets += self._root.read('>256I') - c -= 256 - self._offsets = self._offsets[:count] - - # Read the TOC - self._toc = {} - count = self._root.read('>I')[0] - for n in range(count): - nlen = self._root.read('B')[0] - name = str(self._root.read(nlen)) - value = self._root.read('>I')[0] - self._toc[name] = value - - # Read the free lists - self._free = [] - for n in range(32): - count = self._root.read('>I') - self._free.append(list(self._root.read('>%uI' % count))) - - @classmethod - def open(cls, file_or_name, mode='r+'): - if isinstance(file_or_name, basestring): - f = open(file_or_name, mode) - else: - f = file_or_name - - if mode == 'w' or mode == 'w+': - # Create an empty file in this case - f.truncate() - - # An empty root block needs 1264 bytes: - # - # 0 4 offset count - # 4 4 unknown - # 8 4 root block offset (2048) - # 12 255 * 4 padding (offsets are in multiples of 256) - # 1032 4 toc count (0) - # 1036 228 free list - # total 1264 - - # The free list will contain the following: - # - # 0 5 * 4 no blocks of width less than 5 - # 20 6 * 8 1 block each of widths 5 to 10 - # 68 4 no blocks of width 11 (allocated for the root) - # 72 19 * 8 1 block each of widths 12 to 30 - # 224 4 no blocks of width 31 - # total 228 - # - # (The reason for this layout is that we allocate 2**5 bytes for - # the header, which splits the initial 2GB region into every size - # below 2**31, including *two* blocks of size 2**5, one of which - # we take. The root block itself then needs a block of size - # 2**11. Conveniently, each of these initial blocks will be - # located at offset 2**n where n is its width.) - - # Write the header - header = struct.pack(b'>I4sIII16s', - 1, b'Bud1', - 2048, 1264, 2048, - b'\x00\x00\x10\x0c' - b'\x00\x00\x00\x87' - b'\x00\x00\x20\x0b' - b'\x00\x00\x00\x00') - f.write (header) - f.write(b'\0' * 2016) - - # Write the root block - free_list = [struct.pack(b'>5I', 0, 0, 0, 0, 0)] - for n in range(5, 11): - free_list.append (struct.pack (b'>II', 1, 2**n)) - free_list.append (struct.pack (b'>I', 0)) - for n in range(12, 31): - free_list.append (struct.pack (b'>II', 1, 2**n)) - free_list.append (struct.pack (b'>I', 0)) - - root = ''.join([struct.pack(b'>III', 1, 0, 2048 | 5), - struct.pack(b'>I', 0) * 255, - struct.pack(b'>I', 0)] + free_list) - f.write (root) - - return Allocator (f) - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, traceback): - self.close() - - def close(self): - self.flush() - self._file.close() - - def flush(self): - if self._dirty: - size = self._root_block_size() - self.allocate (size, 0) - with self.get_block(0) as rblk: - self._write_root_block_into (rblk) - - addr = self._offsets[0] - offset = addr & ~0x1f - size = 1 << (addr & 0x1f) - - self._file.seek(0, os.SEEK_SET) - self._file.write(struct.pack(b'>I4sIII16s', - 1, b'Bud1', - offset, size, offset, - self._unknown1)) - - self._dirty = False - - self._file.flush() - - def read(self, offset, size_or_format): - """Read data at `offset', or raise an exception. `size_or_format' - may either be a byte count, in which case we return raw data, - or a format string for `struct.unpack', in which case we - work out the size and unpack the data before returning it.""" - # N.B. There is a fixed offset of four bytes(!) - self._file.seek (offset + 4, os.SEEK_SET) - - if isinstance(size_or_format, basestring): - size = struct.calcsize (size_or_format) - fmt = size_or_format - else: - size = size_or_format - fmt = None - - ret = self._file.read (size) - if len(ret) < size: - ret += b'\0' * (size - len(ret)) - - if fmt is not None: - ret = struct.unpack (fmt, ret) - - return ret - - def write(self, offset, data_or_format, *args): - """Write data at `offset', or raise an exception. `data_or_format' - may either be the data to write, or a format string for `struct.pack', - in which case we pack the additional arguments and write the - resulting data.""" - # N.B. There is a fixed offset of four bytes(!) - self._file.seek (offset + 4, os.SEEK_SET) - - if len(args): - data = struct.pack (data_or_format, *args) - else: - data = data_or_format - - self._file.write (data) - - def get_block(self, block): - try: - addr = self._offsets[block] - except IndexError: - return None - - offset = addr & ~0x1f - size = 1 << (addr & 0x1f) - - return Block(self, offset, size) - - def _root_block_size(self): - """Return the number of bytes required by the root block.""" - # Offsets - size = 8 - size += 4 * ((len(self._offsets) + 255) & ~255) - - # TOC - size += 4 - size += sum([5 + len(s) for s in self._toc]) - - # Free list - size += sum([4 + 4 * len(fl) for fl in self._free]) - - return size - - def _write_root_block_into(self, block): - # Offsets - block.write('>II', len(self._offsets), self._unknown2) - block.write('>%uI' % len(self._offsets), *self._offsets) - extra = len(self._offsets) & 255 - if extra: - block.write(b'\0\0\0\0' * (256 - extra)) - - # TOC - keys = self._toc.keys() - keys.sort() - - block.write('>I', len(keys)) - for k in keys: - b = k.encode('utf-8') - block.write('B', len(b)) - block.write(b) - block.write('>I', self._toc[k]) - - # Free list - for w, f in enumerate(self._free): - block.write('>I', len(f)) - if len(f): - block.write('>%uI' % len(f), *f) - - def _buddy(self, offset, width): - f = self._free[width] - b = offset ^ (1 << width) - - try: - ndx = f.index(b) - except ValueError: - ndx = None - - return (f, b, ndx) - - def _release(self, offset, width): - # Coalesce - while True: - f,b,ndx = self._buddy (offset, width) - - if ndx is None: - break - - offset &= b - width += 1 - del f[ndx] - - # Add to the list - bisect.insort(f, offset) - - # Mark as dirty - self._dirty = True - - def _alloc(self, width): - w = width - while not self._free[w]: - w += 1 - while w > width: - offset = self._free[w].pop(0) - w -= 1 - self._free[w] = [offset, offset ^ (1 << w)] - self._dirty = True - return self._free[width].pop(0) - - def allocate(self, bytes, block=None): - """Allocate or reallocate a block such that it has space for at least - `bytes' bytes.""" - if block is None: - # Find the first unused block - try: - block = self._offsets.index(0) - except ValueError: - block = len(self._offsets) - self._offsets.append(0) - - # Compute block width - width = max(bytes.bit_length(), 5) - - addr = self._offsets[block] - offset = addr & ~0x1f - - if addr: - blkwidth = addr & 0x1f - if blkwidth == width: - return block - self._release (offset, width) - self._offsets[block] = 0 - - offset = self._alloc(width) - self._offsets[block] = offset | width - return block - - def release(self, block): - addr = self._offsets[block] - - if addr: - width = addr & 0x1f - offset = addr & ~0x1f - self._release (offset, width) - - if block == len(self._offsets): - del self._offsets[block] - else: - self._offsets[block] = 0 - - def __len__(self): - return len(self._toc) - - def __getitem__(self, key): - if not isinstance(key, basestring): - raise TypeError('Keys must be of string type') - return self._toc[key] - - def __setitem__(self, key, value): - if not isinstance(key, basestring): - raise TypeError('Keys must be of string type') - self._toc[key] = value - self._dirty = True - - def __delitem__(self, key): - if not isinstance(key, basestring): - raise TypeError('Keys must be of string type') - del self._toc[key] - self._dirty = True - - def iterkeys(self): - return six.iterkeys(self._toc) - - def keys(self): - return six.iterkeys(self._toc) - - def __iter__(self): - return six.iterkeys(self._toc) - - def __contains__(self, key): - return key in self._toc - diff --git a/src/mac-app/tools/createDSStore/ds_store/store.py b/src/mac-app/tools/createDSStore/ds_store/store.py deleted file mode 100644 index 7e62fc194de..00000000000 --- a/src/mac-app/tools/createDSStore/ds_store/store.py +++ /dev/null @@ -1,1201 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals -from __future__ import print_function - -import binascii -import struct -import biplist -import six - -from . import buddy - -class ILocCodec (object): - @staticmethod - def encode(point): - return struct.pack(b'>IIII', point[0], point[1], - 0xffffffff, 0xffff0000) - - @staticmethod - def decode(bytes): - x, y = struct.unpack(b'>II', bytes[:8]) - return (x, y) - -class PlistCodec (object): - @staticmethod - def encode(plist): - return biplist.writePlistToString(plist) - - @staticmethod - def decode(bytes): - return biplist.readPlistFromString(bytes) - -# This list tells the code how to decode particular kinds of entry in the -# .DS_Store file. This is really a convenience, and we currently only -# support a tiny subset of the possible entry types. -codecs = { - 'Iloc': ILocCodec, - 'bwsp': PlistCodec, - 'lsvp': PlistCodec, - 'lsvP': PlistCodec, - 'icvp': PlistCodec, - } - -class DSStoreEntry (object): - """Holds the data from an entry in a ``.DS_Store`` file. Note that this is - not meant to represent the entry itself---i.e. if you change the type - or value, your changes will *not* be reflected in the underlying file. - - If you want to make a change, you should either use the :class:`DSStore` - object's :meth:`DSStore.insert` method (which will replace a key if it - already exists), or the mapping access mode for :class:`DSStore` (often - simpler anyway). - """ - def __init__(self, filename, code, typecode, value=None): - self.filename = filename - self.code = code - self.type = typecode - self.value = value - - @classmethod - def read(cls, block): - """Read a ``.DS_Store`` entry from the containing Block""" - # First read the filename - nlen = block.read(b'>I')[0] - filename = block.read(2 * nlen).decode('utf-16be') - - # Next, read the code and type - code, typecode = block.read(b'>4s4s') - - # Finally, read the data - if typecode == 'bool': - value = block.read(b'>?')[0] - elif typecode == 'long' or typecode == 'shor': - value = block.read(b'>I')[0] - elif typecode == 'blob': - vlen = block.read(b'>I')[0] - value = block.read(vlen) - - codec = codecs.get(code, None) - if codec: - value = codec.decode(value) - typecode = codec - elif typecode == 'ustr': - vlen = block.read(b'>I')[0] - value = block.read(2 * vlen).decode('utf-16be') - elif typecode == 'type': - value = block.read(b'>4s')[0] - elif typecode == 'comp' or typecode == 'dutc': - value = block.read(b'>Q')[0] - else: - raise ValueError('Unknown type code "%s"' % typecode) - - return DSStoreEntry (filename, code, typecode, value) - - def __lt__(self, other): - if not isinstance(other, DSStoreEntry): - raise TypeError('Can only compare against other DSStoreEntry objects') - sfl = self.filename.lower() - ofl = other.filename.lower() - return (sfl < ofl - or (self.filename == other.filename - and self.code < other.code)) - - def __le__(self, other): - if not isinstance(other, DSStoreEntry): - raise TypeError('Can only compare against other DSStoreEntry objects') - sfl = self.filename.lower() - ofl = other.filename.lower() - return (sfl < ofl - or (sfl == ofl - and self.code <= other.code)) - - def __eq__(self, other): - if not isinstance(other, DSStoreEntry): - raise TypeError('Can only compare against other DSStoreEntry objects') - sfl = self.filename.lower() - ofl = other.filename.lower() - return (sfl == ofl - and self.code == other.code) - - def __ne__(self, other): - if not isinstance(other, DSStoreEntry): - raise TypeError('Can only compare against other DSStoreEntry objects') - sfl = self.filename.lower() - ofl = other.filename.lower() - return (sfl != ofl - or self.code != other.code) - - def __gt__(self, other): - if not isinstance(other, DSStoreEntry): - raise TypeError('Can only compare against other DSStoreEntry objects') - sfl = self.filename.lower() - ofl = other.filename.lower() - return (sfl > ofl - or (sfl == ofl - and self.code > other.code)) - - def __ge__(self, other): - if not isinstance(other, DSStoreEntry): - raise TypeError('Can only compare against other DSStoreEntry objects') - sfl = self.filename.lower() - ofl = other.filename.lower() - return (sfl > ofl - or (sfl == ofl - and self.code >= other.code)) - - def __cmp__(self, other): - if not isinstance(other, DSStoreEntry): - raise TypeError('Can only compare against other DSStoreEntry objects') - r = cmp (self.filename.lower(), other.filename.lower()) - if r: - return r - return cmp (self.code, other.code) - - def byte_length(self): - """Compute the length of this entry, in bytes""" - utf16 = self.filename.encode('utf-16be') - l = 4 + len(utf16) + 8 - - if isinstance(self.type, basestring): - entry_type = self.type - value = self.value - else: - entry_type = 'blob' - value = self.type.encode(self.value) - - if entry_type == 'bool': - l += 1 - elif entry_type == 'long' or entry_type == 'shor': - l += 4 - elif entry_type == 'blob': - l += 4 + len(value) - elif entry_type == 'ustr': - utf16 = value.encode('utf-16be') - l += 4 + len(utf16) - elif entry_type == 'type': - l += 4 - elif entry_type == 'comp' or entry_type == 'dutc': - l += 8 - else: - raise ValueError('Unknown type code "%s"' % entry_type) - - return l - - def write(self, block, insert=False): - """Write this entry to the specified Block""" - if insert: - w = block.insert - else: - w = block.write - - if isinstance(self.type, basestring): - entry_type = self.type - value = self.value - else: - entry_type = 'blob' - value = self.type.encode(self.value) - - utf16 = self.filename.encode('utf-16be') - w(b'>I', len(utf16) / 2) - w(utf16) - w(b'>4s4s', self.code.encode('utf-8'), entry_type.encode('utf-8')) - - if entry_type == 'bool': - w(b'>?', value) - elif entry_type == 'long' or entry_type == 'shor': - w(b'>I', value) - elif entry_type == 'blob': - w(b'>I', len(value)) - w(value) - elif entry_type == 'ustr': - utf16 = value.encode('utf-16be') - w(b'>I', len(utf16) / 2) - w(utf16) - elif entry_type == 'type': - w(b'>4s', value.encode('utf-8')) - elif entry_type == 'comp' or entry_type == 'dutc': - w(b'>Q', value) - else: - raise ValueError('Unknown type code "%s"' % entry_type) - - def __repr__(self): - return '<%s %s>' % (self.filename, self.code) - -class DSStore (object): - """Python interface to a ``.DS_Store`` file. Works by manipulating the file - on the disk---so this code will work with ``.DS_Store`` files for *very* - large directories. - - A :class:`DSStore` object can be used as if it was a mapping, e.g.:: - - d['foobar.dat']['Iloc'] - - will fetch the "Iloc" record for "foobar.dat", or raise :class:`KeyError` if - there is no such record. If used in this manner, the :class:`DSStore` object - will return (type, value) tuples, unless the type is "blob" and the module - knows how to decode it. - - Currently, we know how to decode "Iloc", "bwsp", "lsvp", "lsvP" and "icvp" - blobs. "Iloc" decodes to an (x, y) tuple, while the others are all decoded - using ``biplist``. - - Assignment also works, e.g.:: - - d['foobar.dat']['note'] = ('ustr', u'Hello World!') - - as does deletion with ``del``:: - - del d['foobar.dat']['note'] - - This is usually going to be the most convenient interface, though - occasionally (for instance when creating a new ``.DS_Store`` file) you - may wish to drop down to using :class:`DSStoreEntry` objects directly.""" - def __init__(self, store): - self._store = store - self._superblk = self._store['DSDB'] - with self._get_block(self._superblk) as s: - self._rootnode, self._levels, self._records, \ - self._nodes, self._page_size = s.read(b'>IIIII') - self._min_usage = 2 * self._page_size / 3 - self._dirty = False - - @classmethod - def open(cls, file_or_name, mode='r+', initial_entries=None): - """Open a ``.DS_Store`` file; pass either a Python file object, or a - filename in the ``file_or_name`` argument and a file access mode in - the ``mode`` argument. If you are creating a new file using the "w" - or "w+" modes, you may also specify a list of entries with which - to initialise the file.""" - store = buddy.Allocator.open (file_or_name, mode) - - if mode == 'w' or mode == 'w+': - superblk = store.allocate(20) - store['DSDB'] = superblk - page_size = 4096 - - if not initial_entries: - root = store.allocate(page_size) - - with store.get_block(root) as rootblk: - rootblk.zero_fill() - - with store.get_block(superblk) as s: - s.write(b'>IIIII', root, 0, 0, 1, page_size) - else: - # Make sure they're in sorted order - initial_entries = list(initial_entries) - initial_entries.sort() - - # Construct the tree - current_level = initial_entries - next_level = [] - levels = [] - ptr_size = 0 - node_count = 0 - while True: - total = 8 - nodes = [] - node = [] - for e in current_level: - new_total = total + ptr_size + e.byte_length() - if new_total > page_size: - nodes.append(node) - next_level.append(e) - total = 8 - node = [] - else: - total = new_total - node.append(e) - if node: - nodes.append(node) - - node_count += len(nodes) - levels.append(nodes) - - if len(nodes) == 1: - break - - current_level = next_level - next_level = [] - ptr_size = 4 - - # Allocate nodes - ptrs = [store.allocate(page_size) for n in range(node_count)] - - # Generate nodes - pointers = [] - prev_pointers = None - for level in levels: - ppndx = 0 - lptrs = ptrs[-len(level):] - del ptrs[-len(level):] - for node in level: - ndx = lptrs.pop(0) - if prev_pointers is None: - with store.get_block(ndx) as block: - block.write(b'>II', 0, len(node)) - for e in node: - e.write(block) - else: - next_node = prev_pointers[ppndx + len(node)] - node_ptrs = prev_pointers[ppndx:ppndx+len(node)] - - with store.get_block(ndx) as block: - block.write(b'>II', next_node, len(node)) - for ptr, e in zip(node_ptrs, node): - block.write(b'>I', ptr) - e.write(block) - - pointers.append(ndx) - prev_pointers = pointers - pointers = [] - - root = prev_pointers[0] - - with store.get_block(superblk) as s: - s.write(b'>IIIII', root, len(levels), len(initial_entries), - node_count, page_size) - - return DSStore(store) - - def _get_block(self, number): - return self._store.get_block(number) - - def flush(self): - """Flush any dirty data back to the file.""" - if self._dirty: - self._dirty = False - - with self._get_block(self._superblk) as s: - s.write(b'>IIIII', self._rootnode, self._levels, self._records, - self._nodes, self._page_size) - self._store.flush() - - def close(self): - """Flush dirty data and close the underlying file.""" - self.flush() - self._store.close() - - def __enter__(self): - return self - - def __exit__(self, exc_type, exc_value, traceback): - self.close() - - # Internal B-Tree nodes look like this: - # - # [ next | count | (ptr0 | rec0) | (ptr1 | rec1) ... (ptrN | recN) ] - - # Leaf nodes look like this: - # - # [ 0 | count | rec0 | rec1 ... recN ] - - # Iterate over the tree, starting at `node' - def _traverse(self, node): - if node is None: - node = self._rootnode - with self._get_block(node) as block: - next_node, count = block.read(b'>II') - if next_node: - for n in range(count): - ptr = block.read(b'>I')[0] - for e in self._traverse(ptr): - yield e - e = DSStoreEntry.read(block) - yield e - for e in self._traverse(next_node): - yield e - else: - for n in range(count): - e = DSStoreEntry.read(block) - yield e - - # Display the data in `node' - def _dump_node(self, node): - with self._get_block(node) as block: - next_node, count = block.read(b'>II') - print('next: %u\ncount: %u\n' % (next_node, count)) - for n in range(count): - if next_node: - ptr = block.read(b'>I')[0] - print('%8u ' % ptr, end=' ') - else: - print(' ', end=' ') - e = DSStoreEntry.read(block) - print(e, ' (%u)' % e.byte_length()) - print('used: %u' % block.tell()) - - # Display the data in the super block - def _dump_super(self): - print('root: %u\nlevels: %u\nrecords: %u\nnodes: %u\npage-size: %u' \ - % (self._rootnode, self._levels, self._records, - self._nodes, self._page_size)) - - # Splits entries across two blocks, returning one pivot - # - # Tries to balance the block usage across the two as best it can - def _split2(self, blocks, entries, pointers, before, internal): - left_block = blocks[0] - right_block = blocks[1] - - count = len(entries) - - # Find the feasible splits - best_split = None - best_diff = None - total = before[count] - - if 8 + total <= self._page_size: - # We can use a *single* node for this - best_split = count - else: - # Split into two nodes - for n in range(1, count - 1): - left_size = 8 + before[n] - right_size = 8 + total - before[n + 1] - - if left_size > self._page_size: - break - if right_size > self._page_size: - continue - - diff = abs(left_size - right_size) - - if best_split is None or diff < best_diff: - best_split = n - best_diff = diff - - if best_split is None: - return None - - # Write the nodes - left_block.seek(0) - if internal: - next_node = pointers[best_split] - else: - next_node = 0 - left_block.write(b'>II', next_node, best_split) - - for n in range(best_split): - if internal: - left_block.write(b'>I', pointers[n]) - entries[n].write(left_block) - - left_block.zero_fill() - - if best_split == count: - return [] - - right_block.seek(0) - if internal: - next_node = pointers[count] - else: - next_node = 0 - right_block.write(b'>II', next_node, count - best_split - 1) - - for n in range(best_split + 1, count): - if internal: - right_block.write(b'>I', pointers[n]) - entries[n].write(right_block) - - right_block.zero_fill() - - pivot = entries[best_split] - - return [pivot] - - def _split(self, node, entry, right_ptr=0): - self._nodes += 1 - self._dirty = True - new_right = self._store.allocate(self._page_size) - with self._get_block(node) as block, \ - self._get_block(new_right) as right_block: - - # First, measure and extract all the elements - entry_size = entry.byte_length() - entry_pos = None - next_node, count = block.read(b'>II') - if next_node: - entry_size += 4 - pointers = [] - entries = [] - before = [] - total = 0 - for n in range(count): - pos = block.tell() - if next_node: - ptr = block.read(b'>I')[0] - pointers.append(ptr) - e = DSStoreEntry.read(block) - if e > entry: - entry_pos = n - entries.append(entry) - pointers.append(right_ptr) - before.append(total) - total += entry_Size - entries.append(e) - before.append(total) - total += block.tell() - pos - before.append(total) - if next_node: - pointers.append(next_node) - - pivot = self._split2([left_block, right_block], - entries, pointers, before, - bool(next_node))[0] - - self._records += 1 - self._nodes += 1 - self._dirty = True - - return (pivot, new_right) - - # Allocate a new root node containing the element `pivot' and the pointers - # `left' and `right' - def _new_root(self, left, pivot, right): - new_root = self._store.allocate(self._page_size) - with self._get_block(new_root) as block: - block.write(b'>III', right, 1, left) - pivot.write(block) - self._rootnode = new_root - self._levels += 1 - self._nodes += 1 - self._dirty = True - - # Insert an entry into an inner node; `path' is the path from the root - # to `node', not including `node' itself. `right_ptr' is the new node - # pointer (inserted to the RIGHT of `entry') - def _insert_inner(self, path, node, entry, right_ptr): - with self._get_block(node) as block: - next_node, count = block.read(b'>II') - insert_pos = None - insert_ndx = None - n = 0 - while n < count: - pos = block.tell() - ptr = block.read(b'>I')[0] - e = DSStoreEntry.read(block) - if e == entry: - if n == count - 1: - right_ptr = next_node - next_node = ptr - block_seek(pos) - else: - right_ptr = block.read(b'>I')[0] - block.seek(pos + 4) - insert_pos = pos - insert_ndx = n - block.delete(e.byte_length() + 4) - count -= 1 - self._records += 1 - self._dirty = True - continue - elif insert_pos is None and e > entry: - insert_pos = pos - insert_ndx = n - n += 1 - if insert_pos is None: - insert_pos = block.tell() - insert_ndx = count - remaining = self._page_size - block.tell() - - if remaining < entry.byte_length() + 4: - pivot, new_right = self._split (node, entry, right_ptr) - if path: - self._insert_inner(path[:-1], path[-1], pivot, new_right) - else: - self._new_root(node, pivot, new_right) - else: - if insert_ndx == count: - block.seek(insert_pos) - block.write(b'>I', next_node) - entry.write(block) - next_node = right_ptr - else: - block.seek(insert_pos + 4) - entry.write(block, True) - block.insert('>I', right_ptr) - block.seek(0) - count += 1 - block.write(b'>II', next_node, count) - self._records += 1 - self._dirty = True - - # Insert `entry' into the leaf node `node' - def _insert_leaf(self, path, node, entry): - with self._get_block(node) as block: - next_node, count = block.read(b'>II') - insert_pos = None - insert_ndx = None - n = 0 - while n < count: - pos = block.tell() - e = DSStoreEntry.read(block) - if e == entry: - insert_pos = pos - insert_ndx = n - block.seek(pos) - block.delete(e.byte_length()) - count -= 1 - self._records += 1 - self._dirty = True - continue - elif insert_pos is None and e > entry: - insert_pos = pos - insert_ndx = n - n += 1 - if insert_pos is None: - insert_pos = block.tell() - insert_ndx = count - remaining = self._page_size - block.tell() - - if remaining < entry.byte_length(): - pivot, new_right = self._split (node, entry) - if path: - self._insert_inner(path[:-1], path[-1], pivot, new_right) - else: - self._new_root(node, pivot, new_right) - else: - block.seek(insert_pos) - entry.write(block, True) - block.seek(0) - count += 1 - block.write(b'>II', next_node, count) - self._records += 1 - self._dirty = True - - def insert(self, entry): - """Insert ``entry`` (which should be a :class:`DSStoreEntry`) - into the B-Tree.""" - path = [] - node = self._rootnode - while True: - with self._get_block(node) as block: - next_node, count = block.read(b'>II') - if next_node: - for n in range(count): - ptr = block.read(b'>I')[0] - e = DSStoreEntry.read(block) - if entry < e: - next_node = ptr - break - elif entry == e: - # If we find an existing entry the same, replace it - self._insert_inner (path, node, entry, None) - return - path.append(node) - node = next_node - else: - self._insert_leaf (path, node, entry) - return - - # Return usage information for the specified `node' - def _block_usage(self, node): - with self._get_block(node) as block: - next_node, count = block.read(b'>II') - - for n in range(count): - if next_node: - ptr = block.read(b'>I')[0] - e = DSStoreEntry.read(block) - - used = block.tell() - - return (count, used) - - # Splits entries across three blocks, returning two pivots - def _split3(self, blocks, entries, pointers, before, internal): - count = len(entries) - - # Find the feasible splits - best_split = None - best_diff = None - total = before[count] - for n in range(1, count - 3): - left_size = 8 + before[n] - remaining = 16 + total - before[n + 1] - - if left_size > self._page_size: - break - if remaining > 2 * self._page_size: - continue - - for m in range(n + 2, count - 1): - mid_size = 8 + before[m] - before[n + 1] - right_size = 8 + total - before[m + 1] - - if mid_size > self._page_size: - break - if right_size > self._page_size: - continue - - diff = abs(left_size - mid_size) * abs(right_size - mid_size) - - if best_split is None or diff < best_diff: - best_split = (n, m, count) - best_diff = diff - - if best_split is None: - return None - - # Write the nodes - prev_split = -1 - for block, split in zip(blocks, best_split): - block.seek(0) - if internal: - next_node = pointers[split] - else: - next_node = 0 - block.write(b'>II', next_node, split) - - for n in range(prev_split + 1, split): - if internal: - block.write(b'>I', pointers[n]) - entries[n].write(block) - - block.zero_fill() - - prev_split = split - - return (entries[best_split[0]], entries[best_split[1]]) - - # Extract all of the entries from the specified list of `blocks', - # separating them by the specified `pivots'. Also computes the - # amount of space used before each entry. - def _extract(self, blocks, pivots): - pointers = [] - entries = [] - before = [] - total = 0 - ppivots = pivots + [None] - for b,p in zip(blocks, ppivots): - b.seek(0) - next_node, count = b.read(b'>II') - for n in range(count): - pos = b.tell() - if next_node: - ptr = b.read(b'>I')[0] - pointers.append(ptr) - e = DSStoreEntry.read(b) - entries.append(e) - before.append(total) - total += b.tell() - pos - if next_node: - pointers.append(next_node) - if p: - entries.append(p) - before.append(total) - total += p.byte_length() - if next_node: - total += 4 - before.append(total) - - return (entries, pointers, before) - - # Rebalance the specified `node', whose path from the root is `path'. - def _rebalance(self, path, node): - # Can't rebalance the root - if not path: - return - - with self._get_block(node) as block: - next_node, count = block.read(b'>II') - - with self._get_block(path[-1]) as parent: - # Find the left and right siblings and respective pivots - parent_next, parent_count = parent.read(b'>II') - left_pos = None - left_node = None - left_pivot = None - node_pos = None - right_pos = None - right_node = None - right_pivot = None - prev_e = prev_ptr = prev_pos = None - for n in range(parent_count): - pos = parent.tell() - ptr = parent.read(b'>I')[0] - e = DSStoreEntry.read(parent) - - if ptr == node: - node_pos = pos - right_pivot = e - left_pos = prev_pos - left_pivot = prev_e - left_node = prev_ptr - elif prev_ptr == node: - right_node = ptr - right_pos = pos - break - - prev_e = e - prev_ptr = ptr - prev_pos = pos - - if parent_next == node: - node_pos = parent.tell() - left_pos = prev_pos - left_pivot = prev_e - left_node = prev_ptr - elif right_node is None: - right_node = parent_next - right_pos = parent.tell() - - parent_used = parent.tell() - - if left_node and right_node: - with self._get_block(left_node) as left, \ - self._get_block(right_node) as right: - blocks = [left, block, right] - pivots = [left_pivot, right_pivot] - - entries, pointers, before = self._extract(blocks, pivots) - - # If there's a chance that we could use two pages instead - # of three, go for it - pivots = self._split2 (blocks, entries, pointers, - before, bool(next_node)) - if pivots is None: - ptrs = [left_node, node, right_node] - pivots = self._split3 (blocks, entries, pointers, - before, bool(next_node)) - else: - if pivots: - ptrs = [left_node, node] - else: - ptrs = [left_node] - self._store.release (node) - self._nodes -= 1 - node = left_node - self._store.release (right_node) - self._nodes -= 1 - self._dirty = True - - # Remove the pivots from the parent - with self._get_block(path[-1]) as parent: - if right_node == parent_next: - parent.seek(left_pos) - parent.delete(right_pos - left_pos) - parent_next = left_node - else: - parent.seek(left_pos + 4) - parent.delete(right_pos - left_pos) - parent.seek(0) - parent_count -= 2 - parent.write(b'>II', parent_next, parent_count) - self._records -= 2 - - # Replace with those in pivots - for e,rp in zip(pivots, ptrs[1:]): - self._insert_inner(path[:-1], path[-1], e, rp) - elif left_node: - with self._get_block(left_node) as left: - blocks = [left, block] - pivots = [left_pivot] - - entries, pointers, before = self._extract(blocks, pivots) - - pivots = self._split2 (blocks, entries, pointers, - before, bool(next_node)) - - # Remove the pivot from the parent - with self._get_block(path[-1]) as parent: - if node == parent_next: - parent.seek(left_pos) - parent.delete(node_pos - left_pos) - parent_next = left_node - else: - parent.seek(left_pos + 4) - parent.delete(node_pos - left_pos) - parent.seek(0) - parent_count -= 1 - parent.write(b'>II', parent_next, parent_count) - self._records -= 1 - - # Replace the pivot - if pivots: - self._insert_inner(path[:-1], path[-1], pivots[0], node) - elif right_node: - with self._get_block(right_node) as right: - blocks = [block, right] - pivots = [right_pivot] - - entries, pointers, before = self._extract(blocks, pivots) - - pivots = self._split2 (blocks, entries, pointers, - before, bool(next_node)) - - # Remove the pivot from the parent - with self._get_block(path[-1]) as parent: - if right_node == parent_next: - parent.seek(pos) - parent.delete(right_pos - node_pos) - parent_next = node - else: - parent.seek(pos + 4) - parent.delete(right_pos - node_pos) - parent.seek(0) - parent_count -= 1 - parent.write(b'>II', parent_next, parent_count) - self._records -= 1 - - # Replace the pivot - if pivots: - self._insert_inner(path[:-1], path[-1], pivots[0], - right_node) - - if not path and not parent_count: - self._store.release (path[-1]) - self._nodes -= 1 - self._dirty = True - self._rootnode = node - else: - count, used = self._block_usage(path[-1]) - - if used < self._page_size / 2: - self._rebalance (path[:-1], path[-1]) - - # Delete from the leaf node `node'. `filename_lc' has already been - # lower-cased. - def _delete_leaf(self, node, filename_lc, code): - found = False - - with self._get_block(node) as block: - next_node, count = block.read(b'>II') - - for n in range(count): - pos = block.tell() - e = DSStoreEntry.read(block) - if e.filename.lower() == filename_lc \ - and (code is None or e.code == code): - block.seek(pos) - block.delete(e.byte_length()) - found = True - - # This does not affect the loop; THIS IS NOT A BUG - count -= 1 - - self._records -= 1 - self._dirty = True - - if found: - used = block.tell() - - block.seek(0) - block.write(b'>II', next_node, count) - - return used < self._page_size / 2 - else: - return False - - # Remove the largest entry from the subtree starting at `node' (with - # path from root `path'). Returns a tuple (rebalance, entry) where - # rebalance is either None if no rebalancing is required, or a - # (path, node) tuple giving the details of the node to rebalance. - def _take_largest(self, path, node): - path = list(path) - rebalance = None - while True: - with self._get_block(node) as block: - next_node, count = block.read(b'>II') - - if next_node: - path.append(node) - node = next_node - continue - - for n in range(count): - pos = block.tell() - e = DSStoreEntry.read(block) - - count -= 1 - block.seek(0) - block.write(b'>II', next_node, count) - - if pos < self._page_size / 2: - rebalance = (path, node) - break - - return rebalance, e - - # Delete an entry from an inner node, `node' - def _delete_inner(self, path, node, filename_lc, code): - rebalance = False - - with self._get_block(node) as block: - next_node, count = block.read(b'>II') - - for n in range(count): - pos = block.tell() - ptr = block.read(b'>I')[0] - e = DSStoreEntry.read(block) - if e.filename.lower() == filename_lc \ - and (code is None or e.code == code): - # Take the largest from the left subtree - rebalance, largest = self._take_largest(path, ptr) - - # Delete this entry - if n == count - 1: - right_ptr = next_node - next_node = ptr - block.seek(pos) - else: - right_ptr = block.read(b'>I')[0] - block.seek(pos + 4) - - block.delete(e.byte_length() + 4) - - count -= 1 - block.seek(0) - block.write(b'>II', next_node, count) - - self._records -= 1 - self._dirty = True - - break - - # Replace the pivot value - self._insert_inner(path, node, largest, right_ptr) - - # Rebalance from the node we stole from - if rebalance: - self._rebalance (rebalance[0], rebalance[1]) - return True - return False - - def delete(self, filename, code): - """Delete an item, identified by ``filename`` and ``code`` - from the B-Tree.""" - if isinstance(filename, DSStoreEntry): - code = filename.code - filename = filename.filename - - # If we're deleting *every* node for "filename", we must recurse - if code is None: - ###TODO: Fix this so we can do bulk deletes - raise ValueError('You must delete items individually. Sorry') - - # Otherwise, we're deleting *one* specific node - filename_lc = filename.lower() - path = [] - node = self._rootnode - while True: - with self._get_block(node) as block: - next_node, count = block.read(b'>II') - if next_node: - for n in range(count): - ptr = block.read(b'>I')[0] - e = DSStoreEntry.read(block) - e_lc = e.filename.lower() - if filename_lc < e_lc \ - or (filename_lc == e_lc and code < e.code): - next_node = ptr - break - elif filename_lc == e_lc and code == e.code: - self._delete_inner (path, node, filename_lc, code) - return - path.append(node) - node = next_node - else: - if self._delete_leaf (node, filename_lc, code): - self._rebalance (path, node) - return - - # Find implementation - def _find(self, node, filename_lc, code=None): - with self._get_block(node) as block: - next_node, count = block.read(b'>II') - if next_node: - for n in range(count): - ptr = block.read(b'>I')[0] - e = DSStoreEntry.read(block) - if filename_lc < e.filename.lower(): - for e in self._find(ptr, filename_lc, code): - yield e - return - elif filename_lc == e.filename.lower(): - if code is None or (code and code < e.code): - for e in self._find(ptr, filename_lc, code): - yield e - if code is None or code == e.code: - yield e - elif code < e.code: - return - for e in self._find(next_node, filename_lc, code): - yield e - else: - for n in range(count): - e = DSStoreEntry.read(block) - if filename_lc == e.filename.lower(): - if code is None or code == e.code: - yield e - elif code < e.code: - return - - def find(self, filename, code=None): - """Returns a generator that will iterate over matching entries in - the B-Tree.""" - if isinstance(filename, DSStoreEntry): - code = filename.code - filename = filename.filename - - filename_lc = filename.lower() - - return self._find(self._rootnode, filename_lc, code) - - def __len__(self): - return self._records - - def __iter__(self): - return self._traverse(self._rootnode) - - class Partial (object): - """This is used to implement indexing.""" - def __init__(self, store, filename): - self._store = store - self._filename = filename - - def __getitem__(self, code): - if code is None: - raise KeyError('no such key - [%s][None]' % self._filename) - - try: - item = six.advance_iterator( - self._store.find(self._filename, code)) - except StopIteration: - raise KeyError('no such key - [%s][%s]' % (self._filename, - code)) - - if not isinstance(item.type, basestring): - return item.value - - return (item.type, item.value) - - def __setitem__(self, code, value): - if code is None: - raise KeyError('bad key - [%s][None]' % self._filename) - - codec = codecs.get(code, None) - if codec: - entry_type = codec - entry_value = value - else: - entry_type = value[0] - entry_value = value[1] - - self._store.insert(DSStoreEntry (self._filename, code, - entry_type, entry_value)) - - def __delitem__(self, code): - if code is None: - raise KeyError('no such key - [%s][None]' % self._filename) - - self._store.delete(self._filename, code) - - def __iter__(self): - for item in self._store.find(self._filename): - yield item - - def __getitem__(self, filename): - return self.Partial(self, filename) - diff --git a/src/mac-app/tools/createDSStore/mac_alias/__init__.py b/src/mac-app/tools/createDSStore/mac_alias/__init__.py deleted file mode 100644 index 8c9220c9981..00000000000 --- a/src/mac-app/tools/createDSStore/mac_alias/__init__.py +++ /dev/null @@ -1,14 +0,0 @@ -from .alias import * - -__all__ = [ 'ALIAS_KIND_FILE', 'ALIAS_KIND_FOLDER', - 'ALIAS_HFS_VOLUME_SIGNATURE', - 'ALIAS_FIXED_DISK', 'ALIAS_NETWORK_DISK', 'ALIAS_400KB_FLOPPY_DISK', - 'ALIAS_800KB_FLOPPY_DISK', 'ALIAS_1_44MB_FLOPPY_DISK', - 'ALIAS_EJECTABLE_DISK', - 'ALIAS_NO_CNID', - 'AppleShareInfo', - 'VolumeInfo', - 'TargetInfo', - 'Alias' ] - - diff --git a/src/mac-app/tools/createDSStore/mac_alias/alias.py b/src/mac-app/tools/createDSStore/mac_alias/alias.py deleted file mode 100644 index b35f4029b6c..00000000000 --- a/src/mac-app/tools/createDSStore/mac_alias/alias.py +++ /dev/null @@ -1,587 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals -from __future__ import division - -import struct -import datetime -import io -import re -import os -import os.path -import stat -import sys - -if sys.platform == 'darwin': - from . import osx - -from .utils import * - -ALIAS_KIND_FILE = 0 -ALIAS_KIND_FOLDER = 1 - -ALIAS_HFS_VOLUME_SIGNATURE = b'H+' - -ALIAS_FIXED_DISK = 0 -ALIAS_NETWORK_DISK = 1 -ALIAS_400KB_FLOPPY_DISK = 2 -ALIAS_800KB_FLOPPY_DISK = 3 -ALIAS_1_44MB_FLOPPY_DISK = 4 -ALIAS_EJECTABLE_DISK = 5 - -ALIAS_NO_CNID = 0xffffffff - -class AppleShareInfo (object): - def __init__(self, zone=None, server=None, user=None): - #: The AppleShare zone - self.zone = zone - #: The AFP server - self.server = server - #: The username - self.user = user - - def __repr__(self): - return 'AppleShareInfo(%r,%r,%r)' % (self.zone, self.server, self.user) - -class VolumeInfo (object): - def __init__(self, name, creation_date, fs_type, disk_type, - attribute_flags, fs_id, appleshare_info=None, - driver_name=None, posix_path=None, disk_image_alias=None, - dialup_info=None, network_mount_info=None): - #: The name of the volume on which the target resides - self.name = name - - #: The creation date of the target's volume - self.creation_date = creation_date - - #: The filesystem type (a two character code, e.g. ``b'H+'`` for HFS+) - self.fs_type = fs_type - - #: The type of disk; should be one of - #: - #: * ALIAS_FIXED_DISK - #: * ALIAS_NETWORK_DISK - #: * ALIAS_400KB_FLOPPY_DISK - #: * ALIAS_800KB_FLOPPY_DISK - #: * ALIAS_1_44MB_FLOPPY_DISK - #: * ALIAS_EJECTABLE_DISK - self.disk_type = disk_type - - #: Filesystem attribute flags (from HFS volume header) - self.attribute_flags = attribute_flags - - #: Filesystem identifier - self.fs_id = fs_id - - #: AppleShare information (for automatic remounting of network shares) - #: *(optional)* - self.appleshare_info = appleshare_info - - #: Driver name (*probably* contains a disk driver name on older Macs) - #: *(optional)* - self.driver_name = driver_name - - #: POSIX path of the mount point of the target's volume - #: *(optional)* - self.posix_path = posix_path - - #: :class:`Alias` object pointing at the disk image on which the - #: target's volume resides *(optional)* - self.disk_image_alias = disk_image_alias - - #: Dialup information (for automatic establishment of dialup connections) - self.dialup_info = dialup_info - - #: Network mount information (for automatic remounting) - self.network_mount_info = network_mount_info - - def __repr__(self): - args = ['name', 'creation_date', 'fs_type', 'disk_type', - 'attribute_flags', 'fs_id'] - values = [] - for a in args: - v = getattr(self, a) - values.append(repr(v)) - - kwargs = ['appleshare_info', 'driver_name', 'posix_path', - 'disk_image_alias', 'dialup_info', 'network_mount_info'] - for a in kwargs: - v = getattr(self, a) - if v is not None: - values.append('%s=%r' % (a, v)) - return 'VolumeInfo(%s)' % ','.join(values) - -class TargetInfo (object): - def __init__(self, kind, filename, folder_cnid, cnid, creation_date, - creator_code, type_code, levels_from=-1, levels_to=-1, - folder_name=None, cnid_path=None, carbon_path=None, - posix_path=None, user_home_prefix_len=None): - #: Either ALIAS_KIND_FILE or ALIAS_KIND_FOLDER - self.kind = kind - - #: The filename of the target - self.filename = filename - - #: The CNID (Catalog Node ID) of the target's containing folder; - #: CNIDs are similar to but different than traditional UNIX inode - #: numbers - self.folder_cnid = folder_cnid - - #: The CNID (Catalog Node ID) of the target - self.cnid = cnid - - #: The target's *creation* date. - self.creation_date = creation_date - - #: The target's Mac creator code (a four-character binary string) - self.creator_code = creator_code - - #: The target's Mac type code (a four-character binary string) - self.type_code = type_code - - #: The depth of the alias? Always seems to be -1 on OS X. - self.levels_from = levels_from - - #: The depth of the target? Always seems to be -1 on OS X. - self.levels_to = levels_to - - #: The (POSIX) name of the target's containing folder. *(optional)* - self.folder_name = folder_name - - #: The path from the volume root as a sequence of CNIDs. *(optional)* - self.cnid_path = cnid_path - - #: The Carbon path of the target *(optional)* - self.carbon_path = carbon_path - - #: The POSIX path of the target relative to the volume root. Note - #: that this may or may not have a leading '/' character, but it is - #: always relative to the containing volume. *(optional)* - self.posix_path = posix_path - - #: If the path points into a user's home folder, the number of folders - #: deep that we go before we get to that home folder. *(optional)* - self.user_home_prefix_len = user_home_prefix_len - - def __repr__(self): - args = ['kind', 'filename', 'folder_cnid', 'cnid', 'creation_date', - 'creator_code', 'type_code'] - values = [] - for a in args: - v = getattr(self, a) - values.append(repr(v)) - - if self.levels_from != -1: - values.append('levels_from=%r' % self.levels_from) - if self.levels_to != -1: - values.append('levels_to=%r' % self.levels_to) - - kwargs = ['folder_name', 'cnid_path', 'carbon_path', - 'posix_path', 'user_home_prefix_len'] - for a in kwargs: - v = getattr(self, a) - values.append('%s=%r' % (a, v)) - - return 'TargetInfo(%s)' % ','.join(values) - -TAG_CARBON_FOLDER_NAME = 0 -TAG_CNID_PATH = 1 -TAG_CARBON_PATH = 2 -TAG_APPLESHARE_ZONE = 3 -TAG_APPLESHARE_SERVER_NAME = 4 -TAG_APPLESHARE_USERNAME = 5 -TAG_DRIVER_NAME = 6 -TAG_NETWORK_MOUNT_INFO = 9 -TAG_DIALUP_INFO = 10 -TAG_UNICODE_FILENAME = 14 -TAG_UNICODE_VOLUME_NAME = 15 -TAG_HIGH_RES_VOLUME_CREATION_DATE = 16 -TAG_HIGH_RES_CREATION_DATE = 17 -TAG_POSIX_PATH = 18 -TAG_POSIX_PATH_TO_MOUNTPOINT = 19 -TAG_RECURSIVE_ALIAS_OF_DISK_IMAGE = 20 -TAG_USER_HOME_LENGTH_PREFIX = 21 - -class Alias (object): - def __init__(self, appinfo=b'\0\0\0\0', version=2, volume=None, - target=None, extra=[]): - """Construct a new :class:`Alias` object with the specified - contents.""" - - #: Application specific information (four byte byte-string) - self.appinfo = appinfo - - #: Version (we support only version 2) - self.version = version - - #: A :class:`VolumeInfo` object describing the target's volume - self.volume = volume - - #: A :class:`TargetInfo` object describing the target - self.target = target - - #: A list of extra `(tag, value)` pairs - self.extra = list(extra) - - @classmethod - def _from_fd(cls, b): - appinfo, recsize, version = struct.unpack(b'>4shh', b.read(8)) - - if recsize < 150: - raise ValueError('Incorrect alias length') - - if version != 2: - raise ValueError('Unsupported alias version %u' % version) - - kind, volname, voldate, fstype, disktype, \ - folder_cnid, filename, cnid, crdate, creator_code, type_code, \ - levels_from, levels_to, volattrs, volfsid, reserved = \ - struct.unpack(b'>h28pI2shI64pII4s4shhI2s10s', b.read(142)) - - voldate = mac_epoch + datetime.timedelta(seconds=voldate) - crdate = mac_epoch + datetime.timedelta(seconds=crdate) - - alias = Alias() - alias.appinfo = appinfo - - alias.volume = VolumeInfo (volname.replace('/',':'), - voldate, fstype, disktype, - volattrs, volfsid) - alias.target = TargetInfo (kind, filename.replace('/',':'), - folder_cnid, cnid, - crdate, creator_code, type_code) - alias.target.levels_from = levels_from - alias.target.levels_to = levels_to - - tag = struct.unpack(b'>h', b.read(2))[0] - - while tag != -1: - length = struct.unpack(b'>h', b.read(2))[0] - value = b.read(length) - if length & 1: - b.read(1) - - if tag == TAG_CARBON_FOLDER_NAME: - alias.target.folder_name = value.replace('/',':') - elif tag == TAG_CNID_PATH: - alias.target.cnid_path = struct.unpack(b'>%uI' % (length // 4), - value) - elif tag == TAG_CARBON_PATH: - alias.target.carbon_path = value - elif tag == TAG_APPLESHARE_ZONE: - if alias.volume.appleshare_info is None: - alias.volume.appleshare_info = AppleShareInfo() - alias.volume.appleshare_info.zone = value - elif tag == TAG_APPLESHARE_SERVER_NAME: - if alias.volume.appleshare_info is None: - alias.volume.appleshare_info = AppleShareInfo() - alias.volume.appleshare_info.server = value - elif tag == TAG_APPLESHARE_USERNAME: - if alias.volume.appleshare_info is None: - alias.volume.appleshare_info = AppleShareInfo() - alias.volume.appleshare_info.user = value - elif tag == TAG_DRIVER_NAME: - alias.volume.driver_name = value - elif tag == TAG_NETWORK_MOUNT_INFO: - alias.volume.network_mount_info = value - elif tag == TAG_DIALUP_INFO: - alias.volume.dialup_info = value - elif tag == TAG_UNICODE_FILENAME: - alias.target.filename = value[2:].decode('utf-16be') - elif tag == TAG_UNICODE_VOLUME_NAME: - alias.volume.name = value[2:].decode('utf-16be') - elif tag == TAG_HIGH_RES_VOLUME_CREATION_DATE: - seconds = struct.unpack(b'>Q', value)[0] / 65536.0 - alias.volume.creation_date \ - = mac_epoch + datetime.timedelta(seconds=seconds) - elif tag == TAG_HIGH_RES_CREATION_DATE: - seconds = struct.unpack(b'>Q', value)[0] / 65536.0 - alias.target.creation_date \ - = mac_epoch + datetime.timedelta(seconds=seconds) - elif tag == TAG_POSIX_PATH: - alias.target.posix_path = value - elif tag == TAG_POSIX_PATH_TO_MOUNTPOINT: - alias.volume.posix_path = value - elif tag == TAG_RECURSIVE_ALIAS_OF_DISK_IMAGE: - alias.volume.disk_image_alias = Alias.from_bytes(value) - elif tag == TAG_USER_HOME_LENGTH_PREFIX: - alias.target.user_home_prefix_len = struct.unpack(b'>h', value)[0] - else: - alias.extra.append((tag, value)) - - tag = struct.unpack(b'>h', b.read(2))[0] - - return alias - - @classmethod - def from_bytes(cls, bytes): - """Construct an :class:`Alias` object given binary Alias data.""" - with io.BytesIO(bytes) as b: - return cls._from_fd(b) - - @classmethod - def for_file(cls, path): - """Create an :class:`Alias` that points at the specified file.""" - if sys.platform != 'darwin': - raise Exception('Not implemented (requires special support)') - - a = Alias() - - # Find the filesystem - st = osx.statfs(path) - vol_path = st.f_mntonname - - # Grab its attributes - attrs = [osx.ATTR_CMN_CRTIME, - osx.ATTR_VOL_NAME, - 0, 0, 0] - volinfo = osx.getattrlist(vol_path, attrs, 0) - - vol_crtime = volinfo[0] - vol_name = volinfo[1] - - # Also grab various attributes of the file - attrs = [(osx.ATTR_CMN_OBJTYPE - | osx.ATTR_CMN_CRTIME - | osx.ATTR_CMN_FNDRINFO - | osx.ATTR_CMN_FILEID - | osx.ATTR_CMN_PARENTID), 0, 0, 0, 0] - info = osx.getattrlist(path, attrs, osx.FSOPT_NOFOLLOW) - - if info[0] == osx.VDIR: - kind = ALIAS_KIND_FOLDER - else: - kind = ALIAS_KIND_FILE - - cnid = info[3] - folder_cnid = info[4] - - dirname, filename = os.path.split(path) - - if dirname == '' or dirname == '.': - dirname = os.getcwd() - - foldername = os.path.basename(dirname) - - creation_date = info[1] - - if kind == ALIAS_KIND_FILE: - creator_code = struct.pack(b'I', info[2].fileInfo.fileCreator) - type_code = struct.pack(b'I', info[2].fileInfo.fileType) - else: - creator_code = b'\0\0\0\0' - type_code = b'\0\0\0\0' - - a.target = TargetInfo(kind, filename, folder_cnid, cnid, creation_date, - creator_code, type_code) - a.volume = VolumeInfo(vol_name, vol_crtime, b'H+', - ALIAS_FIXED_DISK, 0, b'\0\0') - - a.target.folder_name = foldername - a.volume.posix_path = vol_path - - rel_path = os.path.relpath(path, vol_path) - - # Leave off the initial '/' if vol_path is '/' (no idea why) - if vol_path == '/': - a.target.posix_path = rel_path - else: - a.target.posix_path = '/' + rel_path - - # Construct the Carbon and CNID paths - carbon_path = [] - cnid_path = [] - head, tail = os.path.split(rel_path) - if not tail: - head, tail = os.path.split(head) - while head or tail: - if head: - attrs = [osx.ATTR_CMN_FILEID, 0, 0, 0, 0] - info = osx.getattrlist(os.path.join(vol_path, head), attrs, 0) - cnid_path.append(info[0]) - carbon_tail = tail.replace(':','/') - carbon_path.insert(0, carbon_tail) - head, tail = os.path.split(head) - carbon_path = vol_name + ':' + ':\0'.join(carbon_path) - - a.target.carbon_path = carbon_path - a.target.cnid_path = cnid_path - - return a - - def _to_fd(self, b): - # We'll come back and fix the length when we're done - pos = b.tell() - b.write(struct.pack(b'>4shh', self.appinfo, 0, self.version)) - - carbon_volname = self.volume.name.replace(':','/').encode('utf-8') - carbon_filename = self.target.filename.replace(':','/').encode('utf-8') - voldate = (self.volume.creation_date - mac_epoch).total_seconds() - crdate = (self.target.creation_date - mac_epoch).total_seconds() - - # NOTE: crdate should be in local time, but that's system dependent - # (so doing so is ridiculous, and nothing could rely on it). - b.write(struct.pack(b'>h28pI2shI64pII4s4shhI2s10s', - self.target.kind, - carbon_volname, voldate, - self.volume.fs_type, - self.volume.disk_type, - self.target.folder_cnid, - carbon_filename, - self.target.cnid, - crdate, - self.target.creator_code, - self.target.type_code, - self.target.levels_from, - self.target.levels_to, - self.volume.attribute_flags, - self.volume.fs_id, - b'\0'*10)) - - # Excuse the odd order; we're copying Finder - if self.target.folder_name: - carbon_foldername = self.target.folder_name.replace(':','/')\ - .encode('utf-8') - b.write(struct.pack(b'>hh', TAG_CARBON_FOLDER_NAME, - len(carbon_foldername))) - b.write(carbon_foldername) - if len(carbon_foldername) & 1: - b.write(b'\0') - - b.write(struct.pack(b'>hhQhhQ', - TAG_HIGH_RES_VOLUME_CREATION_DATE, - 8, long(voldate * 65536), - TAG_HIGH_RES_CREATION_DATE, - 8, long(crdate * 65536))) - - if self.target.cnid_path: - cnid_path = struct.pack(b'>%uI' % len(self.target.cnid_path), - *self.target.cnid_path) - b.write(struct.pack(b'>hh', TAG_CNID_PATH, - len(cnid_path))) - b.write(cnid_path) - - if self.target.carbon_path: - carbon_path=self.target.carbon_path.encode('utf-8') - b.write(struct.pack(b'>hh', TAG_CARBON_PATH, - len(carbon_path))) - b.write(carbon_path) - if len(carbon_path) & 1: - b.write(b'\0') - - if self.volume.appleshare_info: - ai = self.volume.appleshare_info - if ai.zone: - b.write(struct.pack(b'>hh', TAG_APPLESHARE_ZONE, - len(ai.zone))) - b.write(ai.zone) - if len(ai.zone) & 1: - b.write(b'\0') - if ai.server: - b.write(struct.pack(b'>hh', TAG_APPLESHARE_SERVER_NAME, - len(ai.server))) - b.write(ai.server) - if len(ai.server) & 1: - b.write(b'\0') - if ai.username: - b.write(struct.pack(b'>hh', TAG_APPLESHARE_USERNAME, - len(ai.username))) - b.write(ai.username) - if len(ai.username) & 1: - b.write(b'\0') - - if self.volume.driver_name: - driver_name = self.volume.driver_name.encode('utf-8') - b.write(struct.pack(b'>hh', TAG_DRIVER_NAME, - len(driver_name))) - b.write(driver_name) - if len(driver_name) & 1: - b.write(b'\0') - - if self.volume.network_mount_info: - b.write(struct.pack(b'>hh', TAG_NETWORK_MOUNT_INFO, - len(self.volume.network_mount_info))) - b.write(self.volume.network_mount_info) - if len(self.volume.network_mount_info) & 1: - b.write(b'\0') - - if self.volume.dialup_info: - b.write(struct.pack(b'>hh', TAG_DIALUP_INFO, - len(self.volume.network_mount_info))) - b.write(self.volume.network_mount_info) - if len(self.volume.network_mount_info) & 1: - b.write(b'\0') - - utf16 = self.target.filename.replace(':','/').encode('utf-16-be') - b.write(struct.pack(b'>hhh', TAG_UNICODE_FILENAME, - len(utf16) + 2, - len(utf16) // 2)) - b.write(utf16) - - utf16 = self.volume.name.replace(':','/').encode('utf-16-be') - b.write(struct.pack(b'>hhh', TAG_UNICODE_VOLUME_NAME, - len(utf16) + 2, - len(utf16) // 2)) - b.write(utf16) - - if self.target.posix_path: - posix_path = self.target.posix_path.encode('utf-8') - b.write(struct.pack(b'>hh', TAG_POSIX_PATH, - len(posix_path))) - b.write(posix_path) - if len(posix_path) & 1: - b.write(b'\0') - - if self.volume.posix_path: - posix_path = self.volume.posix_path.encode('utf-8') - b.write(struct.pack(b'>hh', TAG_POSIX_PATH_TO_MOUNTPOINT, - len(posix_path))) - b.write(posix_path) - if len(posix_path) & 1: - b.write(b'\0') - - if self.volume.disk_image_alias: - d = self.volume.disk_image_alias.to_bytes() - b.write(struct.pack(b'>hh', TAG_RECURSIVE_ALIAS_OF_DISK_IMAGE, - len(d))) - b.write(d) - if len(d) & 1: - b.write(b'\0') - - if self.target.user_home_prefix_len is not None: - b.write(struct.pack(b'>hhh', TAG_USER_HOME_LENGTH_PREFIX, - 2, self.target.user_home_prefix_len)) - - for t,v in self.extra: - b.write(struct.pack(b'>hh', t, len(v))) - b.write(v) - if len(v) & 1: - b.write(b'\0') - - b.write(struct.pack(b'>hh', -1, 0)) - - blen = b.tell() - pos - b.seek(pos + 4, os.SEEK_SET) - b.write(struct.pack(b'>h', blen)) - - def to_bytes(self): - """Returns the binary representation for this :class:`Alias`.""" - with io.BytesIO() as b: - self._to_fd(b) - return b.getvalue() - - def __str__(self): - return '' % self.target.filename - - def __repr__(self): - values = [] - if self.appinfo != b'\0\0\0\0': - values.append('appinfo=%r' % self.appinfo) - if self.version != 2: - values.append('version=%r' % self.version) - if self.volume is not None: - values.append('volume=%r' % self.volume) - if self.target is not None: - values.append('target=%r' % self.target) - if self.extra: - values.append('extra=%r' % self.extra) - return 'Alias(%s)' % ','.join(values) diff --git a/src/mac-app/tools/createDSStore/mac_alias/osx.py b/src/mac-app/tools/createDSStore/mac_alias/osx.py deleted file mode 100644 index bdd5d09e959..00000000000 --- a/src/mac-app/tools/createDSStore/mac_alias/osx.py +++ /dev/null @@ -1,823 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from ctypes import * -import struct -import os -import datetime -import uuid - -from .utils import * - -libc = cdll.LoadLibrary('/usr/lib/libc.dylib') - -# Constants -FSOPT_NOFOLLOW = 0x00000001 -FSOPT_NOINMEMUPDATE = 0x00000002 -FSOPT_REPORT_FULLSIZE = 0x00000004 -FSOPT_PACK_INVAL_ATTRS = 0x00000008 - -VOL_CAPABILITIES_FORMAT = 0 -VOL_CAPABILITIES_INTERFACES = 1 - -VOL_CAP_FMT_PERSISTENTOBJECTIDS = 0x00000001 -VOL_CAP_FMT_SYMBOLICLINKS = 0x00000002 -VOL_CAP_FMT_HARDLINKS = 0x00000004 -VOL_CAP_FMT_JOURNAL = 0x00000008 -VOL_CAP_FMT_JOURNAL_ACTIVE = 0x00000010 -VOL_CAP_FMT_NO_ROOT_TIMES = 0x00000020 -VOL_CAP_FMT_SPARSE_FILES = 0x00000040 -VOL_CAP_FMT_ZERO_RUNS = 0x00000080 -VOL_CAP_FMT_CASE_SENSITIVE = 0x00000100 -VOL_CAP_FMT_CASE_PRESERVING = 0x00000200 -VOL_CAP_FMT_FAST_STATFS = 0x00000400 -VOL_CAP_FMT_2TB_FILESIZE = 0x00000800 -VOL_CAP_FMT_OPENDENYMODES = 0x00001000 -VOL_CAP_FMT_HIDDEN_FILES = 0x00002000 -VOL_CAP_FMT_PATH_FROM_ID = 0x00004000 -VOL_CAP_FMT_NO_VOLUME_SIZES = 0x00008000 -VOL_CAP_FMT_DECMPFS_COMPRESSION = 0x00010000 -VOL_CAP_FMT_64BIT_OBJECT_IDS = 0x00020000 - -VOL_CAP_INT_SEARCHFS = 0x00000001 -VOL_CAP_INT_ATTRLIST = 0x00000002 -VOL_CAP_INT_NFSEXPORT = 0x00000004 -VOL_CAP_INT_READDIRATTR = 0x00000008 -VOL_CAP_INT_EXCHANGEDATA = 0x00000010 -VOL_CAP_INT_COPYFILE = 0x00000020 -VOL_CAP_INT_ALLOCATE = 0x00000040 -VOL_CAP_INT_VOL_RENAME = 0x00000080 -VOL_CAP_INT_ADVLOCK = 0x00000100 -VOL_CAP_INT_FLOCK = 0x00000200 -VOL_CAP_INT_EXTENDED_SECURITY = 0x00000400 -VOL_CAP_INT_USERACCESS = 0x00000800 -VOL_CAP_INT_MANLOCK = 0x00001000 -VOL_CAP_INT_NAMEDSTREAMS = 0x00002000 -VOL_CAP_INT_EXTENDED_ATTR = 0x00004000 - -ATTR_CMN_NAME = 0x00000001 -ATTR_CMN_DEVID = 0x00000002 -ATTR_CMN_FSID = 0x00000004 -ATTR_CMN_OBJTYPE = 0x00000008 -ATTR_CMN_OBJTAG = 0x00000010 -ATTR_CMN_OBJID = 0x00000020 -ATTR_CMN_OBJPERMANENTID = 0x00000040 -ATTR_CMN_PAROBJID = 0x00000080 -ATTR_CMN_SCRIPT = 0x00000100 -ATTR_CMN_CRTIME = 0x00000200 -ATTR_CMN_MODTIME = 0x00000400 -ATTR_CMN_CHGTIME = 0x00000800 -ATTR_CMN_ACCTIME = 0x00001000 -ATTR_CMN_BKUPTIME = 0x00002000 -ATTR_CMN_FNDRINFO = 0x00004000 -ATTR_CMN_OWNERID = 0x00008000 -ATTR_CMN_GRPID = 0x00010000 -ATTR_CMN_ACCESSMASK = 0x00020000 -ATTR_CMN_FLAGS = 0x00040000 -ATTR_CMN_USERACCESS = 0x00200000 -ATTR_CMN_EXTENDED_SECURITY = 0x00400000 -ATTR_CMN_UUID = 0x00800000 -ATTR_CMN_GRPUUID = 0x01000000 -ATTR_CMN_FILEID = 0x02000000 -ATTR_CMN_PARENTID = 0x04000000 -ATTR_CMN_FULLPATH = 0x08000000 -ATTR_CMN_ADDEDTIME = 0x10000000 -ATTR_CMN_RETURNED_ATTRS = 0x80000000 -ATTR_CMN_ALL_ATTRS = 0x9fe7ffff - -ATTR_VOL_FSTYPE = 0x00000001 -ATTR_VOL_SIGNATURE = 0x00000002 -ATTR_VOL_SIZE = 0x00000004 -ATTR_VOL_SPACEFREE = 0x00000008 -ATTR_VOL_SPACEAVAIL = 0x00000010 -ATTR_VOL_MINALLOCATION = 0x00000020 -ATTR_VOL_ALLOCATIONCLUMP = 0x00000040 -ATTR_VOL_IOBLOCKSIZE = 0x00000080 -ATTR_VOL_OBJCOUNT = 0x00000100 -ATTR_VOL_FILECOUNT = 0x00000200 -ATTR_VOL_DIRCOUNT = 0x00000400 -ATTR_VOL_MAXOBJCOUNT = 0x00000800 -ATTR_VOL_MOUNTPOINT = 0x00001000 -ATTR_VOL_NAME = 0x00002000 -ATTR_VOL_MOUNTFLAGS = 0x00004000 -ATTR_VOL_MOUNTEDDEVICE = 0x00008000 -ATTR_VOL_ENCODINGSUSED = 0x00010000 -ATTR_VOL_CAPABILITIES = 0x00020000 -ATTR_VOL_UUID = 0x00040000 -ATTR_VOL_ATTRIBUTES = 0x40000000 -ATTR_VOL_INFO = 0x80000000 -ATTR_VOL_ALL_ATTRS = 0xc007ffff - -ATTR_DIR_LINKCOUNT = 0x00000001 -ATTR_DIR_ENTRYCOUNT = 0x00000002 -ATTR_DIR_MOUNTSTATUS = 0x00000004 -DIR_MNTSTATUS_MNTPOINT = 0x00000001 -DIR_MNTSTATUS_TRIGGER = 0x00000002 -ATTR_DIR_ALL_ATTRS = 0x00000007 - -ATTR_FILE_LINKCOUNT = 0x00000001 -ATTR_FILE_TOTALSIZE = 0x00000002 -ATTR_FILE_ALLOCSIZE = 0x00000004 -ATTR_FILE_IOBLOCKSIZE = 0x00000008 -ATTR_FILE_DEVTYPE = 0x00000020 -ATTR_FILE_DATALENGTH = 0x00000200 -ATTR_FILE_DATAALLOCSIZE = 0x00000400 -ATTR_FILE_RSRCLENGTH = 0x00001000 -ATTR_FILE_RSRCALLOCSIZE = 0x00002000 - -ATTR_FILE_ALL_ATTRS = 0x0000362f - -ATTR_FORK_TOTALSIZE = 0x00000001 -ATTR_FORK_ALLOCSIZE = 0x00000002 -ATTR_FORK_ALL_ATTRS = 0x00000003 - -# These can't be used -ATTR_FILE_FORKCOUNT = 0x00000080 -ATTR_FILE_FORKLIST = 0x00000100 -ATTR_CMN_NAMEDATTRCOUNT = 0x00080000 -ATTR_CMN_NAMEDATTRLIST = 0x00100000 -ATTR_FILE_DATAEXTENTS = 0x00000800 -ATTR_FILE_RSRCEXTENTS = 0x00004000 -ATTR_FILE_CLUMPSIZE = 0x00000010 -ATTR_FILE_FILETYPE = 0x00000040 - -class attrlist(Structure): - _fields_ = [('bitmapcount', c_ushort), - ('reserved', c_ushort), - ('commonattr', c_uint), - ('volattr', c_uint), - ('dirattr', c_uint), - ('fileattr', c_uint), - ('forkattr', c_uint)] - -class attribute_set_t(Structure): - _fields_ = [('commonattr', c_uint), - ('volattr', c_uint), - ('dirattr', c_uint), - ('fileattr', c_uint), - ('forkattr', c_uint)] - -class fsobj_id_t(Structure): - _fields_ = [('fid_objno', c_uint), - ('fid_generation', c_uint)] - -class timespec(Structure): - _fields_ = [('tv_sec', c_long), - ('tv_nsec', c_long)] - -class attrreference_t(Structure): - _fields_ = [('attr_dataoffset', c_int), - ('attr_length', c_uint)] - -class fsid_t(Structure): - _fields_ = [('val', c_uint * 2)] - -class guid_t(Structure): - _fields_ = [('g_guid', c_byte*16)] - -class kauth_ace(Structure): - _fields_ = [('ace_applicable', guid_t), - ('ace_flags', c_uint)] - -class kauth_acl(Structure): - _fields_ = [('acl_entrycount', c_uint), - ('acl_flags', c_uint), - ('acl_ace', kauth_ace * 128)] - -class kauth_filesec(Structure): - _fields_ = [('fsec_magic', c_uint), - ('fsec_owner', guid_t), - ('fsec_group', guid_t), - ('fsec_acl', kauth_acl)] - -class diskextent(Structure): - _fields_ = [('startblock', c_uint), - ('blockcount', c_uint)] - -OSType = c_uint -UInt16 = c_ushort -SInt16 = c_short -SInt32 = c_int - -class Point(Structure): - _fields_ = [('x', SInt16), - ('y', SInt16)] -class Rect(Structure): - _fields_ = [('x', SInt16), - ('y', SInt16), - ('w', SInt16), - ('h', SInt16)] -class FileInfo(Structure): - _fields_ = [('fileType', OSType), - ('fileCreator', OSType), - ('finderFlags', UInt16), - ('location', Point), - ('reservedField', UInt16), - ('reserved1', SInt16 * 4), - ('extendedFinderFlags', UInt16), - ('reserved2', SInt16), - ('putAwayFolderID', SInt32)] -class FolderInfo(Structure): - _fields_ = [('windowBounds', Rect), - ('finderFlags', UInt16), - ('location', Point), - ('reservedField', UInt16), - ('scrollPosition', Point), - ('reserved1', SInt32), - ('extendedFinderFlags', UInt16), - ('reserved2', SInt16), - ('putAwayFolderID', SInt32)] -class FinderInfo(Union): - _fields_ = [('fileInfo', FileInfo), - ('folderInfo', FolderInfo)] - -extentrecord = diskextent * 8 - -vol_capabilities_set_t = c_uint * 4 - -class vol_capabilities_attr_t(Structure): - _fields_ = [('capabilities', vol_capabilities_set_t), - ('valid', vol_capabilities_set_t)] - -class vol_attributes_attr_t(Structure): - _fields_ = [('validattr', attribute_set_t), - ('nativeattr', attribute_set_t)] - -dev_t = c_uint - -fsobj_type_t = c_uint - -VNON = 0 -VREG = 1 -VDIR = 2 -VBLK = 3 -VCHR = 4 -VLNK = 5 -VSOCK = 6 -VFIFO = 7 -VBAD = 8 -VSTR = 9 -VCPLX = 10 - -fsobj_tag_t = c_uint - -VT_NON = 0 -VT_UFS = 1 -VT_NFS = 2 -VT_MFS = 3 -VT_MSDOSFS = 4 -VT_LFS = 5 -VT_LOFS = 6 -VT_FDESC = 7 -VT_PORTAL = 8 -VT_NULL = 9 -VT_UMAP = 10 -VT_KERNFS = 11 -VT_PROCFS = 12 -VT_AFS = 13 -VT_ISOFS = 14 -VT_UNION = 15 -VT_HFS = 16 -VT_ZFS = 17 -VT_DEVFS = 18 -VT_WEBDAV = 19 -VT_UDF = 20 -VT_AFP = 21 -VT_CDDA = 22 -VT_CIFS = 23 -VT_OTHER = 24 - -fsfile_type_t = c_uint -fsvolid_t = c_uint -text_encoding_t = c_uint -uid_t = c_uint -gid_t = c_uint -int32_t = c_int -uint32_t = c_uint -int64_t = c_longlong -uint64_t = c_ulonglong -off_t = c_long -size_t = c_ulong -uuid_t = c_byte*16 - -NAME_MAX = 255 -PATH_MAX = 1024 - -class struct_statfs(Structure): - _fields_ = [('f_bsize', uint32_t), - ('f_iosize', int32_t), - ('f_blocks', uint64_t), - ('f_bfree', uint64_t), - ('f_bavail', uint64_t), - ('f_files', uint64_t), - ('f_ffree', uint64_t), - ('f_fsid', fsid_t), - ('f_owner', uid_t), - ('f_type', uint32_t), - ('f_flags', uint32_t), - ('f_fssubtype', uint32_t), - ('f_fstypename', c_char * 16), - ('f_mntonname', c_char * PATH_MAX), - ('f_mntfromname', c_char * PATH_MAX), - ('f_reserved', uint32_t * 8)] - -# Calculate the maximum number of bytes required for the attribute buffer -_attr_info = ( - # Common attributes - (0, ATTR_CMN_RETURNED_ATTRS, sizeof(attribute_set_t)), - (0, ATTR_CMN_NAME, sizeof(attrreference_t) + NAME_MAX * 3 + 1), - (0, ATTR_CMN_DEVID, sizeof(dev_t)), - (0, ATTR_CMN_FSID, sizeof(fsid_t)), - (0, ATTR_CMN_OBJTYPE, sizeof(fsobj_type_t)), - (0, ATTR_CMN_OBJTAG, sizeof(fsobj_tag_t)), - (0, ATTR_CMN_OBJPERMANENTID, sizeof(fsobj_id_t)), - (0, ATTR_CMN_PAROBJID, sizeof(fsobj_id_t)), - (0, ATTR_CMN_SCRIPT, sizeof(text_encoding_t)), - (0, ATTR_CMN_CRTIME, sizeof(timespec)), - (0, ATTR_CMN_MODTIME, sizeof(timespec)), - (0, ATTR_CMN_CHGTIME, sizeof(timespec)), - (0, ATTR_CMN_ACCTIME, sizeof(timespec)), - (0, ATTR_CMN_BKUPTIME, sizeof(timespec)), - (0, ATTR_CMN_FNDRINFO, sizeof(FinderInfo)), - (0, ATTR_CMN_OWNERID, sizeof(uid_t)), - (0, ATTR_CMN_GRPID, sizeof(gid_t)), - (0, ATTR_CMN_ACCESSMASK, sizeof(uint32_t)), - (0, ATTR_CMN_NAMEDATTRCOUNT, None), - (0, ATTR_CMN_NAMEDATTRLIST, None), - (0, ATTR_CMN_FLAGS, sizeof(uint32_t)), - (0, ATTR_CMN_USERACCESS, sizeof(uint32_t)), - (0, ATTR_CMN_EXTENDED_SECURITY, sizeof(attrreference_t) + sizeof(kauth_filesec)), - (0, ATTR_CMN_UUID, sizeof(guid_t)), - (0, ATTR_CMN_GRPUUID, sizeof(guid_t)), - (0, ATTR_CMN_FILEID, sizeof(uint64_t)), - (0, ATTR_CMN_PARENTID, sizeof(uint64_t)), - (0, ATTR_CMN_FULLPATH, sizeof(attrreference_t) + PATH_MAX), - (0, ATTR_CMN_ADDEDTIME, sizeof(timespec)), - - # Volume attributes - (1, ATTR_VOL_FSTYPE, sizeof(uint32_t)), - (1, ATTR_VOL_SIGNATURE, sizeof(uint32_t)), - (1, ATTR_VOL_SIZE, sizeof(off_t)), - (1, ATTR_VOL_SPACEFREE, sizeof(off_t)), - (1, ATTR_VOL_SPACEAVAIL, sizeof(off_t)), - (1, ATTR_VOL_MINALLOCATION, sizeof(off_t)), - (1, ATTR_VOL_ALLOCATIONCLUMP, sizeof(off_t)), - (1, ATTR_VOL_IOBLOCKSIZE, sizeof(uint32_t)), - (1, ATTR_VOL_OBJCOUNT, sizeof(uint32_t)), - (1, ATTR_VOL_FILECOUNT, sizeof(uint32_t)), - (1, ATTR_VOL_DIRCOUNT, sizeof(uint32_t)), - (1, ATTR_VOL_MAXOBJCOUNT, sizeof(uint32_t)), - (1, ATTR_VOL_MOUNTPOINT, sizeof(attrreference_t) + PATH_MAX), - (1, ATTR_VOL_NAME, sizeof(attrreference_t) + NAME_MAX + 1), - (1, ATTR_VOL_MOUNTFLAGS, sizeof(uint32_t)), - (1, ATTR_VOL_MOUNTEDDEVICE, sizeof(attrreference_t) + PATH_MAX), - (1, ATTR_VOL_ENCODINGSUSED, sizeof(c_ulonglong)), - (1, ATTR_VOL_CAPABILITIES, sizeof(vol_capabilities_attr_t)), - (1, ATTR_VOL_UUID, sizeof(uuid_t)), - (1, ATTR_VOL_ATTRIBUTES, sizeof(vol_attributes_attr_t)), - - # Directory attributes - (2, ATTR_DIR_LINKCOUNT, sizeof(uint32_t)), - (2, ATTR_DIR_ENTRYCOUNT, sizeof(uint32_t)), - (2, ATTR_DIR_MOUNTSTATUS, sizeof(uint32_t)), - - # File attributes - (3, ATTR_FILE_LINKCOUNT, sizeof(uint32_t)), - (3, ATTR_FILE_TOTALSIZE, sizeof(off_t)), - (3, ATTR_FILE_ALLOCSIZE, sizeof(off_t)), - (3, ATTR_FILE_IOBLOCKSIZE, sizeof(uint32_t)), - (3, ATTR_FILE_CLUMPSIZE, sizeof(uint32_t)), - (3, ATTR_FILE_DEVTYPE, sizeof(uint32_t)), - (3, ATTR_FILE_FILETYPE, sizeof(uint32_t)), - (3, ATTR_FILE_FORKCOUNT, sizeof(uint32_t)), - (3, ATTR_FILE_FORKLIST, None), - (3, ATTR_FILE_DATALENGTH, sizeof(off_t)), - (3, ATTR_FILE_DATAALLOCSIZE, sizeof(off_t)), - (3, ATTR_FILE_DATAEXTENTS, sizeof(extentrecord)), - (3, ATTR_FILE_RSRCLENGTH, sizeof(off_t)), - (3, ATTR_FILE_RSRCALLOCSIZE, sizeof(off_t)), - (3, ATTR_FILE_RSRCEXTENTS, sizeof(extentrecord)), - - # Fork attributes - (4, ATTR_FORK_TOTALSIZE, sizeof(off_t)), - (4, ATTR_FORK_ALLOCSIZE, sizeof(off_t)) - ) - -def _attrbuf_size(attrs): - size = 4 - for entry in _attr_info: - if attrs[entry[0]] & entry[1]: - if entry[2] is None: - raise ValueError('Unsupported attribute (%u, %x)' - % (entry[0], entry[1])) - size += entry[2] - return size - -_getattrlist = libc.getattrlist -_getattrlist.argtypes = [c_char_p, POINTER(attrlist), c_void_p, c_ulong, c_ulong] -_getattrlist.restype = c_int - -_fgetattrlist = libc.fgetattrlist -_fgetattrlist.argtypes = [c_int, POINTER(attrlist), c_void_p, c_ulong, c_ulong] -_fgetattrlist.restype = c_int - -_statfs = libc['statfs$INODE64'] -_statfs.argtypes = [c_char_p, POINTER(struct_statfs)] -_statfs.restype = c_int - -_fstatfs = libc['fstatfs$INODE64'] -_fstatfs.argtypes = [c_int, POINTER(struct_statfs)] -_fstatfs.restype = c_int - -def _datetime_from_timespec(ts): - td = datetime.timedelta(seconds=ts.tv_sec + 1.0e-9 * ts.tv_nsec) - return unix_epoch + td - -def _decode_utf8_nul(sz): - nul = sz.find('\0') - if nul > -1: - sz = sz[:nul] - return sz.decode('utf-8') - -def _decode_attrlist_result(buf, attrs, options): - result = [] - - assert len(buf) >= 4 - total_size = uint32_t.from_buffer(buf, 0).value - assert total_size <= len(buf) - - offset = 4 - - # Common attributes - if attrs[0] & ATTR_CMN_RETURNED_ATTRS: - a = attribute_set_t.from_buffer(buf, offset) - result.append(a) - offset += sizeof (attribute_set_t) - if not (options & FSOPT_PACK_INVAL_ATTRS): - attrs = [a.commonattr, a.volattr, a.dirattr, a.fileattr, a.forkattr] - if attrs[0] & ATTR_CMN_NAME: - a = attrreference_t.from_buffer(buf, offset) - ofs = offset + a.attr_dataoffset - name = _decode_utf8_nul(buf[ofs:ofs+a.attr_length]) - offset += sizeof (attrreference_t) - result.append(name) - if attrs[0] & ATTR_CMN_DEVID: - a = dev_t.from_buffer(buf, offset) - offset += sizeof(dev_t) - result.append(a.value) - if attrs[0] & ATTR_CMN_FSID: - a = fsid_t.from_buffer(buf, offset) - offset += sizeof(fsid_t) - result.append(a) - if attrs[0] & ATTR_CMN_OBJTYPE: - a = fsobj_type_t.from_buffer(buf, offset) - offset += sizeof(fsobj_type_t) - result.append(a.value) - if attrs[0] & ATTR_CMN_OBJTAG: - a = fsobj_tag_t.from_buffer(buf, offset) - offset += sizeof(fsobj_tag_t) - result.append(a.value) - if attrs[0] & ATTR_CMN_OBJID: - a = fsobj_id_t.from_buffer(buf, offset) - offset += sizeof(fsobj_id_t) - result.append(a) - if attrs[0] & ATTR_CMN_OBJPERMANENTID: - a = fsobj_id_t.from_buffer(buf, offset) - offset += sizeof(fsobj_id_t) - result.append(a) - if attrs[0] & ATTR_CMN_PAROBJID: - a = fsobj_id_t.from_buffer(buf, offset) - offset += sizeof(fsobj_id_t) - result.append(a) - if attrs[0] & ATTR_CMN_SCRIPT: - a = text_encoding_t.from_buffer(buf, offset) - offset += sizeof(text_encoding_t) - result.append(a.value) - if attrs[0] & ATTR_CMN_CRTIME: - a = timespec.from_buffer(buf, offset) - offset += sizeof(timespec) - result.append(_datetime_from_timespec(a)) - if attrs[0] & ATTR_CMN_MODTIME: - a = timespec.from_buffer(buf, offset) - offset += sizeof(timespec) - result.append(_datetime_from_timespec(a)) - if attrs[0] & ATTR_CMN_CHGTIME: - a = timespec.from_buffer(buf, offset) - offset += sizeof(timespec) - result.append(_datetime_from_timespec(a)) - if attrs[0] & ATTR_CMN_ACCTIME: - a = timespec.from_buffer(buf, offset) - offset += sizeof(timespec) - result.append(_datetime_from_timespec(a)) - if attrs[0] & ATTR_CMN_BKUPTIME: - a = timespec.from_buffer(buf, offset) - offset += sizeof(timespec) - result.append(_datetime_from_timespec(a)) - if attrs[0] & ATTR_CMN_FNDRINFO: - a = FinderInfo.from_buffer(buf, offset) - offset += sizeof(FinderInfo) - result.append(a) - if attrs[0] & ATTR_CMN_OWNERID: - a = uid_t.from_buffer(buf, offset) - offset += sizeof(uid_t) - result.append(a.value) - if attrs[0] & ATTR_CMN_GRPID: - a = gid_t.from_buffer(buf, offset) - offset += sizeof(gid_t) - result.append(a.value) - if attrs[0] & ATTR_CMN_ACCESSMASK: - a = uint32_t.from_buffer(buf, offset) - offset += sizeof(uint32_t) - result.append(a.value) - if attrs[0] & ATTR_CMN_FLAGS: - a = uint32_t.from_buffer(buf, offset) - offset += sizeof(uint32_t) - result.append(a.value) - if attrs[0] & ATTR_CMN_USERACCESS: - a = uint32_t.from_buffer(buf, offset) - offset += sizeof(uint32_t) - result.append(a.value) - if attrs[0] & ATTR_CMN_EXTENDED_SECURITY: - a = attrreference_t.from_buffer(buf, offset) - ofs = offset + a.attr_dataoffset - offset += sizeof(attrreference_t) - ec = uint32_t.from_buffer(buf, ofs + 36).value - class kauth_acl(Structure): - _fields_ = [('acl_entrycount', c_uint), - ('acl_flags', c_uint), - ('acl_ace', kauth_ace * ec)] - class kauth_filesec(Structure): - _fields_ = [('fsec_magic', c_uint), - ('fsec_owner', guid_t), - ('fsec_group', guid_t), - ('fsec_acl', kauth_acl)] - a = kauth_filesec.from_buffer(buf, ofs) - result.append(a) - if attrs[0] & ATTR_CMN_UUID: - result.append(uuid.UUID(bytes=buf[offset:offset+16])) - offset += sizeof(guid_t) - if attrs[0] & ATTR_CMN_GRPUUID: - result.append(uuid.UUID(bytes=buf[offset:offset+16])) - offset += sizeof(guid_t) - if attrs[0] & ATTR_CMN_FILEID: - a = uint64_t.from_buffer(buf, offset) - offset += sizeof(uint64_t) - result.append(a.value) - if attrs[0] & ATTR_CMN_PARENTID: - a = uint64_t.from_buffer(buf, offset) - offset += sizeof(uint64_t) - result.append(a.value) - if attrs[0] & ATTR_CMN_FULLPATH: - a = attrreference_t.from_buffer(buf, offset) - ofs = offset + a.attr_dataoffset - path = _decode_utf8_nul(buf[ofs:ofs+a.attr_length]) - offset += sizeof (attrreference_t) - result.append(path) - if attrs[0] & ATTR_CMN_ADDEDTIME: - a = timespec.from_buffer(buf, offset) - offset += sizeof(timespec) - result.append(_datetime_from_timespec(a)) - - # Volume attributes - if attrs[1] & ATTR_VOL_FSTYPE: - a = uint32_t.from_buffer(buf, offset) - offset += sizeof(uint32_t) - result.append(a.value) - if attrs[1] & ATTR_VOL_SIGNATURE: - a = uint32_t.from_buffer(buf, offset) - offset += sizeof(uint32_t) - result.append(a.value) - if attrs[1] & ATTR_VOL_SIZE: - a = off_t.from_buffer(buf, offset) - offset += sizeof(off_t) - result.append(a.value) - if attrs[1] & ATTR_VOL_SPACEFREE: - a = off_t.from_buffer(buf, offset) - offset += sizeof(off_t) - result.append(a.value) - if attrs[1] & ATTR_VOL_SPACEAVAIL: - a = off_t.from_buffer(buf, offset) - offset += sizeof(off_t) - result.append(a.value) - if attrs[1] & ATTR_VOL_MINALLOCATION: - a = off_t.from_buffer(buf, offset) - offset += sizeof(off_t) - result.append(a.value) - if attrs[1] & ATTR_VOL_ALLOCATIONCLUMP: - a = off_t.from_buffer(buf, offset) - offset += sizeof(off_t) - result.append(a.value) - if attrs[1] & ATTR_VOL_IOBLOCKSIZE: - a = uint32_t.from_buffer(buf, offset) - offset += sizeof(uint32_t) - result.append(a.value) - if attrs[1] & ATTR_VOL_OBJCOUNT: - a = uint32_t.from_buffer(buf, offset) - offset += sizeof(uint32_t) - result.append(a.value) - if attrs[1] & ATTR_VOL_FILECOUNT: - a = uint32_t.from_buffer(buf, offset) - offset += sizeof(uint32_t) - result.append(a.value) - if attrs[1] & ATTR_VOL_DIRCOUNT: - a = uint32_t.from_buffer(buf, offset) - offset += sizeof(uint32_t) - result.append(a.value) - if attrs[1] & ATTR_VOL_MAXOBJCOUNT: - a = uint32_t.from_buffer(buf, offset) - offset += sizeof(uint32_t) - result.append(a.value) - if attrs[1] & ATTR_VOL_MOUNTPOINT: - a = attrreference_t.from_buffer(buf, offset) - ofs = offset + a.attr_dataoffset - path = _decode_utf8_nul(buf[ofs:ofs+a.attr_length]) - offset += sizeof (attrreference_t) - result.append(path) - if attrs[1] & ATTR_VOL_NAME: - a = attrreference_t.from_buffer(buf, offset) - ofs = offset + a.attr_dataoffset - name = _decode_utf8_nul(buf[ofs:ofs+a.attr_length]) - offset += sizeof (attrreference_t) - result.append(name) - if attrs[1] & ATTR_VOL_MOUNTFLAGS: - a = uint32_t.from_buffer(buf, offset) - offset += sizeof(uint32_t) - result.append(a.value) - if attrs[1] & ATTR_VOL_MOUNTEDDEVICE: - a = attrreference_t.from_buffer(buf, offset) - ofs = offset + a.attr_dataoffset - path = _decode_utf8_nul(buf[ofs:ofs+a.attr_length]) - offset += sizeof (attrreference_t) - result.append(path) - if attrs[1] & ATTR_VOL_ENCODINGSUSED: - a = c_ulonglong.from_buffer(buf, offset) - offset += sizeof(c_ulonglong) - result.append(a.value) - if attrs[1] & ATTR_VOL_CAPABILITIES: - a = vol_capabilities_attr_t.from_buffer(buf, offset) - offset += sizeof(vol_capabilities_attr_t) - result.append(a) - if attrs[1] & ATTR_VOL_UUID: - result.append(uuid.UUID(bytes=buf[offset:offset+16])) - offset += sizeof(uuid_t) - if attrs[1] & ATTR_VOL_ATTRIBUTES: - a = vol_attributes_attr_t.from_buffer(buf, offset) - offset += sizeof(vol_attributes_attr_t) - result.append(a) - - # Directory attributes - if attrs[2] & ATTR_DIR_LINKCOUNT: - a = uint32_t.from_buffer(buf, offset) - offset += sizeof(uint32_t) - result.append(a.value) - if attrs[2] & ATTR_DIR_ENTRYCOUNT: - a = uint32_t.from_buffer(buf, offset) - offset += sizeof(uint32_t) - result.append(a.value) - if attrs[2] & ATTR_DIR_MOUNTSTATUS: - a = uint32_t.from_buffer(buf, offset) - offset += sizeof(uint32_t) - result.append(a.value) - - # File attributes - if attrs[3] & ATTR_FILE_LINKCOUNT: - a = uint32_t.from_buffer(buf, offset) - offset += sizeof(uint32_t) - result.append(a.value) - if attrs[3] & ATTR_FILE_TOTALSIZE: - a = off_t.from_buffer(buf, offset) - offset += sizeof(off_t) - result.append(a.value) - if attrs[3] & ATTR_FILE_ALLOCSIZE: - a = off_t.from_buffer(buf, offset) - offset += sizeof(off_t) - result.append(a.value) - if attrs[3] & ATTR_FILE_IOBLOCKSIZE: - a = uint32_t.from_buffer(buf, offset) - offset += sizeof(uint32_t) - result.append(a.value) - if attrs[3] & ATTR_FILE_CLUMPSIZE: - a = uint32_t.from_buffer(buf, offset) - offset += sizeof(uint32_t) - result.append(a.value) - if attrs[3] & ATTR_FILE_DEVTYPE: - a = uint32_t.from_buffer(buf, offset) - offset += sizeof(uint32_t) - result.append(a.value) - if attrs[3] & ATTR_FILE_FILETYPE: - a = uint32_t.from_buffer(buf, offset) - offset += sizeof(uint32_t) - result.append(a.value) - if attrs[3] & ATTR_FILE_FORKCOUNT: - a = uint32_t.from_buffer(buf, offset) - offset += sizeof(uint32_t) - result.append(a.value) - if attrs[3] & ATTR_FILE_DATALENGTH: - a = off_t.from_buffer(buf, offset) - offset += sizeof(off_t) - result.append(a.value) - if attrs[3] & ATTR_FILE_DATAALLOCSIZE: - a = off_t.from_buffer(buf, offset) - offset += sizeof(off_t) - result.append(a.value) - if attrs[3] & ATTR_FILE_DATAEXTENTS: - a = extentrecord.from_buffer(buf, offset) - offset += sizeof(extentrecord) - result.append(a.value) - if attrs[3] & ATTR_FILE_RSRCLENGTH: - a = off_t.from_buffer(buf, offset) - offset += sizeof(off_t) - result.append(a.value) - if attrs[3] & ATTR_FILE_RSRCALLOCSIZE: - a = off_t.from_buffer(buf, offset) - offset += sizeof(off_t) - result.append(a.value) - if attrs[3] & ATTR_FILE_RSRCEXTENTS: - a = extentrecord.from_buffer(buf, offset) - offset += sizeof(extentrecord) - result.append(a.value) - - # Fork attributes - if attrs[4] & ATTR_FORK_TOTALSIZE: - a = off_t.from_buffer(buf, offset) - offset += sizeof(off_t) - result.append(a.value) - if attrs[4] & ATTR_FORK_ALLOCSIZE: - a = off_t.from_buffer(buf, offset) - offset += sizeof(off_t) - result.append(a.value) - - return result - -# Sadly, ctypes.get_errno() seems not to work -__error = libc.__error -__error.restype = POINTER(c_int) - -def _get_errno(): - return __error().contents.value - -def getattrlist(path, attrs, options): - attrs = list(attrs) - if attrs[1]: - attrs[1] |= ATTR_VOL_INFO - alist = attrlist(bitmapcount=5, - commonattr=attrs[0], - volattr=attrs[1], - dirattr=attrs[2], - fileattr=attrs[3], - forkattr=attrs[4]) - - bufsize = _attrbuf_size(attrs) - buf = create_string_buffer(bufsize) - - ret = _getattrlist(path, byref(alist), buf, bufsize, - options | FSOPT_REPORT_FULLSIZE) - - if ret < 0: - err = _get_errno() - raise OSError(err, os.strerror(err), path) - - return _decode_attrlist_result(buf, attrs, options) - -def fgetattrlist(fd, attrs, options): - if hasattr(fd, 'fileno'): - fd = fd.fileno() - attrs = list(attrs) - if attrs[1]: - attrs[1] |= ATTR_VOL_INFO - alist = attrlist(bitmapcount=5, - commonattr=attrs[0], - volattr=attrs[1], - dirattr=attrs[2], - fileattr=attrs[3], - forkattr=attrs[4]) - - bufsize = _attrbuf_size(attrs) - buf = create_string_buffer(bufsize) - - ret = _fgetattrlist(fd, byref(alist), buf, bufsize, - options | FSOPT_REPORT_FULLSIZE) - - if ret < 0: - err = _get_errno() - raise OSError(err, os.strerror(err)) - - return _decode_attrlist_result(buf, attrs, options) - -def statfs(path): - result = struct_statfs() - ret = _statfs(path, byref(result)) - if ret < 0: - err = _get_errno() - raise OSError(err, os.strerror(err), path) - return result - -def fstatfs(fd): - if hasattr(fd, 'fileno'): - fd = fd.fileno() - result = struct_statfs() - ret = _fstatfs(fd, byref(result)) - if ret < 0: - err = _get_errno() - raise OSError(err, os.strerror(err)) - return result diff --git a/src/mac-app/tools/createDSStore/mac_alias/utils.py b/src/mac-app/tools/createDSStore/mac_alias/utils.py deleted file mode 100644 index 3b4613a43c9..00000000000 --- a/src/mac-app/tools/createDSStore/mac_alias/utils.py +++ /dev/null @@ -1,17 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -import datetime - -ZERO = datetime.timedelta(0) -class UTC (datetime.tzinfo): - def utcoffset(self, dt): - return ZERO - def dst(self, dt): - return ZERO - def tzname(self, dt): - return 'UTC' - -utc = UTC() -mac_epoch = datetime.datetime(1904,1,1,0,0,0,0,utc) -unix_epoch = datetime.datetime(1970,1,1,0,0,0,0,utc) diff --git a/src/mac-app/tools/createDSStore/six.py b/src/mac-app/tools/createDSStore/six.py deleted file mode 100644 index 190c0239cd7..00000000000 --- a/src/mac-app/tools/createDSStore/six.py +++ /dev/null @@ -1,868 +0,0 @@ -"""Utilities for writing code that runs on Python 2 and 3""" - -# Copyright (c) 2010-2015 Benjamin Peterson -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in all -# copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. - -from __future__ import absolute_import - -import functools -import itertools -import operator -import sys -import types - -__author__ = "Benjamin Peterson " -__version__ = "1.10.0" - - -# Useful for very coarse version differentiation. -PY2 = sys.version_info[0] == 2 -PY3 = sys.version_info[0] == 3 -PY34 = sys.version_info[0:2] >= (3, 4) - -if PY3: - string_types = str, - integer_types = int, - class_types = type, - text_type = str - binary_type = bytes - - MAXSIZE = sys.maxsize -else: - string_types = basestring, - integer_types = (int, long) - class_types = (type, types.ClassType) - text_type = unicode - binary_type = str - - if sys.platform.startswith("java"): - # Jython always uses 32 bits. - MAXSIZE = int((1 << 31) - 1) - else: - # It's possible to have sizeof(long) != sizeof(Py_ssize_t). - class X(object): - - def __len__(self): - return 1 << 31 - try: - len(X()) - except OverflowError: - # 32-bit - MAXSIZE = int((1 << 31) - 1) - else: - # 64-bit - MAXSIZE = int((1 << 63) - 1) - del X - - -def _add_doc(func, doc): - """Add documentation to a function.""" - func.__doc__ = doc - - -def _import_module(name): - """Import module, returning the module after the last dot.""" - __import__(name) - return sys.modules[name] - - -class _LazyDescr(object): - - def __init__(self, name): - self.name = name - - def __get__(self, obj, tp): - result = self._resolve() - setattr(obj, self.name, result) # Invokes __set__. - try: - # This is a bit ugly, but it avoids running this again by - # removing this descriptor. - delattr(obj.__class__, self.name) - except AttributeError: - pass - return result - - -class MovedModule(_LazyDescr): - - def __init__(self, name, old, new=None): - super(MovedModule, self).__init__(name) - if PY3: - if new is None: - new = name - self.mod = new - else: - self.mod = old - - def _resolve(self): - return _import_module(self.mod) - - def __getattr__(self, attr): - _module = self._resolve() - value = getattr(_module, attr) - setattr(self, attr, value) - return value - - -class _LazyModule(types.ModuleType): - - def __init__(self, name): - super(_LazyModule, self).__init__(name) - self.__doc__ = self.__class__.__doc__ - - def __dir__(self): - attrs = ["__doc__", "__name__"] - attrs += [attr.name for attr in self._moved_attributes] - return attrs - - # Subclasses should override this - _moved_attributes = [] - - -class MovedAttribute(_LazyDescr): - - def __init__(self, name, old_mod, new_mod, old_attr=None, new_attr=None): - super(MovedAttribute, self).__init__(name) - if PY3: - if new_mod is None: - new_mod = name - self.mod = new_mod - if new_attr is None: - if old_attr is None: - new_attr = name - else: - new_attr = old_attr - self.attr = new_attr - else: - self.mod = old_mod - if old_attr is None: - old_attr = name - self.attr = old_attr - - def _resolve(self): - module = _import_module(self.mod) - return getattr(module, self.attr) - - -class _SixMetaPathImporter(object): - - """ - A meta path importer to import six.moves and its submodules. - - This class implements a PEP302 finder and loader. It should be compatible - with Python 2.5 and all existing versions of Python3 - """ - - def __init__(self, six_module_name): - self.name = six_module_name - self.known_modules = {} - - def _add_module(self, mod, *fullnames): - for fullname in fullnames: - self.known_modules[self.name + "." + fullname] = mod - - def _get_module(self, fullname): - return self.known_modules[self.name + "." + fullname] - - def find_module(self, fullname, path=None): - if fullname in self.known_modules: - return self - return None - - def __get_module(self, fullname): - try: - return self.known_modules[fullname] - except KeyError: - raise ImportError("This loader does not know module " + fullname) - - def load_module(self, fullname): - try: - # in case of a reload - return sys.modules[fullname] - except KeyError: - pass - mod = self.__get_module(fullname) - if isinstance(mod, MovedModule): - mod = mod._resolve() - else: - mod.__loader__ = self - sys.modules[fullname] = mod - return mod - - def is_package(self, fullname): - """ - Return true, if the named module is a package. - - We need this method to get correct spec objects with - Python 3.4 (see PEP451) - """ - return hasattr(self.__get_module(fullname), "__path__") - - def get_code(self, fullname): - """Return None - - Required, if is_package is implemented""" - self.__get_module(fullname) # eventually raises ImportError - return None - get_source = get_code # same as get_code - -_importer = _SixMetaPathImporter(__name__) - - -class _MovedItems(_LazyModule): - - """Lazy loading of moved objects""" - __path__ = [] # mark as package - - -_moved_attributes = [ - MovedAttribute("cStringIO", "cStringIO", "io", "StringIO"), - MovedAttribute("filter", "itertools", "builtins", "ifilter", "filter"), - MovedAttribute("filterfalse", "itertools", "itertools", "ifilterfalse", "filterfalse"), - MovedAttribute("input", "__builtin__", "builtins", "raw_input", "input"), - MovedAttribute("intern", "__builtin__", "sys"), - MovedAttribute("map", "itertools", "builtins", "imap", "map"), - MovedAttribute("getcwd", "os", "os", "getcwdu", "getcwd"), - MovedAttribute("getcwdb", "os", "os", "getcwd", "getcwdb"), - MovedAttribute("range", "__builtin__", "builtins", "xrange", "range"), - MovedAttribute("reload_module", "__builtin__", "importlib" if PY34 else "imp", "reload"), - MovedAttribute("reduce", "__builtin__", "functools"), - MovedAttribute("shlex_quote", "pipes", "shlex", "quote"), - MovedAttribute("StringIO", "StringIO", "io"), - MovedAttribute("UserDict", "UserDict", "collections"), - MovedAttribute("UserList", "UserList", "collections"), - MovedAttribute("UserString", "UserString", "collections"), - MovedAttribute("xrange", "__builtin__", "builtins", "xrange", "range"), - MovedAttribute("zip", "itertools", "builtins", "izip", "zip"), - MovedAttribute("zip_longest", "itertools", "itertools", "izip_longest", "zip_longest"), - MovedModule("builtins", "__builtin__"), - MovedModule("configparser", "ConfigParser"), - MovedModule("copyreg", "copy_reg"), - MovedModule("dbm_gnu", "gdbm", "dbm.gnu"), - MovedModule("_dummy_thread", "dummy_thread", "_dummy_thread"), - MovedModule("http_cookiejar", "cookielib", "http.cookiejar"), - MovedModule("http_cookies", "Cookie", "http.cookies"), - MovedModule("html_entities", "htmlentitydefs", "html.entities"), - MovedModule("html_parser", "HTMLParser", "html.parser"), - MovedModule("http_client", "httplib", "http.client"), - MovedModule("email_mime_multipart", "email.MIMEMultipart", "email.mime.multipart"), - MovedModule("email_mime_nonmultipart", "email.MIMENonMultipart", "email.mime.nonmultipart"), - MovedModule("email_mime_text", "email.MIMEText", "email.mime.text"), - MovedModule("email_mime_base", "email.MIMEBase", "email.mime.base"), - MovedModule("BaseHTTPServer", "BaseHTTPServer", "http.server"), - MovedModule("CGIHTTPServer", "CGIHTTPServer", "http.server"), - MovedModule("SimpleHTTPServer", "SimpleHTTPServer", "http.server"), - MovedModule("cPickle", "cPickle", "pickle"), - MovedModule("queue", "Queue"), - MovedModule("reprlib", "repr"), - MovedModule("socketserver", "SocketServer"), - MovedModule("_thread", "thread", "_thread"), - MovedModule("tkinter", "Tkinter"), - MovedModule("tkinter_dialog", "Dialog", "tkinter.dialog"), - MovedModule("tkinter_filedialog", "FileDialog", "tkinter.filedialog"), - MovedModule("tkinter_scrolledtext", "ScrolledText", "tkinter.scrolledtext"), - MovedModule("tkinter_simpledialog", "SimpleDialog", "tkinter.simpledialog"), - MovedModule("tkinter_tix", "Tix", "tkinter.tix"), - MovedModule("tkinter_ttk", "ttk", "tkinter.ttk"), - MovedModule("tkinter_constants", "Tkconstants", "tkinter.constants"), - MovedModule("tkinter_dnd", "Tkdnd", "tkinter.dnd"), - MovedModule("tkinter_colorchooser", "tkColorChooser", - "tkinter.colorchooser"), - MovedModule("tkinter_commondialog", "tkCommonDialog", - "tkinter.commondialog"), - MovedModule("tkinter_tkfiledialog", "tkFileDialog", "tkinter.filedialog"), - MovedModule("tkinter_font", "tkFont", "tkinter.font"), - MovedModule("tkinter_messagebox", "tkMessageBox", "tkinter.messagebox"), - MovedModule("tkinter_tksimpledialog", "tkSimpleDialog", - "tkinter.simpledialog"), - MovedModule("urllib_parse", __name__ + ".moves.urllib_parse", "urllib.parse"), - MovedModule("urllib_error", __name__ + ".moves.urllib_error", "urllib.error"), - MovedModule("urllib", __name__ + ".moves.urllib", __name__ + ".moves.urllib"), - MovedModule("urllib_robotparser", "robotparser", "urllib.robotparser"), - MovedModule("xmlrpc_client", "xmlrpclib", "xmlrpc.client"), - MovedModule("xmlrpc_server", "SimpleXMLRPCServer", "xmlrpc.server"), -] -# Add windows specific modules. -if sys.platform == "win32": - _moved_attributes += [ - MovedModule("winreg", "_winreg"), - ] - -for attr in _moved_attributes: - setattr(_MovedItems, attr.name, attr) - if isinstance(attr, MovedModule): - _importer._add_module(attr, "moves." + attr.name) -del attr - -_MovedItems._moved_attributes = _moved_attributes - -moves = _MovedItems(__name__ + ".moves") -_importer._add_module(moves, "moves") - - -class Module_six_moves_urllib_parse(_LazyModule): - - """Lazy loading of moved objects in six.moves.urllib_parse""" - - -_urllib_parse_moved_attributes = [ - MovedAttribute("ParseResult", "urlparse", "urllib.parse"), - MovedAttribute("SplitResult", "urlparse", "urllib.parse"), - MovedAttribute("parse_qs", "urlparse", "urllib.parse"), - MovedAttribute("parse_qsl", "urlparse", "urllib.parse"), - MovedAttribute("urldefrag", "urlparse", "urllib.parse"), - MovedAttribute("urljoin", "urlparse", "urllib.parse"), - MovedAttribute("urlparse", "urlparse", "urllib.parse"), - MovedAttribute("urlsplit", "urlparse", "urllib.parse"), - MovedAttribute("urlunparse", "urlparse", "urllib.parse"), - MovedAttribute("urlunsplit", "urlparse", "urllib.parse"), - MovedAttribute("quote", "urllib", "urllib.parse"), - MovedAttribute("quote_plus", "urllib", "urllib.parse"), - MovedAttribute("unquote", "urllib", "urllib.parse"), - MovedAttribute("unquote_plus", "urllib", "urllib.parse"), - MovedAttribute("urlencode", "urllib", "urllib.parse"), - MovedAttribute("splitquery", "urllib", "urllib.parse"), - MovedAttribute("splittag", "urllib", "urllib.parse"), - MovedAttribute("splituser", "urllib", "urllib.parse"), - MovedAttribute("uses_fragment", "urlparse", "urllib.parse"), - MovedAttribute("uses_netloc", "urlparse", "urllib.parse"), - MovedAttribute("uses_params", "urlparse", "urllib.parse"), - MovedAttribute("uses_query", "urlparse", "urllib.parse"), - MovedAttribute("uses_relative", "urlparse", "urllib.parse"), -] -for attr in _urllib_parse_moved_attributes: - setattr(Module_six_moves_urllib_parse, attr.name, attr) -del attr - -Module_six_moves_urllib_parse._moved_attributes = _urllib_parse_moved_attributes - -_importer._add_module(Module_six_moves_urllib_parse(__name__ + ".moves.urllib_parse"), - "moves.urllib_parse", "moves.urllib.parse") - - -class Module_six_moves_urllib_error(_LazyModule): - - """Lazy loading of moved objects in six.moves.urllib_error""" - - -_urllib_error_moved_attributes = [ - MovedAttribute("URLError", "urllib2", "urllib.error"), - MovedAttribute("HTTPError", "urllib2", "urllib.error"), - MovedAttribute("ContentTooShortError", "urllib", "urllib.error"), -] -for attr in _urllib_error_moved_attributes: - setattr(Module_six_moves_urllib_error, attr.name, attr) -del attr - -Module_six_moves_urllib_error._moved_attributes = _urllib_error_moved_attributes - -_importer._add_module(Module_six_moves_urllib_error(__name__ + ".moves.urllib.error"), - "moves.urllib_error", "moves.urllib.error") - - -class Module_six_moves_urllib_request(_LazyModule): - - """Lazy loading of moved objects in six.moves.urllib_request""" - - -_urllib_request_moved_attributes = [ - MovedAttribute("urlopen", "urllib2", "urllib.request"), - MovedAttribute("install_opener", "urllib2", "urllib.request"), - MovedAttribute("build_opener", "urllib2", "urllib.request"), - MovedAttribute("pathname2url", "urllib", "urllib.request"), - MovedAttribute("url2pathname", "urllib", "urllib.request"), - MovedAttribute("getproxies", "urllib", "urllib.request"), - MovedAttribute("Request", "urllib2", "urllib.request"), - MovedAttribute("OpenerDirector", "urllib2", "urllib.request"), - MovedAttribute("HTTPDefaultErrorHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPRedirectHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPCookieProcessor", "urllib2", "urllib.request"), - MovedAttribute("ProxyHandler", "urllib2", "urllib.request"), - MovedAttribute("BaseHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPPasswordMgr", "urllib2", "urllib.request"), - MovedAttribute("HTTPPasswordMgrWithDefaultRealm", "urllib2", "urllib.request"), - MovedAttribute("AbstractBasicAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPBasicAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("ProxyBasicAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("AbstractDigestAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPDigestAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("ProxyDigestAuthHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPSHandler", "urllib2", "urllib.request"), - MovedAttribute("FileHandler", "urllib2", "urllib.request"), - MovedAttribute("FTPHandler", "urllib2", "urllib.request"), - MovedAttribute("CacheFTPHandler", "urllib2", "urllib.request"), - MovedAttribute("UnknownHandler", "urllib2", "urllib.request"), - MovedAttribute("HTTPErrorProcessor", "urllib2", "urllib.request"), - MovedAttribute("urlretrieve", "urllib", "urllib.request"), - MovedAttribute("urlcleanup", "urllib", "urllib.request"), - MovedAttribute("URLopener", "urllib", "urllib.request"), - MovedAttribute("FancyURLopener", "urllib", "urllib.request"), - MovedAttribute("proxy_bypass", "urllib", "urllib.request"), -] -for attr in _urllib_request_moved_attributes: - setattr(Module_six_moves_urllib_request, attr.name, attr) -del attr - -Module_six_moves_urllib_request._moved_attributes = _urllib_request_moved_attributes - -_importer._add_module(Module_six_moves_urllib_request(__name__ + ".moves.urllib.request"), - "moves.urllib_request", "moves.urllib.request") - - -class Module_six_moves_urllib_response(_LazyModule): - - """Lazy loading of moved objects in six.moves.urllib_response""" - - -_urllib_response_moved_attributes = [ - MovedAttribute("addbase", "urllib", "urllib.response"), - MovedAttribute("addclosehook", "urllib", "urllib.response"), - MovedAttribute("addinfo", "urllib", "urllib.response"), - MovedAttribute("addinfourl", "urllib", "urllib.response"), -] -for attr in _urllib_response_moved_attributes: - setattr(Module_six_moves_urllib_response, attr.name, attr) -del attr - -Module_six_moves_urllib_response._moved_attributes = _urllib_response_moved_attributes - -_importer._add_module(Module_six_moves_urllib_response(__name__ + ".moves.urllib.response"), - "moves.urllib_response", "moves.urllib.response") - - -class Module_six_moves_urllib_robotparser(_LazyModule): - - """Lazy loading of moved objects in six.moves.urllib_robotparser""" - - -_urllib_robotparser_moved_attributes = [ - MovedAttribute("RobotFileParser", "robotparser", "urllib.robotparser"), -] -for attr in _urllib_robotparser_moved_attributes: - setattr(Module_six_moves_urllib_robotparser, attr.name, attr) -del attr - -Module_six_moves_urllib_robotparser._moved_attributes = _urllib_robotparser_moved_attributes - -_importer._add_module(Module_six_moves_urllib_robotparser(__name__ + ".moves.urllib.robotparser"), - "moves.urllib_robotparser", "moves.urllib.robotparser") - - -class Module_six_moves_urllib(types.ModuleType): - - """Create a six.moves.urllib namespace that resembles the Python 3 namespace""" - __path__ = [] # mark as package - parse = _importer._get_module("moves.urllib_parse") - error = _importer._get_module("moves.urllib_error") - request = _importer._get_module("moves.urllib_request") - response = _importer._get_module("moves.urllib_response") - robotparser = _importer._get_module("moves.urllib_robotparser") - - def __dir__(self): - return ['parse', 'error', 'request', 'response', 'robotparser'] - -_importer._add_module(Module_six_moves_urllib(__name__ + ".moves.urllib"), - "moves.urllib") - - -def add_move(move): - """Add an item to six.moves.""" - setattr(_MovedItems, move.name, move) - - -def remove_move(name): - """Remove item from six.moves.""" - try: - delattr(_MovedItems, name) - except AttributeError: - try: - del moves.__dict__[name] - except KeyError: - raise AttributeError("no such move, %r" % (name,)) - - -if PY3: - _meth_func = "__func__" - _meth_self = "__self__" - - _func_closure = "__closure__" - _func_code = "__code__" - _func_defaults = "__defaults__" - _func_globals = "__globals__" -else: - _meth_func = "im_func" - _meth_self = "im_self" - - _func_closure = "func_closure" - _func_code = "func_code" - _func_defaults = "func_defaults" - _func_globals = "func_globals" - - -try: - advance_iterator = next -except NameError: - def advance_iterator(it): - return it.next() -next = advance_iterator - - -try: - callable = callable -except NameError: - def callable(obj): - return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) - - -if PY3: - def get_unbound_function(unbound): - return unbound - - create_bound_method = types.MethodType - - def create_unbound_method(func, cls): - return func - - Iterator = object -else: - def get_unbound_function(unbound): - return unbound.im_func - - def create_bound_method(func, obj): - return types.MethodType(func, obj, obj.__class__) - - def create_unbound_method(func, cls): - return types.MethodType(func, None, cls) - - class Iterator(object): - - def next(self): - return type(self).__next__(self) - - callable = callable -_add_doc(get_unbound_function, - """Get the function out of a possibly unbound function""") - - -get_method_function = operator.attrgetter(_meth_func) -get_method_self = operator.attrgetter(_meth_self) -get_function_closure = operator.attrgetter(_func_closure) -get_function_code = operator.attrgetter(_func_code) -get_function_defaults = operator.attrgetter(_func_defaults) -get_function_globals = operator.attrgetter(_func_globals) - - -if PY3: - def iterkeys(d, **kw): - return iter(d.keys(**kw)) - - def itervalues(d, **kw): - return iter(d.values(**kw)) - - def iteritems(d, **kw): - return iter(d.items(**kw)) - - def iterlists(d, **kw): - return iter(d.lists(**kw)) - - viewkeys = operator.methodcaller("keys") - - viewvalues = operator.methodcaller("values") - - viewitems = operator.methodcaller("items") -else: - def iterkeys(d, **kw): - return d.iterkeys(**kw) - - def itervalues(d, **kw): - return d.itervalues(**kw) - - def iteritems(d, **kw): - return d.iteritems(**kw) - - def iterlists(d, **kw): - return d.iterlists(**kw) - - viewkeys = operator.methodcaller("viewkeys") - - viewvalues = operator.methodcaller("viewvalues") - - viewitems = operator.methodcaller("viewitems") - -_add_doc(iterkeys, "Return an iterator over the keys of a dictionary.") -_add_doc(itervalues, "Return an iterator over the values of a dictionary.") -_add_doc(iteritems, - "Return an iterator over the (key, value) pairs of a dictionary.") -_add_doc(iterlists, - "Return an iterator over the (key, [values]) pairs of a dictionary.") - - -if PY3: - def b(s): - return s.encode("latin-1") - - def u(s): - return s - unichr = chr - import struct - int2byte = struct.Struct(">B").pack - del struct - byte2int = operator.itemgetter(0) - indexbytes = operator.getitem - iterbytes = iter - import io - StringIO = io.StringIO - BytesIO = io.BytesIO - _assertCountEqual = "assertCountEqual" - if sys.version_info[1] <= 1: - _assertRaisesRegex = "assertRaisesRegexp" - _assertRegex = "assertRegexpMatches" - else: - _assertRaisesRegex = "assertRaisesRegex" - _assertRegex = "assertRegex" -else: - def b(s): - return s - # Workaround for standalone backslash - - def u(s): - return unicode(s.replace(r'\\', r'\\\\'), "unicode_escape") - unichr = unichr - int2byte = chr - - def byte2int(bs): - return ord(bs[0]) - - def indexbytes(buf, i): - return ord(buf[i]) - iterbytes = functools.partial(itertools.imap, ord) - import StringIO - StringIO = BytesIO = StringIO.StringIO - _assertCountEqual = "assertItemsEqual" - _assertRaisesRegex = "assertRaisesRegexp" - _assertRegex = "assertRegexpMatches" -_add_doc(b, """Byte literal""") -_add_doc(u, """Text literal""") - - -def assertCountEqual(self, *args, **kwargs): - return getattr(self, _assertCountEqual)(*args, **kwargs) - - -def assertRaisesRegex(self, *args, **kwargs): - return getattr(self, _assertRaisesRegex)(*args, **kwargs) - - -def assertRegex(self, *args, **kwargs): - return getattr(self, _assertRegex)(*args, **kwargs) - - -if PY3: - exec_ = getattr(moves.builtins, "exec") - - def reraise(tp, value, tb=None): - if value is None: - value = tp() - if value.__traceback__ is not tb: - raise value.with_traceback(tb) - raise value - -else: - def exec_(_code_, _globs_=None, _locs_=None): - """Execute code in a namespace.""" - if _globs_ is None: - frame = sys._getframe(1) - _globs_ = frame.f_globals - if _locs_ is None: - _locs_ = frame.f_locals - del frame - elif _locs_ is None: - _locs_ = _globs_ - exec("""exec _code_ in _globs_, _locs_""") - - exec_("""def reraise(tp, value, tb=None): - raise tp, value, tb -""") - - -if sys.version_info[:2] == (3, 2): - exec_("""def raise_from(value, from_value): - if from_value is None: - raise value - raise value from from_value -""") -elif sys.version_info[:2] > (3, 2): - exec_("""def raise_from(value, from_value): - raise value from from_value -""") -else: - def raise_from(value, from_value): - raise value - - -print_ = getattr(moves.builtins, "print", None) -if print_ is None: - def print_(*args, **kwargs): - """The new-style print function for Python 2.4 and 2.5.""" - fp = kwargs.pop("file", sys.stdout) - if fp is None: - return - - def write(data): - if not isinstance(data, basestring): - data = str(data) - # If the file has an encoding, encode unicode with it. - if (isinstance(fp, file) and - isinstance(data, unicode) and - fp.encoding is not None): - errors = getattr(fp, "errors", None) - if errors is None: - errors = "strict" - data = data.encode(fp.encoding, errors) - fp.write(data) - want_unicode = False - sep = kwargs.pop("sep", None) - if sep is not None: - if isinstance(sep, unicode): - want_unicode = True - elif not isinstance(sep, str): - raise TypeError("sep must be None or a string") - end = kwargs.pop("end", None) - if end is not None: - if isinstance(end, unicode): - want_unicode = True - elif not isinstance(end, str): - raise TypeError("end must be None or a string") - if kwargs: - raise TypeError("invalid keyword arguments to print()") - if not want_unicode: - for arg in args: - if isinstance(arg, unicode): - want_unicode = True - break - if want_unicode: - newline = unicode("\n") - space = unicode(" ") - else: - newline = "\n" - space = " " - if sep is None: - sep = space - if end is None: - end = newline - for i, arg in enumerate(args): - if i: - write(sep) - write(arg) - write(end) -if sys.version_info[:2] < (3, 3): - _print = print_ - - def print_(*args, **kwargs): - fp = kwargs.get("file", sys.stdout) - flush = kwargs.pop("flush", False) - _print(*args, **kwargs) - if flush and fp is not None: - fp.flush() - -_add_doc(reraise, """Reraise an exception.""") - -if sys.version_info[0:2] < (3, 4): - def wraps(wrapped, assigned=functools.WRAPPER_ASSIGNMENTS, - updated=functools.WRAPPER_UPDATES): - def wrapper(f): - f = functools.wraps(wrapped, assigned, updated)(f) - f.__wrapped__ = wrapped - return f - return wrapper -else: - wraps = functools.wraps - - -def with_metaclass(meta, *bases): - """Create a base class with a metaclass.""" - # This requires a bit of explanation: the basic idea is to make a dummy - # metaclass for one level of class instantiation that replaces itself with - # the actual metaclass. - class metaclass(meta): - - def __new__(cls, name, this_bases, d): - return meta(name, bases, d) - return type.__new__(metaclass, 'temporary_class', (), {}) - - -def add_metaclass(metaclass): - """Class decorator for creating a class with a metaclass.""" - def wrapper(cls): - orig_vars = cls.__dict__.copy() - slots = orig_vars.get('__slots__') - if slots is not None: - if isinstance(slots, str): - slots = [slots] - for slots_var in slots: - orig_vars.pop(slots_var) - orig_vars.pop('__dict__', None) - orig_vars.pop('__weakref__', None) - return metaclass(cls.__name__, cls.__bases__, orig_vars) - return wrapper - - -def python_2_unicode_compatible(klass): - """ - A decorator that defines __unicode__ and __str__ methods under Python 2. - Under Python 3 it does nothing. - - To support Python 2 and 3 with a single code base, define a __str__ method - returning text and apply this decorator to the class. - """ - if PY2: - if '__str__' not in klass.__dict__: - raise ValueError("@python_2_unicode_compatible cannot be applied " - "to %s because it doesn't define __str__()." % - klass.__name__) - klass.__unicode__ = klass.__str__ - klass.__str__ = lambda self: self.__unicode__().encode('utf-8') - return klass - - -# Complete the moves implementation. -# This code is at the end of this module to speed up module loading. -# Turn this module into a package. -__path__ = [] # required for PEP 302 and PEP 451 -__package__ = __name__ # see PEP 366 @ReservedAssignment -if globals().get("__spec__") is not None: - __spec__.submodule_search_locations = [] # PEP 451 @UndefinedVariable -# Remove other six meta path importers, since they cause problems. This can -# happen if six is removed from sys.modules and then reloaded. (Setuptools does -# this for some reason.) -if sys.meta_path: - for i, importer in enumerate(sys.meta_path): - # Here's some real nastiness: Another "instance" of the six module might - # be floating around. Therefore, we can't use isinstance() to check for - # the six meta path importer, since the other six instance will have - # inserted an importer with different class. - if (type(importer).__name__ == "_SixMetaPathImporter" and - importer.name == __name__): - del sys.meta_path[i] - break - del i, importer -# Finally, add the importer to the meta path import hook. -sys.meta_path.append(_importer) From 4bb538e4aefddb477fa9a436aa38989026afd8a8 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Sat, 1 Apr 2017 20:33:51 +0200 Subject: [PATCH 121/452] Improve docstrings --- src/doc/en/reference/references/index.rst | 4 +++ .../rings/function_field/function_field.py | 28 ++++++++----------- src/sage/rings/function_field/maps.py | 18 +++++------- 3 files changed, 23 insertions(+), 27 deletions(-) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index a2010e67e33..9d1d79e8fc8 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -760,6 +760,10 @@ REFERENCES: .. [GS1999] Venkatesan Guruswami and Madhu Sudan, Improved Decoding of Reed-Solomon Codes and Algebraic-Geometric Codes, 1999 +.. [GT1996] \P. Gianni and B. Trager. "Square-free algorithms in + positive characteristic". Applicable Algebra in Engineering, + Communication and Computing, 7(1), 1-14 (1996) + .. [GT2014] \M.S. Gowda and J. Tao. On the bilinearity rank of a proper cone and Lyapunov-like transformations. Mathematical Programming, 147 (2014) diff --git a/src/sage/rings/function_field/function_field.py b/src/sage/rings/function_field/function_field.py index cac2edcfb28..74430703a76 100644 --- a/src/sage/rings/function_field/function_field.py +++ b/src/sage/rings/function_field/function_field.py @@ -1285,34 +1285,31 @@ def genus(self): @cached_method def derivation(self): r""" - Return a generator of the space of derivations over the constant base - ring of this function field. + Return a derivation of the function field over the constant base field. + + If the field is a separable extension of the base field, the derivation + is uniquely determined from that of the base function field. - A derivation on `R` is map `R\to R` with + A derivation on `R` is a map `R\to R` satisfying `D(\alpha+\beta)=D(\alpha)+D(\beta)` and `D(\alpha\beta)=\beta - D(\alpha)+\alpha D(\beta)` for all `\alpha,\beta\in R`. For a function + D(\alpha)+\alpha D(\beta)` for all `\alpha, \beta \in R`. For a function field which is a finite extension of `K(x)` with `K` perfect, the derivations form a one-dimensional `K`-vector space generated by the derivation returned by this method. ALGORITHM: - If this field is a separable extension of another function field `F`, - then Proposition 11 of [GT1996]_ describes how to compute the unique - extension of a derivation on `F` to this field; we apply the formula - described there to the generator of the space of derivations on `F`. + Proposition 11 of [GT1996]_ describes how to compute the unique extension + of a derivation on the base function field `F` if the field is a separable + extension of `F`. We apply the formula described there to the generator + of the space of derivations on `F`. + The general inseparable case is not implemented yet (see :trac:`16562`, :trac:`16564`.)` OUTPUT: - An endofunction on this function field. - - REFERENCES: - - .. [GT1996] Gianni, P., & Trager, B. (1996). Square-free algorithms in - positive characteristic. Applicable Algebra in Engineering, - Communication and Computing, 7(1), 1-14. + A derivation of this function field. EXAMPLES:: @@ -1349,7 +1346,6 @@ def derivation(self): Traceback (most recent call last): ... NotImplementedError: construction of separable models not implemented - """ from .maps import FunctionFieldDerivation_separable if self.polynomial().gcd(self.polynomial().derivative()).is_one(): diff --git a/src/sage/rings/function_field/maps.py b/src/sage/rings/function_field/maps.py index 49934428510..b15d67ab095 100644 --- a/src/sage/rings/function_field/maps.py +++ b/src/sage/rings/function_field/maps.py @@ -190,7 +190,7 @@ class FunctionFieldDerivation_separable(FunctionFieldDerivation): - ``L`` -- a function field which is a separable extension of the domain of ``d`` - - ``d`` -- a derivation on a function field + - ``d`` -- a derivation on the base function field of ``L`` EXAMPLES:: @@ -214,20 +214,15 @@ def __init__(self, L, d): """ - if not isinstance(d, FunctionFieldDerivation): - raise TypeError("d must be a derivation on a function field") - from .function_field import is_FunctionField - if not is_FunctionField(L): - raise TypeError("L must be a function field") - if d.domain() is not L.base_ring(): - raise ValueError("L must be an extension of the domain of d") FunctionFieldDerivation.__init__(self, L) - self._d = d f = self.domain().polynomial() if not f.gcd(f.derivative()).is_one(): raise ValueError("L must be a separable extension of its base field.") + x = self.domain().gen() + + self._d = d self._gen_image = - f.map_coefficients(lambda c:d(c))(x) / f.derivative()(x) def _call_(self, x): @@ -254,6 +249,7 @@ def _call_(self, x): """ if x.is_zero(): return self.codomain().zero() + return x._x.map_coefficients(self._d) \ + x._x.derivative()(self.domain().gen()) * self._gen_image @@ -282,9 +278,9 @@ def _repr_defn(self): """ base = self._d._repr_defn() - ret = "%s |--> %s"%(self.domain().gen(),self._gen_image) + ret = '{} |--> {}'.format(self.domain().gen(), self._gen_image) if base: - return base + "\n" + ret + return base + '\n' + ret else: return ret From ed96e1d8e577ccde243d7108ba22610c1ca1f020 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sat, 1 Apr 2017 18:55:01 -0500 Subject: [PATCH 122/452] Removing cmp in PBW bases. --- .../lie_algebras/poincare_birkhoff_witt.py | 91 +++++++++---------- .../categories/lie_algebras_with_basis.py | 4 +- 2 files changed, 46 insertions(+), 49 deletions(-) diff --git a/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py b/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py index 0729dfbda1b..0cf869f5f1b 100644 --- a/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py +++ b/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py @@ -7,17 +7,12 @@ """ #***************************************************************************** -# Copyright (C) 2013 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 -# is available at: +# Copyright (C) 2013-2017 Travis Scrimshaw # +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** @@ -76,7 +71,9 @@ class PoincareBirkhoffWittBasis(CombinatorialFreeModule): Next we construct another instance of the PBW basis, but sorted in the reverse order:: - sage: PBW2 = L.pbw_basis(prefix='PBW2', basis_cmp=lambda x,y: -cmp(x,y)) + sage: def neg_key(x): + ....: return -L.basis().keys().index(x) + sage: PBW2 = L.pbw_basis(prefix='PBW2', basis_key=neg_key) We then check the multiplication is preserved:: @@ -101,7 +98,7 @@ class PoincareBirkhoffWittBasis(CombinatorialFreeModule): PBW[-2]*PBW[2]*PBW[3] - PBW[-2]*PBW[5] """ @staticmethod - def __classcall_private__(cls, g, basis_cmp=None, prefix='PBW', **kwds): + def __classcall_private__(cls, g, basis_key=None, prefix='PBW', **kwds): """ Normalize input to ensure a unique representation. @@ -115,9 +112,9 @@ def __classcall_private__(cls, g, basis_cmp=None, prefix='PBW', **kwds): True """ return super(PoincareBirkhoffWittBasis, cls).__classcall__(cls, - g, basis_cmp, prefix, **kwds) + g, basis_key, prefix, **kwds) - def __init__(self, g, basis_cmp, prefix, **kwds): + def __init__(self, g, basis_key, prefix, **kwds): """ Initialize ``self``. @@ -129,85 +126,83 @@ def __init__(self, g, basis_cmp, prefix, **kwds): sage: TestSuite(PBW).run(elements=[E, F, H]) sage: TestSuite(PBW).run(elements=[E, F, H, E*F + H]) # long time """ - if basis_cmp is not None: - self._basis_cmp = basis_cmp + if basis_key is not None: + self._basis_key = basis_key R = g.base_ring() self._g = g monomials = IndexedFreeAbelianMonoid(g.basis().keys(), prefix, - generator_cmp=self._monoid_cmp, **kwds) + sorting_key=self._monoid_key, **kwds) CombinatorialFreeModule.__init__(self, R, monomials, prefix='', bracket=False, latex_bracket=False, - generator_cmp=self._monomial_cmp, + sorting_key=self._monomial_key, category=Algebras(R).WithBasis()) - def _basis_cmp(self, x, y): + def _basis_key(self, x): """ - Compare the indices of ``x`` and ``y``. + Return a key for sorting for the index ``x``. TESTS:: sage: L = lie_algebras.sl(QQ, 2) sage: PBW = L.pbw_basis() - sage: PBW._basis_cmp('E', 'H') - -1 + sage: PBW._basis_key('E') < PBW._basis_key('H') + True :: sage: L = lie_algebras.sl(QQ, 2) - sage: PBW = L.pbw_basis(basis_cmp=lambda x,y: -cmp(x,y)) - sage: prod(PBW.gens()) + sage: def neg_key(x): + ....: return -L.basis().keys().index(x) + sage: PBW = L.pbw_basis(basis_key=neg_key) + sage: prod(PBW.gens()) # indirect doctest PBW['H']*PBW['F']*PBW['E'] + PBW['H']^2 """ K = self._g.basis().keys() if K.cardinality() == float('inf'): - return cmp(x, y) + return x lst = list(K) - return cmp(lst.index(x), lst.index(y)) + return lst.index(x) - def _monoid_cmp(self, x, y): + def _monoid_key(self, x): """ Comparison function for the underlying monoid. EXAMPLES:: sage: L = lie_algebras.sl(QQ, 2) - sage: PBW = L.pbw_basis(basis_cmp=lambda x,y: -cmp(x,y)) + sage: def neg_key(x): + ....: return -L.basis().keys().index(x) + sage: PBW = L.pbw_basis(basis_key=neg_key) sage: M = PBW.basis().keys() - sage: prod(M.gens()) # indirect doctest + sage: prod(M.gens()) # indirect doctest PBW['H']*PBW['F']*PBW['E'] """ - return self._basis_cmp(x[0], y[0]) + return self._basis_key(x[0]) - def _monomial_cmp(self, x, y): + def _monomial_key(self, x): """ - Compare the monomials ``x`` and ``y`` of ``self`` by reverse - degree lexicographic order. + Compute the key for ``x`` so that the comparison is done by + reverse degree lexicographic order. EXAMPLES:: sage: L = lie_algebras.sl(QQ, 2) sage: PBW = L.pbw_basis() sage: E,F,H = sorted(PBW.algebra_generators(), key=str) - sage: H*F*F*E # indirect doctest + sage: H*F*F*E # indirect doctest PBW['E']*PBW['F']^2*PBW['H'] - 2*PBW['E']*PBW['F']^2 - 2*PBW['F']*PBW['H']^2 + 6*PBW['F']*PBW['H'] - 4*PBW['F'] - sage: PBW = L.pbw_basis(basis_cmp=lambda x,y: -cmp(x,y)) + sage: def neg_key(x): + ....: return -L.basis().keys().index(x) + sage: PBW = L.pbw_basis(basis_key=neg_key) sage: E,F,H = sorted(PBW.algebra_generators(), key=str) - sage: E*F*F*H # indirect doctest + sage: E*F*F*H # indirect doctest PBW['H']*PBW['F']^2*PBW['E'] + 2*PBW['H']^2*PBW['F'] + 2*PBW['F']^2*PBW['E'] + 6*PBW['H']*PBW['F'] + 4*PBW['F'] """ - c = cmp(len(y), len(x)) - if c: - return c - w = y.to_word_list() - for i,a in enumerate(x.to_word_list()): - c = self._basis_cmp(a, w[i]) - if c: - return c - return 0 + return (-len(x), [self._basis_key(l) for l in x.to_word_list()]) def _repr_(self): """ @@ -239,7 +234,9 @@ def _coerce_map_from_(self, R): We can go between PBW bases under different sorting orders:: - sage: PBW2 = L.pbw_basis(basis_cmp=lambda x,y: -cmp(x,y)) + sage: def neg_key(x): + ....: return -L.basis().keys().index(x) + sage: PBW2 = L.pbw_basis(basis_key=neg_key) sage: E,F,H = sorted(PBW.algebra_generators(), key=str) sage: PBW2(E*F*H) PBW['H']*PBW['F']*PBW['E'] + PBW['H']^2 @@ -349,7 +346,7 @@ def product_on_basis(self, lhs, rhs): I = self._indices trail = lhs.trailing_support() lead = rhs.leading_support() - if self._basis_cmp(trail, lead) <= 0: + if self._basis_key(trail) <= self._basis_key(lead): return self.monomial(lhs * rhs) # Create the commutator diff --git a/src/sage/categories/lie_algebras_with_basis.py b/src/sage/categories/lie_algebras_with_basis.py index d7fc9d19744..55c98c041a2 100644 --- a/src/sage/categories/lie_algebras_with_basis.py +++ b/src/sage/categories/lie_algebras_with_basis.py @@ -143,7 +143,7 @@ def dimension(self): """ return self.basis().cardinality() - def pbw_basis(self, basis_cmp=None, **kwds): + def pbw_basis(self, basis_key=None, **kwds): """ Return the Poincare-Birkhoff-Witt basis of the universal enveloping algebra corresponding to ``self``. @@ -155,7 +155,7 @@ def pbw_basis(self, basis_cmp=None, **kwds): """ from sage.algebras.lie_algebras.poincare_birkhoff_witt \ import PoincareBirkhoffWittBasis - return PoincareBirkhoffWittBasis(self, basis_cmp, **kwds) + return PoincareBirkhoffWittBasis(self, basis_key, **kwds) poincare_birkhoff_witt_basis = pbw_basis From 2847da0c1b63a9ebd9281fb0b4e5e8c790561fd3 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Sun, 2 Apr 2017 06:50:29 +0200 Subject: [PATCH 123/452] Trim code and docstrings --- .../rings/function_field/function_field.py | 5 +- src/sage/rings/function_field/maps.py | 74 ++++++++----------- 2 files changed, 34 insertions(+), 45 deletions(-) diff --git a/src/sage/rings/function_field/function_field.py b/src/sage/rings/function_field/function_field.py index 74430703a76..489567b4796 100644 --- a/src/sage/rings/function_field/function_field.py +++ b/src/sage/rings/function_field/function_field.py @@ -358,14 +358,13 @@ def _coerce_map_from_(self, R): return False def _test_derivation(self, **options): - r""" - Test the correctness of the derivations of this function field. + """ + Test the correctness of the derivations of the function field. EXAMPLES:: sage: K. = FunctionField(QQ) sage: TestSuite(K).run() # indirect doctest - """ tester = self._tester(**options) S = tester.some_elements() diff --git a/src/sage/rings/function_field/maps.py b/src/sage/rings/function_field/maps.py index b15d67ab095..08190327698 100644 --- a/src/sage/rings/function_field/maps.py +++ b/src/sage/rings/function_field/maps.py @@ -111,47 +111,41 @@ def is_injective(self): return False class FunctionFieldDerivation_rational(FunctionFieldDerivation): - r""" + """ A derivation on a rational function field. - INPUT: - - - ``K`` -- a rational function field - - - ``u`` -- an element of ``K``, the image of the generator of ``K`` under - the derivation. - EXAMPLES:: sage: K. = FunctionField(QQ) sage: d = K.derivation() sage: isinstance(d, sage.rings.function_field.maps.FunctionFieldDerivation_rational) True - """ def __init__(self, K, u): - r""" + """ Initialize a derivation of ``K`` which sends the generator of ``K`` to ``u``. + INPUT: + + - ``K`` -- a rational function field + + - ``u`` -- an element of ``K``, the image of the generator of ``K`` under + the derivation + EXAMPLES:: sage: K. = FunctionField(QQ) sage: d = K.derivation() # indirect doctest sage: type(d) - """ - from .function_field import is_RationalFunctionField - if not is_RationalFunctionField(K): - raise ValueError("K must be a rational function field") - if u.parent() is not K: - raise ValueError("u must be an element in K") FunctionFieldDerivation.__init__(self, K) + self._u = u def _call_(self, x): - r""" + """ Compute the derivation of ``x``. INPUT: @@ -168,42 +162,38 @@ def _call_(self, x): 3*x^2 sage: d(1/x) -1/x^2 - """ - f,g = x.numerator(),x.denominator() - - if not f.gcd(g).is_one(): - raise NotImplementedError("derivations only implemented for rational functions with coprime numerator and denominator.") + f = x.numerator() + g = x.denominator() - numerator = f.derivative()*g - f*g.derivative() + numerator = f.derivative() * g - f * g.derivative() if numerator.is_zero(): return self.codomain().zero() else: - return self._u * self.codomain()( numerator / g**2 ) + return self._u * self.codomain()(numerator / g**2) class FunctionFieldDerivation_separable(FunctionFieldDerivation): - r""" + """ The unique extension of the derivation ``d`` to ``L``. - INPUT: - - - ``L`` -- a function field which is a separable extension of the domain of - ``d`` - - - ``d`` -- a derivation on the base function field of ``L`` - EXAMPLES:: sage: K. = FunctionField(QQ) sage: R. = K[] sage: L. = K.extension(y^2 - x) sage: d = L.derivation() - """ def __init__(self, L, d): - r""" + """ Initialization. + INPUT: + + - ``L`` -- a function field which is a separable extension of the domain of + ``d`` + + - ``d`` -- a derivation on the base function field of ``L`` + EXAMPLES:: sage: K. = FunctionField(GF(3)) @@ -212,7 +202,6 @@ def __init__(self, L, d): sage: d = L.derivation() # indirect doctest sage: type(d) - """ FunctionFieldDerivation.__init__(self, L) @@ -245,19 +234,20 @@ def _call_(self, x): (-1/2/-x)*y sage: d(y^2) 1 - """ if x.is_zero(): return self.codomain().zero() - return x._x.map_coefficients(self._d) \ - + x._x.derivative()(self.domain().gen()) * self._gen_image + x = x._x + y = self.domain().gen() + + return x.map_coefficients(self._d) + x.derivative()(y) * self._gen_image def _repr_defn(self): - r""" - Helper method to print this map. + """ + Return the string representation of the map. - TESTS:: + EXAMPLES:: sage: K. = FunctionField(QQ) sage: R. = K[] @@ -267,6 +257,7 @@ def _repr_defn(self): From: Function field in y defined by y^2 - x To: Function field in y defined by y^2 - x Defn: y |--> (-1/2/-x)*y + sage: R. = L[] sage: M. = L.extension(z^2 - y) sage: M.derivation() @@ -275,7 +266,6 @@ def _repr_defn(self): To: Function field in z defined by z^2 - y Defn: y |--> (-1/2/-x)*y z |--> 1/4/x*z - """ base = self._d._repr_defn() ret = '{} |--> {}'.format(self.domain().gen(), self._gen_image) From a7cede71e43886f7add313e06b4d9234823a3d5e Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sun, 2 Apr 2017 01:38:00 -0500 Subject: [PATCH 124/452] New data structure for elements. --- .../en/reference/algebras/lie_algebras.rst | 1 + .../lie_algebras/affine_lie_algebra.py | 227 ++++++++++++++++++ src/sage/algebras/lie_algebras/lie_algebra.py | 4 + .../lie_algebras/lie_algebra_element.pxd | 11 + .../lie_algebras/lie_algebra_element.pyx | 189 ++++++++++++++- 5 files changed, 422 insertions(+), 10 deletions(-) create mode 100644 src/sage/algebras/lie_algebras/affine_lie_algebra.py diff --git a/src/doc/en/reference/algebras/lie_algebras.rst b/src/doc/en/reference/algebras/lie_algebras.rst index 4be912c1a72..1ab77e48f76 100644 --- a/src/doc/en/reference/algebras/lie_algebras.rst +++ b/src/doc/en/reference/algebras/lie_algebras.rst @@ -5,6 +5,7 @@ Lie Algebras :maxdepth: 2 sage/algebras/lie_algebras/abelian + sage/algebras/lie_algebras/affine_lie_algebra sage/algebras/lie_algebras/classical_lie_algebra sage/algebras/lie_algebras/examples sage/algebras/lie_algebras/heisenberg diff --git a/src/sage/algebras/lie_algebras/affine_lie_algebra.py b/src/sage/algebras/lie_algebras/affine_lie_algebra.py new file mode 100644 index 00000000000..0f768225fa8 --- /dev/null +++ b/src/sage/algebras/lie_algebras/affine_lie_algebra.py @@ -0,0 +1,227 @@ +""" +Affine Lie Algebras + +AUTHORS: + +- Travis Scrimshaw (2013-05-03): Initial version + +EXAMPLES:: +""" + +#***************************************************************************** +# Copyright (C) 2013-2017 Travis Scrimshaw +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# http://www.gnu.org/licenses/ +#***************************************************************************** + +from sage.misc.cachefunc import cached_method +from sage.misc.misc import repr_lincomb +from sage.structure.element import RingElement +from sage.categories.lie_algebras import LieAlgebras + +from sage.algebras.lie_algebras.lie_algebra import LieAlgebra, FinitelyGeneratedLieAlgebra +from sage.algebras.lie_algebras.lie_algebra_element import UntwistedAffineLieAlgebraElement +from sage.combinat.root_system.cartan_type import CartanType +from sage.combinat.root_system.cartan_matrix import CartanMatrix +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing +from sage.categories.cartesian_product import cartesian_product +from sage.rings.integer_ring import ZZ +from sage.sets.disjoint_union_enumerated_sets import DisjointUnionEnumeratedSets +from sage.sets.family import Family + +class AffineLieAlgebra(FinitelyGeneratedLieAlgebra): + r""" + An (untwisted) affine Lie algebra. + + Given a finite dimensional simple Lie algebra `\mathfrak{g}` over `R`, + we construct an affine Lie algebra `\widehat{\mathfrak{g}}^{\prime}` as + + .. MATH:: + + \widehat{\mathfrak{g}}^{\prime} = \left( \mathfrak{g} \otimes + R[t, t^{-1}] \right) \oplus R c, + + where `c` is the canonical central element and `R[t, t^{-1}]` is the + Laurent polynomial ring over `R`. We define the Lie bracket as + + .. MATH:: + + [a \otimes t^n + \alpha c, b \otimes t^m + \beta c] = + [a, b] \otimes t^{n+m} + \delta_{n+m,0} ( a | b ) n c + + where `( a | b )` is the Killing form on `\mathfrak{g}`. + + There is a canonical derivative on `\widehat{\mathfrak{g}}^{\prime}` + which is known as the *Lie derivative* and is denoted by `\delta`. + The Lie derivative is defined as + + .. MATH:: + + \delta(a \otimes t^m + \alpha c) = a \otimes m t^m, + + or equivalently by `\delta = t \frac{d}{dt}`. + + We can form the affine Kac-Moody algebra `\widehat{\mathfrak{g}}` + by adding the additional generator `d` such that `[d, x] = \delta(x)` + where `\delta` is the Lie derivative. We note that the derived subalgebra + of the Kac-Moody algebra is the affine Lie algebra. + + .. NOTE:: + + Our terminology is following that of :wikipedia:`Affine_Lie_algebra`. + """ + @staticmethod + def __classcall_private__(cls, arg0, kac_moody=True, cartan_type=None): + """ + Parse input to ensure a unique representation. + + INPUT: + + - ``arg0`` -- a simple Lie algebra or a base ring + - ``cartan_type`` -- a Cartan type + + EXAMPLES:: + """ + if isinstance(arg0, LieAlgebra): + ct = arg0.cartan_type() + if not ct.is_finite(): + raise ValueError("the base Lie algebra is not simple") + cartan_type = ct.affine() + g = arg0 + else: + # arg0 is the base ring + cartan_type = CartanType(cartan_type) + if not cartan_type.is_affine(): + raise ValueError("the Cartan type must be affine") + g = LieAlgebra(arg0, cartan_type=cartan_type.classical()) + + if not cartan_type.is_untwisted_affine(): + raise NotImplementedError("only currently implemented for untwisted affine types") + return super(AffineLieAlgebra, cls).__classcall__(cls, g, kac_moody) + + def __init__(self, g, kac_moody): + """ + Initalize ``self``. + """ + self._g = g + self._cartan_type = g.cartan_type() + R = g.base_ring() + names = list(g.variable_names()) + ['e0', 'f0', 'c'] + + if kac_moody: + names += ['delta'] + self._kac_moody = kac_moody + + names = tuple(names) + cat = LieAlgebras(R).WithBasis() + FinitelyGeneratedLieAlgebra.__init__(self, R, names, names, category=cat) + + def _repr_(self): + """ + Return a string representation of ``self``. + """ + base = "Affine " + rep = repr(self._g) + if self._kac_moody: + old_len = len(rep) + rep = rep.replace("Lie", "Kac-Moody") + if len(rep) == old_len: # We did not replace anything + base += "Kac-Moody " + return base + rep + + @cached_method + def basis(self): + """ + Return the basis of ``self``. + """ + K = cartesian_product([self._g.basis().keys(), ZZ]) + if self._kac_moody: + keys = DisjointUnionEnumeratedSets([('c',), ('delta',), K]) + else: + keys = DisjointUnionEnumeratedSets([('c',), K]) + return Family(keys, self.monomial) + + def derived_subalgebra(self): + """ + Return the derived subalgebra of ``self``. + """ + if self._kac_moody: + return AffineLieAlgebra(self._g, False) + raise NotImplementedError # I think this is self... + + def cartan_type(self): + """ + Return the Cartan type of ``self``. + """ + return self._cartan_type + + def classical(self): + """ + Return the classical Lie algebra of ``self``. + """ + return self._g + + def _construct_UEA(self): + """ + Construct the universal enveloping algebra of ``self``. + """ + # These are placeholders and will require something more complex + if self._kac_moody: + PolynomialRing(self._g.universal_enveloping_algebra(), 't,c,delta') + return PolynomialRing(self._g.universal_enveloping_algebra(), 't,c') + + @cached_method + def zero(self): + """ + Return the element `0`. + + EXAMPLES:: + + sage: L. = LieAlgebra(QQ, representation="polynomial") + sage: L.zero() + 0 + """ + zero = self.base_ring().zero() + return self.element_class(self, {}, zero, zero) + + @cached_method + def lie_algebra_generators(self): + """ + Return the Lie algebra generators of ``self``. + """ + zero = self.base_ring().zero() + one = self.base_ring().one() + d = {} + if self._kac_moody: + d['delta'] = self.element_class(self, {}, zero, one) + d['c'] = self.element_class(self, {}, one, zero) + try: + finite_gens = dict(self._g.lie_algebra_generators(True)) + except (TypeError): + finite_gens = dict(self._g.lie_algebra_generators()) + for k,g in finite_gens.items(): + d[k] = self.element_class(self, {0: g}, zero, zero) + # e_0 = f_{\theta} t + d['e0'] = self.element_class(self, {1: self._g.highest_root_basis_elt(False)}, + zero, zero) + # f_0 = e_{\theta} t^-1 + d['f0'] = self.element_class(self, {-1: self._g.highest_root_basis_elt(True)}, + zero, zero) + return Family(self.variable_names(), d.__getitem__) + + def monomial(self, m): + """ + Construct the monomial indexed by ``m``. + """ + if m == 'c' or m == 'delta': + return self.lie_algebra_generators()[m] + G = self._g.lie_algebra_generators() + zero = self.base_ring().zero() + return self.element_class(self, {m[0]: G[m[1]]}, zero, zero) + + Element = UntwistedAffineLieAlgebraElement + diff --git a/src/sage/algebras/lie_algebras/lie_algebra.py b/src/sage/algebras/lie_algebras/lie_algebra.py index 03e1181911c..9b96738bcd6 100644 --- a/src/sage/algebras/lie_algebras/lie_algebra.py +++ b/src/sage/algebras/lie_algebras/lie_algebra.py @@ -301,6 +301,10 @@ def __classcall_private__(cls, R=None, arg0=None, arg1=None, names=None, if ct is not None: from sage.combinat.root_system.cartan_type import CartanType ct = CartanType(ct) + if ct.is_affine(): + from sage.algebras.lie_algebras.affine_lie_algebra import AffineLieAlgebra + return AffineLieAlgebra(R, cartan_type=ct, + kac_moody=kwds.get("kac_moody", True)) if not ct.is_finite(): raise NotImplementedError("non-finite types are not implemented yet, see trac #14901 for details") rep = kwds.get("representation", "bracket") diff --git a/src/sage/algebras/lie_algebras/lie_algebra_element.pxd b/src/sage/algebras/lie_algebras/lie_algebra_element.pxd index 47c46336c51..689ac628b41 100644 --- a/src/sage/algebras/lie_algebras/lie_algebra_element.pxd +++ b/src/sage/algebras/lie_algebras/lie_algebra_element.pxd @@ -1,3 +1,4 @@ +from sage.structure.element cimport Element from sage.structure.element_wrapper cimport ElementWrapper cdef class LieAlgebraElementWrapper(ElementWrapper): @@ -14,3 +15,13 @@ cdef class StructureCoefficientsElement(LieAlgebraMatrixWrapper): cpdef dict monomial_coefficients(self, bint copy=*) #cpdef lift(self) +cdef class UntwistedAffineLieAlgebraElement(Element): + cdef dict _t_dict + cdef _c_coeff + cdef _delta_coeff + + cpdef bracket(self, y) + cpdef _bracket_(self, y) + cpdef lie_derivative(self) + cpdef monomial_coefficients(self, bint copy=*) + diff --git a/src/sage/algebras/lie_algebras/lie_algebra_element.pyx b/src/sage/algebras/lie_algebras/lie_algebra_element.pyx index c5b47732616..fd84f2fe829 100644 --- a/src/sage/algebras/lie_algebras/lie_algebra_element.pyx +++ b/src/sage/algebras/lie_algebras/lie_algebra_element.pyx @@ -21,8 +21,9 @@ from copy import copy from sage.misc.misc import repr_lincomb from sage.combinat.free_module import CombinatorialFreeModule -from sage.structure.element cimport have_same_parent, coercion_model +from sage.structure.element cimport have_same_parent, coercion_model, parent from sage.structure.element_wrapper cimport ElementWrapper +from sage.data_structures.blas_dict cimport axpy, negate, scal # TODO: Inherit from IndexedFreeModuleElement and make cdef once #22632 is merged # TODO: Do we want a dense version? @@ -43,8 +44,8 @@ class LieAlgebraElement(CombinatorialFreeModule.Element): x*y - z """ if self.is_zero() or y.is_zero(): - return self.parent().zero() - if y in self.base_ring(): + return parent(self).zero() + if y in parent(self).base_ring(): return y * self # Otherwise we lift to the UEA return self.lift() * y @@ -281,9 +282,11 @@ cdef class LieAlgebraElementWrapper(ElementWrapper): sage: S(elt) # not tested: needs #16822 (2,3) - (1,3) """ - if self.value == 0 or x == 0: - return self._parent.zero() - if x in self.base_ring(): + if not isinstance(self, LieAlgebraElementWrapper): + x, self = self, x + if not self or not x: + return parent(self).zero() + if x in parent(self).base_ring(): return self._acted_upon_(x, True) # Otherwise we lift to the UEA return self.lift() * x @@ -330,10 +333,10 @@ cdef class LieAlgebraElementWrapper(ElementWrapper): # enough information to detect apriori that this method only # accepts scalars; so it tries on some elements(), and we need # to make sure to report an error. - if hasattr( scalar, 'parent' ) and scalar.parent() != self.base_ring(): + if hasattr( scalar, 'parent' ) and scalar.parent() != self._parent.base_ring(): # Temporary needed by coercion (see Polynomial/FractionField tests). - if self.base_ring().has_coerce_map_from(scalar.parent()): - scalar = self.base_ring()( scalar ) + if self._parent.base_ring().has_coerce_map_from(scalar.parent()): + scalar = self._parent.base_ring()( scalar ) else: return None if self_on_left: @@ -487,7 +490,7 @@ cdef class StructureCoefficientsElement(LieAlgebraMatrixWrapper): sage: list(elt) [('x', 1), ('y', -3/2)] """ - zero = self.base_ring().zero() + zero = self.parent().base_ring().zero() I = self.parent()._indices cdef int i for i,v in enumerate(self.value): @@ -555,3 +558,169 @@ cdef class StructureCoefficientsElement(LieAlgebraMatrixWrapper): """ return self.value[self._parent._indices.index(i)] +cdef class UntwistedAffineLieAlgebraElement(Element): + def __init__(self, parent, dict t_dict, c_coeff, delta_coeff): + Element.__init__(self, parent) + self._t_dict = t_dict + self._c_coeff = c_coeff + self._delta_coeff = delta_coeff + + def _repr_(self): + """ + Return a string representation of ``self``. + """ + ret = ' + '.join('({})#t^{}'.format(g, t) + for t,g in self._t_dict.iteritems()) + if self._c_coeff != 0: + if ret: + ret += ' + ' + if self._c_coeff != 1: + ret += repr(self._c_coeff) + '*c' + else: + ret += 'c' + + if self._delta_coeff != 0: + if ret: + ret += ' + ' + if self._delta_coeff != 1: + ret += repr(self._delta_coeff) + '*delta' + else: + ret += 'delta' + + if not ret: + return '0' + return ret + + def _latex_(self): + """ + Return a latex representation of ``self``. + """ + from sage.misc.latex import latex + ret = ' + '.join('({}) \otimes t^{{{}}}'.format(latex(g), t) + for t,g in self._t_dict.iteritems()) + if self._c_coeff != 0: + if ret: + ret += ' + ' + if self._c_coeff != 1: + ret += latex(self._c_coeff) + ' c' + else: + ret += 'c' + + if self._delta_coeff != 0: + if ret: + ret += ' + ' + if self._delta_coeff != 1: + ret += latex(self._delta_coeff) + ' \\delta' + else: + ret += '\\delta' + + if not ret: + return '0' + return ret + + def __nonzero__(self): + return bool(self._t_dict) or bool(self._c_coeff) or bool(self._delta_coeff) + + cdef _add_(self, other): + cdef UntwistedAffineLieAlgebraElement rt = other + return type(self)(self._parent, axpy(1, self._t_dict, rt._t_dict.copy()), + self._c_coeff + rt._c_coeff, + self._delta_coeff + rt._delta_coeff) + + cdef _sub_(self, other): + cdef UntwistedAffineLieAlgebraElement rt = other + return type(self)(self._parent, axpy(-1, self._t_dict, rt._t_dict.copy()), + self._c_coeff - rt._c_coeff, + self._delta_coeff - rt._delta_coeff) + + cdef _neg_(self): + return type(self)(self._parent, negate(self._t_dict), + -self._c_coeff, -self._delta_coeff) + + cpdef _acted_upon_(self, x, bint self_on_left): + return type(self)(self._parent, scal(x, self._t_dict, self_on_left), + x * self._c_coeff, + x * self._delta_coeff) + + cpdef monomial_coefficients(self, bint copy=True): + cdef dict d = {} + for t,g in self._t_dict.iteritems(): + for k,c in g.monomial_coefficients(copy=False).iteritems(): + d[k,t] = c + if self._c_coeff: + d['c'] = self._c_coeff + if self._delta_coeff: + d['delta'] = self._delta_coeff + return d + + cpdef bracket(self, right): + """ + Return the Lie bracket ``[self, right]``. + + EXAMPLES:: + """ + if not have_same_parent(self, right): + self, right = coercion_model.canonical_coercion(self, right) + return self._bracket_(right) + + cpdef _bracket_(self, y): + """ + Return the Lie bracket ``[self, y]``. + """ + if not self or not y: + return self._parent.zero() + gd = self._parent._g.basis() + cdef dict d = {} + cdef UntwistedAffineLieAlgebraElement rt = (y) + c = self._parent.base_ring().zero() + for tl,gl in self._t_dict.iteritems(): + # \delta contribution from the left + if rt._delta_coeff: + if tl in d: + d[tl] -= rt._delta_coeff * gl * tl + else: + d[tl] = -rt._delta_coeff * gl * tl + if not d[tl]: + del d[tl] + # main bracket of the central extension + for tr,gr in rt._t_dict.iteritems(): + b = gl.bracket(gr) + if b: + if tl+tr in d: + d[tl+tr] += b + else: + d[tl+tr] = b + if not d[tl+tr]: + del d[tl+tr] + if tl + tr == 0: + c += gl.killing_form(gr) * tl + + # \delta contribution from the right + if self._delta_coeff: + for tr,gr in rt._t_dict.iteritems(): + if tr in d: + d[tr] += self._delta_coeff * gr * tr + else: + d[tr] = self._delta_coeff * gr * tr + if not d[tr]: + del d[tr] + + return type(self)(self._parent, d, c, + self._parent.base_ring().zero()) + + cpdef lie_derivative(self): + r""" + Return the Lie derivative `\delta` applied to ``self``. + + The Lie derivative `\delta` is defined as + + .. MATH:: + + \delta(a \otimes t^m + \alpha c) = a \otimes m t^m. + + Another formulation is by `\delta = t \frac{d}{dt}`. + """ + cdef dict d = {tl: tl * gl for tl,gl in self._t_dict.iteritems() if tl != 0} + zero = self._parent.base_ring().zero() + return type(self)(self.parent(), d, zero, zero) + From 321a6b3ea8761420218e9745a6d3782c44dfbf57 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sun, 2 Apr 2017 02:34:31 -0500 Subject: [PATCH 125/452] Adding affine method and fixing highest root element for matrix Lie algebras. --- .../lie_algebras/classical_lie_algebra.py | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/sage/algebras/lie_algebras/classical_lie_algebra.py b/src/sage/algebras/lie_algebras/classical_lie_algebra.py index ef99be1e6e8..0ea78f0ebf8 100644 --- a/src/sage/algebras/lie_algebras/classical_lie_algebra.py +++ b/src/sage/algebras/lie_algebras/classical_lie_algebra.py @@ -262,9 +262,10 @@ def highest_root_basis_elt(self, pos=True): else: gens = self._f cur = gens[i] - for j in w: + for j in reversed(w): for k in range(-r.scalar(coroots[j])): cur = self.bracket(gens[j], cur) + r = r.reflection(coroots[j], True) return cur @cached_method @@ -307,13 +308,12 @@ def basis(self): expanded = True return Family(basis) - # TODO: Uncomment once #16825 is done - #def affine(self, kac_moody=False): - # """ - # Return the (untwisted) affine (Kac-Moody) Lie algebra of ``self``. - # """ - # from sage.algebras.lie_algebras.affine_lie_algebra import AffineLieAlgebra - # return AffineLieAlgebra(self, kac_moody) + def affine(self, kac_moody=False): + """ + Return the (untwisted) affine (Kac-Moody) Lie algebra of ``self``. + """ + from sage.algebras.lie_algebras.affine_lie_algebra import AffineLieAlgebra + return AffineLieAlgebra(self, kac_moody) class gl(LieAlgebraFromAssociative): r""" @@ -747,7 +747,8 @@ class f4(ExceptionalMatrixLieAlgebra): The matrix Lie algebra `\mathfrak{f}_4`. The simple Lie algebra `\mathfrak{f}_f` of type `F_4`. The matrix - representation is given following [HRT2000]_. + representation is given following [HRT2000]_ but indexed in the + reversed order (i.e., interchange 1 with 4 and 2 with 3). """ def __init__(self, R): """ @@ -783,6 +784,9 @@ def __init__(self, R): f[0][14,12] = 2*one f[1][15,13] = 2*one + # Our Cartan matrix convension is dual to that of [HRT2000]_ + e.reverse() + f.reverse() ExceptionalMatrixLieAlgebra.__init__(self, R, CartanType(['F', 4]), e, f) class g2(ExceptionalMatrixLieAlgebra): @@ -1141,13 +1145,12 @@ def weyl_group(self): from sage.combinat.root_system.weyl_group import WeylGroup return WeylGroup(self._cartan_type) - # TODO: Uncomment once #16825 is done - #def affine(self, kac_moody=False): - # """ - # Return the (untwisted) affine Lie algebra of ``self``. - # """ - # from sage.algebras.lie_algebras.affine_lie_algebra import AffineLieAlgebra - # return AffineLieAlgebra(self, kac_moody) + def affine(self, kac_moody=False): + """ + Return the (untwisted) affine Lie algebra of ``self``. + """ + from sage.algebras.lie_algebras.affine_lie_algebra import AffineLieAlgebra + return AffineLieAlgebra(self, kac_moody) # Useful in creating the UEA @cached_method From c75ce5e7e1624590aeee55015fc06c069865a9e0 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 6 Apr 2017 00:26:50 -0500 Subject: [PATCH 126/452] Finishing initial implementation of untwisted affine Lie algebras. --- .../lie_algebras/affine_lie_algebra.py | 228 +++++++++++++-- .../lie_algebras/classical_lie_algebra.py | 20 +- src/sage/algebras/lie_algebras/examples.py | 1 + src/sage/algebras/lie_algebras/lie_algebra.py | 2 +- .../lie_algebras/lie_algebra_element.pxd | 1 + .../lie_algebras/lie_algebra_element.pyx | 269 +++++++++++++++++- 6 files changed, 494 insertions(+), 27 deletions(-) diff --git a/src/sage/algebras/lie_algebras/affine_lie_algebra.py b/src/sage/algebras/lie_algebras/affine_lie_algebra.py index 0f768225fa8..8a28c65aab9 100644 --- a/src/sage/algebras/lie_algebras/affine_lie_algebra.py +++ b/src/sage/algebras/lie_algebras/affine_lie_algebra.py @@ -73,9 +73,28 @@ class AffineLieAlgebra(FinitelyGeneratedLieAlgebra): .. NOTE:: Our terminology is following that of :wikipedia:`Affine_Lie_algebra`. + + INPUT: + + Can be one of the following: + + - a base ring and an affine Cartan type: constructs the affine + (Kac-Moody) Lie algebra of the classical Lie algebra in the + bracket representation over the base ring + + - a classical Lie algebra: constructs the corresponding affine + (Kac-Moody) Lie algebra + + There is the optional argument ``kac_moody``, which can be set + to ``False`` to obtain the affine Lie algebra instead of the affine + Kac-Moody algebra. + + REFERENCES: + + - :wikipedia:`Affine_Lie_algebra` """ @staticmethod - def __classcall_private__(cls, arg0, kac_moody=True, cartan_type=None): + def __classcall_private__(cls, arg0, cartan_type=None, kac_moody=True): """ Parse input to ensure a unique representation. @@ -85,6 +104,14 @@ def __classcall_private__(cls, arg0, kac_moody=True, cartan_type=None): - ``cartan_type`` -- a Cartan type EXAMPLES:: + + sage: L1 = lie_algebras.Affine(QQ, ['A',4,1]) + sage: cl = lie_algebras.sl(QQ, 5) + sage: L2 = lie_algebras.Affine(cl) + sage: L1 is L2 + True + sage: cl.affine() is L1 + True """ if isinstance(arg0, LieAlgebra): ct = arg0.cartan_type() @@ -106,9 +133,14 @@ def __classcall_private__(cls, arg0, kac_moody=True, cartan_type=None): def __init__(self, g, kac_moody): """ Initalize ``self``. + + EXAMPLES:: + + sage: asl = lie_algebras.Affine(QQ, ['A',4,1]) + sage: TestSuite(asl).run() """ self._g = g - self._cartan_type = g.cartan_type() + self._cartan_type = g.cartan_type().affine() R = g.base_ring() names = list(g.variable_names()) + ['e0', 'f0', 'c'] @@ -117,12 +149,21 @@ def __init__(self, g, kac_moody): self._kac_moody = kac_moody names = tuple(names) + self._ordered_indices = names cat = LieAlgebras(R).WithBasis() FinitelyGeneratedLieAlgebra.__init__(self, R, names, names, category=cat) def _repr_(self): """ Return a string representation of ``self``. + + EXAMPLES:: + + sage: L = LieAlgebra(QQ, cartan_type=['D',4,1]) + sage: L + Affine Kac-Moody algebra of ['D', 4] in the Chevalley basis + sage: L.derived_subalgebra() + Affine Lie algebra of ['D', 4] in the Chevalley basis """ base = "Affine " rep = repr(self._g) @@ -137,42 +178,119 @@ def _repr_(self): def basis(self): """ Return the basis of ``self``. + + EXAMPLES:: + + sage: L = LieAlgebra(QQ, cartan_type=['D',4,1]) + sage: B = L.basis() + sage: al = RootSystem(['D',4]).root_lattice().simple_roots() + sage: B[al[1]+al[2]+al[4],4] + (E[alpha[1] + alpha[2] + alpha[4]])#t^4 + sage: B[-al[1]-2*al[2]-al[3]-al[4],2] + (E[-alpha[1] - 2*alpha[2] - alpha[3] - alpha[4]])#t^2 + sage: B[al[4],-2] + (E[alpha[4]])#t^-2 + sage: B['c'] + c + sage: B['delta'] + delta """ K = cartesian_product([self._g.basis().keys(), ZZ]) + from sage.sets.finite_enumerated_set import FiniteEnumeratedSet + c = FiniteEnumeratedSet(['c']) if self._kac_moody: - keys = DisjointUnionEnumeratedSets([('c',), ('delta',), K]) + delta = FiniteEnumeratedSet(['delta']) + keys = DisjointUnionEnumeratedSets([c, delta, K]) else: - keys = DisjointUnionEnumeratedSets([('c',), K]) + keys = DisjointUnionEnumeratedSets([c, K]) return Family(keys, self.monomial) def derived_subalgebra(self): """ Return the derived subalgebra of ``self``. + + EXAMPLES:: + + sage: L = LieAlgebra(QQ, cartan_type=['B',3,1]) + sage: L + Affine Kac-Moody algebra of ['B', 3] in the Chevalley basis + sage: D = L.derived_subalgebra(); D + Affine Lie algebra of ['B', 3] in the Chevalley basis + sage: D.derived_subalgebra() == D + True + """ + if self._kac_moody: + return AffineLieAlgebra(self._g, kac_moody=False) + return self + + def derived_series(self): + """ + Return the derived series of ``self``. + + EXAMPLES:: + + sage: L = LieAlgebra(QQ, cartan_type=['B',3,1]) + sage: L.derived_series() + [Affine Kac-Moody algebra of ['B', 3] in the Chevalley basis, + Affine Lie algebra of ['B', 3] in the Chevalley basis] + sage: L.lower_central_series() + [Affine Kac-Moody algebra of ['B', 3] in the Chevalley basis, + Affine Lie algebra of ['B', 3] in the Chevalley basis] + + sage: D = L.derived_subalgebra() + sage: D.derived_series() + [Affine Lie algebra of ['B', 3] in the Chevalley basis] """ if self._kac_moody: - return AffineLieAlgebra(self._g, False) - raise NotImplementedError # I think this is self... + return [self, self.derived_subalgebra()] + return [self] + + lower_central_series = derived_series + + def is_nilpotent(self): + """ + Return ``False`` as ``self`` is semisimple. + + EXAMPLES:: + + sage: L = LieAlgebra(QQ, cartan_type=['B',3,1]) + sage: L.is_nilpotent() + False + sage: L.is_solvable() + False + """ + return False + + is_solvable = is_nilpotent def cartan_type(self): """ Return the Cartan type of ``self``. + + EXAMPLES:: + + sage: L = LieAlgebra(QQ, cartan_type=['C',3,1]) + sage: L.cartan_type() + ['C', 3, 1] """ return self._cartan_type def classical(self): """ Return the classical Lie algebra of ``self``. - """ - return self._g - def _construct_UEA(self): - """ - Construct the universal enveloping algebra of ``self``. + EXAMPLES:: + + sage: L = LieAlgebra(QQ, cartan_type=['F',4,1]) + sage: L.classical() + Lie algebra of ['F', 4] in the Chevalley basis + + sage: so5 = lie_algebras.so(QQ, 5, 'matrix') + sage: A = so5.affine() + sage: A.classical() == so5 + True """ - # These are placeholders and will require something more complex - if self._kac_moody: - PolynomialRing(self._g.universal_enveloping_algebra(), 't,c,delta') - return PolynomialRing(self._g.universal_enveloping_algebra(), 't,c') + return self._g @cached_method def zero(self): @@ -181,27 +299,74 @@ def zero(self): EXAMPLES:: - sage: L. = LieAlgebra(QQ, representation="polynomial") + sage: L = LieAlgebra(QQ, cartan_type=['F',4,1]) sage: L.zero() 0 """ zero = self.base_ring().zero() return self.element_class(self, {}, zero, zero) + @cached_method + def c(self): + r""" + Return the canonical central element `c` of ``self``. + + EXAMPLES:: + + sage: L = LieAlgebra(QQ, cartan_type=['A',3,1]) + sage: L.c() + c + """ + R = self.base_ring() + return self.element_class(self, {}, R.one(), R.zero()) + + @cached_method + def delta(self): + r""" + Return the Lie derivative element `\delta` or ``self``. + + If ``self`` is the affine Lie algebra, then this returns 0. + + EXAMPLES:: + + sage: L = LieAlgebra(QQ, cartan_type=['A',3,1]) + sage: L.delta() + delta + sage: D = L.derived_subalgebra() + sage: D.delta() + 0 + """ + if not self._kac_moody: + return self.zero() + R = self.base_ring() + return self.element_class(self, {}, R.zero(), R.one()) + @cached_method def lie_algebra_generators(self): """ Return the Lie algebra generators of ``self``. + + EXAMPLES:: + + sage: L = LieAlgebra(QQ, cartan_type=['A',1,1]) + sage: list(L.lie_algebra_generators()) + [(E[alpha[1]])#t^0, + (E[-alpha[1]])#t^0, + (h1)#t^0, + (E[-alpha[1]])#t^1, + (E[alpha[1]])#t^-1, + c, + delta] """ zero = self.base_ring().zero() one = self.base_ring().one() d = {} if self._kac_moody: - d['delta'] = self.element_class(self, {}, zero, one) - d['c'] = self.element_class(self, {}, one, zero) + d['delta'] = self.delta() + d['c'] = self.c() try: finite_gens = dict(self._g.lie_algebra_generators(True)) - except (TypeError): + except TypeError: finite_gens = dict(self._g.lie_algebra_generators()) for k,g in finite_gens.items(): d[k] = self.element_class(self, {0: g}, zero, zero) @@ -216,12 +381,29 @@ def lie_algebra_generators(self): def monomial(self, m): """ Construct the monomial indexed by ``m``. + + EXAMPLES:: + + sage: L = LieAlgebra(QQ, cartan_type=['B',4,1]) + sage: al = RootSystem(['B',4]).root_lattice().simple_roots() + sage: L.monomial((al[1]+al[2]+al[3],4)) + (E[alpha[1] + alpha[2] + alpha[3]])#t^4 + sage: L.monomial((-al[1]-al[2]-2*al[3]-2*al[4],2)) + (E[-alpha[1] - alpha[2] - 2*alpha[3] - 2*alpha[4]])#t^2 + sage: L.monomial((al[4],-2)) + (E[alpha[4]])#t^-2 + sage: L.monomial('c') + c + sage: L.monomial('delta') + delta """ - if m == 'c' or m == 'delta': - return self.lie_algebra_generators()[m] - G = self._g.lie_algebra_generators() + if m == 'c': + return self.c() + if m == 'delta': + return self.delta() + G = self._g.basis() zero = self.base_ring().zero() - return self.element_class(self, {m[0]: G[m[1]]}, zero, zero) + return self.element_class(self, {m[1]: G[m[0]]}, zero, zero) Element = UntwistedAffineLieAlgebraElement diff --git a/src/sage/algebras/lie_algebras/classical_lie_algebra.py b/src/sage/algebras/lie_algebras/classical_lie_algebra.py index 0ea78f0ebf8..bbee1960ffe 100644 --- a/src/sage/algebras/lie_algebras/classical_lie_algebra.py +++ b/src/sage/algebras/lie_algebras/classical_lie_algebra.py @@ -310,7 +310,15 @@ def basis(self): def affine(self, kac_moody=False): """ - Return the (untwisted) affine (Kac-Moody) Lie algebra of ``self``. + Return the affine (Kac-Moody) Lie algebra of ``self``. + + EXAMPLES:: + + sage: so5 = lie_algebras.so(QQ, 5, 'matrix') + sage: so5 + Special orthogonal Lie algebra of rank 5 over Rational Field + sage: so5.affine() + Affine Special orthogonal Lie algebra of rank 5 over Rational Field """ from sage.algebras.lie_algebras.affine_lie_algebra import AffineLieAlgebra return AffineLieAlgebra(self, kac_moody) @@ -1147,7 +1155,15 @@ def weyl_group(self): def affine(self, kac_moody=False): """ - Return the (untwisted) affine Lie algebra of ``self``. + Return the affine Lie algebra of ``self``. + + EXAMPLES:: + + sage: sp6 = lie_algebras.sp(QQ, 6) + sage: sp6 + Lie algebra of ['C', 3] in the Chevalley basis + sage: sp6.affine() + Affine Lie algebra of ['C', 3] in the Chevalley basis """ from sage.algebras.lie_algebras.affine_lie_algebra import AffineLieAlgebra return AffineLieAlgebra(self, kac_moody) diff --git a/src/sage/algebras/lie_algebras/examples.py b/src/sage/algebras/lie_algebras/examples.py index 92dbce05411..88a364c0d2a 100644 --- a/src/sage/algebras/lie_algebras/examples.py +++ b/src/sage/algebras/lie_algebras/examples.py @@ -32,6 +32,7 @@ from sage.algebras.lie_algebras.classical_lie_algebra import gl, sl, so, sp from sage.algebras.lie_algebras.virasoro import VirasoroAlgebra # this is used, just not in this file +from sage.algebras.lie_algebras.affine_lie_algebra import AffineLieAlgebra as Affine def three_dimensional(R, a, b, c, d, names=['X', 'Y', 'Z']): r""" diff --git a/src/sage/algebras/lie_algebras/lie_algebra.py b/src/sage/algebras/lie_algebras/lie_algebra.py index 9b96738bcd6..006e9ad6844 100644 --- a/src/sage/algebras/lie_algebras/lie_algebra.py +++ b/src/sage/algebras/lie_algebras/lie_algebra.py @@ -31,7 +31,6 @@ from sage.categories.morphism import SetMorphism from sage.categories.homset import Hom -from sage.algebras.free_algebra import FreeAlgebra from sage.algebras.lie_algebras.lie_algebra_element import (LieAlgebraElementWrapper, LieAlgebraMatrixWrapper) from sage.rings.all import ZZ @@ -384,6 +383,7 @@ def __classcall_private__(cls, R=None, arg0=None, arg1=None, names=None, # Construct the free Lie algebra from polynomials in the # free (associative unital) algebra # TODO: Change this to accept an index set once FreeAlgebra accepts one + from sage.algebras.free_algebra import FreeAlgebra F = FreeAlgebra(R, names) if index_set is None: index_set = F.variable_names() diff --git a/src/sage/algebras/lie_algebras/lie_algebra_element.pxd b/src/sage/algebras/lie_algebras/lie_algebra_element.pxd index 689ac628b41..aecb8f3d686 100644 --- a/src/sage/algebras/lie_algebras/lie_algebra_element.pxd +++ b/src/sage/algebras/lie_algebras/lie_algebra_element.pxd @@ -19,6 +19,7 @@ cdef class UntwistedAffineLieAlgebraElement(Element): cdef dict _t_dict cdef _c_coeff cdef _delta_coeff + cdef long _hash cpdef bracket(self, y) cpdef _bracket_(self, y) diff --git a/src/sage/algebras/lie_algebras/lie_algebra_element.pyx b/src/sage/algebras/lie_algebras/lie_algebra_element.pyx index fd84f2fe829..51f5764a328 100644 --- a/src/sage/algebras/lie_algebras/lie_algebra_element.pyx +++ b/src/sage/algebras/lie_algebras/lie_algebra_element.pyx @@ -18,11 +18,13 @@ AUTHORS: #***************************************************************************** from copy import copy +from cpython.object cimport Py_EQ, Py_NE from sage.misc.misc import repr_lincomb from sage.combinat.free_module import CombinatorialFreeModule from sage.structure.element cimport have_same_parent, coercion_model, parent from sage.structure.element_wrapper cimport ElementWrapper +from sage.structure.sage_object cimport richcmp from sage.data_structures.blas_dict cimport axpy, negate, scal # TODO: Inherit from IndexedFreeModuleElement and make cdef once #22632 is merged @@ -559,15 +561,65 @@ cdef class StructureCoefficientsElement(LieAlgebraMatrixWrapper): return self.value[self._parent._indices.index(i)] cdef class UntwistedAffineLieAlgebraElement(Element): + """ + An element of an untwisted affine Lie algebra. + """ def __init__(self, parent, dict t_dict, c_coeff, delta_coeff): + """ + Initialize ``self``. + + TESTS:: + + sage: L = lie_algebras.Affine(QQ, ['A',2,1]) + sage: x = L.an_element() + sage: TestSuite(x).run() + """ Element.__init__(self, parent) self._t_dict = t_dict self._c_coeff = c_coeff self._delta_coeff = delta_coeff + self._hash = -1 + + def __reduce__(self): + """ + Used in pickling. + + TESTS:: + + sage: L = lie_algebras.Affine(QQ, ['B',3,1]) + sage: x = L.an_element() + sage: loads(dumps(x)) == x + True + """ + return (_build_untwisted_affine_element, + (self.parent(), self._t_dict, self._c_coeff, self._delta_coeff)) def _repr_(self): """ Return a string representation of ``self``. + + EXAMPLES:: + + sage: L = lie_algebras.Affine(QQ, ['A',1,1]) + sage: list(L.lie_algebra_generators()) + [(E[alpha[1]])#t^0, + (E[-alpha[1]])#t^0, + (h1)#t^0, + (E[-alpha[1]])#t^1, + (E[alpha[1]])#t^-1, + c, + delta] + sage: L.an_element() + (E[alpha[1]] + h1 + E[-alpha[1]])#t^0 + + (E[-alpha[1]])#t^1 + (E[alpha[1]])#t^-1 + + c + delta + sage: L.zero() + 0 + + sage: e1,f1,h1,e0,f0,c,delta = list(L.lie_algebra_generators()) + sage: e1 + 2*f1 - h1 + e0 + 3*c - 2*delta + (E[alpha[1]] - h1 + 2*E[-alpha[1]])#t^0 + (-E[-alpha[1]])#t^1 + + 3*c + -2*delta """ ret = ' + '.join('({})#t^{}'.format(g, t) for t,g in self._t_dict.iteritems()) @@ -592,8 +644,31 @@ cdef class UntwistedAffineLieAlgebraElement(Element): return ret def _latex_(self): - """ + r""" Return a latex representation of ``self``. + + EXAMPLES:: + + sage: L = lie_algebras.Affine(QQ, ['A',1,1]) + sage: [latex(g) for g in L.lie_algebra_generators()] + [(E_{\alpha_{1}}) \otimes t^{0}, + (E_{-\alpha_{1}}) \otimes t^{0}, + (E_{\alpha^\vee_{1}}) \otimes t^{0}, + (E_{-\alpha_{1}}) \otimes t^{1}, + (E_{\alpha_{1}}) \otimes t^{-1}, + c, + \delta] + sage: latex(L.an_element()) + (E_{\alpha_{1}} + E_{\alpha^\vee_{1}} + E_{-\alpha_{1}}) \otimes t^{0} + + (E_{-\alpha_{1}}) \otimes t^{1} + (E_{\alpha_{1}}) \otimes t^{-1} + + c + \delta + sage: latex(L.zero()) + 0 + + sage: e1,f1,h1,e0,f0,c,delta = list(L.lie_algebra_generators()) + sage: latex(e1 + 2*f1 - h1 + e0 + 3*c - 2*delta) + (E_{\alpha_{1}} - E_{\alpha^\vee_{1}} + 2E_{-\alpha_{1}}) \otimes t^{0} + + (-E_{-\alpha_{1}}) \otimes t^{1} + 3 c + -2 \delta """ from sage.misc.latex import latex ret = ' + '.join('({}) \otimes t^{{{}}}'.format(latex(g), t) @@ -618,31 +693,162 @@ cdef class UntwistedAffineLieAlgebraElement(Element): return '0' return ret + cpdef _richcmp_(self, other, int op): + """ + Return the rich comparison of ``self`` with ``other``. + + EXAMPLES:: + + sage: L = lie_algebras.Affine(QQ, ['C',2,1]) + sage: x = L.an_element() + sage: c = L.basis()['c'] + sage: delta = L.basis()['delta'] + sage: c == delta + False + sage: x != c + True + sage: 2*c - delta == c + c - delta + True + sage: x - c != x - c + False + sage: x - c != x - delta + True + """ + if op != Py_EQ and op != Py_NE: + return NotImplemented + cdef UntwistedAffineLieAlgebraElement rt = other + return richcmp((self._t_dict, self._c_coeff, self._delta_coeff), + (rt._t_dict, rt._c_coeff, rt._delta_coeff), + op) + + def __hash__(self): + """ + Return the hash of ``self``. + + EXAMPLES:: + + sage: asl = lie_algebras.Affine(QQ, ['A',4,1]) + sage: x = asl.an_element() + sage: hash(x) + 1782435762440299943 + sage: hash(asl.zero()) + 0 + """ + if not self: + self._hash = 0 + if self._hash == -1: + self._hash = hash((tuple(self._t_dict.iteritems()), + self._c_coeff, self._delta_coeff)) + return self._hash + def __nonzero__(self): + """ + Return ``self`` as a boolean. + + EXAMPLES:: + + sage: L = lie_algebras.Affine(QQ, ['C',2,1]) + sage: x = L.an_element() + sage: bool(x) + True + sage: bool(L.zero()) + False + """ return bool(self._t_dict) or bool(self._c_coeff) or bool(self._delta_coeff) + __bool__ = __nonzero__ + cdef _add_(self, other): + """ + Add ``self`` and ``other``. + + EXAMPLES:: + + sage: L = lie_algebras.Affine(QQ, ['A',1,1]) + sage: e1,f1,h1,e0,f0,c,delta = list(L.lie_algebra_generators()) + sage: e0.bracket(e1) + delta + e1 + c + 3*delta + (E[alpha[1]])#t^0 + (-h1)#t^1 + c + 4*delta + """ cdef UntwistedAffineLieAlgebraElement rt = other return type(self)(self._parent, axpy(1, self._t_dict, rt._t_dict.copy()), self._c_coeff + rt._c_coeff, self._delta_coeff + rt._delta_coeff) cdef _sub_(self, other): + """ + Subtract ``self`` and ``other``. + + EXAMPLES:: + + sage: L = lie_algebras.Affine(QQ, ['A',1,1]) + sage: e1,f1,h1,e0,f0,c,delta = list(L.lie_algebra_generators()) + sage: e0.bracket(e1) + delta - e1 + c - 3*delta + (-E[alpha[1]])#t^0 + (-h1)#t^1 + c + -2*delta + sage: e0.bracket(f0) - 4*c + (h1)#t^0 + sage: e0.bracket(f0) - 4*c - h1 + 0 + sage: e0.bracket(f0) - 4*c - h1 == L.zero() + True + """ cdef UntwistedAffineLieAlgebraElement rt = other return type(self)(self._parent, axpy(-1, self._t_dict, rt._t_dict.copy()), self._c_coeff - rt._c_coeff, self._delta_coeff - rt._delta_coeff) cdef _neg_(self): + """ + Negate ``self``. + + EXAMPLES:: + + sage: L = lie_algebras.Affine(QQ, ['A',1,1]) + sage: e1,f1,h1,e0,f0,c,delta = list(L.lie_algebra_generators()) + sage: x = e0.bracket(e1) + delta + e1 + c + 3*delta + sage: -x + (-E[alpha[1]])#t^0 + (h1)#t^1 + -1*c + -4*delta + """ return type(self)(self._parent, negate(self._t_dict), -self._c_coeff, -self._delta_coeff) cpdef _acted_upon_(self, x, bint self_on_left): + """ + Return ``self`` acted upon by ``x``. + + EXAMPLES:: + + sage: L = lie_algebras.Affine(QQ, ['A',1,1]) + sage: e1,f1,h1,e0,f0,c,delta = list(L.lie_algebra_generators()) + sage: x = e1 + f0.bracket(f1) + 3*c - 2/5 * delta + sage: x + (-E[alpha[1]])#t^0 + (-h1)#t^-1 + 3*c + -2/5*delta + sage: -2 * x + (2*E[alpha[1]])#t^0 + (2*h1)#t^-1 + -6*c + 4/5*delta + """ return type(self)(self._parent, scal(x, self._t_dict, self_on_left), x * self._c_coeff, x * self._delta_coeff) cpdef monomial_coefficients(self, bint copy=True): + """ + Return the monomial coefficients of ``self``. + + EXAMPLES:: + + sage: L = lie_algebras.Affine(QQ, ['C',2,1]) + sage: x = L.an_element() + sage: sorted(x.monomial_coefficients(), key=str) + [(-2*alpha[1] - alpha[2], 1), + (-alpha[1], 0), + (-alpha[2], 0), + (2*alpha[1] + alpha[2], -1), + (alpha[1], 0), + (alpha[2], 0), + (alphacheck[1], 0), + (alphacheck[2], 0), + 'c', + 'delta'] + """ cdef dict d = {} for t,g in self._t_dict.iteritems(): for k,c in g.monomial_coefficients(copy=False).iteritems(): @@ -658,6 +864,19 @@ cdef class UntwistedAffineLieAlgebraElement(Element): Return the Lie bracket ``[self, right]``. EXAMPLES:: + + sage: L = LieAlgebra(QQ, cartan_type=['A',1,1]) + sage: e1,f1,h1,e0,f0,c,delta = list(L.lie_algebra_generators()) + sage: e0.bracket(f0) + (-h1)#t^0 + 4*c + sage: e1.bracket(0) + 0 + sage: e1.bracket(1) + Traceback (most recent call last): + ... + TypeError: no common canonical parent for objects with parents: + 'Affine Kac-Moody algebra of ['A', 1] in the Chevalley basis' + and 'Integer Ring' """ if not have_same_parent(self, right): self, right = coercion_model.canonical_coercion(self, right) @@ -666,9 +885,33 @@ cdef class UntwistedAffineLieAlgebraElement(Element): cpdef _bracket_(self, y): """ Return the Lie bracket ``[self, y]``. + + EXAMPLES:: + + sage: L = LieAlgebra(QQ, cartan_type=['A',1,1]) + sage: e1,f1,h1,e0,f0,c,delta = list(L.lie_algebra_generators()) + sage: al = RootSystem(['A',1]).root_lattice().simple_roots() + sage: x = L.basis()[al[1], 5] + sage: y = L.basis()[-al[1], -3] + sage: z = L.basis()[-al[1], -5] + sage: x._bracket_(y) + (h1)#t^2 + sage: x._bracket_(z) + (h1)#t^0 + 20*c + sage: x._bracket_(e1) + 0 + sage: x._bracket_(f1) + (h1)#t^5 + sage: x._bracket_(h1) + (-2*E[alpha[1]])#t^5 + sage: x._bracket_(delta) + (-5*E[alpha[1]])#t^5 + sage: all(c._bracket_(g) == 0 for g in L.lie_algebra_generators()) + True """ if not self or not y: return self._parent.zero() + gd = self._parent._g.basis() cdef dict d = {} cdef UntwistedAffineLieAlgebraElement rt = (y) @@ -719,8 +962,32 @@ cdef class UntwistedAffineLieAlgebraElement(Element): \delta(a \otimes t^m + \alpha c) = a \otimes m t^m. Another formulation is by `\delta = t \frac{d}{dt}`. + + EXAMPLES:: + + sage: L = lie_algebras.Affine(QQ, ['E',6,1]) + sage: al = RootSystem(['E',6]).root_lattice().simple_roots() + sage: x = L.basis()[al[2]+al[3]+2*al[4]+al[5],5] + 4*L.c() + L.delta() + sage: x.lie_derivative() + (5*E[alpha[2] + alpha[3] + 2*alpha[4] + alpha[5]])#t^5 """ cdef dict d = {tl: tl * gl for tl,gl in self._t_dict.iteritems() if tl != 0} zero = self._parent.base_ring().zero() return type(self)(self.parent(), d, zero, zero) +def _build_untwisted_affine_element(P, t_dict, c, delta): + """ + Used to unpickle an element. + + EXAMPLES:: + + sage: L = lie_algebras.Affine(QQ, ['A',2,1]) + sage: from sage.algebras.lie_algebras.lie_algebra_element import _build_untwisted_affine_element + sage: _build_untwisted_affine_element(L, {}, 0, 0) == L.zero() + True + sage: x = L.an_element() + sage: loads(dumps(x)) == x # indirect doctest + True + """ + return P.element_class(P, t_dict, c, delta) + From a160cfd04aeb57689bf1207653097d71e107d660 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 6 Apr 2017 14:02:22 -0500 Subject: [PATCH 127/452] Adding some coercions and exposing some more data. --- .../lie_algebras/affine_lie_algebra.py | 86 ++++++++++++++++++- .../lie_algebras/lie_algebra_element.pxd | 4 + .../lie_algebras/lie_algebra_element.pyx | 42 +++++++++ 3 files changed, 129 insertions(+), 3 deletions(-) diff --git a/src/sage/algebras/lie_algebras/affine_lie_algebra.py b/src/sage/algebras/lie_algebras/affine_lie_algebra.py index 8a28c65aab9..ba8cb4a345c 100644 --- a/src/sage/algebras/lie_algebras/affine_lie_algebra.py +++ b/src/sage/algebras/lie_algebras/affine_lie_algebra.py @@ -4,8 +4,6 @@ AUTHORS: - Travis Scrimshaw (2013-05-03): Initial version - -EXAMPLES:: """ #***************************************************************************** @@ -20,7 +18,7 @@ from sage.misc.cachefunc import cached_method from sage.misc.misc import repr_lincomb -from sage.structure.element import RingElement +from sage.structure.element import RingElement, parent from sage.categories.lie_algebras import LieAlgebras from sage.algebras.lie_algebras.lie_algebra import LieAlgebra, FinitelyGeneratedLieAlgebra @@ -89,6 +87,45 @@ class AffineLieAlgebra(FinitelyGeneratedLieAlgebra): to ``False`` to obtain the affine Lie algebra instead of the affine Kac-Moody algebra. + EXAMPLES: + + We begin by constructing an affine Kac-Moody algebra of type `G_2^{(1)}` + from the classical Lie algebra of type `G_2`:: + + sage: L = LieAlgebra(QQ, cartan_type=['G',2]) + sage: A = L.affine() + sage: A + Affine Kac-Moody algebra of ['G', 2] in the Chevalley basis + + Next, we construct the generators and perform some computations:: + + sage: A.inject_variables() + Defining e1, e2, f1, f2, h1, h2, e0, f0, c, delta + sage: e1.bracket(f1) + (h1)#t^0 + sage: e0.bracket(f0) + (-h1 - 2*h2)#t^0 + 8*c + sage: e0.bracket(f1) + 0 + sage: A[delta, f0] + (-E[3*alpha[1] + 2*alpha[2]])#t^-1 + sage: A([[e0, e2], [[[e1, e2], [e0, [e1, e2]]], e1]]) + (-6*E[-3*alpha[1] - alpha[2]])#t^2 + sage: f0.bracket(f1) + 0 + sage: f0.bracket(f2) + (E[3*alpha[1] + alpha[2]])#t^-1 + sage: A[h1+3*h2, A[[[f0, f2], f1], [f1,f2]] + f1] + (E[-alpha[1]])#t^0 + (2*E[alpha[1]])#t^-1 + + We can construct its derived subalgebra, the affine Lie algebra + of type `G_2^{(1)}`. In this case, there is no Lie derivative, + so the generator `\delta` is `0`:: + + sage: D = A.derived_subalgebra() + sage: D.delta() + 0 + REFERENCES: - :wikipedia:`Affine_Lie_algebra` @@ -205,6 +242,49 @@ def basis(self): keys = DisjointUnionEnumeratedSets([c, K]) return Family(keys, self.monomial) + def _element_constructor_(self, x): + """ + Construct an element of ``self`` from ``x``. + + EXAMPLES:: + + sage: L = LieAlgebra(QQ, cartan_type=['A',1]) + sage: A = L.affine() + sage: D = A.derived_subalgebra() + sage: A(D.an_element()) + (E[alpha[1]] + h1 + E[-alpha[1]])#t^0 + + (E[-alpha[1]])#t^1 + (E[alpha[1]])#t^-1 + c + sage: A(L.an_element()) + (E[alpha[1]] + h1 + E[-alpha[1]])#t^0 + """ + P = parent(x) + if P is self.derived_subalgebra(): + return self.element_class(self, x.t_dict(), x.c_coefficient(), + x.delta_coefficient()) + if P == self._g: + zero = self.base_ring().zero() + return self.element_class(self, {0: x}, zero, zero) + return super(AffineLieAlgebra, self)._element_constructor_(x) + + def _coerce_map_from_(self, R): + """ + Return the coerce map from ``R`` to ``self`` or ``True`` if + a coerce map exists. + + EXAMPLES:: + + sage: L = LieAlgebra(QQ, cartan_type=['G',2]) + sage: A = L.affine() + sage: A.has_coerce_map_from(L) + True + sage: D = A.derived_subalgebra() + sage: A.has_coerce_map_from(D) + True + """ + if R is self.derived_subalgebra() or R is self._g: + return True + return super(AffineLieAlgebra, self)._coerce_map_from_(R) + def derived_subalgebra(self): """ Return the derived subalgebra of ``self``. diff --git a/src/sage/algebras/lie_algebras/lie_algebra_element.pxd b/src/sage/algebras/lie_algebras/lie_algebra_element.pxd index aecb8f3d686..508721dc7c6 100644 --- a/src/sage/algebras/lie_algebras/lie_algebra_element.pxd +++ b/src/sage/algebras/lie_algebras/lie_algebra_element.pxd @@ -21,6 +21,10 @@ cdef class UntwistedAffineLieAlgebraElement(Element): cdef _delta_coeff cdef long _hash + cpdef dict t_dict(self) + cpdef c_coefficient(self) + cpdef delta_coefficient(self) + cpdef bracket(self, y) cpdef _bracket_(self, y) cpdef lie_derivative(self) diff --git a/src/sage/algebras/lie_algebras/lie_algebra_element.pyx b/src/sage/algebras/lie_algebras/lie_algebra_element.pyx index 51f5764a328..58f0aef5993 100644 --- a/src/sage/algebras/lie_algebras/lie_algebra_element.pyx +++ b/src/sage/algebras/lie_algebras/lie_algebra_element.pyx @@ -693,6 +693,48 @@ cdef class UntwistedAffineLieAlgebraElement(Element): return '0' return ret + cpdef dict t_dict(self): + r""" + Return the ``dict``, whose keys are powers of `t` and values are + elements of the classical Lie algebra, of ``self``. + + EXAMPLES:: + + sage: L = lie_algebras.Affine(QQ, ['A',1,1]) + sage: x = L.an_element() + sage: x.t_dict() + {-1: E[alpha[1]], + 0: E[alpha[1]] + h1 + E[-alpha[1]], + 1: E[-alpha[1]]} + """ + return self._t_dict.copy() + + cpdef c_coefficient(self): + r""" + Return the coefficient of `c` of ``self``. + + EXAMPLES:: + + sage: L = lie_algebras.Affine(QQ, ['A',1,1]) + sage: x = L.an_element() - 3 * L.c() + sage: x.c_coefficient() + -2 + """ + return self._c_coeff + + cpdef delta_coefficient(self): + r""" + Return the coefficient of `\delta` of ``self``. + + EXAMPLES:: + + sage: L = lie_algebras.Affine(QQ, ['A',1,1]) + sage: x = L.an_element() + L.delta() + sage: x.delta_coefficient() + 2 + """ + return self._delta_coeff + cpdef _richcmp_(self, other, int op): """ Return the rich comparison of ``self`` with ``other``. From 999f56ac87015d9392f76711d692f387d5b7a1bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jori=20M=C3=A4ntysalo?= Date: Fri, 7 Apr 2017 10:34:19 +0300 Subject: [PATCH 128/452] Add random Stone lattice. --- src/sage/combinat/posets/poset_examples.py | 67 +++++++++++++++++++++- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/src/sage/combinat/posets/poset_examples.py b/src/sage/combinat/posets/poset_examples.py index 1454a4b71f9..124d6cbd91c 100644 --- a/src/sage/combinat/posets/poset_examples.py +++ b/src/sage/combinat/posets/poset_examples.py @@ -618,7 +618,8 @@ def RandomLattice(n, p, properties=None): * ``None``, no restrictions for lattices to create * ``'planar'``, the lattice has an upward planar drawing * ``'dismantlable'`` (implicated by ``'planar'``) - * ``'distributive'`` + * ``'distributive'`` (implicated by ``'stone'``) + * ``'stone'`` OUTPUT: @@ -708,7 +709,7 @@ def RandomLattice(n, p, properties=None): else: properties = set(properties) - known_properties = set(['planar', 'dismantlable', 'distributive']) + known_properties = set(['planar', 'dismantlable', 'distributive', 'stone']) errors = properties.difference(known_properties) if errors: raise ValueError("unknown value %s for 'properties'" % errors.pop()) @@ -717,9 +718,11 @@ def RandomLattice(n, p, properties=None): # Change this, if property='complemented' is added return Posets.ChainPoset(n) - # Handling properties. Every planar lattice is also dismantlable. + # Handling properties: planar => dismantlable, stone => distributive if 'planar' in properties: properties.discard('dismantlable') + if 'stone' in properties: + properties.discard('distributive') # Test property combinations that are not implemented. if 'distributive' in properties and len(properties) > 1: @@ -735,6 +738,11 @@ def RandomLattice(n, p, properties=None): D.relabel([i-1 for i in Permutations(n).random_element()]) return LatticePoset(D) + if properties == set(['stone']): + D = _random_stone_lattice(n) + D.relabel([i-1 for i in Permutations(n).random_element()]) + return LatticePoset(D) + if properties == set(['distributive']): tmp = Poset(_random_distributive_lattice(n)).order_ideals_lattice(as_ideals=False) D = copy(tmp._hasse_diagram) @@ -1535,7 +1543,11 @@ def _random_distributive_lattice(n): from sage.combinat.posets.hasse_diagram import HasseDiagram from copy import copy from sage.combinat.subset import Subsets + from sage.graphs.digraph_generators import digraphs + if n < 4: + return digraphs.Path(n-1) + H = HasseDiagram({0: []}) while sum(1 for _ in H.antichains_iterator()) < n: D = copy(H) @@ -1559,4 +1571,53 @@ def _random_distributive_lattice(n): H = HasseDiagram(D) return D +def _random_stone_lattice(n): + """ + Return a random Stone lattice of `n` elements. + + INPUT: + + - ``n`` -- number of elements, a non-negative integer + + OUTPUT: + + A random lattice (as DiGraph) of `n` elements. + + EXAMPLES:: + + sage: g = sage.combinat.posets.poset_examples._random_stone_lattice(10) + sage: LatticePoset(g).is_stone() + True + + ALGORITHM: + + Randomly split `n` to some factors. For every factor `p` generate + a random distributive lattice on `p-1` elements and add a new new bottom + element to it. Compute the cartesian product of those lattices. + """ + from sage.arith.misc import factor + from sage.combinat.partition import Partitions + from sage.misc.misc_c import prod + from copy import copy + + factors = sum([[f[0]]*f[1] for f in factor(n)], []) + sage.misc.prandom.shuffle(factors) + + part_lengths = list(Partitions(len(factors)).random_element()) + parts = [] + while part_lengths: + x = part_lengths.pop() + parts.append(prod(factors[:x])) + factors = factors[x:] + + result = DiGraph(1) + for p in parts: + g = _random_distributive_lattice(p-1) + g = copy(Poset(g).order_ideals_lattice(as_ideals=False)._hasse_diagram) + g.add_edge('bottom', 0) + result = result.cartesian_product(g) + result.relabel() + + return result + posets = Posets From f2bfdb249a2791d49233255bc753b5a0de7732de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jori=20M=C3=A4ntysalo?= Date: Fri, 7 Apr 2017 10:35:41 +0300 Subject: [PATCH 129/452] Spaces removed. --- src/sage/combinat/posets/poset_examples.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/sage/combinat/posets/poset_examples.py b/src/sage/combinat/posets/poset_examples.py index 124d6cbd91c..5f8013b603e 100644 --- a/src/sage/combinat/posets/poset_examples.py +++ b/src/sage/combinat/posets/poset_examples.py @@ -1547,7 +1547,7 @@ def _random_distributive_lattice(n): if n < 4: return digraphs.Path(n-1) - + H = HasseDiagram({0: []}) while sum(1 for _ in H.antichains_iterator()) < n: D = copy(H) @@ -1574,23 +1574,23 @@ def _random_distributive_lattice(n): def _random_stone_lattice(n): """ Return a random Stone lattice of `n` elements. - + INPUT: - + - ``n`` -- number of elements, a non-negative integer - + OUTPUT: - + A random lattice (as DiGraph) of `n` elements. - + EXAMPLES:: - + sage: g = sage.combinat.posets.poset_examples._random_stone_lattice(10) sage: LatticePoset(g).is_stone() True - + ALGORITHM: - + Randomly split `n` to some factors. For every factor `p` generate a random distributive lattice on `p-1` elements and add a new new bottom element to it. Compute the cartesian product of those lattices. From b56829c66f00d9c4e5132eb5c77ffbda417ce01a Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Tue, 11 Apr 2017 09:17:39 +0200 Subject: [PATCH 130/452] 21819: Rewrite error functions and documentation --- src/doc/en/reference/functions/index.rst | 1 + src/doc/en/reference/references/index.rst | 6 + src/sage/functions/all.py | 8 +- src/sage/functions/error.py | 530 ++++++++++++++++++++++ src/sage/functions/hypergeometric.py | 2 +- src/sage/functions/other.py | 226 +-------- src/sage/functions/special.py | 32 -- src/sage/interfaces/maxima_lib.py | 2 +- 8 files changed, 545 insertions(+), 262 deletions(-) create mode 100644 src/sage/functions/error.py diff --git a/src/doc/en/reference/functions/index.rst b/src/doc/en/reference/functions/index.rst index 6465c8f81ba..f33b8da08a6 100644 --- a/src/doc/en/reference/functions/index.rst +++ b/src/doc/en/reference/functions/index.rst @@ -8,6 +8,7 @@ Functions sage/functions/trig sage/functions/hyperbolic sage/functions/transcendental + sage/functions/error sage/functions/piecewise sage/functions/spike_function sage/functions/orthogonal_polys diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 9529bafd281..ec27b7b87cb 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -539,6 +539,10 @@ REFERENCES: Functions, in NIST Digital Library of Mathematical Functions. http://dlmf.nist.gov/10 +.. [DLMF-Error] \N. M. Temme: 7. Error Functions, Dawson’s and Fresnel + Integrals, in NIST Digital Library of Mathematical + Functions. http://dlmf.nist.gov/7 + .. [DLMF-Struve] \R. B. Paris: 11. Struve and Related Functions, in NIST Digital Library of Mathematical Functions. http://dlmf.nist.gov/11 @@ -1630,6 +1634,8 @@ REFERENCES: .. [WP-Bessel] :wikipedia:`Bessel_function` +.. [WP-Error] :wikipedia:`Error_function` + .. [WP-Struve] :wikipedia:`Struve_function` .. _ref-X: diff --git a/src/sage/functions/all.py b/src/sage/functions/all.py index 53b0cb654bf..66d5c824800 100644 --- a/src/sage/functions/all.py +++ b/src/sage/functions/all.py @@ -4,6 +4,8 @@ lazy_import('sage.functions.piecewise_old', 'Piecewise') # deprecated lazy_import('sage.functions.piecewise', 'piecewise') +lazy_import('sage.functions.error', ['erf', 'erfi', 'erfc', + 'erfinv', 'error_fcn']) from .trig import ( sin, cos, sec, csc, cot, tan, asin, acos, atan, @@ -21,7 +23,7 @@ from .other import ( ceil, floor, gamma, psi, factorial, beta, binomial, - abs_symbolic, erf, sqrt, log_gamma, + abs_symbolic, sqrt, log_gamma, gamma_inc, incomplete_gamma, gamma_inc_lower, arg, real_part, real, frac, imag_part, imag, imaginary, conjugate) @@ -37,8 +39,7 @@ spherical_bessel_J, spherical_bessel_Y, spherical_hankel1, spherical_hankel2) -from .special import (spherical_harmonic, - error_fcn, elliptic_e, +from .special import (spherical_harmonic, elliptic_e, elliptic_f, elliptic_ec, elliptic_eu, elliptic_kc, elliptic_pi, elliptic_j) @@ -84,3 +85,4 @@ exponential_integral_1, Ei, exp_integral_ei) from .hypergeometric import hypergeometric, hypergeometric_M, hypergeometric_U + diff --git a/src/sage/functions/error.py b/src/sage/functions/error.py new file mode 100644 index 00000000000..5196b269660 --- /dev/null +++ b/src/sage/functions/error.py @@ -0,0 +1,530 @@ +r""" +Error Functions + +This module provides symbolic error functions. These functions use the +`mpmath library` for numerical evaluation and Maxima, Pynac for +symbolics. + +The main objects which are exported from this module are: + + * :meth:`erf ` -- The error function + * :meth:`erfc ` -- The complementary error function + * :meth:`erfi ` -- The imagnary error function + * :meth:`erfinv ` -- The inverse error function + +AUTHORS: + + * Original authors ``erf``/``error_fcn`` (c) 2006-2014: + Karl-Dieter Crisman, Benjamin Jones, Mike Hansen, William Stein, + Burcin Erocal, Jeroen Demeyer, W. D. Joyner, R. Andrew Ohana + * Reorganisation in new file, addition of ``erfi``/``erfinv``/``erfc`` + (c) 2016: Ralf Stephan + +REFERENCES: + +- [DLMF-Error]_ + +- [WP-Error]_ +""" + +#***************************************************************************** +# 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: +# +# http://www.gnu.org/licenses/ +#***************************************************************************** + + +from sage.symbolic.function import BuiltinFunction +from sage.libs.mpmath import utils as mpmath_utils +from sage.symbolic.expression import Expression +from sage.functions.all import sqrt, exp +from sage.symbolic.constants import pi +from sage.rings.infinity import unsigned_infinity +from sage.misc.superseded import deprecation + +class Function_erf(BuiltinFunction): + r""" + The error function, defined for real values as + + `\operatorname{erf}(x) = \frac{2}{\sqrt{\pi}} \int_0^x e^{-t^2} dt`. + + This function is also defined for complex values, via analytic + continuation. + + + EXAMPLES: + + We can evaluate numerically:: + + sage: erf(2) + erf(2) + sage: erf(2).n() + 0.995322265018953 + sage: erf(2).n(100) + 0.99532226501895273416206925637 + sage: erf(ComplexField(100)(2+3j)) + -20.829461427614568389103088452 + 8.6873182714701631444280787545*I + + Basic symbolic properties are handled by Sage and Maxima:: + + sage: x = var("x") + sage: diff(erf(x),x) + 2*e^(-x^2)/sqrt(pi) + sage: integrate(erf(x),x) + x*erf(x) + e^(-x^2)/sqrt(pi) + + ALGORITHM: + + Sage implements numerical evaluation of the error function via the + ``erf()`` function from mpmath. Symbolics are handled by Sage and Maxima. + + REFERENCES: + + - http://en.wikipedia.org/wiki/Error_function + - http://mpmath.googlecode.com/svn/trunk/doc/build/functions/expintegrals.html#error-functions + + TESTS: + + Check limits:: + + sage: limit(erf(x),x=0) + 0 + sage: limit(erf(x),x=infinity) + 1 + + Check that it's odd:: + + sage: erf(1.0) + 0.842700792949715 + sage: erf(-1.0) + -0.842700792949715 + + Check against other implementations and against the definition:: + + sage: erf(3).n() + 0.999977909503001 + sage: maxima.erf(3).n() + 0.999977909503001 + sage: (1-pari(3).erfc()) + 0.999977909503001 + sage: RR(3).erf() + 0.999977909503001 + sage: (integrate(exp(-x**2),(x,0,3))*2/sqrt(pi)).n() + 0.999977909503001 + + :trac:`9044`:: + + sage: N(erf(sqrt(2)),200) + 0.95449973610364158559943472566693312505644755259664313203267 + + :trac:`11626`:: + + sage: n(erf(2),100) + 0.99532226501895273416206925637 + sage: erf(2).n(100) + 0.99532226501895273416206925637 + + Test (indirectly) :trac:`11885`:: + + sage: erf(float(0.5)) + 0.5204998778130465 + sage: erf(complex(0.5)) + (0.5204998778130465+0j) + + Ensure conversion from maxima elements works:: + + sage: merf = maxima(erf(x)).sage().operator() + sage: merf.parent() == erf.parent() + True + + Make sure we can dump and load it:: + + sage: loads(dumps(erf(2))) + erf(2) + + Special-case 0 for immediate evaluation:: + + sage: erf(0) + 0 + sage: solve(erf(x)==0,x) + [x == 0] + + Make sure that we can hold:: + + sage: erf(0,hold=True) + erf(0) + sage: simplify(erf(0,hold=True)) + 0 + + Check that high-precision ComplexField inputs work:: + + sage: CC(erf(ComplexField(1000)(2+3j))) + -20.8294614276146 + 8.68731827147016*I + """ + + def __init__(self): + r""" + See docstring for :meth:`Function_erf`. + + EXAMPLES:: + + sage: maxima(erf(2)) + erf(2) + sage: erf(2)._sympy_() + erf(2) + """ + BuiltinFunction.__init__(self, "erf", latex_name=r"\operatorname{erf}", + conversions=dict(maxima='erf', + sympy='erf', + fricas='erf')) + + def _eval_(self, x): + """ + EXAMPLES: + + Input is not an expression but is exact:: + + sage: erf(0) + 0 + sage: erf(1) + erf(1) + sage: erf(oo) + 1 + sage: erf(SR(-oo)) + -1 + sage: erf(unsigned_infinity) + Infinity + + Input is not an expression and is not exact:: + + sage: erf(0.0) + 0.000000000000000 + + Input is an expression but not a trivial zero:: + + sage: erf(x) + erf(x) + + Input is an expression which is trivially zero:: + + sage: erf(SR(0)) + 0 + """ + if isinstance(x, Expression): + if x.is_trivial_zero(): + return x + elif x.is_infinity(): + if x.is_positive_infinity(): + return 1 + elif x.is_negative_infinity(): + return -1 + else: + return unsigned_infinity + elif not x: + return x + + def _evalf_(self, x, parent=None, algorithm=None): + """ + EXAMPLES:: + + sage: erf(2).n() + 0.995322265018953 + sage: erf(2).n(200) + 0.99532226501895273416206925636725292861089179704006007673835 + sage: erf(pi - 1/2*I).n(100) + 1.0000111669099367825726058952 + 1.6332655417638522934072124547e-6*I + + TESTS: + + Check that PARI/GP through the GP interface gives the same answer:: + + sage: gp.set_real_precision(59) # random + 38 + sage: print(gp.eval("1 - erfc(1)")); print(erf(1).n(200)); + 0.84270079294971486934122063508260925929606699796630290845994 + 0.84270079294971486934122063508260925929606699796630290845994 + + Check that for an imaginary input, the output is also imaginary, see + :trac:`13193`:: + + sage: erf(3.0*I) + 1629.99462260157*I + sage: erf(33.0*I) + 1.51286977510409e471*I + """ + R = parent or s_parent(x) + import mpmath + return mpmath_utils.call(mpmath.erf, x, parent=R) + + def _derivative_(self, x, diff_param=None): + """ + Derivative of erf function + + EXAMPLES:: + + sage: erf(x).diff(x) + 2*e^(-x^2)/sqrt(pi) + + TESTS: + + Check if :trac:`8568` is fixed:: + + sage: var('c,x') + (c, x) + sage: derivative(erf(c*x),x) + 2*c*e^(-c^2*x^2)/sqrt(pi) + sage: erf(c*x).diff(x)._maxima_init_() + '((%pi)^(-1/2))*(_SAGE_VAR_c)*(exp(((_SAGE_VAR_c)^(2))*((_SAGE_VAR_x)^(2))*(-1)))*(2)' + """ + return 2*exp(-x**2)/sqrt(pi) + +erf = Function_erf() + +class Function_erfi(BuiltinFunction): + def __init__(self): + r""" + The imaginary error function + `\operatorname{erfi}(x)=-i\operatorname{erf}(ix)`. + + EXAMPLES:: + + sage: maxima(erfi(2)) + erfi(2) + sage: erfi(2)._sympy_() + erfi(2) + """ + BuiltinFunction.__init__(self, "erfi", + latex_name=r"\operatorname{erfi}", + conversions=dict(maxima='erfi', + sympy='erfi', + fricas='erfi')) + + def _eval_(self, x): + """ + EXAMPLES:: + + sage: erfi(0) + 0 + sage: erfi(SR(0)) + 0 + sage: erfi(oo) + Infinity + sage: erfi(SR(-oo)) + Infinity + """ + if isinstance(x, Expression): + if x.is_trivial_zero(): + return x + elif x.is_infinity(): + return unsigned_infinity + elif not x: + return x + + def _evalf_(self, x, parent=None, algorithm=None): + """ + EXAMPLES:: + + sage: erfi(2.) + 18.5648024145756 + sage: erfi(2).n(100) + 18.564802414575552598704291913 + sage: erfi(-2*I).n(100) + -0.99532226501895273416206925637*I + """ + R = parent or s_parent(x) + import mpmath + return mpmath_utils.call(mpmath.erfi, x, parent=R) + + def _derivative_(self, x, diff_param=None): + """ + Derivative of erfi function. + + EXAMPLES:: + + sage: erfi(x).diff(x) + 2*e^(x^2)/sqrt(pi) + + """ + return 2*exp(x**2)/sqrt(pi) + +erfi = Function_erfi() + +class Function_erfc(BuiltinFunction): + r""" + The complementary error function + `\frac{2}{\sqrt{\pi}}\int_t^\infty e^{-x^2} dx`. + + EXAMPLES:: + + sage: erfc(6) + erfc(6) + sage: erfc(6).n() + 2.15197367124989e-17 + sage: erfc(RealField(100)(1/2)) + 0.47950012218695346231725334611 + + sage: 1 - erfc(0.5) + 0.520499877813047 + sage: erf(0.5) + 0.520499877813047 + """ + def __init__(self): + r""" + EXAMPLES:: + + sage: maxima(erfc(2)) + erfc(2) + sage: erfc(2)._sympy_() + erfc(2) + """ + BuiltinFunction.__init__(self, "erfc", + latex_name=r"\operatorname{erfc}", + conversions=dict(maxima='erfc', + sympy='erfc', + fricas='erfc')) + + def _eval_(self, x): + """ + EXAMPLES:: + + sage: erfc(0) + 1 + sage: erfc(SR(0)) + 1 + sage: erfc(oo) + 0 + sage: erfc(SR(-oo)) + 2 + """ + if isinstance(x, Expression): + if x.is_trivial_zero(): + return 1 + elif x.is_infinity(): + if x.is_positive_infinity(): + return 0 + elif x.is_negative_infinity(): + return 2 + else: + return unsigned_infinity + elif not x: + return 1 + + def _evalf_(self, x, parent=None, algorithm=None): + """ + EXAMPLES:: + + sage: erfc(4).n() + 1.54172579002800e-8 + sage: erfc(4).n(100) + 1.5417257900280018852159673487e-8 + sage: erfc(4*I).n(100) + 1.0000000000000000000000000000 - 1.2969597307176392315279409506e6*I + """ + R = parent or s_parent(x) + import mpmath + return mpmath_utils.call(mpmath.erfc, x, parent=R) + + def _derivative_(self, x, diff_param=None): + """ + Derivative of erfc function. + + EXAMPLES:: + + sage: erfc(x).diff(x) + -2*e^(-x^2)/sqrt(pi) + """ + return -2*exp(-x**2)/sqrt(pi) + +erfc = Function_erfc() + +def error_fcn(x): + """ + Deprecated. Please use erfc(). + + EXAMPLES:: + + sage: error_fcn(x) + doctest:warning + ... + DeprecationWarning: error_fcn() is deprecated. Please use erfc() + See http://trac.sagemath.org/21819 for details. + erfc(x) + """ + deprecation(21819, "error_fcn() is deprecated. Please use erfc()") + return erfc(x) + + +class Function_erfinv(BuiltinFunction): + def __init__(self): + r""" + The inverse error function + `\operatorname{erfinv}(x)=\operatorname{erf}^{-1}(x)`. + + EXAMPLES:: + + sage: erfinv(2)._sympy_() + erfinv(2) + sage: maxima(erfinv(2)) + inverse_erf(2) + """ + BuiltinFunction.__init__(self, "erfinv", + latex_name=r"\operatorname{erfinv}", + conversions=dict(sympy='erfinv', + maxima='inverse_erf')) + + def _eval_(self, x): + """ + EXAMPLES:: + + sage: erfinv(0) + 0 + sage: erfinv(SR(0)) + 0 + sage: erfinv(1) + Infinity + """ + if isinstance(x, Expression): + if x.is_trivial_zero(): + return x + elif (x-1).is_trivial_zero(): + return unsigned_infinity + elif not x: + return x + elif x == 1: + return unsigned_infinity + + def _evalf_(self, x, parent=None, algorithm=None): + """ + EXAMPLES:: + + sage: erfinv(0.2) + 0.179143454621292 + sage: erfinv(1/5).n(100) + 0.17914345462129167649274901663 + """ + R = parent or s_parent(x) + import mpmath + return mpmath_utils.call(mpmath.erfinv, x, parent=R) + + def _derivative_(self, x, diff_param=None): + """ + Derivative of inverse erf function + + EXAMPLES:: + + sage: erfinv(x).diff(x) + 1/2*sqrt(pi)*e^(erfinv(x)^2) + """ + return sqrt(pi)*exp(erfinv(x)**2)/2 + +erfinv = Function_erfinv() + +from sage.structure.sage_object import register_unpickle_override +register_unpickle_override('sage.functions.other', 'Function_erf', Function_erf) diff --git a/src/sage/functions/hypergeometric.py b/src/sage/functions/hypergeometric.py index 8b19bad031c..eff8ff9db88 100644 --- a/src/sage/functions/hypergeometric.py +++ b/src/sage/functions/hypergeometric.py @@ -168,7 +168,7 @@ from sage.functions.log import exp, log from sage.functions.trig import sin from sage.functions.hyperbolic import cosh, sinh -from sage.functions.other import erf +from sage.functions.error import erf from sage.symbolic.constants import pi from sage.symbolic.all import I from sage.symbolic.function import BuiltinFunction diff --git a/src/sage/functions/other.py b/src/sage/functions/other.py index 5bb393999d6..9f17aea6126 100644 --- a/src/sage/functions/other.py +++ b/src/sage/functions/other.py @@ -28,231 +28,6 @@ one_half = ~SR(2) -class Function_erf(BuiltinFunction): - r""" - The error function, defined for real values as - - `\text{erf}(x) = \frac{2}{\sqrt{\pi}} \int_0^x e^{-t^2} dt`. - - This function is also defined for complex values, via analytic - continuation. - - - EXAMPLES: - - We can evaluate numerically:: - - sage: erf(2) - erf(2) - sage: erf(2).n() - 0.995322265018953 - sage: erf(2).n(100) - 0.99532226501895273416206925637 - sage: erf(ComplexField(100)(2+3j)) - -20.829461427614568389103088452 + 8.6873182714701631444280787545*I - - Basic symbolic properties are handled by Sage and Maxima:: - - sage: x = var("x") - sage: diff(erf(x),x) - 2*e^(-x^2)/sqrt(pi) - sage: integrate(erf(x),x) - x*erf(x) + e^(-x^2)/sqrt(pi) - - ALGORITHM: - - Sage implements numerical evaluation of the error function via the - ``erf()`` function from mpmath. Symbolics are handled by Sage and Maxima. - - REFERENCES: - - - http://en.wikipedia.org/wiki/Error_function - - http://mpmath.org/doc/current/functions/expintegrals.html#error-functions - - TESTS: - - Check limits:: - - sage: limit(erf(x),x=0) - 0 - sage: limit(erf(x),x=infinity) - 1 - - Check that it's odd:: - - sage: erf(1.0) - 0.842700792949715 - sage: erf(-1.0) - -0.842700792949715 - - Check against other implementations and against the definition:: - - sage: erf(3).n() - 0.999977909503001 - sage: maxima.erf(3).n() - 0.999977909503001 - sage: (1-pari(3).erfc()) - 0.999977909503001 - sage: RR(3).erf() - 0.999977909503001 - sage: (integrate(exp(-x**2),(x,0,3))*2/sqrt(pi)).n() - 0.999977909503001 - - :trac:`9044`:: - - sage: N(erf(sqrt(2)),200) - 0.95449973610364158559943472566693312505644755259664313203267 - - :trac:`11626`:: - - sage: n(erf(2),100) - 0.99532226501895273416206925637 - sage: erf(2).n(100) - 0.99532226501895273416206925637 - - Test (indirectly) :trac:`11885`:: - - sage: erf(float(0.5)) - 0.5204998778130465 - sage: erf(complex(0.5)) - (0.5204998778130465+0j) - - Ensure conversion from maxima elements works:: - - sage: merf = maxima(erf(x)).sage().operator() - sage: merf == erf - True - - Make sure we can dump and load it:: - - sage: loads(dumps(erf(2))) - erf(2) - - Special-case 0 for immediate evaluation:: - - sage: erf(0) - 0 - sage: solve(erf(x)==0,x) - [x == 0] - - Make sure that we can hold:: - - sage: erf(0,hold=True) - erf(0) - sage: simplify(erf(0,hold=True)) - 0 - - Check that high-precision ComplexField inputs work:: - - sage: CC(erf(ComplexField(1000)(2+3j))) - -20.8294614276146 + 8.68731827147016*I - """ - - def __init__(self): - r""" - See docstring for :meth:`Function_erf`. - - EXAMPLES:: - - sage: maxima(erf(2)) - erf(2) - sage: erf(2)._sympy_() - erf(2) - """ - BuiltinFunction.__init__(self, "erf", latex_name=r"\text{erf}", - conversions=dict(maxima='erf', - sympy='erf', - fricas='erf')) - - def _eval_(self, x): - """ - EXAMPLES: - - Input is not an expression but is exact:: - - sage: erf(0) - 0 - sage: erf(1) - erf(1) - - Input is not an expression and is not exact:: - - sage: erf(0.0) - 0.000000000000000 - - Input is an expression but not a trivial zero:: - - sage: erf(x) - erf(x) - - Input is an expression which is trivially zero:: - - sage: erf(SR(0)) - 0 - """ - if isinstance(x, Expression): - if x.is_trivial_zero(): - return x - elif not x: - return x - - def _evalf_(self, x, parent=None, algorithm=None): - """ - EXAMPLES:: - - sage: erf(2).n() - 0.995322265018953 - sage: erf(2).n(200) - 0.99532226501895273416206925636725292861089179704006007673835 - sage: erf(pi - 1/2*I).n(100) - 1.0000111669099367825726058952 + 1.6332655417638522934072124547e-6*I - - TESTS: - - Check that PARI/GP through the GP interface gives the same answer:: - - sage: gp.set_real_precision(59) # random - 38 - sage: print(gp.eval("1 - erfc(1)")); print(erf(1).n(200)); - 0.84270079294971486934122063508260925929606699796630290845994 - 0.84270079294971486934122063508260925929606699796630290845994 - - Check that for an imaginary input, the output is also imaginary, see - :trac:`13193`:: - - sage: erf(3.0*I) - 1629.99462260157*I - sage: erf(33.0*I) - 1.51286977510409e471*I - """ - R = parent or s_parent(x) - import mpmath - return mpmath_utils.call(mpmath.erf, x, parent=R) - - def _derivative_(self, x, diff_param=None): - """ - Derivative of erf function - - EXAMPLES:: - - sage: erf(x).diff(x) - 2*e^(-x^2)/sqrt(pi) - - TESTS: - - Check if :trac:`8568` is fixed:: - - sage: var('c,x') - (c, x) - sage: derivative(erf(c*x),x) - 2*c*e^(-c^2*x^2)/sqrt(pi) - sage: erf(c*x).diff(x)._maxima_init_() - '((%pi)^(-1/2))*(_SAGE_VAR_c)*(exp(((_SAGE_VAR_c)^(2))*((_SAGE_VAR_x)^(2))*(-1)))*(2)' - """ - return 2*exp(-x**2)/sqrt(pi) - -erf = Function_erf() - class Function_abs(GinacFunction): def __init__(self): r""" @@ -1106,6 +881,7 @@ def _eval_(self, x, y): if x == 0: return -Ei(-y) if x == Rational(1)/2: #only for x>0 + from sage.functions.error import erf return sqrt(pi)*(1-erf(sqrt(y))) return None diff --git a/src/sage/functions/special.py b/src/sage/functions/special.py index d4ba3c93554..2d976ca3b0c 100644 --- a/src/sage/functions/special.py +++ b/src/sage/functions/special.py @@ -1012,35 +1012,3 @@ def _print_latex_(self, n, z, m): elliptic_pi = EllipticPi() - -def error_fcn(t): - r""" - The complementary error function - `\frac{2}{\sqrt{\pi}}\int_t^\infty e^{-x^2} dx` (t belongs - to RR). This function is currently always - evaluated immediately. - - EXAMPLES:: - - sage: error_fcn(6) - 2.15197367124989e-17 - sage: error_fcn(RealField(100)(1/2)) - 0.47950012218695346231725334611 - - Note this is literally equal to `1 - erf(t)`:: - - sage: 1 - error_fcn(0.5) - 0.520499877813047 - sage: erf(0.5) - 0.520499877813047 - """ - try: - return t.erfc() - except AttributeError: - try: - return RR(t).erfc() - except Exception: - raise NotImplementedError - - - diff --git a/src/sage/interfaces/maxima_lib.py b/src/sage/interfaces/maxima_lib.py index 552c96a0b91..9788f457b7a 100644 --- a/src/sage/interfaces/maxima_lib.py +++ b/src/sage/interfaces/maxima_lib.py @@ -1208,7 +1208,7 @@ def reduce_load_MaximaLib(): sage.functions.log.log : "%LOG", sage.functions.log.lambert_w : "%LAMBERT_W", sage.functions.other.factorial : "MFACTORIAL", - sage.functions.other.erf : "%ERF", + sage.functions.error.erf : "%ERF", sage.functions.other.gamma_inc : "%GAMMA_INCOMPLETE", } #we compile the dictionary From 2901da8005a7f2eefdb317fd4bbce66a1e6751e1 Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Tue, 11 Apr 2017 09:34:42 +0200 Subject: [PATCH 131/452] 11349: doctest fix for: Sage can't make sense of a Maxima result --- src/sage/functions/error.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/sage/functions/error.py b/src/sage/functions/error.py index 5196b269660..0cfe6316a49 100644 --- a/src/sage/functions/error.py +++ b/src/sage/functions/error.py @@ -473,6 +473,19 @@ def __init__(self): erfinv(2) sage: maxima(erfinv(2)) inverse_erf(2) + + TESTS: + + Check that :trac:`11349` is fixed:: + + sage: _ = var('z,t') + sage: PDF = exp(-x^2 /2)/sqrt(2*pi) + sage: integralExpr = integrate(PDF,x,z,oo).subs(z==log(t)) + sage: y = solve(integralExpr==z,t)[0].rhs().subs(z==1/4) + sage: y + e^(sqrt(2)*erfinv(1/2)) + sage: y.n() + 1.96303108415826 """ BuiltinFunction.__init__(self, "erfinv", latex_name=r"\operatorname{erfinv}", From 4b90c163b2d85c5fd6a661ef8308471ddf2cd6bd Mon Sep 17 00:00:00 2001 From: Jeroen Demeyer Date: Tue, 11 Apr 2017 14:32:48 +0200 Subject: [PATCH 132/452] Remove deprecated_callable_import --- src/doc/en/developer/coding_in_python.rst | 24 +++--- src/sage/coding/all.py | 42 +--------- src/sage/combinat/designs/design_catalog.py | 21 ----- src/sage/misc/superseded.py | 76 ------------------- src/sage/numerical/all.py | 18 ----- .../numerical/interactive_simplex_method.py | 4 - 6 files changed, 15 insertions(+), 170 deletions(-) diff --git a/src/doc/en/developer/coding_in_python.rst b/src/doc/en/developer/coding_in_python.rst index bd37d0fb53c..4cd2570e350 100644 --- a/src/doc/en/developer/coding_in_python.rst +++ b/src/doc/en/developer/coding_in_python.rst @@ -522,19 +522,17 @@ documentation for more information on its behaviour and optional arguments. lazy_import('sage.new.module.name', '*', deprecation=666) lazy_import('sage.other.module', ('func1', 'func2'), deprecation=666) -* **Remove a name from the global namespace:** the function - :func:`~sage.misc.superseded.deprecated_callable_import` imports an object into - the global namespace. Any user who calls it sees a message inviting him to - import the object manually:: - - from sage.misc.superseded import deprecated_callable_import - deprecated_callable_import(666, - 'sage.combinat.name_of_the_module', - globals(), - locals(), - ["name_of_the_function"]) - - Alternatively, a lazy_import with deprecation would also work in this case. +* **Remove a name from a global namespace:** this is when you want to + remove a name from a global namespace (say, ``sage.all`` or some + other ``all.py`` file) but you want to keep the functionality + available with an explicit import. + This case is similar as the previous one: use a lazy import with + deprecation. One detail: in this case, you don't want the name + ``lazy_import`` to be visible in the global namespace, so we add + a leading underscore:: + + from sage.misc.lazy_import import lazy_import as _lazy_import + _lazy_import('sage.some.package', 'some_function', deprecation=666) * **Any other case:** if none of the cases above apply, call :func:`~sage.misc.superseded.deprecation` in the function that you want to diff --git a/src/sage/coding/all.py b/src/sage/coding/all.py index 78e3e7b0d4d..7a4f825f9aa 100644 --- a/src/sage/coding/all.py +++ b/src/sage/coding/all.py @@ -5,34 +5,6 @@ _lazy_import("sage.coding.code_constructions", ["permutation_action", "walsh_matrix"]) -from sage.misc.superseded import \ - deprecated_callable_import as _deprecated_callable_import, \ - deprecated_function_alias as _deprecated_function_alias - -_deprecated_callable_import(19315, - "sage.coding.code_bounds", - globals(), - locals(), - ["codesize_upper_bound", - "dimension_upper_bound", - "volume_hamming", - "gilbert_lower_bound", - "plotkin_upper_bound", - "griesmer_upper_bound", - "elias_upper_bound", - "hamming_upper_bound", - "singleton_upper_bound", - "gv_info_rate", - "entropy", - "gv_bound_asymp", - "hamming_bound_asymp", - "singleton_bound_asymp", - "plotkin_bound_asymp", - "elias_bound_asymp", - "mrrw1_bound_asymp"], - ("This method soon will not be available in that way." - "Please call codes.bounds.%(name)s instead")) - _lazy_import("sage.coding.linear_code", [ "LinearCode", "LinearCodeFromVectorSpace", @@ -55,16 +27,10 @@ _lazy_import('sage.coding.delsarte_bounds','krawtchouk', "Kravchuk", deprecation=(20908, "Kravchuk will be removed from the global namespace. Please use codes.bounds.krawtchouk instead.")) -_deprecated_callable_import(20908, - "sage.coding.delsarte_bounds", - globals(), - locals(), - ["delsarte_bound_hamming_space", - "delsarte_bound_additive_hamming_space"], - ("This function will soon be removed from the global namespace. " - "Please call it using codes.bounds.%(name)s instead")) - - +_lazy_import('sage.coding.delsarte_bounds', + ["delsarte_bound_hamming_space", "delsarte_bound_additive_hamming_space"], + deprecation=(20908, "This function will soon be removed from the global namespace. " + "Please call it using codes.bounds.... instead")) _lazy_import('sage.coding', 'codes_catalog', 'codes') _lazy_import('sage.coding', 'channels_catalog', 'channels') diff --git a/src/sage/combinat/designs/design_catalog.py b/src/sage/combinat/designs/design_catalog.py index c3f7d71bb63..3c838715308 100644 --- a/src/sage/combinat/designs/design_catalog.py +++ b/src/sage/combinat/designs/design_catalog.py @@ -98,29 +98,8 @@ from sage.combinat.designs.difference_family import difference_family from .difference_matrices import difference_matrix -from sage.misc.superseded import deprecated_callable_import -deprecated_callable_import(19096, - 'sage.combinat.designs.incidence_structures', - globals(), - locals(), - ["IncidenceStructure"], - ("This alias will soon be removed. You can call the same object by removing 'designs.' in your command")) - -Hypergraph = BlockDesign = IncidenceStructure # just an alias from sage.combinat.designs.bibd import balanced_incomplete_block_design, steiner_triple_system from sage.combinat.designs.resolvable_bibd import resolvable_balanced_incomplete_block_design, kirkman_triple_system from sage.combinat.designs.group_divisible_designs import group_divisible_design from .orthogonal_arrays import OAMainFunctions as orthogonal_arrays - -# When this deprecated function is removed, remove the handling of k=None in the -# function orthogonal_arrays.orthogonal_array() -deprecated_callable_import(17034, - 'sage.combinat.designs.orthogonal_arrays', - globals(), - locals(), - ["orthogonal_array"], - ("This function will soon be removed. Use the designs.orthogonal_arrays.* functions instead")) - -# We don't want this to appear in designs. -del deprecated_callable_import diff --git a/src/sage/misc/superseded.py b/src/sage/misc/superseded.py index f95c6fd1dcb..9561d70fda0 100644 --- a/src/sage/misc/superseded.py +++ b/src/sage/misc/superseded.py @@ -508,79 +508,3 @@ def deprecated_function_alias(trac_number, func): if module_name is None: module_name = '__main__' return DeprecatedFunctionAlias(trac_number, func, module_name) - - -def deprecated_callable_import(trac_number, module_name, globs, locs, fromlist, message=None): - """ - Imports a list of callables into the namespace from - which it is called. These callables however give a deprecation - warning whenever they are called. This is primarily used from - deprecating things from Sage's ``all.py`` files. - - INPUT: - - - ``trac_number`` -- integer. The trac ticket number where the - deprecation is introduced. - - - ``param module_name`` -- string or ``None``. The name of the - module from which to import the callables or ``None``. - - - ``globs`` -- dictionary. The ``globals()`` from where this is being called. - - - ``locs`` -- dictionary. The ``locals()`` from where this is being called. - - - ``fromlist`` -- list of strings. The list the names of the - callables to deprecate - - - ``message`` -- string. Message to display when the deprecated functions are called. - - .. note:: - - If ``module_name`` is ``None``, then no importing will be done, and - it will be assumed that the functions have already been - imported and are present in ``globs`` - - .. warning:: - - This should really only be used for functions. - - EXAMPLES:: - - sage: from sage.misc.superseded import deprecated_callable_import - sage: is_prime(3) - True - sage: message = "Using %(name)s from here is deprecated." - sage: deprecated_callable_import(13109, None, globals(), locals(), ['is_prime'], message) - sage: is_prime(3) - doctest:...: DeprecationWarning: - Using is_prime from here is deprecated. - See http://trac.sagemath.org/13109 for details. - True - sage: del is_prime - sage: deprecated_callable_import(13109, 'sage.arith.all', globals(), locals(), ['is_prime']) - sage: is_prime(3) - doctest:...: DeprecationWarning: - Using is_prime from here is deprecated. If you need to use it, please import it directly from sage.arith.all. - See http://trac.sagemath.org/13109 for details. - True - """ - _check_trac_number(trac_number) - if message is None: - message = '\nUsing %(name)s from here is deprecated. ' + \ - 'If you need to use it, please import it directly from %(module_name)s.' - from functools import partial - from sage.misc.decorators import sage_wraps - if module_name is None: - mod_dict = globs - else: - mod_dict = __import__(module_name, globs, locs, fromlist).__dict__ - for name in fromlist: - func = mod_dict[name] - def wrapper(func, name, *args, **kwds): - from sage.misc.superseded import deprecation - deprecation(trac_number, message%{'name': name, 'module_name': module_name}) - return func(*args, **kwds) - wrapped_function = sage_wraps(func)(partial(wrapper, func, name)) - wrapped_function.__doc__ = message%{'name': name, 'module_name': module_name} - globs[name] = wrapped_function - del name diff --git a/src/sage/numerical/all.py b/src/sage/numerical/all.py index f13906e1214..06ca1dd1a60 100644 --- a/src/sage/numerical/all.py +++ b/src/sage/numerical/all.py @@ -9,21 +9,3 @@ lazy_import("sage.numerical.interactive_simplex_method", ["InteractiveLPProblem", "InteractiveLPProblemStandardForm"]) - -from sage.misc.superseded import deprecated_callable_import - -# Deprecation (#17867) -- two lines at the end of -# sage.numerical.interactive_simplex_method should be removed too. -deprecated_callable_import(17867, - "sage.numerical.interactive_simplex_method", - globals(), - locals(), - ["LPProblem"], - ("This class meant for **educational purposes only** has been renamed to InteractiveLPProblem")) - -deprecated_callable_import(17867, - "sage.numerical.interactive_simplex_method", - globals(), - locals(), - ["LPProblemStandardForm"], - ("This class meant for **educational purposes only** has been renamed to InteractiveLPProblemStandardForm")) diff --git a/src/sage/numerical/interactive_simplex_method.py b/src/sage/numerical/interactive_simplex_method.py index 2d65b2aedee..0e15aea357a 100644 --- a/src/sage/numerical/interactive_simplex_method.py +++ b/src/sage/numerical/interactive_simplex_method.py @@ -5449,7 +5449,3 @@ def y(self): # Aliases for the standard notation x_B = basic_variables x_N = nonbasic_variables - -# DEPRECATION (those two lines should be removed when cleaning #17867) -LPProblem = InteractiveLPProblem -LPProblemStandardForm = InteractiveLPProblemStandardForm From e96e7e14cca7e9062bb3e8d8becb52b43790e3f8 Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Thu, 13 Apr 2017 09:17:40 +0200 Subject: [PATCH 133/452] 21819: move error_fcn back to functions.other --- src/sage/functions/all.py | 5 ++--- src/sage/functions/error.py | 17 ----------------- src/sage/functions/special.py | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/sage/functions/all.py b/src/sage/functions/all.py index 66d5c824800..1c04b124ea0 100644 --- a/src/sage/functions/all.py +++ b/src/sage/functions/all.py @@ -4,8 +4,7 @@ lazy_import('sage.functions.piecewise_old', 'Piecewise') # deprecated lazy_import('sage.functions.piecewise', 'piecewise') -lazy_import('sage.functions.error', ['erf', 'erfi', 'erfc', - 'erfinv', 'error_fcn']) +lazy_import('sage.functions.error', ['erf', 'erfc', 'erfi', 'erfinv']) from .trig import ( sin, cos, sec, csc, cot, tan, asin, acos, atan, @@ -41,7 +40,7 @@ from .special import (spherical_harmonic, elliptic_e, elliptic_f, elliptic_ec, elliptic_eu, - elliptic_kc, elliptic_pi, elliptic_j) + elliptic_kc, elliptic_pi, elliptic_j, error_fcn) from .jacobi import (jacobi, inverse_jacobi, jacobi_nd, jacobi_ns, jacobi_nc, jacobi_dn, jacobi_ds, jacobi_dc, jacobi_sn, jacobi_sd, diff --git a/src/sage/functions/error.py b/src/sage/functions/error.py index 5196b269660..79924ac974a 100644 --- a/src/sage/functions/error.py +++ b/src/sage/functions/error.py @@ -47,7 +47,6 @@ from sage.functions.all import sqrt, exp from sage.symbolic.constants import pi from sage.rings.infinity import unsigned_infinity -from sage.misc.superseded import deprecation class Function_erf(BuiltinFunction): r""" @@ -444,22 +443,6 @@ def _derivative_(self, x, diff_param=None): erfc = Function_erfc() -def error_fcn(x): - """ - Deprecated. Please use erfc(). - - EXAMPLES:: - - sage: error_fcn(x) - doctest:warning - ... - DeprecationWarning: error_fcn() is deprecated. Please use erfc() - See http://trac.sagemath.org/21819 for details. - erfc(x) - """ - deprecation(21819, "error_fcn() is deprecated. Please use erfc()") - return erfc(x) - class Function_erfinv(BuiltinFunction): def __init__(self): diff --git a/src/sage/functions/special.py b/src/sage/functions/special.py index 2d976ca3b0c..2ca349605c3 100644 --- a/src/sage/functions/special.py +++ b/src/sage/functions/special.py @@ -1012,3 +1012,21 @@ def _print_latex_(self, n, z, m): elliptic_pi = EllipticPi() + +def error_fcn(x): + """ + Deprecated. Please use erfc(). + + EXAMPLES:: + + sage: error_fcn(x) + doctest:warning + ... + DeprecationWarning: error_fcn() is deprecated. Please use erfc() + See http://trac.sagemath.org/21819 for details. + erfc(x) + """ + from .error import erfc + from sage.misc.superseded import deprecation + deprecation(21819, "error_fcn() is deprecated. Please use erfc()") + return erfc(x) From a0241073b64a4f26ad37171d237e02b5ec3f0485 Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Thu, 13 Apr 2017 08:26:12 -0400 Subject: [PATCH 134/452] Alter example to a more standard one --- src/sage/combinat/set_partition.py | 190 +++++++++++++++-------------- 1 file changed, 96 insertions(+), 94 deletions(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index bc7cd86ff0c..fd27e1f73ed 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -417,11 +417,10 @@ def set_latex_options(self, **kwargs): - ``tikz_scale`` -- (default: 1) scale for use with tikz package - - ``plot`` -- (default: ``''``) ``''`` returns the set notation, + - ``plot`` -- (default: None) None returns the set notation, ``linear`` returns a linear plot, ``cyclic`` returns a cyclic plot - - ``color`` -- (default: black) the arc colors - ``fill`` -- (default: False) if True then fills black, else you can @@ -457,8 +456,8 @@ def set_latex_options(self, **kwargs): if key not in valid_args: raise ValueError("unknown keyword argument: %s"%key) if key == 'plot': - if kwargs['plot'] != 'cyclic' and kwargs['plot'] != 'linear' and kwargs['plot'] != '': - raise ValueError("plot must be blank, 'cyclic', or 'linear'") + if kwargs['plot'] != 'cyclic' and kwargs['plot'] != 'linear' and kwargs['plot'] != None: + raise ValueError("plot must be None, 'cyclic', or 'linear'") for opt in kwargs: self._latex_options[opt] = kwargs[opt] @@ -468,7 +467,7 @@ def latex_options(self): Return the latex options for use in the ``_latex_`` function as a dictionary. The default values are set using the global options. - Options can be found in set_latex_options() + Options can be found in :meth:`set_latex_options` EXAMPLES:: @@ -476,7 +475,7 @@ def latex_options(self): {'angle': 0, 'color': 'black', 'fill': False, - 'plot': '', + 'plot': None, 'radius': '1cm', 'show_labels': True, 'tikz_scale': 1} @@ -485,7 +484,7 @@ def latex_options(self): if "tikz_scale" not in opts: opts["tikz_scale"] = 1 if "plot" not in opts: - opts["plot"] = '' + opts["plot"] = None if "color" not in opts: opts['color']= 'black' if "fill" not in opts: @@ -528,83 +527,83 @@ def _latex_(self): """ latex_options = self.latex_options() - if latex_options["plot"] == "": + if latex_options["plot"] == None: return repr(self).replace("{",r"\{").replace("}",r"\}") + + latex.add_package_to_preamble_if_available("tikz") + res = "\\begin{tikzpicture}[scale="+str(latex_options['tikz_scale'])+"]\n" + + cardinality = self.base_set_cardinality() + base_set = self.base_set().list() + color= latex_options['color'] + + # If we want cyclic plots + if latex_options['plot'] == 'cyclic': + degrees = 360 / cardinality + radius = latex_options['radius'] + + # Add nodes + for k,i in enumerate(base_set): + location = (cardinality - k) * degrees - 270 + res += "\\node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black" + if latex_options['show_labels']: + res += ",label=" + str(location) + ":" + str(i) + res += "] (" + str(k) + ") at (" + str(location) + ":" + radius + ") {};\n" + + # Add the circle + for k,i in enumerate(base_set): + xangle = k * degrees + yangle = (k+1) * degrees + res += "\\draw[-] (" + str(xangle) + ":" + radius + ")" + res += " arc " + res += "(" + str(xangle) + ":" + str(yangle) + ":" + radius + ");\n" + + # Setup partitions + for partition in self: + res += "\\draw[-,thick,color="+color + if latex_options['fill'] != False: + if isinstance(latex_options['fill'],str): + res += ",fill="+latex_options['fill'] + else: + res += ",fill={rgb:" + color + ",1;white,10}" + res += "] " + firstDone = False + for j in partition: + if firstDone: + res += " -- (" + str(base_set.index(j)) + ".center)" + else: + firstDone = True + res += "(" + str(base_set.index(j)) + ".center)" + res += " -- cycle;\n" + + # If we want line plots + elif latex_options['plot'] == 'linear': + angle = latex_options['angle'] + # setup line + for k,i in enumerate(base_set): + if latex_options['show_labels']: + res += "\\node[below=.05cm] at (" + str(k) + ",0) {$" + str(i) + "$};\n" + res += "\\node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black] " + res += "(" + str(k) + ") at (" + str(k) + ",0) {};\n" + #res += "\t\\draw (0) -- (" + str(cardinality - 1) + ");\n" + + # setup arcs + for partition in self: + if partition.cardinality() > 1: + for k,i in enumerate(partition.list()): + if k != 0: + #res += "\\draw (" + str(base_set.index(partition[0])) + ")" + #res += " to [out=90,in=90] " + #res += "(" + str(base_set.index(partition[-1])) + ");" + #else: + res += "\\draw[color=" + color + "] (" + str(base_set.index(partition[k])) + ")" + res += " to [out=" + str(90+angle) + ",in=" + str(90-angle) + "] " + res += "(" + str(base_set.index(partition[k-1])) + ");\n" else: - latex.add_package_to_preamble_if_available("tikz") - res = "\\begin{tikzpicture}[scale="+str(latex_options['tikz_scale'])+"]\n" - - cardinality = self.base_set_cardinality() - base_set = self.base_set().list() - color= latex_options['color'] - - # If we want cyclic plots - if latex_options['plot'] == 'cyclic': - degrees = 360 / cardinality - radius = latex_options['radius'] - - # Add nodes - for k,i in enumerate(base_set): - location = (cardinality - k) * degrees - 270 - res += "\\node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black" - if latex_options['show_labels']: - res += ",label=" + str(location) + ":" + str(i) - res += "] (" + str(k) + ") at (" + str(location) + ":" + radius + ") {};\n" - - # Add the circle - for k,i in enumerate(base_set): - xangle = k * degrees - yangle = (k+1) * degrees - res += "\\draw[-] (" + str(xangle) + ":" + radius + ")" - res += " arc " - res += "(" + str(xangle) + ":" + str(yangle) + ":" + radius + ");\n" - - # Setup partitions - for partition in self: - res += "\\draw[-,thick,color="+color - if latex_options['fill'] != False: - if isinstance(latex_options['fill'],str): - res += ",fill="+latex_options['fill'] - else: - res += ",fill={rgb:" + color + ",1;white,10}" - res += "] " - firstDone = False - for j in partition: - if firstDone: - res += " -- (" + str(base_set.index(j)) + ".center)" - else: - firstDone = True - res += "(" + str(base_set.index(j)) + ".center)" - res += " -- cycle;\n" - - # If we want line plots - elif latex_options['plot'] == 'linear': - angle = latex_options['angle'] - # setup line - for k,i in enumerate(base_set): - if latex_options['show_labels']: - res += "\\node[below=.05cm] at (" + str(k) + ",0) {$" + str(i) + "$};\n" - res += "\\node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black] " - res += "(" + str(k) + ") at (" + str(k) + ",0) {};\n" - #res += "\t\\draw (0) -- (" + str(cardinality - 1) + ");\n" - - # setup arcs - for partition in self: - if partition.cardinality() > 1: - for k,i in enumerate(partition.list()): - if k != 0: - #res += "\\draw (" + str(base_set.index(partition[0])) + ")" - #res += " to [out=90,in=90] " - #res += "(" + str(base_set.index(partition[-1])) + ");" - #else: - res += "\\draw[color=" + color + "] (" + str(base_set.index(partition[k])) + ")" - res += " to [out=" + str(90+angle) + ",in=" + str(90-angle) + "] " - res += "(" + str(base_set.index(partition[k-1])) + ");\n" - else: - raise ValueError("plot must be blank, 'cyclic', or 'linear'") + raise ValueError("plot must be None, 'cyclic', or 'linear'") - res += "\\end{tikzpicture}" - return res + res += "\\end{tikzpicture}" + return res cardinality = ClonableArray.__len__ @@ -1185,32 +1184,32 @@ def plot(self, angle=None, color='black', base_set_dict=None): Arc with center (1.0,-1.0) radii (1.41421356237,1.41421356237) angle 0.0 inside the sector (0.785398163397,2.35619449019) Arc with center (2.5,-0.5) radii (0.707106781187,0.707106781187) angle 0.0 inside the sector (0.785398163397,2.35619449019) Arc with center (2.5,-1.5) radii (2.12132034356,2.12132034356) angle 0.0 inside the sector (0.785398163397,2.35619449019) - sage: p=SetPartition([['a','c'],['b',-1],[20.2]]) + sage: p=SetPartition([['a','c'],['b','d'],['e']]) sage: print(p.plot().description()) Point set defined by 1 point(s): [(0.0, 0.0)] Point set defined by 1 point(s): [(1.0, 0.0)] Point set defined by 1 point(s): [(2.0, 0.0)] Point set defined by 1 point(s): [(3.0, 0.0)] Point set defined by 1 point(s): [(4.0, 0.0)] - Text '-1' at the point (0.0,-0.1) - Text '20.2000000000000' at the point (1.0,-0.1) - Text 'a' at the point (2.0,-0.1) - Text 'b' at the point (3.0,-0.1) - Text 'c' at the point (4.0,-0.1) - Arc with center (1.5,-1.5) radii (2.12132034356,2.12132034356) angle 0.0 inside the sector (0.785398163397,2.35619449019) - Arc with center (3.0,-1.0) radii (1.41421356237,1.41421356237) angle 0.0 inside the sector (0.785398163397,2.35619449019) - sage: p=SetPartition([['a','c'],['b',-1],[20.2]]) - sage: print(p.plot(base_set_dict={'a':0,'b':1,'c':2,-1:-2.3,20.2:5.4}).description()) + Text 'a' at the point (0.0,-0.1) + Text 'b' at the point (1.0,-0.1) + Text 'c' at the point (2.0,-0.1) + Text 'd' at the point (3.0,-0.1) + Text 'e' at the point (4.0,-0.1) + Arc with center (1.0,-1.0) radii (1.41421356237,1.41421356237) angle 0.0 inside the sector (0.785398163397,2.35619449019) + Arc with center (2.0,-1.0) radii (1.41421356237,1.41421356237) angle 0.0 inside the sector (0.785398163397,2.35619449019) + sage: p=SetPartition([['a','c'],['b','d'],['e']]) + sage: print(p.plot(base_set_dict={'a':0,'b':1,'c':2,'d':-2.3,'e':5.4}).description()) Point set defined by 1 point(s): [(-2.3, 0.0)] Point set defined by 1 point(s): [(0.0, 0.0)] Point set defined by 1 point(s): [(1.0, 0.0)] Point set defined by 1 point(s): [(2.0, 0.0)] Point set defined by 1 point(s): [(5.4, 0.0)] - Text '-1' at the point (-2.3,-0.1) - Text '20.2000000000000' at the point (5.4,-0.1) Text 'a' at the point (0.0,-0.1) Text 'b' at the point (1.0,-0.1) Text 'c' at the point (2.0,-0.1) + Text 'd' at the point (-2.3,-0.1) + Text 'e' at the point (5.4,-0.1) Arc with center (-0.65,-1.65) radii (2.33345237792,2.33345237792) angle 0.0 inside the sector (0.785398163397,2.35619449019) Arc with center (1.0,-1.0) radii (1.41421356237,1.41421356237) angle 0.0 inside the sector (0.785398163397,2.35619449019) @@ -1247,7 +1246,10 @@ def plot(self, angle=None, color='black', base_set_dict=None): # TODO: change 0.1 to something proportional to the height of the picture for (k,j) in self.arcs(): pos_k,pos_j = float(vertices_dict[k]),float(vertices_dict[j]) - diag += arc(center=((pos_k+pos_j)/2,-abs(pos_j-pos_k)/(2*tan(angle))), r1=abs((pos_j-pos_k)/(2*sin(angle))), sector=(sgn(angle)*(pi/2-angle),sgn(angle)*(pi/2+angle)),color=color) + center = ((pos_k+pos_j)/2,-abs(pos_j-pos_k)/(2*tan(angle))) + r1 = abs((pos_j-pos_k)/(2*sin(angle))) + sector = (sgn(angle)*(pi/2-angle),sgn(angle)*(pi/2+angle)) + diag += arc(center=center, r1=r1, sector=sector, color=color) diag.axes(False) return diag From 1f32d6989e76bdf5b73a9cb24c112f2ad3403471 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 15 Apr 2017 22:54:29 +0200 Subject: [PATCH 135/452] care for cmp in combinat/combinat --- src/sage/combinat/combinat.py | 102 +++++++++++++++++----------------- 1 file changed, 52 insertions(+), 50 deletions(-) diff --git a/src/sage/combinat/combinat.py b/src/sage/combinat/combinat.py index 75f73dda864..4ad2377cea4 100644 --- a/src/sage/combinat/combinat.py +++ b/src/sage/combinat/combinat.py @@ -915,31 +915,31 @@ def __str__(self): """ return str(self._list) - def __cmp__(self, other): + def _repr_(self): """ EXAMPLES:: sage: c = CombinatorialObject([1,2,3]) - sage: d = CombinatorialObject([3,2,1]) - sage: cmp(c, d) - -1 - sage: cmp(d, c) - 1 - sage: cmp(c, c) - 0 + sage: c.__repr__() + '[1, 2, 3]' + """ + return repr(self._list) - Check that :trac:`14065` is fixed:: + def __eq__(self, other): + """ + Test equality of self and other. - sage: from sage.structure.element import Element - sage: class Foo(CombinatorialObject, Element): pass - sage: L = [Foo([4-i]) for i in range(4)]; L - [[4], [3], [2], [1]] - sage: sorted(L) - [[1], [2], [3], [4]] - sage: f = Foo([4]) - sage: f is None + EXAMPLES:: + + sage: c = CombinatorialObject([1,2,3]) + sage: d = CombinatorialObject([2,3,4]) + sage: c == [1,2,3] + True + sage: c == [2,3,4] False - sage: f is not None + sage: c == d + False + sage: c == c True .. WARNING:: @@ -959,34 +959,6 @@ def __cmp__(self, other): ... NotImplementedError: comparison not implemented for """ - if isinstance(other, CombinatorialObject): - return cmp(self._list, other._list) - else: - return cmp(self._list, other) - - def _repr_(self): - """ - EXAMPLES:: - - sage: c = CombinatorialObject([1,2,3]) - sage: c.__repr__() - '[1, 2, 3]' - """ - return repr(self._list) - - def __eq__(self, other): - """ - EXAMPLES:: - - sage: c = CombinatorialObject([1,2,3]) - sage: d = CombinatorialObject([2,3,4]) - sage: c == [1,2,3] - True - sage: c == [2,3,4] - False - sage: c == d - False - """ if isinstance(other, CombinatorialObject): return self._list == other._list else: @@ -1002,6 +974,22 @@ def __lt__(self, other): True sage: c < [2,3,4] True + sage: c < c + False + + Check that :trac:`14065` is fixed:: + + sage: from sage.structure.element import Element + sage: class Foo(CombinatorialObject, Element): pass + sage: L = [Foo([4-i]) for i in range(4)]; L + [[4], [3], [2], [1]] + sage: sorted(L) + [[1], [2], [3], [4]] + sage: f = Foo([4]) + sage: f is None + False + sage: f is not None + True """ if isinstance(other, CombinatorialObject): return self._list < other._list @@ -1441,10 +1429,11 @@ def __contains__(self, x): """ raise NotImplementedError - def __cmp__(self, x): + def __eq__(self, other): """ - Compares two different combinatorial classes. For now, the - comparison is done just on their repr's. + Compare two different combinatorial classes. + + For now, the comparison is done just on their repr's. EXAMPLES:: @@ -1455,7 +1444,20 @@ def __cmp__(self, x): sage: p5 == p6 False """ - return cmp(repr(self), repr(x)) + return repr(self) == repr(other) + + def __ne__(self, other): + """ + Test unequality of self and other. + + EXAMPLES:: + + sage: p5 = Partitions(5) + sage: p6 = Partitions(6) + sage: p5 != p6 + True + """ + return not (self == other) def __cardinality_from_iterator(self): """ From 99a665d0d9cfa290803e9e0f11eca3f5535fa7f6 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sat, 15 Apr 2017 23:40:46 -0500 Subject: [PATCH 136/452] Some last reviewer tweaks. --- src/sage/combinat/set_partition.py | 122 ++++++++++++++++------------- 1 file changed, 68 insertions(+), 54 deletions(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index 9c0230bec90..cfffb68de47 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -27,6 +27,7 @@ # # http://www.gnu.org/licenses/ #***************************************************************************** +from __future__ import print_function, absolute_import, division from six.moves import range from six import add_metaclass @@ -51,7 +52,6 @@ from sage.combinat.combinat import bell_number, stirling_number2 from sage.combinat.permutation import Permutation from functools import reduce -from sage.misc.latex import latex @add_metaclass(InheritComparisonClasscallMetaclass) @@ -420,22 +420,23 @@ def set_latex_options(self, **kwargs): - ``tikz_scale`` -- (default: 1) scale for use with tikz package - - ``plot`` -- (default: None) None returns the set notation, + - ``plot`` -- (default: ``None``) ``None`` returns the set notation, ``linear`` returns a linear plot, ``cyclic`` returns a cyclic plot - - ``color`` -- (default: black) the arc colors + - ``color`` -- (default: ``'black'``) the arc colors - - ``fill`` -- (default: False) if True then fills black, else you can - pass in a color to alter the fill color - *only works with cyclic plot* + - ``fill`` -- (default: ``False``) if True then fills black, else + you can pass in a color to alter the fill color - + *only works with cyclic plot* - - ``show_labels`` -- (default: True) if True shows labels - *only works - with plots* + - ``show_labels`` -- (default: ``True``) if ``True`` shows labels - + *only works with plots* - - ``radius`` -- (default: "1cm") radius of circle for cyclic plot - *Only - works with cyclic plot* + - ``radius`` -- (default: ``"1cm"``) radius of circle for cyclic + plot - *only works with cyclic plot* - - ``angle`` -- (default: 0) angle for linear + - ``angle`` -- (default: 0) angle for linear plot EXAMPLES:: @@ -459,11 +460,13 @@ def set_latex_options(self, **kwargs): if key not in valid_args: raise ValueError("unknown keyword argument: %s"%key) if key == 'plot': - if kwargs['plot'] != 'cyclic' and kwargs['plot'] != 'linear' and kwargs['plot'] != None: + if not (kwargs['plot'] == 'cyclic' + or kwargs['plot'] == 'linear' + or kwargs['plot'] is None): raise ValueError("plot must be None, 'cyclic', or 'linear'") - for opt in kwargs: - self._latex_options[opt] = kwargs[opt] + for opt in kwargs: + self._latex_options[opt] = kwargs[opt] def latex_options(self): r""" @@ -489,7 +492,7 @@ def latex_options(self): if "plot" not in opts: opts["plot"] = None if "color" not in opts: - opts['color']= 'black' + opts['color'] = 'black' if "fill" not in opts: opts["fill"] = False if "show_labels" not in opts: @@ -530,9 +533,10 @@ def _latex_(self): """ latex_options = self.latex_options() - if latex_options["plot"] == None: + if latex_options["plot"] is None: return repr(self).replace("{",r"\{").replace("}",r"\}") - + + from sage.misc.latex import latex latex.add_package_to_preamble_if_available("tikz") res = "\\begin{tikzpicture}[scale="+str(latex_options['tikz_scale'])+"]\n" @@ -542,7 +546,7 @@ def _latex_(self): # If we want cyclic plots if latex_options['plot'] == 'cyclic': - degrees = 360 / cardinality + degrees = 360 // cardinality radius = latex_options['radius'] # Add nodes @@ -1152,27 +1156,33 @@ def arcs(self): return arcs def plot(self, angle=None, color='black', base_set_dict=None): - """ + r""" Return a plot of ``self``. - .. PLOT:: - - p=SetPartition([[1,10,11],[2,3,7],[4,5,6],[8,9]]) - sphinx_plot(p.plot()) - INPUT: - - ``angle`` -- the angle at which the arcs take off (if angle is negative, - the arcs are drawn below the horizontal line) + - ``angle`` -- (default: `\pi/4`) the angle at which the arcs take off + (if angle is negative, the arcs are drawn below the horizontal line) - - ``color`` -- color of the arcs + - ``color`` -- (default: ``'black'``) color of the arcs - - ``base_set_dict`` -- dictionary with keys elements of self.base_set() - and values as integer or float + - ``base_set_dict`` -- (optional) dictionary with keys elements + of :meth:`base_set()` and values as integer or float EXAMPLES:: - sage: p=SetPartition([[1,3,4],[2,5]]) + sage: p = SetPartition([[1,10,11],[2,3,7],[4,5,6],[8,9]]) + sage: p.plot() + Graphics object consisting of 29 graphics primitives + + .. PLOT:: + + p = SetPartition([[1,10,11],[2,3,7],[4,5,6],[8,9]]) + sphinx_plot(p.plot()) + + :: + + sage: p = SetPartition([[1,3,4],[2,5]]) sage: print(p.plot().description()) Point set defined by 1 point(s): [(0.0, 0.0)] Point set defined by 1 point(s): [(1.0, 0.0)] @@ -1184,10 +1194,13 @@ def plot(self, angle=None, color='black', base_set_dict=None): Text '3' at the point (2.0,-0.1) Text '4' at the point (3.0,-0.1) Text '5' at the point (4.0,-0.1) - Arc with center (1.0,-1.0) radii (1.41421356237,1.41421356237) angle 0.0 inside the sector (0.785398163397,2.35619449019) - Arc with center (2.5,-0.5) radii (0.707106781187,0.707106781187) angle 0.0 inside the sector (0.785398163397,2.35619449019) - Arc with center (2.5,-1.5) radii (2.12132034356,2.12132034356) angle 0.0 inside the sector (0.785398163397,2.35619449019) - sage: p=SetPartition([['a','c'],['b','d'],['e']]) + Arc with center (1.0,-1.0) radii (1.41421356237,1.41421356237) + angle 0.0 inside the sector (0.785398163397,2.35619449019) + Arc with center (2.5,-0.5) radii (0.707106781187,0.707106781187) + angle 0.0 inside the sector (0.785398163397,2.35619449019) + Arc with center (2.5,-1.5) radii (2.12132034356,2.12132034356) + angle 0.0 inside the sector (0.785398163397,2.35619449019) + sage: p = SetPartition([['a','c'],['b','d'],['e']]) sage: print(p.plot().description()) Point set defined by 1 point(s): [(0.0, 0.0)] Point set defined by 1 point(s): [(1.0, 0.0)] @@ -1199,9 +1212,11 @@ def plot(self, angle=None, color='black', base_set_dict=None): Text 'c' at the point (2.0,-0.1) Text 'd' at the point (3.0,-0.1) Text 'e' at the point (4.0,-0.1) - Arc with center (1.0,-1.0) radii (1.41421356237,1.41421356237) angle 0.0 inside the sector (0.785398163397,2.35619449019) - Arc with center (2.0,-1.0) radii (1.41421356237,1.41421356237) angle 0.0 inside the sector (0.785398163397,2.35619449019) - sage: p=SetPartition([['a','c'],['b','d'],['e']]) + Arc with center (1.0,-1.0) radii (1.41421356237,1.41421356237) + angle 0.0 inside the sector (0.785398163397,2.35619449019) + Arc with center (2.0,-1.0) radii (1.41421356237,1.41421356237) + angle 0.0 inside the sector (0.785398163397,2.35619449019) + sage: p = SetPartition([['a','c'],['b','d'],['e']]) sage: print(p.plot(base_set_dict={'a':0,'b':1,'c':2,'d':-2.3,'e':5.4}).description()) Point set defined by 1 point(s): [(-2.3, 0.0)] Point set defined by 1 point(s): [(0.0, 0.0)] @@ -1213,9 +1228,10 @@ def plot(self, angle=None, color='black', base_set_dict=None): Text 'c' at the point (2.0,-0.1) Text 'd' at the point (-2.3,-0.1) Text 'e' at the point (5.4,-0.1) - Arc with center (-0.65,-1.65) radii (2.33345237792,2.33345237792) angle 0.0 inside the sector (0.785398163397,2.35619449019) - Arc with center (1.0,-1.0) radii (1.41421356237,1.41421356237) angle 0.0 inside the sector (0.785398163397,2.35619449019) - + Arc with center (-0.65,-1.65) radii (2.33345237792,2.33345237792) + angle 0.0 inside the sector (0.785398163397,2.35619449019) + Arc with center (1.0,-1.0) radii (1.41421356237,1.41421356237) + angle 0.0 inside the sector (0.785398163397,2.35619449019) """ from sage.plot.graphics import Graphics from sage.plot.point import point @@ -1223,36 +1239,34 @@ def plot(self, angle=None, color='black', base_set_dict=None): from sage.plot.arc import arc from sage.functions.other import sqrt from sage.symbolic.constants import pi - from sage.functions.trig import tan - from sage.functions.trig import sin + from sage.functions.trig import tan, sin from sage.functions.generalized import sgn diag = Graphics() - sorted_vertices_list=list(self.base_set()) + sorted_vertices_list = list(self.base_set()) sorted_vertices_list.sort() - vertices_dict = dict() - if not angle: - angle = pi/4 - # the case angle = 0 should maybe treated separately + if angle is None: + angle = pi / 4 - if base_set_dict: + if base_set_dict is not None: vertices_dict = base_set_dict else: - for pos in range(len(sorted_vertices_list)): - vertices_dict[sorted_vertices_list[pos]]=pos + vertices_dict = {val: pos for pos,val in enumerate(sorted_vertices_list)} for elt in vertices_dict: pos = vertices_dict[elt] - diag += point((pos,0),size=30, color=color) - diag += text(elt, (pos,-sgn(angle)*0.1), color=color) + diag += point((pos,0), size=30, color=color) + diag += text(elt, (pos, -sgn(angle)*0.1), color=color) # TODO: change 0.1 to something proportional to the height of the picture + for (k,j) in self.arcs(): pos_k,pos_j = float(vertices_dict[k]),float(vertices_dict[j]) - center = ((pos_k+pos_j)/2,-abs(pos_j-pos_k)/(2*tan(angle))) - r1 = abs((pos_j-pos_k)/(2*sin(angle))) - sector = (sgn(angle)*(pi/2-angle),sgn(angle)*(pi/2+angle)) + center = ((pos_k+pos_j) / 2, -abs(pos_j-pos_k) / (2*tan(angle))) + r1 = abs((pos_j-pos_k) / (2*sin(angle))) + sector = (sgn(angle) * (pi/2 - angle), sgn(angle) * (pi/2 + angle)) diag += arc(center=center, r1=r1, sector=sector, color=color) + diag.axes(False) return diag From e2663727b93cdfe35019f76432c4b7ecfcddc530 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sun, 16 Apr 2017 13:06:26 -0500 Subject: [PATCH 137/452] Doctest fixes. --- src/sage/algebras/lie_algebras/classical_lie_algebra.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/algebras/lie_algebras/classical_lie_algebra.py b/src/sage/algebras/lie_algebras/classical_lie_algebra.py index bbee1960ffe..1ea15b8446b 100644 --- a/src/sage/algebras/lie_algebras/classical_lie_algebra.py +++ b/src/sage/algebras/lie_algebras/classical_lie_algebra.py @@ -318,7 +318,7 @@ def affine(self, kac_moody=False): sage: so5 Special orthogonal Lie algebra of rank 5 over Rational Field sage: so5.affine() - Affine Special orthogonal Lie algebra of rank 5 over Rational Field + Affine Special orthogonal Kac-Moody algebra of rank 5 over Rational Field """ from sage.algebras.lie_algebras.affine_lie_algebra import AffineLieAlgebra return AffineLieAlgebra(self, kac_moody) @@ -1163,7 +1163,7 @@ def affine(self, kac_moody=False): sage: sp6 Lie algebra of ['C', 3] in the Chevalley basis sage: sp6.affine() - Affine Lie algebra of ['C', 3] in the Chevalley basis + Affine Kac-Moody algebra of ['C', 3] in the Chevalley basis """ from sage.algebras.lie_algebras.affine_lie_algebra import AffineLieAlgebra return AffineLieAlgebra(self, kac_moody) From e2b65836f988579c7d5de59e6f0f8320ce147eb7 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 23 Nov 2016 07:07:18 -0600 Subject: [PATCH 138/452] Some small fixes and updates. --- src/sage/combinat/crystals/mv_polytopes.py | 7 ++++++- src/sage/combinat/crystals/pbw_crystal.py | 10 ++++++++-- src/sage/combinat/crystals/pbw_datum.pyx | 11 +++++++---- src/sage/combinat/root_system/__init__.py | 1 + .../combinat/root_system/braid_move_calculator.py | 2 +- 5 files changed, 23 insertions(+), 8 deletions(-) diff --git a/src/sage/combinat/crystals/mv_polytopes.py b/src/sage/combinat/crystals/mv_polytopes.py index af8a06d05e1..7dc21b0cfc1 100644 --- a/src/sage/combinat/crystals/mv_polytopes.py +++ b/src/sage/combinat/crystals/mv_polytopes.py @@ -1,10 +1,15 @@ # -*- coding: utf-8 -*- r""" Crystal Of Mirković-Vilonen (MV) Polytopes + +AUTHORS: + +- Dinakar Muthiah, Travis Scrimshaw (2015-05-11): initial version """ #***************************************************************************** -# Copyright (C) 2015 Dinakar Muthiah +# Copyright (C) 2015 Dinakar Muthiah +# 2015 Travis Scrimshaw # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/src/sage/combinat/crystals/pbw_crystal.py b/src/sage/combinat/crystals/pbw_crystal.py index 51482ee015b..7f18dde0e3d 100644 --- a/src/sage/combinat/crystals/pbw_crystal.py +++ b/src/sage/combinat/crystals/pbw_crystal.py @@ -1,13 +1,19 @@ +# -*- coding: utf-8 -*- r""" `\mathcal{B}(\infty)` Crystal Of PBW Monomials. AUTHORS: - Dinakar Muthiah (2015-05-11): initial version + +.. SEEALSO:: + + For infromation on PBW datum, see + :ref:`sage.combinat.crystals.pbw_datum`. """ #***************************************************************************** -# Copyright (C) 2015 Dinakar Muthiah +# Copyright (C) 2015 Dinakar Muthiah # # 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 @@ -340,7 +346,7 @@ class PBWCrystal(Parent, UniqueRepresentation): Crystal of `\mathcal{B}(\infty)` given by PBW monomials. A model of the crystal `\mathcal{B}(\infty)` whose elements are - PBW datum up to equivalence by the tropical Plucker relations. + PBW datum up to equivalence by the tropical Plücker relations. EXAMPLES:: diff --git a/src/sage/combinat/crystals/pbw_datum.pyx b/src/sage/combinat/crystals/pbw_datum.pyx index cb0d8c5f065..7f706fb0d79 100644 --- a/src/sage/combinat/crystals/pbw_datum.pyx +++ b/src/sage/combinat/crystals/pbw_datum.pyx @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- r""" PBW Data @@ -7,10 +8,12 @@ in finite type. AUTHORS: - Dinakar Muthiah (2015-05): initial version +- Travis Scrimshaw (2016-06): simplfied code and converted to Cython """ #***************************************************************************** -# Copyright (C) 2015 Dinakar Muthiah +# Copyright (C) 2015 Dinakar Muthiah +# Travis Scrimshaw # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -84,7 +87,7 @@ class PBWDatum(object): def is_equivalent_to(self, other_pbw_datum): r""" Return whether ``self`` is equivalent to ``other_pbw_datum``. - modulo the tropical Plucker relations. + modulo the tropical Plücker relations. EXAMPLES:: @@ -276,7 +279,7 @@ class PBWData(object): # UniqueRepresentation? #enhanced_braid_chain is an ugly data structure. cpdef tuple compute_new_lusztig_datum(enhanced_braid_chain, initial_lusztig_datum): """ - Return the lusztig datum obtained by applying Tropical Plucker + Return the lusztig datum obtained by applying tropical Plücker relations along ``enhanced_braid_chain`` starting with ``initial_lusztig_datum``. @@ -319,7 +322,7 @@ cpdef tuple compute_new_lusztig_datum(enhanced_braid_chain, initial_lusztig_datu # The tropical plucker relations cpdef tuple tropical_plucker_relation(tuple a, lusztig_datum): r""" - Apply the tropical Plucker relation of type ``a`` to ``lusztig_datum``. + Apply the tropical Plücker relation of type ``a`` to ``lusztig_datum``. The relations are obtained by tropicalizing the relations in Proposition 7.1 of [BZ01]_. diff --git a/src/sage/combinat/root_system/__init__.py b/src/sage/combinat/root_system/__init__.py index 5ae9b4841dd..95cb5c10883 100644 --- a/src/sage/combinat/root_system/__init__.py +++ b/src/sage/combinat/root_system/__init__.py @@ -56,6 +56,7 @@ - :ref:`sage.combinat.root_system.weyl_group` - :ref:`sage.combinat.root_system.extended_affine_weyl_group` - :ref:`sage.combinat.root_system.fundamental_group` +- :ref:`sage.combinat.root_system.braid_move_calculator` .. SEEALSO:: diff --git a/src/sage/combinat/root_system/braid_move_calculator.py b/src/sage/combinat/root_system/braid_move_calculator.py index 02f4e4b356e..608b33683ab 100644 --- a/src/sage/combinat/root_system/braid_move_calculator.py +++ b/src/sage/combinat/root_system/braid_move_calculator.py @@ -7,7 +7,7 @@ """ #***************************************************************************** -# Copyright (C) 2014 Dinakar Muthiah +# Copyright (C) 2014 Dinakar Muthiah # # 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 From 8dab19c10f1d828090934b1a4e7cf18e2a61e286 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sat, 3 Dec 2016 11:21:29 -0600 Subject: [PATCH 139/452] Removing trailing whitespace. --- src/sage/combinat/crystals/pbw_crystal.py | 10 +++++----- src/sage/combinat/crystals/pbw_datum.pyx | 16 ++++++++-------- .../root_system/braid_move_calculator.py | 10 +++++----- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/sage/combinat/crystals/pbw_crystal.py b/src/sage/combinat/crystals/pbw_crystal.py index 7f18dde0e3d..9185cc02913 100644 --- a/src/sage/combinat/crystals/pbw_crystal.py +++ b/src/sage/combinat/crystals/pbw_crystal.py @@ -61,7 +61,7 @@ def _repr_(self): sage: B = crystals.infinity.PBW(['B', 4]) sage: u = B.highest_weight_vector() sage: u.f_string([1,2,3,4,2,3,2,3,4,1,2]) - PBW monomial with Lusztig datum + PBW monomial with Lusztig datum (0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 1, 0, 1, 2) """ pbw_datum = self._pbw_datum.convert_to_new_long_word(self.parent()._default_word) @@ -229,8 +229,8 @@ def f(self, i): sage: c == b.f_string([1,2,4,1,2,3,3]) True """ - equiv_PBWDatum = self._pbw_datum.convert_to_long_word_with_first_letter(i) - new_long_word = equiv_PBWDatum.long_word + equiv_PBWDatum = self._pbw_datum.convert_to_long_word_with_first_letter(i) + new_long_word = equiv_PBWDatum.long_word new_lusztig_datum = list(equiv_PBWDatum.lusztig_datum) new_lusztig_datum[0] += 1 return type(self)(self.parent(), tuple(new_lusztig_datum), new_long_word) @@ -248,7 +248,7 @@ def epsilon(self, i): sage: s.epsilon(2) 0 """ - equiv_pbw_datum = self._pbw_datum.convert_to_long_word_with_first_letter(i) + equiv_pbw_datum = self._pbw_datum.convert_to_long_word_with_first_letter(i) return equiv_pbw_datum.lusztig_datum[0] def phi(self, i): @@ -397,7 +397,7 @@ def __init__(self, cartan_type): i = self._cartan_type.index_set()[0] self._default_word = self._pbw_datum_parent._long_word_begin_with(i) zero_lusztig_datum = [0]*len(self._default_word) - self.module_generators = (self.element_class(self, + self.module_generators = (self.element_class(self, zero_lusztig_datum, self._default_word),) diff --git a/src/sage/combinat/crystals/pbw_datum.pyx b/src/sage/combinat/crystals/pbw_datum.pyx index 7f706fb0d79..c9d7e01c6a4 100644 --- a/src/sage/combinat/crystals/pbw_datum.pyx +++ b/src/sage/combinat/crystals/pbw_datum.pyx @@ -64,7 +64,7 @@ class PBWDatum(object): cartan_type=self.parent.cartan_type) return_str += "long word {long_word} and Lusztig datum {lusztig_datum}".format( long_word=self.long_word, - lusztig_datum=self.lusztig_datum) + lusztig_datum=self.lusztig_datum) return return_str def __eq__(self, other_PBWDatum): @@ -104,7 +104,7 @@ class PBWDatum(object): other_lusztig_datum = other_pbw_datum.lusztig_datum equiv_pbw_datum = self.convert_to_new_long_word(other_long_word) return equiv_pbw_datum.lusztig_datum == other_lusztig_datum - + def convert_to_long_word_with_first_letter(self, i): r""" Return a new PBWDatum equivalent to ``self`` @@ -231,7 +231,7 @@ class PBWData(object): # UniqueRepresentation? @cached_method def _root_list_from(self, reduced_word): """ - Return the list of positive roots in the order determined by + Return the list of positive roots in the order determined by ``reduced_word``. .. WARNING:: @@ -293,7 +293,7 @@ cpdef tuple compute_new_lusztig_datum(enhanced_braid_chain, initial_lusztig_datu sage: B = BraidMoveCalculator(W) sage: chain = B.chain_of_reduced_words((1,2,1),(2,1,2)) sage: enhanced_braid_chain = enhance_braid_move_chain(chain, ct) - sage: compute_new_lusztig_datum(enhanced_braid_chain,(1,0,1)) + sage: compute_new_lusztig_datum(enhanced_braid_chain,(1,0,1)) (0, 1, 0) TESTS:: @@ -432,7 +432,7 @@ cpdef enhance_braid_move_chain(braid_move_chain, cartan_type): ....: (3, 1, 2, 1, 3, 2), ....: (3, 2, 1, 2, 3, 2), ....: (3, 2, 1, 3, 2, 3)] - sage: enhanced_chain = enhance_braid_move_chain(braid_chain, CartanType(["A",5])) + sage: enhanced_chain = enhance_braid_move_chain(braid_chain, CartanType(["A",5])) sage: enhanced_chain[0] (None, None) sage: enhanced_chain[7] @@ -457,9 +457,9 @@ cpdef enhance_braid_move_chain(braid_move_chain, cartan_type): return output_list cdef tuple diff_interval(tuple t1, tuple t2): - """ - Return the smallest contiguous half-open interval [a,b) - that contains the indices where ``list1`` and ``list2`` differ. + r""" + Return the smallest contiguous half-open interval `[a,b)` + that contains the indices where ``list1`` and ``list2`` differ. Return ``None`` if the lists don't differ. INPUT: diff --git a/src/sage/combinat/root_system/braid_move_calculator.py b/src/sage/combinat/root_system/braid_move_calculator.py index 608b33683ab..f2315d2a424 100644 --- a/src/sage/combinat/root_system/braid_move_calculator.py +++ b/src/sage/combinat/root_system/braid_move_calculator.py @@ -35,7 +35,7 @@ def __init__(self, coxeter_group): """ self.coxeter_matrix = coxeter_group.coxeter_matrix() - def _apply_put_in_front_recur_step(self, k, input_word, coxeter_matrix_entry): + def _apply_put_in_front_recur_step(self, k, input_word, coxeter_matrix_entry): """ Recurrence step for :meth:`put_in_front`. @@ -58,13 +58,13 @@ def partial_braid_word(length, swap=False, i=i, k=k): if length % 2 == 1: running_braid_word.append(i) return tuple(running_braid_word) - + current_last_word = input_word current_first_letter = k - output_word_list = [current_last_word] + output_word_list = [current_last_word] for counter in range(1, coxeter_matrix_entry): current_word_list = self.put_in_front(current_first_letter, current_last_word[1:]) - output_word_list += [partial_braid_word(counter) + word + output_word_list += [partial_braid_word(counter) + word for word in current_word_list[1:]] if current_first_letter == k: current_first_letter = i @@ -132,7 +132,7 @@ def chain_of_reduced_words(self, start_word, end_word): k = end_word[0] first_word_list = self.put_in_front(k, start_word) first_last_word = first_word_list[-1] - return (first_word_list[:-1] + + return (first_word_list[:-1] + tuple([ (k,) + word for word in self.chain_of_reduced_words(first_last_word[1:], end_word[1:]) ])) From f0071f55cba20bbd3b5d86e4e0067680dc3a2e6c Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sun, 16 Apr 2017 17:01:17 -0500 Subject: [PATCH 140/452] Adding more documentation and doing a bit more Cython tweaks. --- src/doc/en/reference/references/index.rst | 7 ++ src/sage/combinat/crystals/mv_polytopes.py | 111 ++++++++++++++++++++- src/sage/combinat/crystals/pbw_crystal.py | 26 ++++- src/sage/combinat/crystals/pbw_datum.pxd | 4 + src/sage/combinat/crystals/pbw_datum.pyx | 74 +++++++------- 5 files changed, 183 insertions(+), 39 deletions(-) create mode 100644 src/sage/combinat/crystals/pbw_datum.pxd diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 86a478ba3c7..55b1335b9f0 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -918,6 +918,13 @@ REFERENCES: .. [Kal1980] \T. Kaliath, "Linear Systems", Prentice-Hall, 1980, 383--386. +.. [Kam2007] Joel Kamnitzer, + *The crystal structure on the set of Mirković-Vilonen polytopes*, + Adv. Math. **215** (2007), 66-93. + +.. [Kam2010] Joel Kamnitzer, *Mirković-Vilonen cycles and polytopes*, + Ann. Math. (2) **171** (2010), 731-777. + .. [Kan1958] \D. M. Kan, *A combinatorial definition of homotopy groups*, Ann. Math. (2) 67 (1958), 282-312. diff --git a/src/sage/combinat/crystals/mv_polytopes.py b/src/sage/combinat/crystals/mv_polytopes.py index 7dc21b0cfc1..35cc0e1fab9 100644 --- a/src/sage/combinat/crystals/mv_polytopes.py +++ b/src/sage/combinat/crystals/mv_polytopes.py @@ -244,12 +244,121 @@ def plot(self, P=None, **options): return P.plot_mv_polytope(self, **options) class MVPolytopes(PBWCrystal): - """ + r""" The crystal of Mirković-Vilonen (MV) polytopes. + Let `W` denote the corresponding Weyl group and `P_{\RR} = \RR \otimes P`. + Let `\Gamma = \{ w \Lambda_i \mid w \in W, i \in I \}`. Consider + `M = (M_{\gamma} \in \ZZ)_{\gamma \in \Gamma}` that satisfy the + *tropical Plücker relations* (see Proposition 7.1 of [BZ01]_). + The *MV polytope* is defined as + + .. MATH:: + + P(M) = \{ \alpha \in P_{\RR} \mid + \langle \alpha, \gamma \rangle \geq M_{\gamma} + \text{ for all } \gamma \in \Gamma \}. + + The vertices `\(\mu_w\)_{w \in W}` are given by + + .. MATH:: + + \langle \mu_w, \gamma \rangle = M_{\gamma} + + and are known as the GGMS datum of the MV polytope. + + Each path from `\mu_e` to `\mu_{w_0}` corresponds to a reduced + expression `\mathbf{i} = (i_1, \ldots, i_m)` for `w_0` and the + corresponding edge lengths `(n_k)_{k=1}^m` from the Lusztig datum + with respect to `\mathbf{i}`. Explicitly, we have + + .. MATH:: + + \begin{aligned} + n_k & = -M_{w_{k-1} \Lambda_{i_k}} - M_{w_k \Lambda_{i_k}} + - \sum_{j \neq i} a_{ji} M_{w_k \Lambda_j}, + \\ \mu_{w_k} - \mu_{w_{k-1}} & = n_k w_{k-1} \alpha_{i_k}, + \end{aligned} + + where `w_k = s_{i_1} \cdots s_{i_k}` and `(a_{ji)` is the Cartan matrix. + + MV polytopes have a crystal structure that corresponds to the + crystal structure, which is isomorphic to `\mathcal{B}(\infty)` + with `\mu_{w_0} = 0`, on + :class:`PBW data `. + Specifically, we have `f_j P(M)` as being the unique MV polytope + given by shifting `\mu_e` by `-\alpha_j` and fixing the vertices + `\mu_w` when `s_j w < w` (in Bruhat order) and the weight is given by + `\mu_e`. Furthermore, the `*`-involution is given by negating `P(M)`. + INPUT: - ``cartan_type`` -- a Cartan type + + EXAMPLES:: + + sage: MV = crystals.infinity.MVPolytopes(['B', 3]) + sage: hw = MV.highest_weight_vector() + sage: x = hw.f_string([1,2,2,3,3,1,3,3,2,3,2,1,3,1,2,3,1,2,1,3,2]); x + MV polytope with Lusztig datum (1, 1, 1, 3, 1, 0, 0, 1, 1) + + Elements are expressed in terms of Lusztig datum for a fixed + reduced expression of `w_0`:: + + sage: MV.default_long_word() + [1, 3, 2, 3, 1, 2, 3, 1, 2] + sage: MV.set_default_long_word([2,1,3,2,1,3,2,3,1]) + sage: x + MV polytope with Lusztig datum (3, 1, 1, 0, 1, 0, 1, 3, 4) + sage: MV.set_default_long_word([1, 3, 2, 3, 1, 2, 3, 1, 2]) + + We can construct elements by giving it Lusztig data (with respect + to the default long word reduced expression):: + + sage: MV([1,1,1,3,1,0,0,1,1]) + MV polytope with Lusztig datum (1, 1, 1, 3, 1, 0, 0, 1, 1) + + We can also construct elements by passing in a reduced expression + for a long word:: + + sage: x = MV([1,1,1,3,1,0,0,1,1], [3,2,1,3,2,3,2,1,2]); x + MV polytope with Lusztig datum (1, 1, 1, 0, 1, 0, 5, 1, 1) + sage: x.to_highest_weight()[1] + [1, 2, 2, 2, 2, 2, 1, 3, 3, 3, 3, 2, 3, 2, 3, 3, 2, 3, 3, 2, 1, 3] + + The highest weight crystal `B(\lambda) \subseteq B(\infty)` is + characterized by the MV polytopes that sit inside of `W \lambda` + (translating `\mu_{w_0} \mapsto \lambda`):: + + sage: MV = crystals.infinity.MVPolytopes(['A',2]) + sage: La = MV.weight_lattice_realization().fundamental_weights() + sage: R = crystals.elementary.R(La[1]+La[2]) + sage: T = tensor([R, MV]) + sage: x = T(R.module_generators[0], MV.highest_weight_vector()) + sage: lw = x.to_lowest_weight()[0]; lw + [(2, 1, 0), MV polytope with Lusztig datum (1, 1, 1)] + sage: lw[1].polytope().vertices() + (A vertex at (0, 0, 0), + A vertex at (0, 1, -1), + A vertex at (1, -1, 0), + A vertex at (1, 1, -2), + A vertex at (2, -1, -1), + A vertex at (2, 0, -2)) + + .. PLOT:: + :width: 300 px + + MV = crystals.infinity.MVPolytopes(['A',2]) + x = MV.module_generators[0].f_string([1,2,2,1]) + L = RootSystem(['A',2,1]).ambient_space() + p = L.plot(bounding_box=[[-2,2],[-4,2]]) + x.plot() + p.axes(False) + sphinx_plot(x.plot()) + + REFERENCES: + + - [Kam2007]_ + - [Kam2010]_ """ def __init__(self, cartan_type): """ diff --git a/src/sage/combinat/crystals/pbw_crystal.py b/src/sage/combinat/crystals/pbw_crystal.py index 9185cc02913..4edb3576587 100644 --- a/src/sage/combinat/crystals/pbw_crystal.py +++ b/src/sage/combinat/crystals/pbw_crystal.py @@ -347,15 +347,39 @@ class PBWCrystal(Parent, UniqueRepresentation): A model of the crystal `\mathcal{B}(\infty)` whose elements are PBW datum up to equivalence by the tropical Plücker relations. + The crystal structure on Lusztig data `x = (x_1, \ldots, x_m)` + for the reduced word `s_{i_1} \cdots s_{i_m} = w_0` is given as + follows. Suppose `i_1 = j`, then `f_j x = (x_1 + 1, x_2, \ldots, x_m)`. + If `i_1 \neq j`, then we use the tropical Plücker relations to + change the reduced expression such that `i_1' = j` and then we + change back to the original word. EXAMPLES:: sage: PBW = crystals.infinity.PBW(['B', 3]) sage: hw = PBW.highest_weight_vector() - sage: hw.f_string([1,2,2,3,3,1,3,3,2,3,2,1,3,1,2,3,1,2,1,3,2]) + sage: x = hw.f_string([1,2,2,3,3,1,3,3,2,3,2,1,3,1,2,3,1,2,1,3,2]); x PBW monomial with Lusztig datum (1, 1, 1, 3, 1, 0, 0, 1, 1) + + Elements are expressed in terms of Lusztig datum for a fixed + reduced expression of `w_0`:: + + sage: PBW.default_long_word() + [1, 3, 2, 3, 1, 2, 3, 1, 2] + sage: PBW.set_default_long_word([2,1,3,2,1,3,2,3,1]) + sage: x + PBW monomial with Lusztig datum (3, 1, 1, 0, 1, 0, 1, 3, 4) + sage: PBW.set_default_long_word([1, 3, 2, 3, 1, 2, 3, 1, 2]) + + We can construct elements by giving it Lusztig data (with respect + to the default long word):: + sage: PBW([1,1,1,3,1,0,0,1,1]) PBW monomial with Lusztig datum (1, 1, 1, 3, 1, 0, 0, 1, 1) + + We can also construct elements by passing in a reduced expression + for a long word:: + sage: x = PBW([1,1,1,3,1,0,0,1,1], [3,2,1,3,2,3,2,1,2]); x PBW monomial with Lusztig datum (1, 1, 1, 0, 1, 0, 5, 1, 1) sage: x.to_highest_weight()[1] diff --git a/src/sage/combinat/crystals/pbw_datum.pxd b/src/sage/combinat/crystals/pbw_datum.pxd new file mode 100644 index 00000000000..039c197ea90 --- /dev/null +++ b/src/sage/combinat/crystals/pbw_datum.pxd @@ -0,0 +1,4 @@ +cpdef tuple compute_new_lusztig_datum(list enhanced_braid_chain, initial_lusztig_datum) +cpdef tuple tropical_plucker_relation(tuple a, lusztig_datum) +cpdef list enhance_braid_move_chain(braid_move_chain, cartan_type) + diff --git a/src/sage/combinat/crystals/pbw_datum.pyx b/src/sage/combinat/crystals/pbw_datum.pyx index c9d7e01c6a4..5eb504ad1db 100644 --- a/src/sage/combinat/crystals/pbw_datum.pyx +++ b/src/sage/combinat/crystals/pbw_datum.pyx @@ -29,6 +29,8 @@ from sage.combinat.root_system.coxeter_group import CoxeterGroup from sage.combinat.root_system.root_system import RootSystem from sage.combinat.root_system.braid_move_calculator import BraidMoveCalculator +cimport cython + class PBWDatum(object): """ Helper class which represents a PBW datum. @@ -223,7 +225,7 @@ class PBWData(object): # UniqueRepresentation? assert pbw_datum.parent is self chain = self._braid_move_calc.chain_of_reduced_words(pbw_datum.long_word, new_long_word) - enhanced_braid_chain = enhance_braid_move_chain(chain, self.cartan_type) + cdef list enhanced_braid_chain = enhance_braid_move_chain(chain, self.cartan_type) new_lusztig_datum = compute_new_lusztig_datum(enhanced_braid_chain, pbw_datum.lusztig_datum) return PBWDatum(self, new_long_word, new_lusztig_datum) @@ -277,7 +279,9 @@ class PBWData(object): # UniqueRepresentation? return tuple([i] + (si * w0).reduced_word()) #enhanced_braid_chain is an ugly data structure. -cpdef tuple compute_new_lusztig_datum(enhanced_braid_chain, initial_lusztig_datum): +@cython.boundscheck(False) +@cython.wraparound(False) +cpdef tuple compute_new_lusztig_datum(list enhanced_braid_chain, initial_lusztig_datum): """ Return the lusztig datum obtained by applying tropical Plücker relations along ``enhanced_braid_chain`` starting with @@ -312,7 +316,9 @@ cpdef tuple compute_new_lusztig_datum(enhanced_braid_chain, initial_lusztig_datu cdef tuple interval_of_change # Does not currently check that len(initial_lusztig_datum) is appropriate cdef list new_lusztig_datum = list(initial_lusztig_datum) #shallow copy - for interval_of_change, type_data in enhanced_braid_chain[1:]: + cdef int i + for i in range(1, len(enhanced_braid_chain)): + interval_of_change, type_data = enhanced_braid_chain[i] a,b = interval_of_change old_interval_datum = new_lusztig_datum[a:b] new_interval_datum = tropical_plucker_relation(type_data, old_interval_datum) @@ -320,6 +326,8 @@ cpdef tuple compute_new_lusztig_datum(enhanced_braid_chain, initial_lusztig_datu return tuple(new_lusztig_datum) # The tropical plucker relations +@cython.boundscheck(False) +@cython.wraparound(False) cpdef tuple tropical_plucker_relation(tuple a, lusztig_datum): r""" Apply the tropical Plücker relation of type ``a`` to ``lusztig_datum``. @@ -390,7 +398,9 @@ cpdef tuple tropical_plucker_relation(tuple a, lusztig_datum): # Maybe we need to be more specific, and pass not the Cartan type, but the root lattice? # TODO: Move to PBW_data? -cpdef enhance_braid_move_chain(braid_move_chain, cartan_type): +@cython.boundscheck(False) +@cython.wraparound(False) +cpdef list enhance_braid_move_chain(braid_move_chain, cartan_type): r""" Return a list of tuples that records the data of the long words in ``braid_move_chain`` plus the data of the intervals where the braid moves @@ -439,46 +449,36 @@ cpdef enhance_braid_move_chain(braid_move_chain, cartan_type): ((3, 6), (-1, -1)) """ cdef int i, j + cdef int k, pos, first, last cdef tuple interval_of_change, cartan_sub_matrix cdef list output_list = [] output_list.append( (None, None) ) - previous_word = braid_move_chain[0] + cdef tuple previous_word = (braid_move_chain[0]) + cdef tuple current_word cartan_matrix = cartan_type.cartan_matrix() - # TODO - Optimize this by avoiding calls to diff_interval? + cdef int ell = len(previous_word) + # TODO - Optimize this by avoiding calls to here? # This likely could be done when performing chain_of_reduced_words # Things in here get called the most (about 50x more than enhance_braid_move_chain) - for current_word in braid_move_chain[1:]: - interval_of_change = diff_interval(previous_word, current_word) - i = previous_word[interval_of_change[0]] - 1 # -1 for indexing - j = current_word[interval_of_change[0]] - 1 # -1 for indexing + for pos in range(1, len(braid_move_chain)): + # This gets the smallest continguous half-open interval [a, b) + # that contains the indices where current_word and previous_word differ. + current_word = (braid_move_chain[pos]) + for k in range(ell): + i = previous_word[k] + j = current_word[k] + if i != j: + i -= 1 # -1 for indexing + j -= 1 # -1 for indexing + first = k + break + for k in range(ell-1, k-1, -1): + if previous_word[k] != current_word[k]: + last = k + 1 + break + cartan_sub_matrix = (cartan_matrix[i,j], cartan_matrix[j,i]) - output_list.append( (interval_of_change, cartan_sub_matrix) ) + output_list.append( ((first, last), cartan_sub_matrix) ) previous_word = current_word return output_list -cdef tuple diff_interval(tuple t1, tuple t2): - r""" - Return the smallest contiguous half-open interval `[a,b)` - that contains the indices where ``list1`` and ``list2`` differ. - Return ``None`` if the lists don't differ. - - INPUT: - - - ``t1``, ``t2`` -- two tuples of the same length - - .. NOTE:: - - The input is not checked for speed. - """ - cdef int first = -1 # Set when >= 0 - cdef int last - cdef int i, elt - for i,elt in enumerate(t1): - if elt != t2[i]: - if first == -1: - first = i - last = i - if first == -1: - return None - return (first, last + 1) - From f42be53b8e0f7f594a077c4e67157ffa653123e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 17 Apr 2017 10:40:40 +0200 Subject: [PATCH 141/452] trac 22729 some doc details and code formatting --- .../modular/overconvergent/hecke_series.py | 37 +++++++++++-------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/src/sage/modular/overconvergent/hecke_series.py b/src/sage/modular/overconvergent/hecke_series.py index 1b91ded6349..b62578106df 100644 --- a/src/sage/modular/overconvergent/hecke_series.py +++ b/src/sage/modular/overconvergent/hecke_series.py @@ -670,12 +670,15 @@ def hecke_series_degree_bound(p,N,k,m): # Returns matrix A modulo p^m from Step 6 of Algorithm 2. -def higher_level_UpGj(p,N,klist,m,modformsring,bound,extra_data=False): +def higher_level_UpGj(p, N, klist, m, modformsring, bound, extra_data=False): r""" - Returns a list ``[A_k]`` of square matrices over ``IntegerRing(p^m)`` - parameterised by the weights k in ``klist``. The matrix `A_k` is the finite - square matrix which occurs on input p,k,N and m in Step 6 of Algorithm 2 in - [Lau2011]_. Notational change from paper: In Step 1 following Wan we defined + Return a list ``[A_k]`` of square matrices over ``IntegerRing(p^m)`` + parameterised by the weights k in ``klist``. + + The matrix `A_k` is the finite square matrix which occurs on input + p, k, N and m in Step 6 of Algorithm 2 in [Lau2011]_. + + Notational change from paper: In Step 1 following Wan we defined j by `k = k_0 + j(p-1)` with `0 \le k_0 < p-1`. Here we replace j by ``kdiv`` so that we may use j as a column index for matrices.) @@ -685,14 +688,15 @@ def higher_level_UpGj(p,N,klist,m,modformsring,bound,extra_data=False): - ``N`` -- integer at least 2 and not divisible by p (level). - ``klist`` -- list of integers all congruent modulo (p-1) (the weights). - ``m`` -- positive integer. - - ``modformsring`` -- True or False. + - ``modformsring`` -- ``True`` or ``False``. - ``bound`` -- (even) positive integer. - - ``extra_data`` -- (default: False) True or False. + - ``extra_data`` -- (default: ``False``) boolean. OUTPUT: - - list of square matrices. If extra_data is True, return also extra intermediate - data, namely the matrix E in [Lau2011] and the integers elldash and mdash. + - list of square matrices. If ``extra_data`` is ``True``, return also + extra intermediate data, namely the matrix `E` in [Lau2011]_ and + the integers ``elldash`` and ``mdash``. EXAMPLES:: @@ -718,11 +722,12 @@ def higher_level_UpGj(p,N,klist,m,modformsring,bound,extra_data=False): elldashp = elldash*p mdash = m + ceil(n/(p+1)) - verbose("done step 1",t) + verbose("done step 1", t) t = cputime() # Steps 2 and 3 - e,Ep1 = higher_level_katz_exp(p,N,k0,m,mdash,elldash,elldashp,modformsring,bound) + e, Ep1 = higher_level_katz_exp(p, N, k0, m, mdash, elldash, elldashp, + modformsring, bound) ell = dimension(transpose(e)[0].parent()) S = e[0,0].parent() @@ -756,14 +761,14 @@ def higher_level_UpGj(p,N,klist,m,modformsring,bound,extra_data=False): # a solution over Z/(p^mdash). This has always been the case in # examples computed by the author, see Note 3.1. - A = matrix(S,ell,ell) + A = matrix(S, ell, ell) verbose("solving a square matrix problem of dimension %s" % ell) verbose("elldash is %s" % elldash) - for i in range(0,ell): + for i in range(ell): Ti = T[i] - for j in range(0,ell): - ej = Ti.parent()([e[j][l] for l in range(0,elldash)]) + for j in range(ell): + ej = Ti.parent()([e[j][l] for l in range(elldash)]) ejleadpos = ej.nonzero_positions()[0] lj = ZZ(ej[ejleadpos]) A[i,j] = S(ZZ(Ti[j])/lj) @@ -772,7 +777,7 @@ def higher_level_UpGj(p,N,klist,m,modformsring,bound,extra_data=False): Alist.append(MatrixSpace(Zmod(p**m),ell,ell)(A)) verbose("done step 6", t) - if extra_data == True: + if extra_data: return Alist, e, elldash, mdash else: return Alist From aa3e71fda2926a11883dcf24a568637f2d4f86f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 17 Apr 2017 10:46:30 +0200 Subject: [PATCH 142/452] trac 22729 more doc and code details --- .../modular/overconvergent/hecke_series.py | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/sage/modular/overconvergent/hecke_series.py b/src/sage/modular/overconvergent/hecke_series.py index b62578106df..8590272dff2 100644 --- a/src/sage/modular/overconvergent/hecke_series.py +++ b/src/sage/modular/overconvergent/hecke_series.py @@ -926,12 +926,15 @@ def katz_expansions(k0,p,ellp,mdash,n): # *** MAIN FUNCTION FOR LEVEL 1 *** -def level1_UpGj(p,klist,m,extra_data=False): +def level1_UpGj(p, klist, m, extra_data=False): r""" - Returns a list `[A_k]` of square matrices over ``IntegerRing(p^m)`` - parameterised by the weights k in ``klist``. The matrix `A_k` is the finite - square matrix which occurs on input p,k and m in Step 6 of Algorithm 1 in - [Lau2011]_. Notational change from paper: In Step 1 following Wan we defined + Return a list `[A_k]` of square matrices over ``IntegerRing(p^m)`` + parameterised by the weights k in ``klist``. + + The matrix `A_k` is the finite square matrix which occurs on input + p, k and m in Step 6 of Algorithm 1 in [Lau2011]_. + + Notational change from paper: In Step 1 following Wan we defined j by `k = k_0 + j(p-1)` with `0 \le k_0 < p-1`. Here we replace j by ``kdiv`` so that we may use j as a column index for matrices. @@ -940,12 +943,13 @@ def level1_UpGj(p,klist,m,extra_data=False): - ``p`` -- prime at least 5. - ``klist`` -- list of integers congruent modulo `(p-1)` (the weights). - ``m`` -- positive integer. - - ``extra_data`` -- (default: False) True or False. + - ``extra_data`` -- (default: ``False``) boolean OUTPUT: - - list of square matrices. If extra_data is True, return also extra intermediate - data, namely the matrix E in [Lau2011] and the integers elldash and mdash. + - list of square matrices. If ``extra_data`` is ``True``, return also + extra intermediate data, namely the matrix `E` in [Lau2011]_ and + the integers ``elldash`` and ``mdash``. EXAMPLES:: @@ -1028,7 +1032,7 @@ def level1_UpGj(p,klist,m,extra_data=False): Alist.append(MatrixSpace(Zmod(p**m),ell,ell)(A)) verbose("done step 6", t) - if extra_data == True: + if extra_data: return Alist, e, ell, mdash else: return Alist From 6229d3fd786865a39a467042c1a4dcdeab6e008c Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Mon, 17 Apr 2017 14:56:41 -0500 Subject: [PATCH 143/452] Fixing doctests by simplifying hash. --- .../lie/affine_finite_crystals.rst | 2 +- .../en/thematic_tutorials/lie/crystals.rst | 2 +- src/sage/categories/crystals.py | 38 +++++++++---------- .../categories/highest_weight_crystals.py | 2 +- .../combinat/crystals/elementary_crystals.py | 2 +- .../combinat/crystals/kirillov_reshetikhin.py | 16 ++++---- src/sage/combinat/crystals/subcrystal.py | 2 +- src/sage/combinat/crystals/tensor_product.py | 1 - .../crystals/tensor_product_element.pyx | 16 ++++++++ .../tensor_product_kr_tableaux.py | 4 +- 10 files changed, 50 insertions(+), 35 deletions(-) diff --git a/src/doc/en/thematic_tutorials/lie/affine_finite_crystals.rst b/src/doc/en/thematic_tutorials/lie/affine_finite_crystals.rst index 0c456e1b19c..305590cf9fc 100644 --- a/src/doc/en/thematic_tutorials/lie/affine_finite_crystals.rst +++ b/src/doc/en/thematic_tutorials/lie/affine_finite_crystals.rst @@ -68,7 +68,7 @@ the methods ``lift`` and ``retract``:: sage: b.lift() [[1], [3]] sage: type(b.lift()) - + sage: b = crystals.Tableaux(['A',3], shape = [1,1])(rows=[[1],[3]]) sage: K.retract(b) diff --git a/src/doc/en/thematic_tutorials/lie/crystals.rst b/src/doc/en/thematic_tutorials/lie/crystals.rst index 77ba5c45e4b..8047c549a1f 100644 --- a/src/doc/en/thematic_tutorials/lie/crystals.rst +++ b/src/doc/en/thematic_tutorials/lie/crystals.rst @@ -772,7 +772,7 @@ You can see how its done as follows:: sage: T = crystals.Tableaux("A4",shape=[3,2]) sage: v = T.highest_weight_vector().f(1).f(2).f(3).f(2).f(1).f(4).f(2).f(3); v [[1, 2, 5], [3, 4]] - sage: v._list + sage: list(v) [3, 1, 4, 2, 5] We've looked at the internal representation of `v`, where it is diff --git a/src/sage/categories/crystals.py b/src/sage/categories/crystals.py index 08ad389ccda..35e7caa2fe5 100644 --- a/src/sage/categories/crystals.py +++ b/src/sage/categories/crystals.py @@ -391,9 +391,9 @@ def subcrystal(self, index_set=None, generators=None, max_depth=float("inf"), sage: len(S) 6 sage: list(C.subcrystal(index_set=[1,3], generators=[C(1,4)])) - [[[1, 4]], [[2, 4]], [[1, 3]], [[2, 3]]] + [[[1, 4]], [[1, 3]], [[2, 4]], [[2, 3]]] sage: list(C.subcrystal(index_set=[1,3], generators=[C(1,4)], max_depth=1)) - [[[1, 4]], [[2, 4]], [[1, 3]]] + [[[1, 4]], [[1, 3]], [[2, 4]]] sage: list(C.subcrystal(index_set=[1,3], generators=[C(1,4)], direction='upper')) [[[1, 4]], [[1, 3]]] sage: list(C.subcrystal(index_set=[1,3], generators=[C(1,4)], direction='lower')) @@ -592,7 +592,7 @@ def crystal_morphism(self, on_gens, codomain=None, [The crystal of tableaux of type ['A', 2] and shape(s) [[1]], The crystal of tableaux of type ['A', 2] and shape(s) [[1]], The crystal of tableaux of type ['A', 2] and shape(s) [[1]]] - Defn: [2, 1, 1] |--> [[[1]], [[2]], [[1]]] + Defn: [[1, 1], [2]] |--> [[[1]], [[2]], [[1]]] sage: b = B.module_generators[0] sage: b.pp() 1 1 @@ -634,7 +634,7 @@ def crystal_morphism(self, on_gens, codomain=None, ['D', 4] -> ['D', 4, 1] Virtual Crystal morphism: From: The crystal of tableaux of type ['D', 4] and shape(s) [[1, 1]] To: Kirillov-Reshetikhin crystal of type ['D', 4, 1] with (r,s)=(2,2) - Defn: [2, 1] |--> [[1], [2]] + Defn: [[1], [2]] |--> [[1], [2]] sage: b = B.module_generators[0] sage: psi(b) [[1], [2]] @@ -1655,9 +1655,9 @@ def subcrystal(self, index_set=None, max_depth=float("inf"), direction="both", sage: C = crystals.KirillovReshetikhin(['A',3,1], 1, 2) sage: elt = C(1,4) sage: list(elt.subcrystal(index_set=[1,3])) - [[[1, 4]], [[2, 4]], [[1, 3]], [[2, 3]]] + [[[1, 4]], [[1, 3]], [[2, 4]], [[2, 3]]] sage: list(elt.subcrystal(index_set=[1,3], max_depth=1)) - [[[1, 4]], [[2, 4]], [[1, 3]]] + [[[1, 4]], [[1, 3]], [[2, 4]]] sage: list(elt.subcrystal(index_set=[1,3], direction='upper')) [[[1, 4]], [[1, 3]]] sage: list(elt.subcrystal(index_set=[1,3], direction='lower')) @@ -1990,8 +1990,8 @@ def _repr_defn(self): sage: psi = H((None, b, b, None), generators=T.highest_weight_vectors()) sage: print(psi._repr_defn()) [[[1]], [[1]], [[1]]] |--> None - [[[2]], [[1]], [[1]]] |--> [2, 1, 1] - [[[1]], [[2]], [[1]]] |--> [2, 1, 1] + [[[2]], [[1]], [[1]]] |--> [[1, 1], [2]] + [[[1]], [[2]], [[1]]] |--> [[1, 1], [2]] [[[3]], [[2]], [[1]]] |--> None """ return '\n'.join(['{} |--> {}'.format(mg, im) @@ -2314,7 +2314,7 @@ class CrystalHomset(Homset): To: Direct sum of the crystals Family (The crystal of tableaux of type ['A', 1] and shape(s) [[2]], The crystal of tableaux of type ['A', 1] and shape(s) [[]]) - Defn: [[[1]], [[1]]] |--> [1, 1] + Defn: [[[1]], [[1]]] |--> [[1, 1]] [[[2]], [[1]]] |--> [] sage: psi.is_isomorphism() True @@ -2368,15 +2368,15 @@ class CrystalHomset(Homset): ['B', 3] -> ['D', 4] Virtual Crystal morphism: From: The crystal of tableaux of type ['B', 3] and shape(s) [[1]] To: The crystal of tableaux of type ['D', 4] and shape(s) [[2]] - Defn: [1] |--> [1, 1] + Defn: [[1]] |--> [[1, 1]] sage: for b in B: print("{} |--> {}".format(b, psi(b))) - [1] |--> [1, 1] - [2] |--> [2, 2] - [3] |--> [3, 3] - [0] |--> [3, -3] - [-3] |--> [-3, -3] - [-2] |--> [-2, -2] - [-1] |--> [-1, -1] + [[1]] |--> [[1, 1]] + [[2]] |--> [[2, 2]] + [[3]] |--> [[3, 3]] + [[0]] |--> [[3, -3]] + [[-3]] |--> [[-3, -3]] + [[-2]] |--> [[-2, -2]] + [[-1]] |--> [[-1, -1]] """ def __init__(self, X, Y, category=None): """ @@ -2416,7 +2416,7 @@ def _coerce_impl(self, x): sage: H = Hom(B, B) sage: H(H.an_element()) # indirect doctest ['B', 3] Crystal endomorphism of The crystal of tableaux of type ['B', 3] and shape(s) [[2, 1]] - Defn: [2, 1, 1] |--> None + Defn: [[1, 1], [2]] |--> None """ if not isinstance(x, CrystalMorphism): raise TypeError @@ -2502,7 +2502,7 @@ def _an_element_(self): ['A', 2] Crystal morphism: From: The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]] To: The infinity crystal of tableaux of type ['A', 2] - Defn: [2, 1, 1] |--> None + Defn: [[1, 1], [2]] |--> None """ return self.element_class(self, lambda x: None) diff --git a/src/sage/categories/highest_weight_crystals.py b/src/sage/categories/highest_weight_crystals.py index 0a38a5691a3..b247ce0ea84 100644 --- a/src/sage/categories/highest_weight_crystals.py +++ b/src/sage/categories/highest_weight_crystals.py @@ -837,7 +837,7 @@ def _call_(self, x): [The T crystal of type ['A', 2] and weight Lambda[2], The crystal of tableaux of type ['A', 2] and shape(s) [[1]]] To: The crystal of tableaux of type ['A', 2] and shape(s) [[2, 1]] - Defn: [Lambda[2], [[3]]] |--> [2, 1, 3] + Defn: [Lambda[2], [[3]]] |--> [[1, 3], [2]] sage: psi(Bp.highest_weight_vector()) [[1, 1], [2]] """ diff --git a/src/sage/combinat/crystals/elementary_crystals.py b/src/sage/combinat/crystals/elementary_crystals.py index 9f2d10eb0d1..177bf3de3fc 100644 --- a/src/sage/combinat/crystals/elementary_crystals.py +++ b/src/sage/combinat/crystals/elementary_crystals.py @@ -474,8 +474,8 @@ class RCrystal(UniqueRepresentation, Parent): (1, 2, 0) (1, 1, 1) (1, 1, 1) - (1, 0, 2) (0, 2, 1) + (1, 0, 2) (0, 1, 2) sage: C = crystals.Tableaux("A2", shape=[2,1]) sage: for x in C: x.weight() diff --git a/src/sage/combinat/crystals/kirillov_reshetikhin.py b/src/sage/combinat/crystals/kirillov_reshetikhin.py index f8e82f6cf88..7cbc76906a6 100644 --- a/src/sage/combinat/crystals/kirillov_reshetikhin.py +++ b/src/sage/combinat/crystals/kirillov_reshetikhin.py @@ -1411,10 +1411,10 @@ def highest_weight_dict(self): sage: K = crystals.KirillovReshetikhin(['E',6,1],2,1) sage: K.highest_weight_dict() - {[]: ((0, 0, 0, 0, 0, 0, 0), 0), - [[(2, -1), (1,)]]: ((-2, 0, 1, 0, 0, 0, 0), 1), - [[(6, -2), (-6, 2)]]: ((0, 0, 0, 0, 0, 0, 0), 1), + {[[(2, -1), (1,)]]: ((-2, 0, 1, 0, 0, 0, 0), 1), [[(3, -1, -6), (1,)]]: ((-1, 0, 0, 1, 0, 0, -1), 1), + []: ((0, 0, 0, 0, 0, 0, 0), 0), + [[(6, -2), (-6, 2)]]: ((0, 0, 0, 0, 0, 0, 0), 1), [[(5, -2, -6), (-6, 2)]]: ((0, 0, 0, 0, 0, 1, -2), 1)} """ hw = [x for x in self.hw_auxiliary() if x.epsilon(1) == 0] @@ -1452,10 +1452,10 @@ def automorphism_on_affine_weight(self, weight): sage: K = crystals.KirillovReshetikhin(['E',6,1],2,1) sage: [[x[0], K.automorphism_on_affine_weight(x[0])] for x in K.highest_weight_dict().values()] - [[(0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0)], + [[(-1, 0, 0, 1, 0, 0, -1), (-1, -1, 0, 0, 0, 1, 0)], + [(0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0)], [(0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0)], [(-2, 0, 1, 0, 0, 0, 0), (0, -2, 0, 1, 0, 0, 0)], - [(-1, 0, 0, 1, 0, 0, -1), (-1, -1, 0, 0, 0, 1, 0)], [(0, 0, 0, 0, 0, 1, -2), (-2, 0, 1, 0, 0, 0, 0)]] """ f = self.dynkin_diagram_automorphism @@ -1472,10 +1472,10 @@ def promotion_on_highest_weight_vectors(self): sage: K = crystals.KirillovReshetikhin(['E',6,1],2,1) sage: dic = K.promotion_on_highest_weight_vectors() sage: dic - {[]: [[(1, -3), (-1, 3)]], - [[(2, -1), (1,)]]: [[(-1,), (-1, 3)]], - [[(6, -2), (-6, 2)]]: [], + {[[(2, -1), (1,)]]: [[(-1,), (-1, 3)]], [[(3, -1, -6), (1,)]]: [[(5, -3), (-1, 3)]], + []: [[(1, -3), (-1, 3)]], + [[(6, -2), (-6, 2)]]: [], [[(5, -2, -6), (-6, 2)]]: [[(2, -1), (1,)]]} """ dic = self.highest_weight_dict() diff --git a/src/sage/combinat/crystals/subcrystal.py b/src/sage/combinat/crystals/subcrystal.py index 6bedd570fca..476fa40907c 100644 --- a/src/sage/combinat/crystals/subcrystal.py +++ b/src/sage/combinat/crystals/subcrystal.py @@ -84,8 +84,8 @@ class Subcrystal(UniqueRepresentation, Parent): [[[1, 1], [3]], [[1, 1], [2]], [[1, 2], [3]], - [[1, 2], [2]], [[2, 2], [3]], + [[1, 2], [2]], [[2, 3], [3]], [[1, 3], [2]], [[1, 3], [3]]] diff --git a/src/sage/combinat/crystals/tensor_product.py b/src/sage/combinat/crystals/tensor_product.py index 87b6c9082d4..1ef9760a8b1 100644 --- a/src/sage/combinat/crystals/tensor_product.py +++ b/src/sage/combinat/crystals/tensor_product.py @@ -1149,7 +1149,6 @@ def to_classical_hw(cur): return self._known_values[x] - # deprecations from trac:18555 from sage.misc.superseded import deprecated_function_alias TensorProductOfCrystals.global_options=deprecated_function_alias(18555, TensorProductOfCrystals.options) diff --git a/src/sage/combinat/crystals/tensor_product_element.pyx b/src/sage/combinat/crystals/tensor_product_element.pyx index c9f93c0baf8..b314ea8bf67 100644 --- a/src/sage/combinat/crystals/tensor_product_element.pyx +++ b/src/sage/combinat/crystals/tensor_product_element.pyx @@ -57,6 +57,18 @@ cdef class ImmutableListWithParent(ClonableArray): """ ClonableArray.__init__(self, parent, list, check=False) + cpdef long _hash_(self) except? -1: + """ + Return the hash of ``self``. + + TESTS:: + + sage: b = crystals.Tableaux(['A',2], shape=[2,1]).module_generators[0] + sage: b._hash_() == hash(b) + True + """ + return hash(tuple(self._list)) + def reversed(self): """ Return a copy of ``self`` but in the reversed order. @@ -1329,3 +1341,7 @@ cdef class InfinityCrystalOfTableauxElementTypeD(InfinityCrystalOfTableauxElemen ret._list.insert(0, self._parent.letters(j+1)) return ret +# for unpickling +from sage.structure.sage_object import register_unpickle_override +register_unpickle_override('sage.combinat.crystals.tensor_product', 'ImmutableListWithParent', ImmutableListWithParent) + diff --git a/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py b/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py index ec300a227c5..5b4ac01976a 100644 --- a/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py +++ b/src/sage/combinat/rigged_configurations/tensor_product_kr_tableaux.py @@ -330,9 +330,9 @@ def __iter__(self): sage: KRT = crystals.TensorProductOfKirillovReshetikhinTableaux(['A', 3, 1], [[2,1], [1,1]]) sage: g = KRT.__iter__() sage: next(g) - [[1], [2]] (X) [[1]] + [[2], [3]] (X) [[1]] sage: next(g) - [[1], [2]] (X) [[2]] + [[2], [4]] (X) [[1]] """ index_set = self._cartan_type.classical().index_set() from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet From 7b5155386073f973e52134ced95a028eb72ce0fb Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Mon, 17 Apr 2017 18:13:00 -0500 Subject: [PATCH 144/452] Fixing unpickling old pickles and removing readded TestParent. --- src/sage/combinat/crystals/tensor_product.py | 6 +++--- .../combinat/crystals/tensor_product_element.pyx | 14 ++++++++++++++ 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/sage/combinat/crystals/tensor_product.py b/src/sage/combinat/crystals/tensor_product.py index 1ef9760a8b1..b36bdf37f4e 100644 --- a/src/sage/combinat/crystals/tensor_product.py +++ b/src/sage/combinat/crystals/tensor_product.py @@ -160,6 +160,8 @@ def one_dimensional_configuration_sum(self, q=None, group_components=True): return sum(q**(c[0].energy_function())*B.sum(B(P0(b.weight())) for b in c) for c in C) return B.sum(q**(b.energy_function())*B(P0(b.weight())) for b in self) + Element = TensorProductOfCrystalsElement + class TensorProductOfCrystals(CrystalOfWords): r""" @@ -549,7 +551,7 @@ def __init__(self, crystals, generators, cartan_type): Parent.__init__(self, category = category) self.crystals = crystals self._cartan_type = cartan_type - self.module_generators = [ self(*x) for x in generators ] + self.module_generators = tuple([self(*x) for x in generators]) def _repr_(self): """ @@ -673,8 +675,6 @@ def weight_lattice_realization(self): return cm.common_parent(*[crystal.weight_lattice_realization() for crystal in self.crystals]) -CrystalOfWords.Element = TensorProductOfCrystalsElement - class FullTensorProductOfRegularCrystals(FullTensorProductOfCrystals): """ Full tensor product of regular crystals. diff --git a/src/sage/combinat/crystals/tensor_product_element.pyx b/src/sage/combinat/crystals/tensor_product_element.pyx index b314ea8bf67..1b47b73082b 100644 --- a/src/sage/combinat/crystals/tensor_product_element.pyx +++ b/src/sage/combinat/crystals/tensor_product_element.pyx @@ -69,6 +69,20 @@ cdef class ImmutableListWithParent(ClonableArray): """ return hash(tuple(self._list)) + def __setstate__(self, state): + """ + For unpickling old pickles. + + EXAMPLES:: + + sage: T = crystals.Tableaux(['A',2], shape=[2,1]) + sage: b = T.module_generators[0] + sage: b.__setstate__([T, {'_list': list(b)}]) + """ + self._parent = state[0] + self._list = state[1]['_list'] + self._is_immutable = True + def reversed(self): """ Return a copy of ``self`` but in the reversed order. From cfc5218e125bee556f56e5b5dd83c14b4e77268d Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Mon, 17 Apr 2017 19:14:36 -0500 Subject: [PATCH 145/452] Some small tweaks from Anne's comments. --- .../crystals/tensor_product_element.pyx | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/sage/combinat/crystals/tensor_product_element.pyx b/src/sage/combinat/crystals/tensor_product_element.pyx index 1b47b73082b..e6a43c8b53b 100644 --- a/src/sage/combinat/crystals/tensor_product_element.pyx +++ b/src/sage/combinat/crystals/tensor_product_element.pyx @@ -1,5 +1,5 @@ """ -Tensor Products of Crystals Elements +Tensor Products of Crystal Elements AUTHORS: @@ -304,7 +304,7 @@ cdef class TensorProductOfCrystalsElement(ImmutableListWithParent): INPUT: - - ``i`` -- An element of the index set + - ``i`` -- an element of the index set EXAMPLES:: @@ -324,7 +324,7 @@ cdef class TensorProductOfCrystalsElement(ImmutableListWithParent): INPUT: - - ``i`` -- An element of the index set + - ``i`` -- an element of the index set EXAMPLES:: @@ -372,9 +372,9 @@ cdef class TensorProductOfCrystalsElement(ImmutableListWithParent): INPUT: - - ``i`` -- An element of the index set + - ``i`` -- an element of the index set - - ``k`` -- The (1-based) index of the tensor factor of ``self`` + - ``k`` -- the (1-based) index of the tensor factor of ``self`` EXAMPLES:: @@ -419,7 +419,7 @@ cdef class TensorProductOfCrystalsElement(ImmutableListWithParent): INPUT: - - ``i`` -- An element of the index set + - ``i`` -- an element of the index set EXAMPLES:: @@ -452,7 +452,7 @@ cdef class TensorProductOfCrystalsElement(ImmutableListWithParent): INPUT: - - ``i`` -- An element of the index set + - ``i`` -- an element of the index set EXAMPLES:: @@ -1203,7 +1203,7 @@ cdef class InfinityCrystalOfTableauxElement(CrystalOfTableauxElement): INPUT: - - ``i`` -- An element of the index set + - ``i`` -- an element of the index set EXAMPLES:: @@ -1241,7 +1241,7 @@ cdef class InfinityCrystalOfTableauxElement(CrystalOfTableauxElement): INPUT: - - ``i`` -- An element of the index set + - ``i`` -- an element of the index set EXAMPLES:: @@ -1287,7 +1287,7 @@ cdef class InfinityCrystalOfTableauxElementTypeD(InfinityCrystalOfTableauxElemen INPUT: - - ``i`` -- An element of the index set + - ``i`` -- an element of the index set EXAMPLES:: @@ -1326,7 +1326,7 @@ cdef class InfinityCrystalOfTableauxElementTypeD(InfinityCrystalOfTableauxElemen INPUT: - - ``i`` -- An element of the index set + - ``i`` -- an element of the index set EXAMPLES:: From 54fbc405725523afe4842778462bfa7e08c712c0 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 19 Apr 2017 13:23:32 -0500 Subject: [PATCH 146/452] Hopefully taking care of last doctest failures. --- src/sage/categories/crystals.py | 2 +- .../combinat/crystals/elementary_crystals.py | 4 ++-- .../combinat/crystals/kirillov_reshetikhin.py | 8 ++++---- src/sage/combinat/crystals/tensor_product.py | 19 +++++++++++-------- .../crystals/tensor_product_element.pyx | 1 + 5 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/sage/categories/crystals.py b/src/sage/categories/crystals.py index 35e7caa2fe5..f470192f1e3 100644 --- a/src/sage/categories/crystals.py +++ b/src/sage/categories/crystals.py @@ -1139,7 +1139,7 @@ def tensor(self, *crystals, **options): The crystal of letters for type ['A', 2], The crystal of letters for type ['A', 2]] sage: T.module_generators - [[2, 1, 1], [1, 2, 1]] + ([2, 1, 1], [1, 2, 1]) """ from sage.combinat.crystals.tensor_product import TensorProductOfCrystals return TensorProductOfCrystals(self, *crystals, **options) diff --git a/src/sage/combinat/crystals/elementary_crystals.py b/src/sage/combinat/crystals/elementary_crystals.py index 177bf3de3fc..a2c8b4ca16a 100644 --- a/src/sage/combinat/crystals/elementary_crystals.py +++ b/src/sage/combinat/crystals/elementary_crystals.py @@ -470,12 +470,12 @@ class RCrystal(UniqueRepresentation, Parent): sage: S = T.subcrystal(generators=[mg]) sage: for x in S: x.weight() (2, 1, 0) - (2, 0, 1) (1, 2, 0) + (2, 0, 1) (1, 1, 1) (1, 1, 1) - (0, 2, 1) (1, 0, 2) + (0, 2, 1) (0, 1, 2) sage: C = crystals.Tableaux("A2", shape=[2,1]) sage: for x in C: x.weight() diff --git a/src/sage/combinat/crystals/kirillov_reshetikhin.py b/src/sage/combinat/crystals/kirillov_reshetikhin.py index 7cbc76906a6..023904a5e6d 100644 --- a/src/sage/combinat/crystals/kirillov_reshetikhin.py +++ b/src/sage/combinat/crystals/kirillov_reshetikhin.py @@ -1413,9 +1413,9 @@ def highest_weight_dict(self): sage: K.highest_weight_dict() {[[(2, -1), (1,)]]: ((-2, 0, 1, 0, 0, 0, 0), 1), [[(3, -1, -6), (1,)]]: ((-1, 0, 0, 1, 0, 0, -1), 1), - []: ((0, 0, 0, 0, 0, 0, 0), 0), [[(6, -2), (-6, 2)]]: ((0, 0, 0, 0, 0, 0, 0), 1), - [[(5, -2, -6), (-6, 2)]]: ((0, 0, 0, 0, 0, 1, -2), 1)} + [[(5, -2, -6), (-6, 2)]]: ((0, 0, 0, 0, 0, 1, -2), 1), + []: ((0, 0, 0, 0, 0, 0, 0), 0)} """ hw = [x for x in self.hw_auxiliary() if x.epsilon(1) == 0] dic = dict( ( x, tuple( [self.affine_weight(x), len(x)] ) ) for x in hw ) @@ -1474,9 +1474,9 @@ def promotion_on_highest_weight_vectors(self): sage: dic {[[(2, -1), (1,)]]: [[(-1,), (-1, 3)]], [[(3, -1, -6), (1,)]]: [[(5, -3), (-1, 3)]], - []: [[(1, -3), (-1, 3)]], [[(6, -2), (-6, 2)]]: [], - [[(5, -2, -6), (-6, 2)]]: [[(2, -1), (1,)]]} + [[(5, -2, -6), (-6, 2)]]: [[(2, -1), (1,)]], + []: [[(1, -3), (-1, 3)]]} """ dic = self.highest_weight_dict() dic_inv = self.highest_weight_dict_inv() diff --git a/src/sage/combinat/crystals/tensor_product.py b/src/sage/combinat/crystals/tensor_product.py index b36bdf37f4e..997dc481219 100644 --- a/src/sage/combinat/crystals/tensor_product.py +++ b/src/sage/combinat/crystals/tensor_product.py @@ -160,8 +160,8 @@ def one_dimensional_configuration_sum(self, q=None, group_components=True): return sum(q**(c[0].energy_function())*B.sum(B(P0(b.weight())) for b in c) for c in C) return B.sum(q**(b.energy_function())*B(P0(b.weight())) for b in self) - Element = TensorProductOfCrystalsElement - + class Element(TensorProductOfCrystalsElement): + pass class TensorProductOfCrystals(CrystalOfWords): r""" @@ -321,7 +321,7 @@ class TensorProductOfCrystals(CrystalOfWords): 24 sage: TestSuite(T).run() sage: T.module_generators - [[[[1], [2]], [[1]]], [[[2], [3]], [[1]]]] + ([[[1], [2]], [[1]]], [[[2], [3]], [[1]]]) sage: [x.weight() for x in T.module_generators] [(2, 1, 0, 0), (1, 1, 1, 0)] @@ -679,13 +679,15 @@ class FullTensorProductOfRegularCrystals(FullTensorProductOfCrystals): """ Full tensor product of regular crystals. """ - Element = TensorProductOfRegularCrystalsElement + class Element(TensorProductOfRegularCrystalsElement): + pass class TensorProductOfRegularCrystalsWithGenerators(TensorProductOfCrystalsWithGenerators): """ Tensor product of regular crystals with a generating set. """ - Element = TensorProductOfRegularCrystalsElement + class Element(TensorProductOfRegularCrystalsElement): + pass ######################################################### ## Crystal of tableaux @@ -789,7 +791,7 @@ class CrystalOfTableaux(CrystalOfWords): sage: T.cardinality() 48 sage: T.module_generators - [[+++, [[1]]]] + ([+++, [[1]]],) sage: TestSuite(T).run() sage: T = crystals.Tableaux(['D',3],shape=[3/2,1/2,-1/2]); T @@ -797,7 +799,7 @@ class CrystalOfTableaux(CrystalOfWords): sage: T.cardinality() 20 sage: T.module_generators - [[++-, [[1]]]] + ([++-, [[1]]],) sage: TestSuite(T).run() TESTS: @@ -996,7 +998,8 @@ def _element_constructor_(self, *args, **options): """ return self.element_class(self, *args, **options) -CrystalOfTableaux.Element = CrystalOfTableauxElement + class Element(CrystalOfTableauxElement): + pass ##################################################################### ## Local energy function diff --git a/src/sage/combinat/crystals/tensor_product_element.pyx b/src/sage/combinat/crystals/tensor_product_element.pyx index e6a43c8b53b..9d79296676a 100644 --- a/src/sage/combinat/crystals/tensor_product_element.pyx +++ b/src/sage/combinat/crystals/tensor_product_element.pyx @@ -82,6 +82,7 @@ cdef class ImmutableListWithParent(ClonableArray): self._parent = state[0] self._list = state[1]['_list'] self._is_immutable = True + self._hash = 0 def reversed(self): """ From 645811e397a5844908903373fb865f21a2b04263 Mon Sep 17 00:00:00 2001 From: Thierry Monteil Date: Fri, 21 Apr 2017 07:12:56 +0200 Subject: [PATCH 147/452] #22684 update normaliz to 3.2.1. --- build/pkgs/normaliz/checksums.ini | 6 +++--- build/pkgs/normaliz/package-version.txt | 2 +- build/pkgs/normaliz/spkg-install | 3 --- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/build/pkgs/normaliz/checksums.ini b/build/pkgs/normaliz/checksums.ini index e54ddf63dcc..afe7ac682f2 100644 --- a/build/pkgs/normaliz/checksums.ini +++ b/build/pkgs/normaliz/checksums.ini @@ -1,4 +1,4 @@ tarball=normaliz-VERSION.tar.gz -sha1=87bd2846a9132eb87ed6e9fa8cf875a0d6f5cc37 -md5=0eab32959e10b0c41b92c768ef562136 -cksum=1044635248 +sha1=81c89b5b2f8ff15d6939a3fd5822a288440f4d51 +md5=245b1c025ee45d0e2ffd3a77a585768e +cksum=3791680398 diff --git a/build/pkgs/normaliz/package-version.txt b/build/pkgs/normaliz/package-version.txt index 0aec50e6ede..e4604e3afd0 100644 --- a/build/pkgs/normaliz/package-version.txt +++ b/build/pkgs/normaliz/package-version.txt @@ -1 +1 @@ -3.1.4 +3.2.1 diff --git a/build/pkgs/normaliz/spkg-install b/build/pkgs/normaliz/spkg-install index 0e6526ed38d..a73ea271a5a 100755 --- a/build/pkgs/normaliz/spkg-install +++ b/build/pkgs/normaliz/spkg-install @@ -14,6 +14,3 @@ cd src $MAKE || die "Error building normaliz" $MAKE install || die "Error installing normaliz" -cd Singular || die "Normaliz distribution has no Singular subdirectory" -cp -pf normaliz.lib "$SAGE_LOCAL/share/singular/" || die "Error installing normaliz.lib for Singular." - From c3a81c0657ac87c1f3d1e15f5c30de416cb77809 Mon Sep 17 00:00:00 2001 From: Thierry Monteil Date: Fri, 21 Apr 2017 07:13:37 +0200 Subject: [PATCH 148/452] #22684 update PyNormaliz to 1.5. --- build/pkgs/pynormaliz/checksums.ini | 6 +++--- build/pkgs/pynormaliz/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/pynormaliz/checksums.ini b/build/pkgs/pynormaliz/checksums.ini index 8867a73bbf6..c534d164a98 100644 --- a/build/pkgs/pynormaliz/checksums.ini +++ b/build/pkgs/pynormaliz/checksums.ini @@ -1,4 +1,4 @@ tarball=PyNormaliz-VERSION.tar.gz -sha1=e69046012a18f73cc820cf072d43f7d852020d49 -md5=27a5f7d3fa0d96766d4f811495b0f5ce -cksum=1643770354 +sha1=6a584ab5e6fb6159a2c1b54f4f8e101b03fbeaa9 +md5=89d99966599db1c694fb1f229d44860f +cksum=322380391 diff --git a/build/pkgs/pynormaliz/package-version.txt b/build/pkgs/pynormaliz/package-version.txt index d3827e75a5c..c239c60cba2 100644 --- a/build/pkgs/pynormaliz/package-version.txt +++ b/build/pkgs/pynormaliz/package-version.txt @@ -1 +1 @@ -1.0 +1.5 From fcccd289a3986725bcda00c1390208786d782bc0 Mon Sep 17 00:00:00 2001 From: "Erik M. Bray" Date: Fri, 8 Jul 2016 14:31:04 +0200 Subject: [PATCH 149/452] Include ECL .fas binaries (which are DLLs) when calling rebase(all) Not sure if the -s options to rebaseall are strictly needed, but it can't hurt to include. --- src/bin/sage-rebase.sh | 2 +- src/bin/sage-rebaseall.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bin/sage-rebase.sh b/src/bin/sage-rebase.sh index 68f425cd1d6..e4f4caf37ed 100755 --- a/src/bin/sage-rebase.sh +++ b/src/bin/sage-rebase.sh @@ -11,6 +11,6 @@ # Invoke this script from a shell after going to the SAGE_ROOT directory. echo "Getting list of dlls. This may take a while..." -/bin/find local -name "*.dll" -o -name "*.so" > /tmp/sage-dlls.lst +/bin/find local -name "*.dll" -o -name "*.so" -o -name "*.fas" > /tmp/sage-dlls.lst echo "Now rebasing..." /bin/rebase -O -T /tmp/sage-dlls.lst diff --git a/src/bin/sage-rebaseall.sh b/src/bin/sage-rebaseall.sh index 09398ca8fbf..3b922812cc5 100755 --- a/src/bin/sage-rebaseall.sh +++ b/src/bin/sage-rebaseall.sh @@ -17,6 +17,6 @@ # (which usually means admin rights). echo "Getting list of dlls. This may take a while..." -/bin/find local -name "*.dll" -o -name "*.so" > /tmp/sage-dlls.lst +/bin/find local -name "*.dll" -o -name "*.so" -o -name "*.fas" > /tmp/sage-dlls.lst echo "Now rebasing..." -/bin/rebaseall -T /tmp/sage-dlls.lst +/bin/rebaseall -s dll -s exe -s so -s fas -T /tmp/sage-dlls.lst From 6d5ad32aa94c6292bb759b07d0c0026a02545b9f Mon Sep 17 00:00:00 2001 From: "Erik M. Bray" Date: Fri, 8 Jul 2016 14:41:26 +0200 Subject: [PATCH 150/452] These scripts don't necessarily need to know where SAGE_ROOT is, just SAGE_LOCAL (SAGE_LOCAL may not even be *in* SAGE_ROOT) --- src/bin/sage-rebase.bat | 10 +++++----- src/bin/sage-rebase.sh | 6 +++--- src/bin/sage-rebaseall.bat | 10 +++++----- src/bin/sage-rebaseall.sh | 6 +++--- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/bin/sage-rebase.bat b/src/bin/sage-rebase.bat index 68777b06dfe..f0e45f87d3a 100755 --- a/src/bin/sage-rebase.bat +++ b/src/bin/sage-rebase.bat @@ -2,23 +2,23 @@ rem Author: rem * Jean-Pierre Flori rem -rem Rebase all dlls in the SAGE_ROOT directory (and its subdirectories), +rem Rebase all dlls in the SAGE_LOCAL directory (and its subdirectories), rem but do not touch the ones already stored in the system database, rem and do not update it. rem Note that subsequent calls to 'rebaseall' will not update the Sage dlls. rem rem Invoke this script from a Windows command prompt, -rem after adjusting SAGE_ROOT to the Windows location of the Sage directory, +rem after adjusting SAGE_LOCAL to the Windows location of the Sage directory, rem and, if Cygwin is installed in a non-standard location, rem adjusting CYGWIN_ROOT. set CYGWIN_ROOT=C:\cygwin\ -set SAGE_ROOT=C:\cygwin\usr\local\sage\ +set SAGE_LOCAL=C:\cygwin\usr\local\sage\ rem Make sure bash can be called from MSDOS prompt: path %CYGWIN_ROOT%\bin;%path% rem Suppress warning about MSDOS-style path: set CYGWIN=%CYGWIN% nodosfilewarning rem Call the bash script to do the real work: -cd %SAGE_ROOT% -bash .\local\bin\sage-rebase.sh +cd %SAGE_LOCAL% +bash bin\sage-rebase.sh diff --git a/src/bin/sage-rebase.sh b/src/bin/sage-rebase.sh index e4f4caf37ed..46f0affb987 100755 --- a/src/bin/sage-rebase.sh +++ b/src/bin/sage-rebase.sh @@ -3,14 +3,14 @@ # Author: # * Jean-Pierre Flori # -# Rebase all dlls in the SAGE_ROOT directory (and its subdirectories), +# Rebase all dlls in the SAGE_LOCAL directory (and its subdirectories), # but do not touch the ones already stored in the system database, # and do not update it. # Note that subsequent calls to 'rebaseall' will not update the Sage dlls. # -# Invoke this script from a shell after going to the SAGE_ROOT directory. +# Invoke this script from a shell after going to the SAGE_LOCAL directory. echo "Getting list of dlls. This may take a while..." -/bin/find local -name "*.dll" -o -name "*.so" -o -name "*.fas" > /tmp/sage-dlls.lst +/bin/find . -name "*.dll" -o -name "*.so" -o -name "*.fas" > /tmp/sage-dlls.lst echo "Now rebasing..." /bin/rebase -O -T /tmp/sage-dlls.lst diff --git a/src/bin/sage-rebaseall.bat b/src/bin/sage-rebaseall.bat index 75122e335a3..4078a37bd20 100755 --- a/src/bin/sage-rebaseall.bat +++ b/src/bin/sage-rebaseall.bat @@ -3,14 +3,14 @@ rem Authors: rem * Dmitrii Pasechnik rem * Jean-Pierre Flori rem -rem Rebase all dlls in the SAGE_ROOT directory (and its subdirectories), +rem Rebase all dlls in the SAGE_LOCAL directory (and its subdirectories), rem as well as the ones already stored in the system database, rem and update the database. rem This system-wide database is located in '/etc/rebase.db.i386' and rem includes the Cygwin system dlls. rem rem Invoke this script from a Windows command prompt, -rem after adjusting SAGE_ROOT to the Windows location of the Sage directory, +rem after adjusting SAGE_LOCAL to the Windows location of the Sage directory, rem and, if Cygwin is installed in a non-standard location, rem adjusting CYGWIN_ROOT. rem Ensure that no other Cygwin processes are currently running. @@ -18,12 +18,12 @@ rem Note that you need write access to the system-wide rebase database rem (which usually means admin rights). set CYGWIN_ROOT=C:\cygwin\ -set SAGE_ROOT=C:\cygwin\usr\local\sage\ +set SAGE_LOCAL=C:\cygwin\usr\local\sage\ rem Make sure dash can be called from MSDOS prompt: path %CYGWIN_ROOT%\bin;%path% rem Suppress warning about MSDOS-style path: set CYGWIN=%CYGWIN% nodosfilewarning rem Call the dash script to do the real work: -cd %SAGE_ROOT% -dash .\local\bin\sage-rebaseall.sh +cd %SAGE_LOCAL% +dash bin\sage-rebaseall.sh diff --git a/src/bin/sage-rebaseall.sh b/src/bin/sage-rebaseall.sh index 3b922812cc5..f43d73f39e5 100755 --- a/src/bin/sage-rebaseall.sh +++ b/src/bin/sage-rebaseall.sh @@ -5,18 +5,18 @@ # * Dmitrii Pasechnik # * Jean-Pierre Flori # -# Rebase all dlls in the SAGE_ROOT directory (and its subdirectories) +# Rebase all dlls in the SAGE_LOCAL directory (and its subdirectories) # as well as the ones already stored in the system database, # and update the database. # This system-wide database is located in '/etc/rebase.db.i386' and # includes the Cygwin system dlls. # -# Invoke this script from a dash shell after going to the SAGE_ROOT directory. +# Invoke this script from a dash shell after going to the SAGE_LOCAL directory. # Ensure that no other Cygwin processes are currently running. # Note that you need write access to the system-wide rebase database # (which usually means admin rights). echo "Getting list of dlls. This may take a while..." -/bin/find local -name "*.dll" -o -name "*.so" -o -name "*.fas" > /tmp/sage-dlls.lst +/bin/find . -name "*.dll" -o -name "*.so" -o -name "*.fas" > /tmp/sage-dlls.lst echo "Now rebasing..." /bin/rebaseall -s dll -s exe -s so -s fas -T /tmp/sage-dlls.lst From b5daf807f74fe7f5415441f2fa9c92c6229b3a05 Mon Sep 17 00:00:00 2001 From: "Erik M. Bray" Date: Fri, 8 Jul 2016 15:16:34 +0200 Subject: [PATCH 151/452] Update these batch scripts so that it's not necessary to manually specify the paths of SAGE_LOCAL or CYGWIN_ROOT --- src/bin/sage-rebase.bat | 36 ++++++++++++++++++++++++++++++++---- src/bin/sage-rebaseall.bat | 35 +++++++++++++++++++++++++++++++---- 2 files changed, 63 insertions(+), 8 deletions(-) diff --git a/src/bin/sage-rebase.bat b/src/bin/sage-rebase.bat index f0e45f87d3a..de481343786 100755 --- a/src/bin/sage-rebase.bat +++ b/src/bin/sage-rebase.bat @@ -1,19 +1,32 @@ @echo off rem Author: rem * Jean-Pierre Flori +rem * Erik M. Bray rem rem Rebase all dlls in the SAGE_LOCAL directory (and its subdirectories), rem but do not touch the ones already stored in the system database, rem and do not update it. rem Note that subsequent calls to 'rebaseall' will not update the Sage dlls. rem -rem Invoke this script from a Windows command prompt, -rem after adjusting SAGE_LOCAL to the Windows location of the Sage directory, +rem Invoke this script from a Windows command prompt rem and, if Cygwin is installed in a non-standard location, rem adjusting CYGWIN_ROOT. -set CYGWIN_ROOT=C:\cygwin\ -set SAGE_LOCAL=C:\cygwin\usr\local\sage\ +setlocal ENABLEEXTENSIONS + +set THIS_BIN=%~dp0 + +rem SAGE_LOCAL should be one level up from the bin/ this script is in +rem This is about the most elegant way to do this I can find thanks +rem http://stackoverflow.com/a/33404867/982257 +call :NORMALIZEPATH "%THIS_BIN%.." +set SAGE_LOCAL=%RETVAL% + +rem Cygwin saves its installation root here +rem If there is more than one Cygwin installation on the system this +rem will just pick up the first one +call :READREGISTRY HKEY_LOCAL_MACHINE\SOFTWARE\Cygwin\setup rootdir +set CYGWIN_ROOT=%RETVAL% rem Make sure bash can be called from MSDOS prompt: path %CYGWIN_ROOT%\bin;%path% @@ -22,3 +35,18 @@ set CYGWIN=%CYGWIN% nodosfilewarning rem Call the bash script to do the real work: cd %SAGE_LOCAL% bash bin\sage-rebase.sh + + +:: ========== FUNCTIONS ========== +exit /B + +:READREGISTRY + for /F "usebackq skip=2 tokens=3" %%V in (`reg query %1 /v %2 2^>nul`) do ( + set RETVAL=%%V + break + ) + exit /B + +:NORMALIZEPATH + set RETVAL=%~dpfn1 + exit /B diff --git a/src/bin/sage-rebaseall.bat b/src/bin/sage-rebaseall.bat index 4078a37bd20..0ae927f5e64 100755 --- a/src/bin/sage-rebaseall.bat +++ b/src/bin/sage-rebaseall.bat @@ -2,6 +2,7 @@ rem Authors: rem * Dmitrii Pasechnik rem * Jean-Pierre Flori +rem * Erik M. Bray rem rem Rebase all dlls in the SAGE_LOCAL directory (and its subdirectories), rem as well as the ones already stored in the system database, @@ -9,16 +10,27 @@ rem and update the database. rem This system-wide database is located in '/etc/rebase.db.i386' and rem includes the Cygwin system dlls. rem -rem Invoke this script from a Windows command prompt, -rem after adjusting SAGE_LOCAL to the Windows location of the Sage directory, +rem Invoke this script from a Windows command prompt rem and, if Cygwin is installed in a non-standard location, rem adjusting CYGWIN_ROOT. +rem rem Ensure that no other Cygwin processes are currently running. rem Note that you need write access to the system-wide rebase database rem (which usually means admin rights). -set CYGWIN_ROOT=C:\cygwin\ -set SAGE_LOCAL=C:\cygwin\usr\local\sage\ +set THIS_BIN=%~dp0 + +rem SAGE_LOCAL should be one level up from the bin/ this script is in +rem This is about the most elegant way to do this I can find thanks +rem http://stackoverflow.com/a/33404867/982257 +call :NORMALIZEPATH "%THIS_BIN%.." +set SAGE_LOCAL=%RETVAL% + +rem Cygwin saves its installation root here +rem If there is more than one Cygwin installation on the system this +rem will just pick up the first one +call :READREGISTRY HKEY_LOCAL_MACHINE\SOFTWARE\Cygwin\setup rootdir +set CYGWIN_ROOT=%RETVAL% rem Make sure dash can be called from MSDOS prompt: path %CYGWIN_ROOT%\bin;%path% @@ -27,3 +39,18 @@ set CYGWIN=%CYGWIN% nodosfilewarning rem Call the dash script to do the real work: cd %SAGE_LOCAL% dash bin\sage-rebaseall.sh + + +:: ========== FUNCTIONS ========== +exit /B + +:READREGISTRY + for /F "usebackq skip=2 tokens=3" %%V in (`reg query %1 /v %2 2^>nul`) do ( + set RETVAL=%%V + break + ) + exit /B + +:NORMALIZEPATH + set RETVAL=%~dpfn1 + exit /B From 23a5a04d3f477738a2da86e3e5b21f529e483f10 Mon Sep 17 00:00:00 2001 From: "Erik M. Bray" Date: Fri, 21 Apr 2017 16:46:45 +0200 Subject: [PATCH 152/452] Accept the path to SAGE_LOCAL as an argument (this is useful for running outside the Sage shell). Exclude /var/tmp from the list of DLLs to rebase. --- src/bin/sage-rebase.sh | 11 ++++++++++- src/bin/sage-rebaseall.sh | 12 +++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/bin/sage-rebase.sh b/src/bin/sage-rebase.sh index 46f0affb987..ba17749b964 100755 --- a/src/bin/sage-rebase.sh +++ b/src/bin/sage-rebase.sh @@ -9,8 +9,17 @@ # Note that subsequent calls to 'rebaseall' will not update the Sage dlls. # # Invoke this script from a shell after going to the SAGE_LOCAL directory. +SAGE_LOCAL=${1%/} + +if [ -z "$SAGE_LOCAL" ]; then + # Assume we are in $SAGE_LOCAL by default (the old behavior of this script) + SAGE_LOCAL=. +fi + +FINDFLAGS="-type f ( -name *.dll -o -name *.so -o -name *.fas ) -print" +FINDFLAGS="$FINDFLAGS -o -path "$SAGE_LOCAL"/var/tmp -prune" echo "Getting list of dlls. This may take a while..." -/bin/find . -name "*.dll" -o -name "*.so" -o -name "*.fas" > /tmp/sage-dlls.lst +/bin/find "$SAGE_LOCAL" $FINDFLAGS > /tmp/sage-dlls.lst echo "Now rebasing..." /bin/rebase -O -T /tmp/sage-dlls.lst diff --git a/src/bin/sage-rebaseall.sh b/src/bin/sage-rebaseall.sh index f43d73f39e5..6db661c00d4 100755 --- a/src/bin/sage-rebaseall.sh +++ b/src/bin/sage-rebaseall.sh @@ -16,7 +16,17 @@ # Note that you need write access to the system-wide rebase database # (which usually means admin rights). +SAGE_LOCAL=${1%/} + +if [ -z "$SAGE_LOCAL" ]; then + # Assume we are in $SAGE_LOCAL by default (the old behavior of this script) + SAGE_LOCAL=. +fi + +FINDFLAGS="-type f ( -name *.dll -o -name *.so -o -name *.fas ) -print" +FINDFLAGS="$FINDFLAGS -o -path "$SAGE_LOCAL"/var/tmp -prune" + echo "Getting list of dlls. This may take a while..." -/bin/find . -name "*.dll" -o -name "*.so" -o -name "*.fas" > /tmp/sage-dlls.lst +/bin/find "$SAGE_LOCAL" $FINDFLAGS > /tmp/sage-dlls.lst echo "Now rebasing..." /bin/rebaseall -s dll -s exe -s so -s fas -T /tmp/sage-dlls.lst From 939fda60785e9a082d59b0d6a8e0c2afd2f9ec36 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Sat, 22 Apr 2017 09:15:31 +0200 Subject: [PATCH 153/452] Refine docstrings --- .../rings/function_field/function_field.py | 63 +++++++------------ 1 file changed, 22 insertions(+), 41 deletions(-) diff --git a/src/sage/rings/function_field/function_field.py b/src/sage/rings/function_field/function_field.py index 489567b4796..11d247f6dba 100644 --- a/src/sage/rings/function_field/function_field.py +++ b/src/sage/rings/function_field/function_field.py @@ -53,11 +53,11 @@ sage: M.base_field().base_field() Rational function field in x over Finite Field in a of size 5^2 -It is also possible to work with function fields over an imperfect base field:: +It is also possible to construct function fields over an imperfect base field:: sage: N. = FunctionField(K) -Function field extensions can be inseparable:: +and function fields as inseparable extensions:: sage: R. = K[] sage: O. = K.extension(v^5 - x) @@ -1286,29 +1286,16 @@ def derivation(self): r""" Return a derivation of the function field over the constant base field. - If the field is a separable extension of the base field, the derivation - is uniquely determined from that of the base function field. - A derivation on `R` is a map `R\to R` satisfying `D(\alpha+\beta)=D(\alpha)+D(\beta)` and `D(\alpha\beta)=\beta - D(\alpha)+\alpha D(\beta)` for all `\alpha, \beta \in R`. For a function - field which is a finite extension of `K(x)` with `K` perfect, the - derivations form a one-dimensional `K`-vector space generated by the - derivation returned by this method. - - ALGORITHM: - - Proposition 11 of [GT1996]_ describes how to compute the unique extension - of a derivation on the base function field `F` if the field is a separable - extension of `F`. We apply the formula described there to the generator - of the space of derivations on `F`. - - The general inseparable case is not implemented yet (see :trac:`16562`, - :trac:`16564`.)` + D(\alpha)+\alpha D(\beta)` for all `\alpha, \beta \in R`. For a + function field which is a finite extension of `K(x)` with `K` perfect, + the derivations form a one-dimensional `K`-vector space generated by + the derivation returned by this method. OUTPUT: - A derivation of this function field. + - a derivation of the function field EXAMPLES:: @@ -1336,15 +1323,14 @@ def derivation(self): sage: d(x*y) == x*d(y) + y*d(x) True - Currently the functionality for finding a separable model is not - implemented (see :trac:`16562`, :trac:`16564`):: + If the field is a separable extension of the base field, the derivation + extending a derivation of the base function field is uniquely + determined. Proposition 11 of [GT1996]_ describes how to compute the + extension. We apply the formula described there to the generator + of the space of derivations on the base field. - sage: R. = K[] - sage: L. = K.extension(y^3 - x) - sage: L.derivation() - Traceback (most recent call last): - ... - NotImplementedError: construction of separable models not implemented + The general inseparable case is not implemented yet (see :trac:`16562`, + :trac:`16564`.)` """ from .maps import FunctionFieldDerivation_separable if self.polynomial().gcd(self.polynomial().derivative()).is_one(): @@ -1962,28 +1948,24 @@ def vector_space(self, base=None): @cached_method def derivation(self): r""" - Return a generator of the space of derivations over the constant base - field of this function field. - - A derivation on `R` is a map `R \to R` with - `D(\alpha + \beta) = D(\alpha) + D(\beta)` and - `D(\alpha \beta) = \beta D(\alpha)+\alpha D(\beta)` - for all `\alpha, \beta \in R`. For a function - field `K(x)` with `K` perfect, the derivations form a one-dimensional - `K`-vector space generated by the extension of the usual derivation on - `K[x]` (cf. Proposition 10 in [GT1996]_.) + Return a derivation of the rational function field over the constant + base field. OUTPUT: - An endofunction on this function field. + - a derivation of the rational function field + + The derivation maps the generator of the rational function field to 1. EXAMPLES:: sage: K. = FunctionField(GF(3)) - sage: K.derivation() + sage: m = K.derivation(); m Derivation map: From: Rational function field in x over Finite Field of size 3 To: Rational function field in x over Finite Field of size 3 + sage: m(x) + 1 TESTS:: @@ -1992,7 +1974,6 @@ def derivation(self): Traceback (most recent call last): ... NotImplementedError: not implemented for non-perfect base fields - """ from .maps import FunctionFieldDerivation_rational if not self.constant_base_field().is_perfect(): From 72ec42e2d15afbaad18dd31adc19d4ff1db23a05 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sat, 22 Apr 2017 11:05:03 -0500 Subject: [PATCH 154/452] Some cleanup of the tikz code. --- src/sage/combinat/set_partition.py | 103 ++++++++++++++--------------- 1 file changed, 49 insertions(+), 54 deletions(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index cfffb68de47..f50e818b795 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -426,8 +426,8 @@ def set_latex_options(self, **kwargs): - ``color`` -- (default: ``'black'``) the arc colors - - ``fill`` -- (default: ``False``) if True then fills black, else - you can pass in a color to alter the fill color - + - ``fill`` -- (default: ``False``) if ``True`` then fills ``color``, + else you can pass in a color to alter the fill color - *only works with cyclic plot* - ``show_labels`` -- (default: ``True``) if ``True`` shows labels - @@ -516,21 +516,21 @@ def _latex_(self): sage: p.set_latex_options(plot='cyclic', color='blue', angle=45, fill=True, tikz_scale=2) sage: latex(p) \begin{tikzpicture}[scale=2] - \node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black,label=90:a] (0) at (90:1cm) {}; - \node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black,label=18:1] (1) at (18:1cm) {}; - \node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black,label=-54:c] (2) at (-54:1cm) {}; - \node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black,label=-126:b] (3) at (-126:1cm) {}; - \node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black,label=-198:20] (4) at (-198:1cm) {}; - \draw[-] (0:1cm) arc (0:72:1cm); - \draw[-] (72:1cm) arc (72:144:1cm); - \draw[-] (144:1cm) arc (144:216:1cm); - \draw[-] (216:1cm) arc (216:288:1cm); - \draw[-] (288:1cm) arc (288:360:1cm); - \draw[-,thick,color=blue,fill={rgb:blue,1;white,10}] (1.center) -- (3.center) -- cycle; - \draw[-,thick,color=blue,fill={rgb:blue,1;white,10}] (4.center) -- cycle; - \draw[-,thick,color=blue,fill={rgb:blue,1;white,10}] (0.center) -- (2.center) -- cycle; + \draw (0,0) circle [radius=1cm]; + \node[label=90:1] (0) at (90:1cm) {}; + \node[label=18:20] (1) at (18:1cm) {}; + \node[label=-54:a] (2) at (-54:1cm) {}; + \node[label=-126:b] (3) at (-126:1cm) {}; + \node[label=-198:c] (4) at (-198:1cm) {}; + \draw[-,thick,color=blue,fill=blue,fill opacity=0.1] (0.center) -- (3.center) -- cycle; + \draw[-,thick,color=blue,fill=blue,fill opacity=0.1] (1.center) -- cycle; + \draw[-,thick,color=blue,fill=blue,fill opacity=0.1] (2.center) -- (4.center) -- cycle; + \fill[color=black] (0) circle (1.5pt); + \fill[color=black] (1) circle (1.5pt); + \fill[color=black] (2) circle (1.5pt); + \fill[color=black] (3) circle (1.5pt); + \fill[color=black] (4) circle (1.5pt); \end{tikzpicture} - """ latex_options = self.latex_options() if latex_options["plot"] is None: @@ -538,74 +538,69 @@ def _latex_(self): from sage.misc.latex import latex latex.add_package_to_preamble_if_available("tikz") - res = "\\begin{tikzpicture}[scale="+str(latex_options['tikz_scale'])+"]\n" + res = "\\begin{{tikzpicture}}[scale={}]\n".format(latex_options['tikz_scale']) cardinality = self.base_set_cardinality() - base_set = self.base_set().list() - color= latex_options['color'] + from sage.rings.integer_ring import ZZ + if all(x in ZZ for x in self.base_set()): + sort_key = ZZ + else: + sort_key = str + base_set = sorted(self.base_set(), key=sort_key) + color = latex_options['color'] # If we want cyclic plots if latex_options['plot'] == 'cyclic': degrees = 360 // cardinality radius = latex_options['radius'] + res += "\\draw (0,0) circle [radius={}];\n".format(radius) + # Add nodes for k,i in enumerate(base_set): location = (cardinality - k) * degrees - 270 - res += "\\node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black" if latex_options['show_labels']: - res += ",label=" + str(location) + ":" + str(i) - res += "] (" + str(k) + ") at (" + str(location) + ":" + radius + ") {};\n" - - # Add the circle - for k,i in enumerate(base_set): - xangle = k * degrees - yangle = (k+1) * degrees - res += "\\draw[-] (" + str(xangle) + ":" + radius + ")" - res += " arc " - res += "(" + str(xangle) + ":" + str(yangle) + ":" + radius + ");\n" + res += "\\node[label={}:{}]".format(location, i) + else: + res += "\\node" + res += " ({}) at ({}:{}) {{}};\n".format(k, location, radius) # Setup partitions for partition in self: res += "\\draw[-,thick,color="+color - if latex_options['fill'] != False: - if isinstance(latex_options['fill'],str): - res += ",fill="+latex_options['fill'] + if latex_options['fill'] is not False: + if isinstance(latex_options['fill'], str): + res += ",fill=" + latex_options['fill'] else: - res += ",fill={rgb:" + color + ",1;white,10}" + res += ",fill={},fill opacity=0.1".format(color) res += "] " - firstDone = False - for j in partition: - if firstDone: - res += " -- (" + str(base_set.index(j)) + ".center)" - else: - firstDone = True - res += "(" + str(base_set.index(j)) + ".center)" + res += " -- ".join("({}.center)".format(base_set.index(j)) + for j in sorted(partition, key=sort_key)) res += " -- cycle;\n" + # Draw the circles on top + for k in range(len(base_set)): + res += "\\fill[color=black] ({}) circle (1.5pt);\n".format(k) + # If we want line plots elif latex_options['plot'] == 'linear': angle = latex_options['angle'] # setup line for k,i in enumerate(base_set): if latex_options['show_labels']: - res += "\\node[below=.05cm] at (" + str(k) + ",0) {$" + str(i) + "$};\n" + res += "\\node[below=.05cm] at ({},0) {{${}$}};\n".format(k, i) res += "\\node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black] " - res += "(" + str(k) + ") at (" + str(k) + ",0) {};\n" - #res += "\t\\draw (0) -- (" + str(cardinality - 1) + ");\n" + res += "({k}) at ({k},0) {{}};\n".format(k=k) # setup arcs for partition in self: - if partition.cardinality() > 1: - for k,i in enumerate(partition.list()): - if k != 0: - #res += "\\draw (" + str(base_set.index(partition[0])) + ")" - #res += " to [out=90,in=90] " - #res += "(" + str(base_set.index(partition[-1])) + ");" - #else: - res += "\\draw[color=" + color + "] (" + str(base_set.index(partition[k])) + ")" - res += " to [out=" + str(90+angle) + ",in=" + str(90-angle) + "] " - res += "(" + str(base_set.index(partition[k-1])) + ");\n" + p = sorted(partition, key=str) + if len(p) <= 1: + continue + for k in range(1, len(p)): + res += "\\draw[color={}] ({})".format(color, base_set.index(p[k])) + res += " to [out={},in={}] ".format(90+angle, 90-angle) + res += "({});\n".format(base_set.index(p[k-1])) else: raise ValueError("plot must be None, 'cyclic', or 'linear'") From c314fef1f6af261f9781b1ef23c8942b1ab86aad Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sun, 23 Apr 2017 17:24:06 -0500 Subject: [PATCH 155/452] Fixing nondeterministic doctest ordering, last time. --- .../lie/affine_finite_crystals.rst | 2 +- .../combinat/crystals/elementary_crystals.py | 24 +++++-------------- .../combinat/crystals/kirillov_reshetikhin.py | 24 +++++++++---------- 3 files changed, 19 insertions(+), 31 deletions(-) diff --git a/src/doc/en/thematic_tutorials/lie/affine_finite_crystals.rst b/src/doc/en/thematic_tutorials/lie/affine_finite_crystals.rst index 305590cf9fc..0c456e1b19c 100644 --- a/src/doc/en/thematic_tutorials/lie/affine_finite_crystals.rst +++ b/src/doc/en/thematic_tutorials/lie/affine_finite_crystals.rst @@ -68,7 +68,7 @@ the methods ``lift`` and ``retract``:: sage: b.lift() [[1], [3]] sage: type(b.lift()) - + sage: b = crystals.Tableaux(['A',3], shape = [1,1])(rows=[[1],[3]]) sage: K.retract(b) diff --git a/src/sage/combinat/crystals/elementary_crystals.py b/src/sage/combinat/crystals/elementary_crystals.py index a2c8b4ca16a..a5153cafb5c 100644 --- a/src/sage/combinat/crystals/elementary_crystals.py +++ b/src/sage/combinat/crystals/elementary_crystals.py @@ -468,25 +468,13 @@ class RCrystal(UniqueRepresentation, Parent): sage: T = crystals.TensorProduct(R, B) sage: mg = T(R.highest_weight_vector(), B.highest_weight_vector()) sage: S = T.subcrystal(generators=[mg]) - sage: for x in S: x.weight() - (2, 1, 0) - (1, 2, 0) - (2, 0, 1) - (1, 1, 1) - (1, 1, 1) - (1, 0, 2) - (0, 2, 1) - (0, 1, 2) + sage: sorted([x.weight() for x in S], key=str) + [(0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 1, 1), + (1, 1, 1), (1, 2, 0), (2, 0, 1), (2, 1, 0)] sage: C = crystals.Tableaux("A2", shape=[2,1]) - sage: for x in C: x.weight() - (2, 1, 0) - (1, 2, 0) - (1, 1, 1) - (1, 0, 2) - (0, 1, 2) - (2, 0, 1) - (1, 1, 1) - (0, 2, 1) + sage: sorted([x.weight() for x in C], key=str) + [(0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 1, 1), + (1, 1, 1), (1, 2, 0), (2, 0, 1), (2, 1, 0)] sage: GT = T.digraph(subset=S) sage: GC = C.digraph() sage: GT.is_isomorphic(GC, edge_labels=True) diff --git a/src/sage/combinat/crystals/kirillov_reshetikhin.py b/src/sage/combinat/crystals/kirillov_reshetikhin.py index 023904a5e6d..d3d49b3e560 100644 --- a/src/sage/combinat/crystals/kirillov_reshetikhin.py +++ b/src/sage/combinat/crystals/kirillov_reshetikhin.py @@ -1410,12 +1410,12 @@ def highest_weight_dict(self): EXAMPLES:: sage: K = crystals.KirillovReshetikhin(['E',6,1],2,1) - sage: K.highest_weight_dict() - {[[(2, -1), (1,)]]: ((-2, 0, 1, 0, 0, 0, 0), 1), - [[(3, -1, -6), (1,)]]: ((-1, 0, 0, 1, 0, 0, -1), 1), - [[(6, -2), (-6, 2)]]: ((0, 0, 0, 0, 0, 0, 0), 1), - [[(5, -2, -6), (-6, 2)]]: ((0, 0, 0, 0, 0, 1, -2), 1), - []: ((0, 0, 0, 0, 0, 0, 0), 0)} + sage: sorted(K.highest_weight_dict().items()) + [([[(2, -1), (1,)]], ((-2, 0, 1, 0, 0, 0, 0), 1)), + ([[(3, -1, -6), (1,)]], ((-1, 0, 0, 1, 0, 0, -1), 1)), + ([[(6, -2), (-6, 2)]], ((0, 0, 0, 0, 0, 0, 0), 1)), + ([[(5, -2, -6), (-6, 2)]], ((0, 0, 0, 0, 0, 1, -2), 1)), + ([], ((0, 0, 0, 0, 0, 0, 0), 0))] """ hw = [x for x in self.hw_auxiliary() if x.epsilon(1) == 0] dic = dict( ( x, tuple( [self.affine_weight(x), len(x)] ) ) for x in hw ) @@ -1471,12 +1471,12 @@ def promotion_on_highest_weight_vectors(self): sage: K = crystals.KirillovReshetikhin(['E',6,1],2,1) sage: dic = K.promotion_on_highest_weight_vectors() - sage: dic - {[[(2, -1), (1,)]]: [[(-1,), (-1, 3)]], - [[(3, -1, -6), (1,)]]: [[(5, -3), (-1, 3)]], - [[(6, -2), (-6, 2)]]: [], - [[(5, -2, -6), (-6, 2)]]: [[(2, -1), (1,)]], - []: [[(1, -3), (-1, 3)]]} + sage: sorted(dic.items()) + [([[(2, -1), (1,)]], [[(-1,), (-1, 3)]]), + ([[(3, -1, -6), (1,)]], [[(5, -3), (-1, 3)]]), + ([[(6, -2), (-6, 2)]], []), + ([[(5, -2, -6), (-6, 2)]], [[(2, -1), (1,)]]), + ([], [[(1, -3), (-1, 3)]])] """ dic = self.highest_weight_dict() dic_inv = self.highest_weight_dict_inv() From 8548f0ceae68db1d3d81c362fd1241927f32ea44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jori=20M=C3=A4ntysalo?= Date: Mon, 24 Apr 2017 09:43:49 +0300 Subject: [PATCH 156/452] Add check for a property combination. --- src/sage/combinat/posets/poset_examples.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sage/combinat/posets/poset_examples.py b/src/sage/combinat/posets/poset_examples.py index 5f8013b603e..b41093a175f 100644 --- a/src/sage/combinat/posets/poset_examples.py +++ b/src/sage/combinat/posets/poset_examples.py @@ -727,6 +727,8 @@ def RandomLattice(n, p, properties=None): # Test property combinations that are not implemented. if 'distributive' in properties and len(properties) > 1: raise NotImplementedError("combining 'distributive' with other properties is not implemented") + if 'stone' in properties and len(properties) > 1: + raise NotImplementedError("combining 'stone' with other properties is not implemented") if properties == set(['planar']): D = _random_planar_lattice(n) From 1a99adfca86bf9d40c741f2d7ee6e0ecc3760193 Mon Sep 17 00:00:00 2001 From: Mark Ioppolo Date: Mon, 24 Apr 2017 22:27:33 +0800 Subject: [PATCH 157/452] Modified coding thematic tutorial imports MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I made the following changes to the "Create your own coding theory classes" thematic tutorial located at ​https://doc.sagemath.org/html/en/thematic_tutorials/structures_in_coding_theory.html#structures-in-coding-theory 'repetition_code.py' requires the line {{{from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF"}}} Import statements such as {{{from repetition_code.py import BinaryRepetitionCode}}} were changed to {{{from sage.coding.repetition_code.py import BinaryRepetitionCode}}} See ​https://groups.google.com/forum/#!topic/sage-devel/81j1BoMwWb4 for full details --- .../structures_in_coding_theory.rst | 33 +++++++++++-------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/src/doc/en/thematic_tutorials/structures_in_coding_theory.rst b/src/doc/en/thematic_tutorials/structures_in_coding_theory.rst index f8e269a615a..afe9b65c631 100644 --- a/src/doc/en/thematic_tutorials/structures_in_coding_theory.rst +++ b/src/doc/en/thematic_tutorials/structures_in_coding_theory.rst @@ -81,6 +81,7 @@ Let us now write the constructor for our code class, that we store in some file called ``repetition_code.py``:: sage: from sage.coding.linear_code import AbstractLinearCode + sage: from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF sage: class BinaryRepetitionCode(AbstractLinearCode): ....: _registered_encoders = {} ....: _registered_decoders = {} @@ -523,9 +524,9 @@ we do not wish to store all our classes directly in Sage's global namespace. We propose several catalog files to store our constructions, namely: - ``codes_catalog.py``, -- ``encoders_catalog``, -- ``decoders_catalog`` and -- ``channels_catalog``. +- ``encoders_catalog.py``, +- ``decoders_catalog.py`` and +- ``channels_catalog.py``. Everytime one creates a new object, it should be added in the dedicated catalog file instead of coding theory folder's ``all.py``. @@ -534,19 +535,19 @@ Here it means the following: - add the following in ``codes_catalog.py``:: - from repetition_code import BinaryRepetitionCode + from sage.coding.repetition_code import BinaryRepetitionCode - add the following in ``encoders_catalog.py``:: - from repetition_code import BinaryRepetitionCodeGeneratorMatrixEncoder + from sage.coding.repetition_code import BinaryRepetitionCodeGeneratorMatrixEncoder - add the following in ``decoders_catalog.py``:: - from repetition_code import BinaryRepetitionCodeMajorityVoteDecoder + from sage.coding.repetition_code import BinaryRepetitionCodeMajorityVoteDecoder - add the following in ``channels_catalog.py``:: - from channel_constructions import BinaryStaticErrorRateChannel + from sage.coding.channel_constructions import BinaryStaticErrorRateChannel VII. Complete code of this tutorial =================================== @@ -559,6 +560,7 @@ derive from the one that follows. from sage.coding.linear_code import AbstractLinearCode from sage.coding.encoder import Encoder from sage.coding.decoder import Decoder + from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF class BinaryRepetitionCode(AbstractLinearCode): @@ -701,11 +703,16 @@ derive from the one that follows. w[i] += F.one() return w -``codes_catalog.py`` (continued, do the same in ``encoders_catalog.py``, -``decoders_catalog.py`` and ``channels_catalog.py``):: - - :class:`repetition_code.BinaryRepetitionCode ` +``codes_catalog.py`` (continued):: + :class:`sage.coding.repetition_code.BinaryRepetitionCode ` #the line above creates a link to the class in the html documentation of coding theory library - from repetition_code import BinaryRepetitionCode - from channel_constructions import (ErrorErasureChannel, StaticErrorRateChannel, BinaryStaticErrorRateChannel) + from sage.coding.repetition_code import BinaryRepetitionCode + +``encoders_catalog.py`` (continued):: + from sage.coding.repetition_code import (BinaryRepetitionCodeGeneratorMatrixEncoder, BinaryRepetitionCodeStraightforwardEncoder) + +``decoders_catalog.py`` (continued):: + from sage.coding.repetition_code import BinaryRepetitionCodeMajorityVoteDecoder +``channels_catalog.py`` (continued):: + from sage.coding.channel_constructions import (ErrorErasureChannel, StaticErrorRateChannel, BinaryStaticErrorRateChannel) From f4ec77f701291c9f687dd6bdce4a8d738c9fe96a Mon Sep 17 00:00:00 2001 From: Mark Ioppolo Date: Tue, 25 Apr 2017 07:54:24 +0800 Subject: [PATCH 158/452] Added blank lines after ``codes_catalog.py`` (continued):: --- src/doc/en/thematic_tutorials/structures_in_coding_theory.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/doc/en/thematic_tutorials/structures_in_coding_theory.rst b/src/doc/en/thematic_tutorials/structures_in_coding_theory.rst index afe9b65c631..7260886965e 100644 --- a/src/doc/en/thematic_tutorials/structures_in_coding_theory.rst +++ b/src/doc/en/thematic_tutorials/structures_in_coding_theory.rst @@ -704,15 +704,19 @@ derive from the one that follows. return w ``codes_catalog.py`` (continued):: + :class:`sage.coding.repetition_code.BinaryRepetitionCode ` #the line above creates a link to the class in the html documentation of coding theory library from sage.coding.repetition_code import BinaryRepetitionCode ``encoders_catalog.py`` (continued):: + from sage.coding.repetition_code import (BinaryRepetitionCodeGeneratorMatrixEncoder, BinaryRepetitionCodeStraightforwardEncoder) ``decoders_catalog.py`` (continued):: + from sage.coding.repetition_code import BinaryRepetitionCodeMajorityVoteDecoder ``channels_catalog.py`` (continued):: + from sage.coding.channel_constructions import (ErrorErasureChannel, StaticErrorRateChannel, BinaryStaticErrorRateChannel) From e2f0b401f9708fa80a91a908048576bad7cbe8b6 Mon Sep 17 00:00:00 2001 From: "Erik M. Bray" Date: Tue, 25 Apr 2017 09:50:17 +0200 Subject: [PATCH 159/452] Enhance sage-rebase.sh to be able to pass additional arguments to rebase, and to wrap the call to rebaseall sage-rebaseall.sh is now just a wrapper around sage-rebase.sh so there doesn't have to be so much duplication between them. --- src/bin/sage-rebase.sh | 54 +++++++++++++++++++++++++++++++++++++-- src/bin/sage-rebaseall.sh | 16 ++---------- 2 files changed, 54 insertions(+), 16 deletions(-) diff --git a/src/bin/sage-rebase.sh b/src/bin/sage-rebase.sh index ba17749b964..79b0b4bdc1c 100755 --- a/src/bin/sage-rebase.sh +++ b/src/bin/sage-rebase.sh @@ -2,14 +2,59 @@ # Author: # * Jean-Pierre Flori +# * Gary Zablackis +# * Dmitrii Pasechnik +# * Erik M. Bray # # Rebase all dlls in the SAGE_LOCAL directory (and its subdirectories), # but do not touch the ones already stored in the system database, # and do not update it. # Note that subsequent calls to 'rebaseall' will not update the Sage dlls. # +# Usage: +# +# sage-rebase.sh [--all] [sage_local] [-- additional_flags] +# +# Positional arguments: +# +# sage_local optionally, provide the path to the $SAGE_LOCAL directory to +# search for DLLs to rebase; otherwise the current working +# directory is assumed to be $SAGE_LOCAL unless $SAGE_LOCAL +# is already set in the environment +# +# Optional arguments: +# +# --all run rebaseall instead of rebase (originally the call to +# rebaseall was in the sage-rebaseall.sh script, but now that is +# just a wrapper around this script) +# +# -- additional arguments passed in after -- are passed to the +# rebase/rebaseall call in addition to the default arguments +# passed in by this script +# # Invoke this script from a shell after going to the SAGE_LOCAL directory. -SAGE_LOCAL=${1%/} +ALL=0 +REBASEFLAGS="" + +while [ $# -gt 0 ]; do + case "$1" in + --all) + ALL=1 + ;; + --) + shift + REBASEFLAGS="$REBASEFLAGS $1" + ;; + *) + if [ -z "$REBASEFLAGS" ]; then + SAGE_LOCAL="${1%/}" + else + REBASEFLAGS="$REBASEFLAGS $1" + fi + ;; + esac + shift +done if [ -z "$SAGE_LOCAL" ]; then # Assume we are in $SAGE_LOCAL by default (the old behavior of this script) @@ -22,4 +67,9 @@ FINDFLAGS="$FINDFLAGS -o -path "$SAGE_LOCAL"/var/tmp -prune" echo "Getting list of dlls. This may take a while..." /bin/find "$SAGE_LOCAL" $FINDFLAGS > /tmp/sage-dlls.lst echo "Now rebasing..." -/bin/rebase -O -T /tmp/sage-dlls.lst + +if [ $ALL -eq 0 ]; then + /bin/rebase -O -T /tmp/sage-dlls.lst $REBASEFLAGS +else + /bin/rebaseall -s dll -s exe -s so -s fas -T /tmp/sage-dlls.lst $REBASEFLAGS +fi diff --git a/src/bin/sage-rebaseall.sh b/src/bin/sage-rebaseall.sh index 6db661c00d4..b4de6dbcdb0 100755 --- a/src/bin/sage-rebaseall.sh +++ b/src/bin/sage-rebaseall.sh @@ -16,17 +16,5 @@ # Note that you need write access to the system-wide rebase database # (which usually means admin rights). -SAGE_LOCAL=${1%/} - -if [ -z "$SAGE_LOCAL" ]; then - # Assume we are in $SAGE_LOCAL by default (the old behavior of this script) - SAGE_LOCAL=. -fi - -FINDFLAGS="-type f ( -name *.dll -o -name *.so -o -name *.fas ) -print" -FINDFLAGS="$FINDFLAGS -o -path "$SAGE_LOCAL"/var/tmp -prune" - -echo "Getting list of dlls. This may take a while..." -/bin/find "$SAGE_LOCAL" $FINDFLAGS > /tmp/sage-dlls.lst -echo "Now rebasing..." -/bin/rebaseall -s dll -s exe -s so -s fas -T /tmp/sage-dlls.lst +DIR=$(dirname "$(readlink -f "$0")") +exec "$DIR"/sage-rebase.sh" $@ From 8c4a3df506fe7f0fde88134cac9b29c053e98259 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jori=20M=C3=A4ntysalo?= Date: Tue, 25 Apr 2017 11:12:30 +0300 Subject: [PATCH 160/452] Add more tests for being doubling constructible. --- src/sage/combinat/posets/lattices.py | 66 ++++++++++++++++++++++++---- 1 file changed, 57 insertions(+), 9 deletions(-) diff --git a/src/sage/combinat/posets/lattices.py b/src/sage/combinat/posets/lattices.py index 373c3bb238a..26814b46ce2 100644 --- a/src/sage/combinat/posets/lattices.py +++ b/src/sage/combinat/posets/lattices.py @@ -66,6 +66,7 @@ :meth:`~FiniteLatticePoset.is_uniform` | Return ``True`` if all congruences of the lattice consists of equal-sized blocks. :meth:`~FiniteLatticePoset.is_regular` | Return ``True`` if all congruences of lattice are determined by any of the congruence blocks. :meth:`~FiniteLatticePoset.is_subdirectly_reducible` | Return ``True`` if the lattice is a sublattice of the product of smaller lattices. + :meth:`~FiniteLatticePoset.is_constructible_by_doublings` | Return ``True`` if the lattice is constructible by doublings from the one-element lattice. :meth:`~FiniteLatticePoset.breadth` | Return the breadth of the lattice. **Specific elements** @@ -3599,24 +3600,47 @@ def is_constructible_by_doublings(self, type): subset of the lattice with a unique minimal element * ``'upper'`` - allow doublings of upper pseudo-interval; that is, a subset of the lattice with a unique maximal element - * ``'convex'`` - allow doubling of any convex set (not implemented) + * ``'convex'`` - allow doubling of any convex set + * ``'any'`` - allow doubling of any set .. SEEALSO:: :meth:`day_doubling` - EXAMPLES:: + EXAMPLES: + + The pentagon can be constructed by doubling intervals; the 5-element + diamond can not be constructed by any doublings:: sage: Posets.PentagonPoset().is_constructible_by_doublings('interval') True + + sage: Posets.DiamondPoset(5).is_constructible_by_doublings('any') + False + + After doubling both upper and lower pseudo-interval a lattice is + constructible by convex subset doubling:: + sage: L = Posets.BooleanLattice(2) sage: L = L.day_doubling([0, 1, 2]) # A lower pseudo-interval sage: L.is_constructible_by_doublings('interval') False sage: L.is_constructible_by_doublings('lower') True - sage: Posets.DiamondPoset(5).is_constructible_by_doublings('convex') # Not implemented + sage: L = L.day_doubling([(3,0), (1,1), (2,1)]) # An upper pseudo-interval + sage: L.is_constructible_by_doublings('upper') + False + sage: L.is_constructible_by_doublings('convex') + True + + An example of a lattice that can be constructed by doublings + of a non-convex subsets:: + + sage: L = LatticePoset(DiGraph('OQC?a?@CO?G_C@?GA?O??_??@?BO?A_?G??C??_?@???')) + sage: L.is_constructible_by_doublings('convex') False + sage: L.is_constructible_by_doublings('any') + True TESTS:: @@ -3627,13 +3651,13 @@ def is_constructible_by_doublings(self, type): According to [HOLM2016]_ a lattice `L` is lower bounded if and only if `|\mathrm{Ji}(L)| = |\mathrm{Ji}(\mathrm{Con}\ L)|`, and so dually - `|\mathrm{Mi}(L)| = |\mathrm{Mi}(\mathrm{Con}\ L)|` in - upper bounded lattices. + `|\mathrm{Mi}(L)| = |\mathrm{Mi}(\mathrm{Con}\ L)|` in upper bounded + lattices. The same reference gives a test for being constructible by + convex or by any subset. """ - if type not in ['interval', 'lower', 'upper', 'convex']: - raise ValueError("type must be one on 'interval', 'lower', 'upper' or 'convex'") - if type == 'convex': - raise NotImplementedError("type 'convex' is not yet implemented") + if type not in ['interval', 'lower', 'upper', 'convex', 'any']: + raise ValueError("type must be one of 'interval', 'lower', 'upper', 'convex' or 'any'") + if self.cardinality() < 5: return True @@ -3647,6 +3671,30 @@ def is_constructible_by_doublings(self, type): if type == 'upper': return (len(self.meet_irreducibles()) == self._hasse_diagram.principal_congruences_poset()[0].cardinality()) + if type == 'convex': + return self._hasse_diagram.is_congruence_normal() + # type == 'any' + def splitting_depth_2(a, b): + """ + Return ``True`` if every block of `b` is made from + combining at most two blocks of `a`. + """ + return all(len([x for x in a if x.issubset(y)]) <= 2 for y in b) + + conL = self.congruences_lattice() + todo = [conL[0]] + reachable = [] + + while todo: + e = todo.pop() + for e_up in conL.upper_covers(e): + if e_up not in reachable: + if splitting_depth_2(e, e_up): + if len(e_up) == 1: # = the top of the cong. lattice + return True + reachable.append(e_up) + todo.append(e_up) + return False def is_isoform(self, certificate=False): """ From bd403fd911b32e4116125f12c51d1e0359e3e835 Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Tue, 25 Apr 2017 16:20:23 +0200 Subject: [PATCH 161/452] 22844:internal symbolic limit function --- src/sage/functions/other.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/sage/functions/other.py b/src/sage/functions/other.py index 5bb393999d6..df831ea2f94 100644 --- a/src/sage/functions/other.py +++ b/src/sage/functions/other.py @@ -2607,3 +2607,27 @@ def __init__(self): conversions=dict(maxima='sum')) symbolic_sum = Function_sum() + + +class Function_limit(BuiltinFunction): + """ + Placeholder symbolic limit function that is only accessible internally. + + EXAMPLES:: + + sage: from sage.functions.other import symbolic_limit as slimit + sage: slimit(1/x, x, +oo) + limit(1/x, x, +Infinity) + """ + def __init__(self): + """ + EXAMPLES:: + + sage: from sage.functions.other import symbolic_limit as slimit + sage: maxima(slimit(1/x, x, +oo)) + 0 + """ + BuiltinFunction.__init__(self, "limit", nargs=3, + conversions=dict(maxima='limit')) + +symbolic_limit = Function_limit() From c4e3cc31ef78814eb5c6b355e31e462e3297d994 Mon Sep 17 00:00:00 2001 From: Thierry Monteil Date: Wed, 26 Apr 2017 17:05:55 +0200 Subject: [PATCH 162/452] #22684 patch implementing comment 27. --- .../patches/22684_cone_reduce_memory_usage.patch | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 build/pkgs/normaliz/patches/22684_cone_reduce_memory_usage.patch diff --git a/build/pkgs/normaliz/patches/22684_cone_reduce_memory_usage.patch b/build/pkgs/normaliz/patches/22684_cone_reduce_memory_usage.patch new file mode 100644 index 00000000000..2a4e9e35c40 --- /dev/null +++ b/build/pkgs/normaliz/patches/22684_cone_reduce_memory_usage.patch @@ -0,0 +1,12 @@ +diff -druN src/source/libnormaliz/cone.cpp patches/source/libnormaliz/cone.cpp +--- src/source/libnormaliz/cone.cpp 2017-02-22 17:59:08.000000000 +0100 ++++ patches/source/libnormaliz/cone.cpp 2017-04-26 16:33:57.460366489 +0200 +@@ -3223,7 +3223,7 @@ + Deg1Elements=Matrix(0,dim); + ModuleGenerators=Matrix(0,dim); + +- Matrix Raw=ApproxCone.getDeg1ElementsMatrix(); ++ const Matrix& Raw=ApproxCone.getDeg1ElementsMatrix(); + Matrix Result(0,dim); + Matrix Eq=BasisChange.getEquations(); + Matrix Cong=BasisChange.getCongruences(); From a3d37576e3f8acad34579fa73b868867500c437f Mon Sep 17 00:00:00 2001 From: Leif Leonhardy Date: Wed, 3 Aug 2016 03:57:06 +0200 Subject: [PATCH 163/452] GMP-ECM: #20385: Upgrade package to 7.0.4 (preliminary patch, see below) * I haven't repackaged the upstream tarball (.tar.gz) [yet]. Not sure whether we could/should also delete some stuff not needed for Sage (cf. SPKG.txt); at least there's no spkg-src script. * I haven't touched spkg-install yet. We may address potential issues with SAGE_FAT_BINARY (mentioned both there and in SPKG.txt), as well as known problems with '-march=native -O3' on bdver[1-4] (AMD FX-???? Bulldozer/Piledriver, AMD Opteron 6[23]xx, etc.) where we should add '-mno-xop' because of bugs in (AFAIK) *every* GCC version that supports these processors, silently leading to broken code ("just" testsuite failures IIRC). Also, we currently copy Sage's config.guess (because it was newer at some point), which presumably is no longer necessary (but shouldn't hurt either, provided we keep Sage's up-to-date and GMP-ECM won't rely on its own.) * The doctests in sage/libs/libecm.pyx may need some changes, especially with respect to 'verbose' mode tests. --- build/pkgs/ecm/SPKG.txt | 6 - build/pkgs/ecm/checksums.ini | 8 +- build/pkgs/ecm/package-version.txt | 2 +- build/pkgs/ecm/patches/asm-align.patch | 627 ------------------------- 4 files changed, 5 insertions(+), 638 deletions(-) delete mode 100644 build/pkgs/ecm/patches/asm-align.patch diff --git a/build/pkgs/ecm/SPKG.txt b/build/pkgs/ecm/SPKG.txt index 9d3efd62a19..e8c3e7446ad 100644 --- a/build/pkgs/ecm/SPKG.txt +++ b/build/pkgs/ecm/SPKG.txt @@ -42,9 +42,3 @@ LGPL V3+ * We could save some space by removing the `src/build.vc10/` directory which isn't used in Sage. (It gets probably more worth in case also directories / files for later versions of Microsoft Visual C get added.) - -=== Patches === - * asm-align.patch: on OS X using Xcode 7, ".align 64" in the files - "x86_64/mulredc*.asm" causes an error, and similarly with ".align - 32,,16". These need to be changed to ".p2align 6" and ".p2align - 5,,4", respectively diff --git a/build/pkgs/ecm/checksums.ini b/build/pkgs/ecm/checksums.ini index e244bada1ca..9c24b0797ae 100644 --- a/build/pkgs/ecm/checksums.ini +++ b/build/pkgs/ecm/checksums.ini @@ -1,4 +1,4 @@ -tarball=ecm-VERSION.tar.bz2 -sha1=97a6f9fc68337d8dadebc4754a61fdfe97bb0136 -md5=6d70cd667b46e34080615ae361608fa7 -cksum=134247046 +tarball=ecm-VERSION.tar.gz +sha1=407e41af6f93214509810b954b88251e4b89e82b +md5=559b13454b2094fbf26b33ff4fc824b7 +cksum=3785569195 diff --git a/build/pkgs/ecm/package-version.txt b/build/pkgs/ecm/package-version.txt index ca08977a763..af19623c101 100644 --- a/build/pkgs/ecm/package-version.txt +++ b/build/pkgs/ecm/package-version.txt @@ -1 +1 @@ -6.4.4.p0 +7.0.4.p0 diff --git a/build/pkgs/ecm/patches/asm-align.patch b/build/pkgs/ecm/patches/asm-align.patch deleted file mode 100644 index 88e7a8f4f80..00000000000 --- a/build/pkgs/ecm/patches/asm-align.patch +++ /dev/null @@ -1,627 +0,0 @@ -diff -r -u ecm-6.4.4-orig/x86_64/mulredc10.asm ecm-6.4.4/x86_64/mulredc10.asm ---- ecm-6.4.4-orig/x86_64/mulredc10.asm 2013-02-27 07:17:52.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc10.asm 2015-09-23 21:02:14.000000000 -0700 -@@ -23,7 +23,7 @@ - include(`config.m4') - - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 bytes long - GLOBL GSYM_PREFIX`'mulredc10 - TYPE(GSYM_PREFIX`'mulredc`'10,`function') - -@@ -535,7 +535,7 @@ - # i > 0 passes - ######################################################################### - --.align 32,,16 -+.p2align 5,,4 - LABEL_SUFFIX(1) - - # register values at loop entry: %TP = tmp, %I = i, %YP = y, %MP = m -diff -r -u ecm-6.4.4-orig/x86_64/mulredc11.asm ecm-6.4.4/x86_64/mulredc11.asm ---- ecm-6.4.4-orig/x86_64/mulredc11.asm 2013-02-27 07:17:52.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc11.asm 2015-09-23 21:05:49.000000000 -0700 -@@ -23,7 +23,7 @@ - include(`config.m4') - - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 bytes long - GLOBL GSYM_PREFIX`'mulredc11 - TYPE(GSYM_PREFIX`'mulredc`'11,`function') - -@@ -579,7 +579,7 @@ - # i > 0 passes - ######################################################################### - --.align 32,,16 -+.p2align 5,,4 - LABEL_SUFFIX(1) - - # register values at loop entry: %TP = tmp, %I = i, %YP = y, %MP = m -diff -r -u ecm-6.4.4-orig/x86_64/mulredc12.asm ecm-6.4.4/x86_64/mulredc12.asm ---- ecm-6.4.4-orig/x86_64/mulredc12.asm 2013-02-27 07:17:52.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc12.asm 2015-09-23 21:05:55.000000000 -0700 -@@ -23,7 +23,7 @@ - include(`config.m4') - - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 bytes long - GLOBL GSYM_PREFIX`'mulredc12 - TYPE(GSYM_PREFIX`'mulredc`'12,`function') - -@@ -623,7 +623,7 @@ - # i > 0 passes - ######################################################################### - --.align 32,,16 -+.p2align 5,,4 - LABEL_SUFFIX(1) - - # register values at loop entry: %TP = tmp, %I = i, %YP = y, %MP = m -diff -r -u ecm-6.4.4-orig/x86_64/mulredc13.asm ecm-6.4.4/x86_64/mulredc13.asm ---- ecm-6.4.4-orig/x86_64/mulredc13.asm 2013-02-27 07:17:52.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc13.asm 2015-09-23 21:05:57.000000000 -0700 -@@ -23,7 +23,7 @@ - include(`config.m4') - - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 bytes long - GLOBL GSYM_PREFIX`'mulredc13 - TYPE(GSYM_PREFIX`'mulredc`'13,`function') - -@@ -667,7 +667,7 @@ - # i > 0 passes - ######################################################################### - --.align 32,,16 -+.p2align 5,,4 - LABEL_SUFFIX(1) - - # register values at loop entry: %TP = tmp, %I = i, %YP = y, %MP = m -diff -r -u ecm-6.4.4-orig/x86_64/mulredc14.asm ecm-6.4.4/x86_64/mulredc14.asm ---- ecm-6.4.4-orig/x86_64/mulredc14.asm 2013-02-27 07:17:52.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc14.asm 2015-09-23 21:05:59.000000000 -0700 -@@ -23,7 +23,7 @@ - include(`config.m4') - - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 bytes long - GLOBL GSYM_PREFIX`'mulredc14 - TYPE(GSYM_PREFIX`'mulredc`'14,`function') - -@@ -711,7 +711,7 @@ - # i > 0 passes - ######################################################################### - --.align 32,,16 -+.p2align 5,,4 - LABEL_SUFFIX(1) - - # register values at loop entry: %TP = tmp, %I = i, %YP = y, %MP = m -diff -r -u ecm-6.4.4-orig/x86_64/mulredc15.asm ecm-6.4.4/x86_64/mulredc15.asm ---- ecm-6.4.4-orig/x86_64/mulredc15.asm 2013-02-27 07:17:52.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc15.asm 2015-09-23 21:06:02.000000000 -0700 -@@ -23,7 +23,7 @@ - include(`config.m4') - - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 bytes long - GLOBL GSYM_PREFIX`'mulredc15 - TYPE(GSYM_PREFIX`'mulredc`'15,`function') - -@@ -755,7 +755,7 @@ - # i > 0 passes - ######################################################################### - --.align 32,,16 -+.p2align 5,,4 - LABEL_SUFFIX(1) - - # register values at loop entry: %TP = tmp, %I = i, %YP = y, %MP = m -diff -r -u ecm-6.4.4-orig/x86_64/mulredc16.asm ecm-6.4.4/x86_64/mulredc16.asm ---- ecm-6.4.4-orig/x86_64/mulredc16.asm 2013-02-27 07:17:52.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc16.asm 2015-09-23 21:06:03.000000000 -0700 -@@ -23,7 +23,7 @@ - include(`config.m4') - - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 bytes long - GLOBL GSYM_PREFIX`'mulredc16 - TYPE(GSYM_PREFIX`'mulredc`'16,`function') - -@@ -799,7 +799,7 @@ - # i > 0 passes - ######################################################################### - --.align 32,,16 -+.p2align 5,,4 - LABEL_SUFFIX(1) - - # register values at loop entry: %TP = tmp, %I = i, %YP = y, %MP = m -diff -r -u ecm-6.4.4-orig/x86_64/mulredc17.asm ecm-6.4.4/x86_64/mulredc17.asm ---- ecm-6.4.4-orig/x86_64/mulredc17.asm 2013-02-27 07:17:52.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc17.asm 2015-09-23 21:06:05.000000000 -0700 -@@ -23,7 +23,7 @@ - include(`config.m4') - - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 bytes long - GLOBL GSYM_PREFIX`'mulredc17 - TYPE(GSYM_PREFIX`'mulredc`'17,`function') - -@@ -843,7 +843,7 @@ - # i > 0 passes - ######################################################################### - --.align 32,,16 -+.p2align 5,,4 - LABEL_SUFFIX(1) - - # register values at loop entry: %TP = tmp, %I = i, %YP = y, %MP = m -diff -r -u ecm-6.4.4-orig/x86_64/mulredc18.asm ecm-6.4.4/x86_64/mulredc18.asm ---- ecm-6.4.4-orig/x86_64/mulredc18.asm 2013-02-27 07:17:52.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc18.asm 2015-09-23 21:06:07.000000000 -0700 -@@ -23,7 +23,7 @@ - include(`config.m4') - - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 bytes long - GLOBL GSYM_PREFIX`'mulredc18 - TYPE(GSYM_PREFIX`'mulredc`'18,`function') - -@@ -887,7 +887,7 @@ - # i > 0 passes - ######################################################################### - --.align 32,,16 -+.p2align 5,,4 - LABEL_SUFFIX(1) - - # register values at loop entry: %TP = tmp, %I = i, %YP = y, %MP = m -diff -r -u ecm-6.4.4-orig/x86_64/mulredc19.asm ecm-6.4.4/x86_64/mulredc19.asm ---- ecm-6.4.4-orig/x86_64/mulredc19.asm 2013-02-27 07:17:53.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc19.asm 2015-09-23 21:06:10.000000000 -0700 -@@ -23,7 +23,7 @@ - include(`config.m4') - - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 bytes long - GLOBL GSYM_PREFIX`'mulredc19 - TYPE(GSYM_PREFIX`'mulredc`'19,`function') - -@@ -931,7 +931,7 @@ - # i > 0 passes - ######################################################################### - --.align 32,,16 -+.p2align 5,,4 - LABEL_SUFFIX(1) - - # register values at loop entry: %TP = tmp, %I = i, %YP = y, %MP = m -diff -r -u ecm-6.4.4-orig/x86_64/mulredc1_10.asm ecm-6.4.4/x86_64/mulredc1_10.asm ---- ecm-6.4.4-orig/x86_64/mulredc1_10.asm 2013-02-27 07:17:53.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc1_10.asm 2015-09-23 20:52:08.000000000 -0700 -@@ -18,7 +18,7 @@ - define(`INVM_PARAM',`%r8')dnl' - )dnl - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 bytes long - GLOBL GSYM_PREFIX`'mulredc1_10 - TYPE(GSYM_PREFIX`'mulredc1_`'10,`function') - -diff -r -u ecm-6.4.4-orig/x86_64/mulredc1_11.asm ecm-6.4.4/x86_64/mulredc1_11.asm ---- ecm-6.4.4-orig/x86_64/mulredc1_11.asm 2013-02-27 07:17:53.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc1_11.asm 2015-09-23 21:03:24.000000000 -0700 -@@ -18,7 +18,7 @@ - define(`INVM_PARAM',`%r8')dnl' - )dnl - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc1_11 - TYPE(GSYM_PREFIX`'mulredc1_`'11,`function') - -diff -r -u ecm-6.4.4-orig/x86_64/mulredc1_12.asm ecm-6.4.4/x86_64/mulredc1_12.asm ---- ecm-6.4.4-orig/x86_64/mulredc1_12.asm 2013-02-27 07:17:53.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc1_12.asm 2015-09-23 21:03:25.000000000 -0700 -@@ -18,7 +18,7 @@ - define(`INVM_PARAM',`%r8')dnl' - )dnl - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc1_12 - TYPE(GSYM_PREFIX`'mulredc1_`'12,`function') - -diff -r -u ecm-6.4.4-orig/x86_64/mulredc1_13.asm ecm-6.4.4/x86_64/mulredc1_13.asm ---- ecm-6.4.4-orig/x86_64/mulredc1_13.asm 2013-02-27 07:17:53.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc1_13.asm 2015-09-23 21:03:25.000000000 -0700 -@@ -18,7 +18,7 @@ - define(`INVM_PARAM',`%r8')dnl' - )dnl - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc1_13 - TYPE(GSYM_PREFIX`'mulredc1_`'13,`function') - -diff -r -u ecm-6.4.4-orig/x86_64/mulredc1_14.asm ecm-6.4.4/x86_64/mulredc1_14.asm ---- ecm-6.4.4-orig/x86_64/mulredc1_14.asm 2013-02-27 07:17:53.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc1_14.asm 2015-09-23 21:03:25.000000000 -0700 -@@ -18,7 +18,7 @@ - define(`INVM_PARAM',`%r8')dnl' - )dnl - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc1_14 - TYPE(GSYM_PREFIX`'mulredc1_`'14,`function') - -diff -r -u ecm-6.4.4-orig/x86_64/mulredc1_15.asm ecm-6.4.4/x86_64/mulredc1_15.asm ---- ecm-6.4.4-orig/x86_64/mulredc1_15.asm 2013-02-27 07:17:53.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc1_15.asm 2015-09-23 21:03:25.000000000 -0700 -@@ -18,7 +18,7 @@ - define(`INVM_PARAM',`%r8')dnl' - )dnl - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc1_15 - TYPE(GSYM_PREFIX`'mulredc1_`'15,`function') - -diff -r -u ecm-6.4.4-orig/x86_64/mulredc1_16.asm ecm-6.4.4/x86_64/mulredc1_16.asm ---- ecm-6.4.4-orig/x86_64/mulredc1_16.asm 2013-02-27 07:17:53.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc1_16.asm 2015-09-23 21:03:26.000000000 -0700 -@@ -18,7 +18,7 @@ - define(`INVM_PARAM',`%r8')dnl' - )dnl - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc1_16 - TYPE(GSYM_PREFIX`'mulredc1_`'16,`function') - -diff -r -u ecm-6.4.4-orig/x86_64/mulredc1_17.asm ecm-6.4.4/x86_64/mulredc1_17.asm ---- ecm-6.4.4-orig/x86_64/mulredc1_17.asm 2013-02-27 07:17:53.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc1_17.asm 2015-09-23 21:03:26.000000000 -0700 -@@ -18,7 +18,7 @@ - define(`INVM_PARAM',`%r8')dnl' - )dnl - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc1_17 - TYPE(GSYM_PREFIX`'mulredc1_`'17,`function') - -diff -r -u ecm-6.4.4-orig/x86_64/mulredc1_18.asm ecm-6.4.4/x86_64/mulredc1_18.asm ---- ecm-6.4.4-orig/x86_64/mulredc1_18.asm 2013-02-27 07:17:53.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc1_18.asm 2015-09-23 21:03:26.000000000 -0700 -@@ -18,7 +18,7 @@ - define(`INVM_PARAM',`%r8')dnl' - )dnl - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc1_18 - TYPE(GSYM_PREFIX`'mulredc1_`'18,`function') - -diff -r -u ecm-6.4.4-orig/x86_64/mulredc1_19.asm ecm-6.4.4/x86_64/mulredc1_19.asm ---- ecm-6.4.4-orig/x86_64/mulredc1_19.asm 2013-02-27 07:17:53.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc1_19.asm 2015-09-23 21:03:26.000000000 -0700 -@@ -18,7 +18,7 @@ - define(`INVM_PARAM',`%r8')dnl' - )dnl - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc1_19 - TYPE(GSYM_PREFIX`'mulredc1_`'19,`function') - -diff -r -u ecm-6.4.4-orig/x86_64/mulredc1_2.asm ecm-6.4.4/x86_64/mulredc1_2.asm ---- ecm-6.4.4-orig/x86_64/mulredc1_2.asm 2013-02-27 07:17:53.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc1_2.asm 2015-09-23 21:03:26.000000000 -0700 -@@ -18,7 +18,7 @@ - define(`INVM_PARAM',`%r8')dnl' - )dnl - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc1_2 - TYPE(GSYM_PREFIX`'mulredc1_`'2,`function') - -diff -r -u ecm-6.4.4-orig/x86_64/mulredc1_20.asm ecm-6.4.4/x86_64/mulredc1_20.asm ---- ecm-6.4.4-orig/x86_64/mulredc1_20.asm 2013-02-27 07:17:53.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc1_20.asm 2015-09-23 21:03:27.000000000 -0700 -@@ -18,7 +18,7 @@ - define(`INVM_PARAM',`%r8')dnl' - )dnl - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc1_20 - TYPE(GSYM_PREFIX`'mulredc1_`'20,`function') - -diff -r -u ecm-6.4.4-orig/x86_64/mulredc1_3.asm ecm-6.4.4/x86_64/mulredc1_3.asm ---- ecm-6.4.4-orig/x86_64/mulredc1_3.asm 2013-02-27 07:17:53.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc1_3.asm 2015-09-23 21:03:27.000000000 -0700 -@@ -18,7 +18,7 @@ - define(`INVM_PARAM',`%r8')dnl' - )dnl - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc1_3 - TYPE(GSYM_PREFIX`'mulredc1_`'3,`function') - -diff -r -u ecm-6.4.4-orig/x86_64/mulredc1_4.asm ecm-6.4.4/x86_64/mulredc1_4.asm ---- ecm-6.4.4-orig/x86_64/mulredc1_4.asm 2013-02-27 07:17:53.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc1_4.asm 2015-09-23 21:03:28.000000000 -0700 -@@ -18,7 +18,7 @@ - define(`INVM_PARAM',`%r8')dnl' - )dnl - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc1_4 - TYPE(GSYM_PREFIX`'mulredc1_`'4,`function') - -diff -r -u ecm-6.4.4-orig/x86_64/mulredc1_5.asm ecm-6.4.4/x86_64/mulredc1_5.asm ---- ecm-6.4.4-orig/x86_64/mulredc1_5.asm 2013-02-27 07:17:53.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc1_5.asm 2015-09-23 21:03:28.000000000 -0700 -@@ -18,7 +18,7 @@ - define(`INVM_PARAM',`%r8')dnl' - )dnl - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc1_5 - TYPE(GSYM_PREFIX`'mulredc1_`'5,`function') - -diff -r -u ecm-6.4.4-orig/x86_64/mulredc1_6.asm ecm-6.4.4/x86_64/mulredc1_6.asm ---- ecm-6.4.4-orig/x86_64/mulredc1_6.asm 2013-02-27 07:17:53.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc1_6.asm 2015-09-23 21:03:28.000000000 -0700 -@@ -18,7 +18,7 @@ - define(`INVM_PARAM',`%r8')dnl' - )dnl - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc1_6 - TYPE(GSYM_PREFIX`'mulredc1_`'6,`function') - -diff -r -u ecm-6.4.4-orig/x86_64/mulredc1_7.asm ecm-6.4.4/x86_64/mulredc1_7.asm ---- ecm-6.4.4-orig/x86_64/mulredc1_7.asm 2013-02-27 07:17:53.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc1_7.asm 2015-09-23 21:03:28.000000000 -0700 -@@ -18,7 +18,7 @@ - define(`INVM_PARAM',`%r8')dnl' - )dnl - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc1_7 - TYPE(GSYM_PREFIX`'mulredc1_`'7,`function') - -diff -r -u ecm-6.4.4-orig/x86_64/mulredc1_8.asm ecm-6.4.4/x86_64/mulredc1_8.asm ---- ecm-6.4.4-orig/x86_64/mulredc1_8.asm 2013-02-27 07:17:53.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc1_8.asm 2015-09-23 21:03:28.000000000 -0700 -@@ -18,7 +18,7 @@ - define(`INVM_PARAM',`%r8')dnl' - )dnl - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc1_8 - TYPE(GSYM_PREFIX`'mulredc1_`'8,`function') - -diff -r -u ecm-6.4.4-orig/x86_64/mulredc1_9.asm ecm-6.4.4/x86_64/mulredc1_9.asm ---- ecm-6.4.4-orig/x86_64/mulredc1_9.asm 2013-02-27 07:17:53.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc1_9.asm 2015-09-23 21:03:29.000000000 -0700 -@@ -18,7 +18,7 @@ - define(`INVM_PARAM',`%r8')dnl' - )dnl - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc1_9 - TYPE(GSYM_PREFIX`'mulredc1_`'9,`function') - -diff -r -u ecm-6.4.4-orig/x86_64/mulredc2.asm ecm-6.4.4/x86_64/mulredc2.asm ---- ecm-6.4.4-orig/x86_64/mulredc2.asm 2013-02-27 07:17:52.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc2.asm 2015-09-23 21:04:57.000000000 -0700 -@@ -23,7 +23,7 @@ - include(`config.m4') - - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc2 - TYPE(GSYM_PREFIX`'mulredc`'2,`function') - -@@ -183,7 +183,7 @@ - # i > 0 passes - ######################################################################### - --.align 32,,16 -+.p2align 5,,4 - LABEL_SUFFIX(1) - - # register values at loop entry: %TP = tmp, %I = i, %YP = y, %MP = m -diff -r -u ecm-6.4.4-orig/x86_64/mulredc20.asm ecm-6.4.4/x86_64/mulredc20.asm ---- ecm-6.4.4-orig/x86_64/mulredc20.asm 2013-02-27 07:17:53.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc20.asm 2015-09-23 21:05:17.000000000 -0700 -@@ -23,7 +23,7 @@ - include(`config.m4') - - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc20 - TYPE(GSYM_PREFIX`'mulredc`'20,`function') - -@@ -975,7 +975,7 @@ - # i > 0 passes - ######################################################################### - --.align 32,,16 -+.p2align 5,,4 - LABEL_SUFFIX(1) - - # register values at loop entry: %TP = tmp, %I = i, %YP = y, %MP = m -diff -r -u ecm-6.4.4-orig/x86_64/mulredc3.asm ecm-6.4.4/x86_64/mulredc3.asm ---- ecm-6.4.4-orig/x86_64/mulredc3.asm 2013-02-27 07:17:52.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc3.asm 2015-09-23 21:06:14.000000000 -0700 -@@ -23,7 +23,7 @@ - include(`config.m4') - - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc3 - TYPE(GSYM_PREFIX`'mulredc`'3,`function') - -@@ -227,7 +227,7 @@ - # i > 0 passes - ######################################################################### - --.align 32,,16 -+.p2align 5,,4 - LABEL_SUFFIX(1) - - # register values at loop entry: %TP = tmp, %I = i, %YP = y, %MP = m -diff -r -u ecm-6.4.4-orig/x86_64/mulredc4.asm ecm-6.4.4/x86_64/mulredc4.asm ---- ecm-6.4.4-orig/x86_64/mulredc4.asm 2013-02-27 07:17:52.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc4.asm 2015-09-23 21:06:18.000000000 -0700 -@@ -23,7 +23,7 @@ - include(`config.m4') - - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc4 - TYPE(GSYM_PREFIX`'mulredc`'4,`function') - -@@ -271,7 +271,7 @@ - # i > 0 passes - ######################################################################### - --.align 32,,16 -+.p2align 5,,4 - LABEL_SUFFIX(1) - - # register values at loop entry: %TP = tmp, %I = i, %YP = y, %MP = m -diff -r -u ecm-6.4.4-orig/x86_64/mulredc5.asm ecm-6.4.4/x86_64/mulredc5.asm ---- ecm-6.4.4-orig/x86_64/mulredc5.asm 2013-02-27 07:17:52.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc5.asm 2015-09-23 21:06:23.000000000 -0700 -@@ -23,7 +23,7 @@ - include(`config.m4') - - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc5 - TYPE(GSYM_PREFIX`'mulredc`'5,`function') - -@@ -315,7 +315,7 @@ - # i > 0 passes - ######################################################################### - --.align 32,,16 -+.p2align 5,,4 - LABEL_SUFFIX(1) - - # register values at loop entry: %TP = tmp, %I = i, %YP = y, %MP = m -diff -r -u ecm-6.4.4-orig/x86_64/mulredc6.asm ecm-6.4.4/x86_64/mulredc6.asm ---- ecm-6.4.4-orig/x86_64/mulredc6.asm 2013-02-27 07:17:52.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc6.asm 2015-09-23 21:06:27.000000000 -0700 -@@ -23,7 +23,7 @@ - include(`config.m4') - - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc6 - TYPE(GSYM_PREFIX`'mulredc`'6,`function') - -@@ -359,7 +359,7 @@ - # i > 0 passes - ######################################################################### - --.align 32,,16 -+.p2align 5,,4 - LABEL_SUFFIX(1) - - # register values at loop entry: %TP = tmp, %I = i, %YP = y, %MP = m -diff -r -u ecm-6.4.4-orig/x86_64/mulredc7.asm ecm-6.4.4/x86_64/mulredc7.asm ---- ecm-6.4.4-orig/x86_64/mulredc7.asm 2013-02-27 07:17:52.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc7.asm 2015-09-23 21:06:31.000000000 -0700 -@@ -23,7 +23,7 @@ - include(`config.m4') - - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc7 - TYPE(GSYM_PREFIX`'mulredc`'7,`function') - -@@ -403,7 +403,7 @@ - # i > 0 passes - ######################################################################### - --.align 32,,16 -+.p2align 5,,4 - LABEL_SUFFIX(1) - - # register values at loop entry: %TP = tmp, %I = i, %YP = y, %MP = m -diff -r -u ecm-6.4.4-orig/x86_64/mulredc8.asm ecm-6.4.4/x86_64/mulredc8.asm ---- ecm-6.4.4-orig/x86_64/mulredc8.asm 2013-02-27 07:17:52.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc8.asm 2015-09-23 21:06:34.000000000 -0700 -@@ -23,7 +23,7 @@ - include(`config.m4') - - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc8 - TYPE(GSYM_PREFIX`'mulredc`'8,`function') - -@@ -447,7 +447,7 @@ - # i > 0 passes - ######################################################################### - --.align 32,,16 -+.p2align 5,,4 - LABEL_SUFFIX(1) - - # register values at loop entry: %TP = tmp, %I = i, %YP = y, %MP = m -diff -r -u ecm-6.4.4-orig/x86_64/mulredc9.asm ecm-6.4.4/x86_64/mulredc9.asm ---- ecm-6.4.4-orig/x86_64/mulredc9.asm 2013-02-27 07:17:52.000000000 -0800 -+++ ecm-6.4.4/x86_64/mulredc9.asm 2015-09-23 21:06:38.000000000 -0700 -@@ -23,7 +23,7 @@ - include(`config.m4') - - TEXT --.align 64 # Opteron L1 code cache line is 64 bytes long -+.p2align 6 # Opteron L1 code cache line is 64 5,,4 - GLOBL GSYM_PREFIX`'mulredc9 - TYPE(GSYM_PREFIX`'mulredc`'9,`function') - -@@ -491,7 +491,7 @@ - # i > 0 passes - ######################################################################### - --.align 32,,16 -+.p2align 5,,4 - LABEL_SUFFIX(1) - - # register values at loop entry: %TP = tmp, %I = i, %YP = y, %MP = m From 4caf9b78cc3d13ab661848d3421c0d2ad10efbab Mon Sep 17 00:00:00 2001 From: Leif Leonhardy Date: Wed, 3 Aug 2016 07:25:14 +0200 Subject: [PATCH 164/452] GMP-ECM: #20385: (Also) run 'make longcheck' in spkg-check --- build/pkgs/ecm/spkg-check | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/ecm/spkg-check b/build/pkgs/ecm/spkg-check index 0a5c34e24a7..1f42390bff7 100755 --- a/build/pkgs/ecm/spkg-check +++ b/build/pkgs/ecm/spkg-check @@ -14,7 +14,7 @@ cd src echo echo "Now running GMP-ECM's test suite..." -$MAKE check +$MAKE check longcheck if [ $? -ne 0 ]; then echo >&2 "Error: GMP-ECM's test suite failed." From a403b06a3bcb457d2c4af5a7d33f7a4950f14246 Mon Sep 17 00:00:00 2001 From: Leif Leonhardy Date: Wed, 3 Aug 2016 10:34:48 +0200 Subject: [PATCH 165/452] GMP-ECM: #20385: Restore note on work-around in SPKG.txt that accidentally got dropped in the 6.4.4 package. In spkg-install, we still work around a linker bug on MacOS X 10.5 PowerPC, namely when debugging is enabled ('-g'), 'configure' fails because Apple's linker crashes with a bus error. --- build/pkgs/ecm/SPKG.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/build/pkgs/ecm/SPKG.txt b/build/pkgs/ecm/SPKG.txt index e8c3e7446ad..78c9dacbfa3 100644 --- a/build/pkgs/ecm/SPKG.txt +++ b/build/pkgs/ecm/SPKG.txt @@ -39,6 +39,9 @@ LGPL V3+ "-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.) + * 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. + This *might* get fixed in later upstream releases. * We could save some space by removing the `src/build.vc10/` directory which isn't used in Sage. (It gets probably more worth in case also directories / files for later versions of Microsoft Visual C get added.) From d991a34aeb126324c163229ea415f0eb0caa90f0 Mon Sep 17 00:00:00 2001 From: Jeroen Demeyer Date: Thu, 27 Apr 2017 11:27:35 +0200 Subject: [PATCH 166/452] Remove Cygwin patch --- build/pkgs/ecm/patches/cygwin.patch | 26 -------------------------- 1 file changed, 26 deletions(-) delete mode 100644 build/pkgs/ecm/patches/cygwin.patch diff --git a/build/pkgs/ecm/patches/cygwin.patch b/build/pkgs/ecm/patches/cygwin.patch deleted file mode 100644 index 219d8f34ed9..00000000000 --- a/build/pkgs/ecm/patches/cygwin.patch +++ /dev/null @@ -1,26 +0,0 @@ -Make sure the assembly routines use the appropriate calling convention -for Windows in Cygwin as well. See https://trac.sagemath.org/ticket/21223 -diff -ruN a/configure.in b/configure.in ---- a/configure.in 2016-08-11 13:51:46.869520300 +0200 -+++ b/configure.in 2016-08-11 13:52:46.240830400 +0200 -@@ -256,7 +256,7 @@ - GMP_ASM_TYPE - - case $host in -- *-*-mingw32) GMP_DEFINE([WINDOWS64_ABI], 1) -+ *-*-mingw32|*cygwin*) GMP_DEFINE([WINDOWS64_ABI], 1) - AC_DEFINE([WINDOWS64_ABI], 1,[Define to 1 if x86_64 mulredc*() functions should be called with Windows ABI]);; - *) ;; - esac -diff -ruN a/configure b/configure ---- a/configure 2016-08-11 13:51:46.936572300 +0200 -+++ b/configure 2016-08-11 13:53:31.281801500 +0200 -@@ -12957,7 +12957,7 @@ - - - case $host in -- *-*-mingw32) -+ *-*-mingw32|*cygwin*) - echo 'define(, <1>)' >>$gmp_tmpconfigm4 - - From eaee6e002fd1b89dc5c63401f72a3ff93678825c Mon Sep 17 00:00:00 2001 From: Jeroen Demeyer Date: Thu, 27 Apr 2017 15:49:40 +0200 Subject: [PATCH 167/452] Fix libecm doctests --- src/sage/libs/libecm.pyx | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/sage/libs/libecm.pyx b/src/sage/libs/libecm.pyx index c06b9b96048..2825542bf5e 100644 --- a/src/sage/libs/libecm.pyx +++ b/src/sage/libs/libecm.pyx @@ -17,12 +17,16 @@ EXAMPLES:: sage: from sage.libs.libecm import ecmfactor sage: result = ecmfactor(999, 0.00) - sage: result[0] and (result[1] in [27, 37, 999]) + sage: result[0] + True + sage: result[1] in [3, 9, 27, 37, 999] or result[1] True sage: result = ecmfactor(999, 0.00, verbose=True) Performing one curve with B1=0 Found factor in step 1: ... - sage: result[0] and (result[1] in [27, 37, 999]) + sage: result[0] + True + sage: result[1] in [3, 9, 27, 37, 999] or result[1] True sage: ecmfactor(2^128+1,1000,sigma=227140902) (True, 5704689200685129054721, 227140902) From 89d245dfb738f78a6be12092e594038250adef7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 27 Apr 2017 17:54:59 +0200 Subject: [PATCH 168/452] py3: change doc for comparison in element classes --- .../coercion_and_categories.rst | 32 ++++++++----------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/src/doc/en/thematic_tutorials/coercion_and_categories.rst b/src/doc/en/thematic_tutorials/coercion_and_categories.rst index ea441a31ab6..102f90c3fd6 100644 --- a/src/doc/en/thematic_tutorials/coercion_and_categories.rst +++ b/src/doc/en/thematic_tutorials/coercion_and_categories.rst @@ -308,24 +308,21 @@ considerations: etc. **We do not override the default double underscore __add__, __mul__**, since otherwise, we could not use Sage's coercion model. -- Comparisons can be implemented using ``_cmp_``. This automatically - makes the relational operators like ``==`` and ``<`` work. In order - to support the Python ``cmp()`` function, it is safest to define both - ``_cmp_`` and ``__cmp__`` (because ``__cmp__`` is not inherited if - other comparison operators or ``__hash__`` are defined). Of course you - can just do ``__cmp__ = _cmp_``. +- Comparisons can be implemented using ``_richcmp_`` (recommended) or + ``_cmp_``. This automatically makes the relational operators like + ``==`` and ``<`` work. - Note that ``_cmp_`` should be provided, since otherwise comparison - does not work:: + Note that either ``_cmp_`` or ``_richcmp_`` should be provided, + since otherwise comparison does not work:: sage: class Foo(sage.structure.element.Element): ....: def __init__(self, parent, x): ....: self.x = x ....: def _repr_(self): - ....: return "<%s>"%self.x + ....: return "<%s>" % self.x sage: a = Foo(ZZ, 1) sage: b = Foo(ZZ, 2) - sage: cmp(a,b) + sage: a <= b Traceback (most recent call last): ... NotImplementedError: comparison not implemented for @@ -366,9 +363,9 @@ This gives rise to the following code:: ....: return self.d ....: def _repr_(self): ....: return "(%s):(%s)"%(self.n,self.d) - ....: def _cmp_(self, other): - ....: return cmp(self.n*other.denominator(), other.numerator()*self.d) - ....: __cmp__ = _cmp_ + ....: def _richcmp_(self, other, op): + ....: from sage.structure.sage_object import richcmp + ....: return richcmp(self.n*other.denominator(), other.numerator()*self.d, op) ....: def _add_(self, other): ....: C = self.__class__ ....: D = self.d*other.denominator() @@ -1857,12 +1854,9 @@ Appendix: The complete code # into the same parent, which is a fraction field. Hence, we # are allowed to use the denominator() and numerator() methods # on the second argument. - def _cmp_(self, other): - return cmp(self.n*other.denominator(), other.numerator()*self.d) - - # Support for cmp() (in this example, we don't define __hash__ - # so this is not strictly needed) - __cmp__ = _cmp_ + def _richcmp_(self, other, op): + from sage.structure.sage_object import richcmp + return richcmp(self.n*other.denominator(), other.numerator()*self.d, op) # Arithmetic methods, single underscore. We can assume that both # arguments are coerced into the same parent. From 19fb17de3547760c00d17b86c11fe18946f625f9 Mon Sep 17 00:00:00 2001 From: Jeroen Demeyer Date: Fri, 28 Apr 2017 16:45:47 +0200 Subject: [PATCH 169/452] Stop using stdsage.pxi --- src/sage/categories/map.pyx | 20 +- src/sage/combinat/combinat_cython.pyx | 8 +- .../groups/perm_gps/permgroup_element.pyx | 21 +- src/sage/libs/flint/fmpz_poly.pyx | 8 +- .../libs/linkages/padics/fmpz_poly_unram.pxi | 5 +- src/sage/libs/linkages/padics/mpz.pxi | 4 +- src/sage/libs/mpmath/ext_impl.pyx | 16 +- src/sage/libs/mpmath/ext_main.pyx | 17 +- src/sage/libs/ntl/ntl_ZZ.pyx | 8 +- src/sage/libs/ntl/ntl_ZZ_pX.pyx | 6 +- src/sage/libs/sirocco.pyx | 11 +- src/sage/matrix/docs.py | 4 +- src/sage/matrix/matrix_integer_dense.pyx | 19 +- src/sage/matrix/matrix_rational_dense.pyx | 14 +- src/sage/matrix/matrix_rational_sparse.pyx | 23 +- .../modular/modform/eis_series_cython.pyx | 13 +- src/sage/modular/pollack_stevens/dist.pyx | 390 +----------------- src/sage/modules/vector_integer_dense.pyx | 10 +- src/sage/rings/fast_arith.pyx | 4 +- src/sage/rings/finite_rings/integer_mod.pyx | 5 +- src/sage/rings/integer.pyx | 9 +- src/sage/rings/integer_ring.pyx | 15 +- .../number_field/number_field_element.pyx | 20 +- .../number_field_element_quadratic.pyx | 18 +- src/sage/rings/number_field/totallyreal.pyx | 12 +- src/sage/rings/padics/CA_template.pxi | 8 +- src/sage/rings/padics/CR_template.pxi | 10 +- src/sage/rings/padics/FM_template.pxi | 9 +- .../rings/padics/padic_ZZ_pX_FM_element.pyx | 21 +- .../padics/padic_capped_absolute_element.pyx | 11 +- src/sage/rings/padics/pow_computer_ext.pyx | 15 +- .../polynomial_integer_dense_flint.pyx | 35 +- .../polynomial_integer_dense_ntl.pyx | 18 +- .../polynomial/polynomial_rational_flint.pyx | 8 +- src/sage/rings/rational.pyx | 34 +- src/sage/rings/real_double.pyx | 6 +- src/sage/structure/list_clone.pyx | 23 +- src/sage/structure/parent_base.pyx | 55 +-- src/sage/structure/parent_gens.pyx | 20 +- src/sage/structure/parent_old.pyx | 29 +- 40 files changed, 271 insertions(+), 711 deletions(-) diff --git a/src/sage/categories/map.pyx b/src/sage/categories/map.pyx index fde87261ba5..07846e65d74 100644 --- a/src/sage/categories/map.pyx +++ b/src/sage/categories/map.pyx @@ -8,26 +8,22 @@ AUTHORS: - Sebastien Besnier (2014-05-5): :class:`FormalCompositeMap` contains a list of Map instead of only two Map. See :trac:`16291`. """ + #***************************************************************************** # Copyright (C) 2008 Robert Bradshaw # -# 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: -# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** -from __future__ import absolute_import -from __future__ import print_function -include "sage/ext/stdsage.pxi" +from __future__ import absolute_import, print_function + from . import homset import weakref +from sage.ext.stdsage cimport HAS_DICTIONARY from sage.structure.parent cimport Set_PythonType from sage.misc.constant_function import ConstantFunction from sage.misc.superseded import deprecated_function_alias diff --git a/src/sage/combinat/combinat_cython.pyx b/src/sage/combinat/combinat_cython.pyx index f4c3ef65c1e..0d87fabcc04 100644 --- a/src/sage/combinat/combinat_cython.pyx +++ b/src/sage/combinat/combinat_cython.pyx @@ -9,8 +9,7 @@ AUTHORS: """ -include "sage/ext/stdsage.pxi" - +from cysignals.memory cimport check_allocarray, sig_free from sage.libs.gmp.all cimport * from sage.rings.integer cimport Integer @@ -93,7 +92,7 @@ cdef mpz_stirling_s2(mpz_t s, unsigned long n, unsigned long k): mpz_init(t) mpz_init(u) max_bc = (k+1)//2 - bc = sig_malloc((max_bc+1) * sizeof(mpz_t)) + bc = check_allocarray(max_bc+1, sizeof(mpz_t)) mpz_init_set_ui(bc[0], 1) for j in range(1, max_bc+1): mpz_init_set(bc[j], bc[j-1]) @@ -131,7 +130,6 @@ def _stirling_number2(n, k): This is wrapped again by stirling_number2 in combinat.py. """ - cdef Integer s - s = PY_NEW(Integer) + cdef Integer s = Integer.__new__(Integer) mpz_stirling_s2(s.value, n, k) return s diff --git a/src/sage/groups/perm_gps/permgroup_element.pyx b/src/sage/groups/perm_gps/permgroup_element.pyx index c2dea51a6b5..4e91c4b23bf 100644 --- a/src/sage/groups/perm_gps/permgroup_element.pyx +++ b/src/sage/groups/perm_gps/permgroup_element.pyx @@ -45,22 +45,27 @@ degree. (1,30)(2,29)(3,28)(4,27)(5,26)(6,25)(7,24)(8,23)(9,22)(10,21)(11,20)(12,19)(13,18)(14,17)(15,16) """ -########################################################################### -# Copyright (C) 2006 William Stein -# Copyright (C) 2006 David Joyner +#***************************************************************************** +# Copyright (C) 2006 William Stein +# Copyright (C) 2006 David Joyner # -# Distributed under the terms of the GNU General Public License (GPL) +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. # http://www.gnu.org/licenses/ -########################################################################### -from __future__ import print_function - +#***************************************************************************** + +from __future__ import absolute_import, print_function + import random import sage.groups.old as group -include "sage/ext/stdsage.pxi" +from cysignals.memory cimport sig_malloc, sig_realloc, sig_free from cpython.list cimport * +from sage.ext.stdsage cimport HAS_DICTIONARY from sage.rings.all import ZZ, Integer from sage.rings.polynomial.polynomial_element import is_Polynomial from sage.rings.polynomial.multi_polynomial import is_MPolynomial diff --git a/src/sage/libs/flint/fmpz_poly.pyx b/src/sage/libs/flint/fmpz_poly.pyx index 2b197e688e9..4a08558827a 100644 --- a/src/sage/libs/flint/fmpz_poly.pyx +++ b/src/sage/libs/flint/fmpz_poly.pyx @@ -17,12 +17,12 @@ AUTHORS: # (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** -include 'sage/ext/stdsage.pxi' - -from sage.misc.long cimport pyobject_to_long from cpython.sequence cimport * +from cysignals.memory cimport sig_free + +from sage.misc.long cimport pyobject_to_long from sage.structure.sage_object cimport SageObject from sage.rings.integer cimport Integer from sage.libs.flint.fmpz_poly cimport * @@ -102,7 +102,7 @@ cdef class Fmpz_poly(SageObject): sage: f[200] 0 """ - cdef Integer res = PY_NEW(Integer) + cdef Integer res = Integer.__new__(Integer) fmpz_poly_get_coeff_mpz(res.value, self.poly, i) return res diff --git a/src/sage/libs/linkages/padics/fmpz_poly_unram.pxi b/src/sage/libs/linkages/padics/fmpz_poly_unram.pxi index f5915a824be..17dd038d12b 100644 --- a/src/sage/libs/linkages/padics/fmpz_poly_unram.pxi +++ b/src/sage/libs/linkages/padics/fmpz_poly_unram.pxi @@ -17,10 +17,11 @@ AUTHORS: # http://www.gnu.org/licenses/ #***************************************************************************** -include "sage/ext/stdsage.pxi" -include "cysignals/signals.pxi" +from cysignals.signals cimport sig_on, sig_off from cpython.list cimport PyList_Check, PyList_New, PyList_Append +from sage.ext.stdsage cimport PY_NEW + 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 from sage.rings.integer cimport Integer diff --git a/src/sage/libs/linkages/padics/mpz.pxi b/src/sage/libs/linkages/padics/mpz.pxi index 8bb4d23a232..7436ffee109 100644 --- a/src/sage/libs/linkages/padics/mpz.pxi +++ b/src/sage/libs/linkages/padics/mpz.pxi @@ -16,10 +16,10 @@ AUTHORS: # http://www.gnu.org/licenses/ #***************************************************************************** -include "sage/ext/stdsage.pxi" -include "cysignals/signals.pxi" +from cysignals.signals cimport sig_on, sig_off from cpython.list cimport * +from sage.ext.stdsage cimport PY_NEW from sage.libs.gmp.mpz cimport * from sage.libs.gmp.pylong cimport mpz_pythonhash from sage.arith.rational_reconstruction cimport mpq_rational_reconstruction diff --git a/src/sage/libs/mpmath/ext_impl.pyx b/src/sage/libs/mpmath/ext_impl.pyx index f143beab906..952b20b7998 100644 --- a/src/sage/libs/mpmath/ext_impl.pyx +++ b/src/sage/libs/mpmath/ext_impl.pyx @@ -16,10 +16,17 @@ See if :trac:`15118` is fixed:: ... ZeroDivisionError """ -from __future__ import print_function -include "cysignals/signals.pxi" -include "sage/ext/stdsage.pxi" +#***************************************************************************** +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# http://www.gnu.org/licenses/ +#***************************************************************************** + +from __future__ import absolute_import, print_function + from cpython.int cimport * from cpython.long cimport * from cpython.float cimport * @@ -29,6 +36,9 @@ from cpython.number cimport * from libc.math cimport sqrt as fsqrt from libc.math cimport frexp +from cysignals.signals cimport sig_check + +from sage.ext.stdsage import PY_NEW from sage.libs.gmp.all cimport * from sage.libs.mpfr cimport * from sage.rings.integer cimport Integer diff --git a/src/sage/libs/mpmath/ext_main.pyx b/src/sage/libs/mpmath/ext_main.pyx index 77afb2b5bcb..a7a278be4ff 100644 --- a/src/sage/libs/mpmath/ext_main.pyx +++ b/src/sage/libs/mpmath/ext_main.pyx @@ -5,16 +5,27 @@ Implements mpf and mpc types, with binary operations and support for interaction with other types. Also implements the main context class, and related utilities. """ -from __future__ import print_function -include "cysignals/signals.pxi" -include "sage/ext/stdsage.pxi" +#***************************************************************************** +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# http://www.gnu.org/licenses/ +#***************************************************************************** + +from __future__ import absolute_import, print_function + from cpython.int cimport * from cpython.long cimport * from cpython.float cimport * from cpython.complex cimport * from cpython.number cimport * +from cysignals.signals cimport sig_on, sig_off + +from sage.ext.stdsage cimport PY_NEW + from sage.libs.gmp.all cimport * from sage.rings.integer cimport Integer diff --git a/src/sage/libs/ntl/ntl_ZZ.pyx b/src/sage/libs/ntl/ntl_ZZ.pyx index 4c29605ae68..17f143e2f79 100644 --- a/src/sage/libs/ntl/ntl_ZZ.pyx +++ b/src/sage/libs/ntl/ntl_ZZ.pyx @@ -14,8 +14,8 @@ #***************************************************************************** from __future__ import print_function -include "cysignals/signals.pxi" -include "sage/ext/stdsage.pxi" +from cysignals.signals cimport sig_on, sig_off + include 'misc.pxi' include 'decl.pxi' @@ -167,7 +167,7 @@ cdef class ntl_ZZ(object): Agrees with the hash of the corresponding sage integer. """ - cdef Integer v = PY_NEW(Integer) + cdef Integer v = Integer.__new__(Integer) ZZ_to_mpz(v.value, &self.x) return v.hash_c() @@ -293,7 +293,7 @@ cdef class ntl_ZZ(object): AUTHOR: Joel B. Mohler """ - cdef Integer ans = PY_NEW(Integer) + cdef Integer ans = Integer.__new__(Integer) ZZ_to_mpz(ans.value, &self.x) return ans #return (ZZ_sage)._coerce_ZZ(&self.x) diff --git a/src/sage/libs/ntl/ntl_ZZ_pX.pyx b/src/sage/libs/ntl/ntl_ZZ_pX.pyx index 9fe37f096f3..7fa70db4441 100644 --- a/src/sage/libs/ntl/ntl_ZZ_pX.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_pX.pyx @@ -15,8 +15,8 @@ from __future__ import absolute_import, division, print_function -include "cysignals/signals.pxi" -include "sage/ext/stdsage.pxi" +from cysignals.signals cimport sig_on, sig_off + include 'misc.pxi' include 'decl.pxi' @@ -1421,7 +1421,7 @@ cdef class ntl_ZZ_pX_Modulus(object): return "NTL ZZ_pXModulus %s (mod %s)"%(self.poly, self.poly.c.p) def degree(self): - cdef Integer ans = PY_NEW(Integer) + cdef Integer ans = Integer.__new__(Integer) mpz_set_ui(ans.value, ZZ_pX_Modulus_deg(self.x)) return ans diff --git a/src/sage/libs/sirocco.pyx b/src/sage/libs/sirocco.pyx index 77e0484ed99..25486975b4a 100644 --- a/src/sage/libs/sirocco.pyx +++ b/src/sage/libs/sirocco.pyx @@ -9,16 +9,13 @@ AUTHORS: - Miguel Marco (2016-07-19): initial version. """ -include "cysignals/signals.pxi" -include "sage/ext/stdsage.pxi" +from cysignals.signals cimport sig_on, sig_off +from cysignals.memory cimport check_allocarray, sig_free as free from sage.libs.mpfr cimport * from sage.rings.real_mpfr cimport RealNumber from sage.rings.real_mpfr import RealField -cdef extern from "stdlib.h": - void free(void* ptr) - cdef extern from "sirocco.h": mpfr_t* homotopyPath_mp(int degree, mpfr_t *_coef, mpfr_t _y0R, mpfr_t _y0I, int prec) double* homotopyPath(int degree, double *_coef, double _y0R, double _y0I) @@ -34,7 +31,7 @@ cpdef list[list] contpath_mp(int deg, list values, RealNumber y0r, RealNumber y0 - A extra argument is needed, indicating the bits of precission used in the computations. """ - cdef mpfr_t* cvalues = sage_malloc(sizeof(mpfr_t)*len(values)) + cdef mpfr_t* cvalues = check_allocarray(len(values), sizeof(mpfr_t)) cdef mpfr_t* rop cdef int i, j cdef mpfr_t y0R @@ -98,7 +95,7 @@ cpdef list[list] contpath(int deg, list values, double y0r, double y0i): the piecewise linear approximation of the path tracked by the root. """ cdef double* rop - cdef double* c_values = sage_malloc(sizeof(double)*len(values)) + cdef double* c_values = check_allocarray(len(values), sizeof(double)) cdef int clen = len(values) cdef int i for i,v in enumerate(values): diff --git a/src/sage/matrix/docs.py b/src/sage/matrix/docs.py index d9add7956f1..97091b05d6d 100644 --- a/src/sage/matrix/docs.py +++ b/src/sage/matrix/docs.py @@ -365,8 +365,8 @@ class derived from Matrix). They can be either sparse or dense, and For each base field it is *absolutely* essential to completely implement the following functionality for that base ring: - * __cinit__ -- should use sig_malloc from ext/stdsage.pxi (only - needed if allocate memory) + * __cinit__ -- should use check_allocarray from cysignals.memory + (only needed if allocate memory) * __init__ -- this signature: 'def __init__(self, parent, entries, copy, coerce)' * __dealloc__ -- use sig_free (only needed if allocate memory) * set_unsafe(self, size_t i, size_t j, x) -- doesn't do bounds or any other checks; assumes x is in self._base_ring diff --git a/src/sage/matrix/matrix_integer_dense.pyx b/src/sage/matrix/matrix_integer_dense.pyx index 5ef68fd7d2b..bcd30f3234c 100644 --- a/src/sage/matrix/matrix_integer_dense.pyx +++ b/src/sage/matrix/matrix_integer_dense.pyx @@ -59,6 +59,10 @@ from __future__ import absolute_import, print_function from libc.stdint cimport int64_t from libc.string cimport strcpy, strlen + +from cysignals.signals cimport sig_check, sig_on, sig_str, sig_off +from cysignals.memory cimport sig_malloc, sig_free + from sage.libs.gmp.mpz cimport * from sage.modules.vector_integer_dense cimport Vector_integer_dense @@ -82,10 +86,6 @@ from cypari2.stack cimport clear_stack from cypari2.paridecl cimport * ######################################################### -include "cysignals/signals.pxi" -include "sage/ext/stdsage.pxi" - - from sage.arith.multi_modular cimport MultiModularBasis from sage.libs.flint.fmpz cimport * from sage.libs.flint.fmpz_mat cimport * @@ -506,7 +506,7 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse sage: a[-1,0] 6 """ - cdef Integer z = PY_NEW(Integer) + cdef Integer z = Integer.__new__(Integer) self.get_unsafe_mpz(i, j, z.value) return z @@ -1356,7 +1356,7 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse sage: a.height() 389 """ - cdef Integer x = PY_NEW(Integer) + cdef Integer x = Integer.__new__(Integer) self.mpz_height(x.value) return x @@ -3210,8 +3210,7 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse raise IndexError("matrix column index out of range") fmpz_add(s, s, fmpz_mat_entry(self._matrix,row,c)) fmpz_mul(pr, pr, s) - cdef Integer z - z = PY_NEW(Integer) + cdef Integer z = Integer.__new__(Integer) fmpz_get_mpz(z.value, pr) fmpz_clear(s) fmpz_clear(pr) @@ -3635,7 +3634,7 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse sig_on() cdef GEN d = det0(pari_GEN(self), flag) # now convert d to a Sage integer e - cdef Integer e = PY_NEW(Integer) + cdef Integer e = Integer.__new__(Integer) INT_to_mpz(e.value, d) clear_stack() return e @@ -4207,7 +4206,7 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse for j from 0 <= j < M._ncols: fmpz_set_mpz(fmpz_mat_entry(M._matrix,i,j), mp_N[k]) k += 1 - D = PY_NEW(Integer) + D = Integer.__new__(Integer) mpz_set(D.value, mp_D) return M, D finally: diff --git a/src/sage/matrix/matrix_rational_dense.pyx b/src/sage/matrix/matrix_rational_dense.pyx index 73aec6b4a93..07219126f22 100644 --- a/src/sage/matrix/matrix_rational_dense.pyx +++ b/src/sage/matrix/matrix_rational_dense.pyx @@ -55,10 +55,10 @@ from __future__ import absolute_import, print_function from libc.string cimport strcpy, strlen -from sage.modules.vector_rational_dense cimport Vector_rational_dense +from cysignals.signals cimport sig_check, sig_on, sig_off +from cysignals.memory cimport sig_malloc, sig_free -include "cysignals/signals.pxi" -include "sage/ext/stdsage.pxi" +from sage.modules.vector_rational_dense cimport Vector_rational_dense from sage.arith.rational_reconstruction cimport mpq_rational_reconstruction from sage.libs.gmp.randomize cimport * @@ -821,8 +821,7 @@ cdef class Matrix_rational_dense(Matrix_dense): sage: b.denominator() 293 """ - cdef Integer z - z = PY_NEW(Integer) + cdef Integer z = Integer.__new__(Integer) self.mpz_denom(z.value) return z @@ -872,7 +871,7 @@ cdef class Matrix_rational_dense(Matrix_dense): cdef fmpz_t aij fmpz_init(aij) mpz_init(tmp) - D = PY_NEW(Integer) + D = Integer.__new__(Integer) self.mpz_denom(D.value) from sage.matrix.matrix_space import MatrixSpace MZ = MatrixSpace(ZZ, self._nrows, self._ncols, sparse=self.is_sparse()) @@ -1121,8 +1120,7 @@ cdef class Matrix_rational_dense(Matrix_dense): sage: b.height() 5007 """ - cdef Integer z - z = PY_NEW(Integer) + cdef Integer z = Integer.__new__(Integer) self.mpz_height(z.value) return z diff --git a/src/sage/matrix/matrix_rational_sparse.pyx b/src/sage/matrix/matrix_rational_sparse.pyx index c4c34c26ad6..97081c5d9c5 100644 --- a/src/sage/matrix/matrix_rational_sparse.pyx +++ b/src/sage/matrix/matrix_rational_sparse.pyx @@ -14,20 +14,25 @@ TESTS:: [] """ -############################################################################## +#***************************************************************************** # Copyright (C) 2007 William Stein -# Distributed under the terms of the GNU General Public License (GPL) -# The full text of the GPL is available at: +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. # http://www.gnu.org/licenses/ -############################################################################## +#***************************************************************************** + from __future__ import absolute_import +from cysignals.signals cimport sig_on, sig_off +from cysignals.memory cimport sig_malloc, sig_free + from sage.data_structures.binary_search cimport * from sage.modules.vector_integer_sparse cimport * from sage.modules.vector_rational_sparse cimport * -include 'sage/ext/stdsage.pxi' -include "cysignals/signals.pxi" from cpython.sequence cimport * from sage.rings.rational cimport Rational @@ -375,8 +380,7 @@ cdef class Matrix_rational_sparse(Matrix_sparse): sage: b.height() 5007 """ - cdef Integer z - z = PY_NEW(Integer) + cdef Integer z = Integer.__new__(Integer) self.mpz_height(z.value) return z @@ -431,8 +435,7 @@ cdef class Matrix_rational_sparse(Matrix_sparse): sage: b.denominator() 293 """ - cdef Integer z - z = PY_NEW(Integer) + cdef Integer z = Integer.__new__(Integer) self.mpz_denom(z.value) return z diff --git a/src/sage/modular/modform/eis_series_cython.pyx b/src/sage/modular/modform/eis_series_cython.pyx index b6c0e484055..f7e944cb055 100644 --- a/src/sage/modular/modform/eis_series_cython.pyx +++ b/src/sage/modular/modform/eis_series_cython.pyx @@ -1,8 +1,9 @@ """ Eisenstein Series (optimized compiled functions) """ -include 'sage/ext/stdsage.pxi' -include "cysignals/signals.pxi" + +from cysignals.memory cimport check_allocarray, sig_free +from cysignals.signals cimport sig_on, sig_off from sage.rings.rational_field import QQ from sage.rings.power_series_ring import PowerSeriesRing @@ -60,8 +61,8 @@ cpdef Ek_ZZ(int k, int prec=10): # allocate the list for the result cdef list val = [] - for i from 0 <= i < prec: - pp = (PY_NEW(Integer)) + for i in range(prec): + pp = Integer.__new__(Integer) mpz_set_si(pp.value, 1) val.append(pp) @@ -71,7 +72,7 @@ cpdef Ek_ZZ(int k, int prec=10): max_power_sum = prec while max_power_sum: max_power_sum >>= 1 - pp = (PY_NEW(Integer)) + pp = Integer.__new__(Integer) mpz_set_si(pp.value, 1) power_sum_ls.append(pp) @@ -158,7 +159,7 @@ cpdef eisenstein_series_poly(int k, int prec = 10) : sage: eisenstein_series_poly(12, prec=5) 5 691 65520 134250480 11606736960 274945048560 """ - cdef mpz_t *val = sig_malloc(prec * sizeof(mpz_t)) + cdef mpz_t *val = check_allocarray(prec, sizeof(mpz_t)) cdef mpz_t one, mult, term, last, term_m1, last_m1 cdef unsigned long int expt cdef long ind, ppow, int_p diff --git a/src/sage/modular/pollack_stevens/dist.pyx b/src/sage/modular/pollack_stevens/dist.pyx index 945f6bf1a24..65c58d1bf12 100644 --- a/src/sage/modular/pollack_stevens/dist.pyx +++ b/src/sage/modular/pollack_stevens/dist.pyx @@ -52,9 +52,6 @@ from sage.rings.rational cimport Rational from sage.misc.misc import verbose, cputime from sage.rings.infinity import Infinity -include "cysignals/signals.pxi" -include "sage/ext/stdsage.pxi" - from sage.libs.flint.nmod_poly cimport (nmod_poly_init2_preinv, nmod_poly_set_coeff_ui, nmod_poly_inv_series, @@ -855,7 +852,7 @@ cdef class Dist_vector(Dist): sage: D = OverconvergentDistributions(3,5,4) # indirect doctest sage: v = D([1,1,1]) """ - cdef Dist_vector ans = PY_NEW(Dist_vector) + cdef Dist_vector ans = Dist_vector.__new__(Dist_vector) ans._parent = self._parent return ans @@ -1237,391 +1234,6 @@ cdef class Dist_vector(Dist): return ans -# cdef class Dist_long(Dist): -# r""" -# A class for distributions implemented using a C array of longs. - -# INPUT: - -# - ``moments`` -- the list of moments. If ``check == False`` it -# must be a vector in the appropriate approximation module. - -# - ``parent`` -- a :class:`distributions.OverconvergentDistributions_class` or -# :class:`distributions.Symk_class` instance - -# - ``check`` -- (default: True) boolean, whether to validate input - -# EXAMPLES:: - -# sage: from sage.modular.pollack_stevens.distributions import OverconvergentDistributions, Symk -# """ -# def __init__(self, moments, parent, ordp=0, check=True): -# """ -# Initialization. - -# TESTS:: - -# sage: from sage.modular.pollack_stevens.distributions import OverconvergentDistributions, Symk -# """ -# # if not hasattr(parent,'Element'): -# # parent, moments = moments, parent - -# Dist.__init__(self, parent) -# p = parent._p -# cdef int i -# if check: - -# # case 1: input is a distribution already -# if isinstance(moments, Dist): -# M = len(moments) -# moments = [ZZ(moments.moment(i)) for i in range(M)] -# # case 2: input is a vector, or something with a len -# elif hasattr(moments, '__len__'): -# M = len(moments) -# moments = [ZZ(a) for a in parent.approx_module(M)(moments)] -# # case 3: input is zero -# elif moments == 0: -# M = parent.precision_cap() -# moments = [ZZ(0)] * M -# else: -# M = 1 -# moments = [ZZ(moments)] -# if M > 100 or 7 * p ** M > ZZ(2) ** (4 * sizeof(long) - 1): # 6 is so that we don't overflow on gathers -# raise ValueError("moments too long") -# else: -# M = len(moments) - -# for i in range(len(moments)): -# self._moments[i] = moments[i] -# self.relprec = M -# self.prime_pow = parent.prime_pow -# self.normalize() - -# cdef Dist_long _new_c(self): -# r""" - - -# OUTPUT: - -# - - -# EXAMPLES:: - -# sage: from sage.modular.pollack_stevens.distributions import OverconvergentDistributions, Symk -# """ -# cdef Dist_long ans = PY_NEW(Dist_long) -# ans._parent = self._parent -# ans.prime_pow = self.prime_pow -# return ans - -# def _repr_(self): -# r""" - - -# OUTPUT: - -# - - -# EXAMPLES:: - -# sage: from sage.modular.pollack_stevens.distributions import OverconvergentDistributions, Symk -# """ -# valstr = "" -# if self.ordp == 1: -# valstr = "%s * " % (self.prime_pow.prime) -# elif self.ordp != 0: -# valstr = "%s^%s * " % (self.prime_pow.prime, self.ordp) -# if self.relprec == 1: -# return valstr + repr(self._moments[0]) -# else: -# return valstr + "(" + ", ".join([repr(self._moments[i]) for i in range(self.relprec)]) + ")" - -# cdef int quasi_normalize(self) except -1: -# r""" - - -# OUTPUT: - -# - - -# EXAMPLES:: - -# sage: from sage.modular.pollack_stevens.distributions import OverconvergentDistributions, Symk -# """ -# cdef int i -# for i in range(self.relprec): -# if self._moments[i] > overflow: -# self._moments[i] = self._moments[i] % self.prime_pow(self.relprec - i) -# elif self._moments[i] < underflow: -# self._moments[i] = self._moments[i] % self.prime_pow(self.relprec - i) -# self._moments[i] += self.prime_pow(self.relprec - i) - -# cpdef normalize(self): -# r""" - - -# OUTPUT: - -# - - -# EXAMPLES:: - -# sage: from sage.modular.pollack_stevens.distributions import OverconvergentDistributions, Symk -# """ -# cdef int i -# for i in range(1, self.relprec): # Don't normalize the zeroth moment -# if self._moments[i] < 0: -# self._moments[i] = self._moments[i] % self.prime_pow(self.relprec - i) -# self._moments[i] += self.prime_pow(self.relprec - i) -# elif self._moments[i] >= self.prime_pow(self.relprec - i): -# self._moments[i] = self._moments[i] % self.prime_pow(self.relprec - i) -# return self - -# cdef long _relprec(self): -# return self.relprec - -# cdef _unscaled_moment(self, long _n): -# r""" - - -# INPUT: - -# - ``_n`` -- an integer or slice giving an index into the -# moments. - -# OUTPUT: - -# - - -# EXAMPLES:: - -# sage: from sage.modular.pollack_stevens.distributions import OverconvergentDistributions, Symk -# """ -# if isinstance(_n, slice): -# a, b, c = _n.indices(self.relprec) -# return [self.moment(i) for i in range(a, b, c)] -# cdef int n = _n -# if n < 0: -# n += self.relprec -# if n < 0 or n >= self.relprec: -# raise IndexError("list index out of range") -# return self._moments[n] - -# cdef Dist_long _addsub(self, Dist_long right, bint negate): -# r""" -# Common code for the sum and the difference of two distributions -# """ -# cdef Dist_long ans = self._new_c() -# cdef long aprec = min(self.ordp + self.relprec, right.ordp + right.relprec) -# ans.ordp = min(self.ordp, right.ordp) -# ans.relprec = aprec - ans.ordp -# # In the case of symk, rprec will always be k -# cdef int i, n -# cdef long diff, cutoff -# # The following COULD overflow, but it would require 2^32 -# # additions (on a 64-bit machine), since we restrict p^k to be -# # less than 2^31/7. -# if self.ordp == right.ordp: -# n = min(self.relprec, right.relprec) -# for i in range(n): -# ans._moments[i] = self._moments[i] - right._moments[i] if negate else self._moments[i] + right._moments[i] -# if self.relprec < ans.relprec: -# for i in range(n, ans.relprec): -# ans._moments[i] = -right._moments[i] if negate else right._moments[i] -# elif ans.relprec < self.relprec: -# for i in range(n, ans.relprec): -# ans._moments[i] = self._moments[i] -# elif self.ordp < right.ordp: -# diff = right.ordp - self.ordp -# n = min(right.relprec, ans.relprec - diff) -# for i in range(n): -# ans._moments[i] = self.prime_pow(diff) * (right._moments[i] % self.prime_pow(ans.relprec - diff - i)) -# ans._moments[i] = self._moments[i] - ans._moments[i] if negate else self._moments[i] + ans._moments[i] -# if n < ans.relprec: -# for i in range(n, ans.relprec): -# ans._moments[i] = self._moments[i] -# else: # self.ordp > right.ordp -# diff = self.ordp - right.ordp -# n = min(self.relprec, ans.relprec - diff) -# for i in range(n): -# ans._moments[i] = self.prime_pow(diff) * (self._moments[i] % self.prime_pow(ans.relprec - diff - i)) -# ans._moments[i] += -right._moments[i] if negate else right._moments[i] -# if n < ans.relprec: -# for i in range(n, ans.relprec): -# ans._moments[i] = -right._moments[i] if negate else right._moments[i] -# return ans - -# cpdef _add_(self, ModuleElement right): -# r""" - - -# EXAMPLES:: - -# sage: from sage.modular.pollack_stevens.distributions import OverconvergentDistributions, Symk -# """ -# return self._addsub( right, False) - -# cpdef _sub_(self, ModuleElement right): -# r""" - - -# EXAMPLES:: - -# sage: from sage.modular.pollack_stevens.distributions import OverconvergentDistributions, Symk -# """ -# return self._addsub( right, True) - -# cpdef _lmul_(self, RingElement _right): -# r""" - - -# EXAMPLES:: - -# sage: from sage.modular.pollack_stevens.distributions import OverconvergentDistributions, Symk -# """ -# cdef Dist_long ans = self._new_c() -# ans.relprec = self.relprec -# self.quasi_normalize() -# cdef long scalar, absprec, ordp -# cdef Integer iright, unit, ppow, p = self.prime_pow.prime -# cdef Rational qright, qunit -# cdef pAdicCappedAbsoluteElement pcaright -# cdef pAdicCappedRelativeElement pcrright -# cdef pAdicFixedModElement pfmright -# if isinstance(_right, Integer): -# iright = _right -# if mpz_sgn(iright.value) == 0: -# ans.ordp = maxordp -# ans.relprec = 0 -# return ans -# unit = PY_NEW(Integer) -# ordp = mpz_remove(unit.value, iright.value, p.value) -# if mpz_fits_slong_p(unit.value): -# scalar = mpz_get_si(iright.value) % self.prime_pow(self.relprec) -# else: -# scalar = mpz_fdiv_ui(iright.value, self.prime_pow(self.relprec)) -# elif isinstance(_right, Rational): -# qright = _right -# if mpq_sgn(qright.value) == 0: -# ans.ordp = maxordp -# ans.relprec = 0 -# return ans -# qunit = PY_NEW(Rational) -# ordp = mpz_remove(mpq_numref(qunit.value), mpq_numref(qright.value), p.value) -# if ordp == 0: -# ordp = -mpz_remove(mpq_denref(qunit.value), mpq_denref(qright.value), p.value) -# else: -# mpz_set(mpq_denref(qunit.value), mpq_denref(qright.value)) -# ppow = PY_NEW(Integer) -# mpz_set_ui(ppow.value, self.prime_pow(self.relprec)) -# # We reuse the pointers inside qunit, since we're going to discard it. -# mpz_invert(mpq_denref(qunit.value), mpq_denref(qunit.value), ppow.value) -# mpz_mul(mpq_numref(qunit.value), mpq_numref(qunit.value), mpq_denref(qunit.value)) -# scalar = mpz_fdiv_ui(mpq_numref(qunit.value), self.prime_pow(self.relprec)) -# # qunit should not be used now (it's unnormalized) -# elif isinstance(_right, pAdicCappedAbsoluteElement): -# pcaright = _right -# unit = PY_NEW(Integer) -# ordp = mpz_remove(unit.value, pcaright.value, p.value) -# if pcaright.absprec - ordp <= self.relprec: -# ans.relprec = pcaright.absprec - ordp -# scalar = mpz_get_si(unit.value) -# else: -# scalar = mpz_fdiv_ui(unit.value, self.prime_pow(self.relprec)) -# elif isinstance(_right, pAdicCappedRelativeElement): -# pcrright = _right -# ordp = pcrright.ordp -# if pcrright.relprec <= self.relprec: -# ans.relprec = pcrright.relprec -# scalar = mpz_get_si(pcrright.unit) -# else: -# scalar = mpz_fdiv_ui(pcrright.unit, self.prime_pow(self.relprec)) -# elif isinstance(_right, pAdicFixedModElement): -# pfmright = _right -# scalar = mpz_get_si(pfmright.value) -# ordp = 0 -# cdef int i -# for i in range(self.relprec): -# ans._moments[i] = self._moments[i] * scalar -# ans.ordp = self.ordp + ordp -# ans.quasi_normalize() -# return ans - -# def precision_relative(self): -# return Integer(self.relprec) - -# def precision_absolute(self): -# r""" - - -# OUTPUT: - -# - - -# EXAMPLES:: - -# sage: from sage.modular.pollack_stevens.distributions import OverconvergentDistributions, Symk -# """ -# return Integer(self.relprec + self.ordp) - -# def reduce_precision(self, M): -# r""" - - -# INPUT: - -# - ``M`` -- a positive integer less than the precision of this -# distribution. - -# OUTPUT: - -# - - -# EXAMPLES:: - -# sage: from sage.modular.pollack_stevens.distributions import OverconvergentDistributions, Symk -# """ -# if M > self.relprec: -# raise ValueError("not enough moments") -# if M < 0: -# raise ValueError("precision must be non-negative") -# cdef Dist_long ans = self._new_c() -# ans.relprec = M -# cdef int i -# for i in range(ans.relprec): -# ans._moments[i] = self._moments[i] -# ans.ordp = self.ordp -# return ans - -# def solve_diff_eqn(self): -# r""" - - -# OUTPUT: - -# - - -# EXAMPLES:: - -# sage: from sage.modular.pollack_stevens.distributions import OverconvergentDistributions, Symk -# """ -# raise NotImplementedError - -# def __reduce__(self): -# r""" -# Used in pickling. - -# EXAMPLES:: - -# sage: D = OverconvergentDistributions(0, 5, 10) -# sage: D([1,2,3,4]).__reduce__() -# (, ([1, 2, 3, 4], Space of 5-adic distributions with k=0 action and precision cap 10, 0, False)) -# """ -# return (self.__class__, ([self._moments[i] -# for i in xrange(self.relprec)], -# self.parent(), self.ordp, False)) - - cdef class WeightKAction(Action): r""" Encode the action of the monoid `\Sigma_0(N)` on the space of distributions. diff --git a/src/sage/modules/vector_integer_dense.pyx b/src/sage/modules/vector_integer_dense.pyx index 2424976cf35..f921da42f10 100644 --- a/src/sage/modules/vector_integer_dense.pyx +++ b/src/sage/modules/vector_integer_dense.pyx @@ -54,7 +54,8 @@ TESTS:: #***************************************************************************** from __future__ import absolute_import -include 'sage/ext/stdsage.pxi' +from cysignals.memory cimport check_allocarray, sig_free +from cysignals.signals cimport sig_on, sig_off from sage.structure.element cimport Element, ModuleElement, RingElement, Vector @@ -68,7 +69,7 @@ from sage.libs.gmp.mpz cimport * cdef inline _Integer_from_mpz(mpz_t e): - cdef Integer z = PY_NEW(Integer) + cdef Integer z = Integer.__new__(Integer) mpz_set(z.value, e) return z @@ -182,7 +183,7 @@ cdef class Vector_integer_dense(free_module_element.FreeModuleElement): sage: v[::-1] (3, 2, 1) """ - cdef Integer z = PY_NEW(Integer) + cdef Integer z = Integer.__new__(Integer) mpz_set(z.value, self._entries[i]) return z @@ -254,8 +255,7 @@ cdef class Vector_integer_dense(free_module_element.FreeModuleElement): 4 """ cdef Vector_integer_dense r = right - cdef Integer z - z = PY_NEW(Integer) + cdef Integer z = Integer.__new__(Integer) cdef mpz_t t mpz_init(t) mpz_set_si(z.value, 0) diff --git a/src/sage/rings/fast_arith.pyx b/src/sage/rings/fast_arith.pyx index 543c94d61c6..e9d25059d67 100644 --- a/src/sage/rings/fast_arith.pyx +++ b/src/sage/rings/fast_arith.pyx @@ -41,8 +41,10 @@ Basic arithmetic with C integers # The int definitions +from libc.math cimport sqrt +from sage.libs.gmp.mpz cimport mpz_set_ui + from sage.ext.stdsage cimport PY_NEW -include "sage/ext/cdefs.pxi" from cypari2.paridecl cimport * from cypari2.gen cimport Gen as pari_gen diff --git a/src/sage/rings/finite_rings/integer_mod.pyx b/src/sage/rings/finite_rings/integer_mod.pyx index 7bbf12bf5bd..be96bb7b9f0 100644 --- a/src/sage/rings/finite_rings/integer_mod.pyx +++ b/src/sage/rings/finite_rings/integer_mod.pyx @@ -69,8 +69,7 @@ TESTS:: #***************************************************************************** from __future__ import print_function, division -include "cysignals/signals.pxi" -include "sage/ext/stdsage.pxi" +from cysignals.signals cimport sig_on, sig_off from cpython.int cimport * from cpython.list cimport * @@ -4235,7 +4234,7 @@ cdef class IntegerMod_to_Integer(Map): Morphism.__init__(self, sage.categories.homset.Hom(R, integer_ring.ZZ, Sets())) cpdef Element _call_(self, x): - cdef Integer ans = PY_NEW(Integer) + cdef Integer ans = Integer.__new__(Integer) if isinstance(x, IntegerMod_gmp): mpz_set(ans.value, (x).value) elif isinstance(x, IntegerMod_int): diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index 60ade68bdcb..d1e05beb823 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -136,17 +136,18 @@ cimport cython from libc.math cimport ldexp from libc.string cimport memcpy +from cysignals.memory cimport check_allocarray, check_malloc, sig_free +from cysignals.signals cimport sig_on, sig_off + import operator import sys +from sage.ext.stdsage cimport PY_NEW from sage.libs.gmp.mpz cimport * from sage.libs.gmp.mpq cimport * from sage.misc.superseded import deprecated_function_alias from sage.misc.long cimport pyobject_to_long -include "cysignals/signals.pxi" -include "sage/ext/stdsage.pxi" -include "cysignals/memory.pxi" from cpython.list cimport * from cpython.number cimport * from cpython.int cimport * @@ -7050,7 +7051,7 @@ cdef hook_fast_tp_functions(): """ global global_dummy_Integer, sizeof_Integer, integer_pool - integer_pool = sig_malloc(integer_pool_size * sizeof(PyObject*)) + integer_pool = check_allocarray(integer_pool_size, sizeof(PyObject*)) cdef PyObject* o o = global_dummy_Integer diff --git a/src/sage/rings/integer_ring.pyx b/src/sage/rings/integer_ring.pyx index 9dec9d241bd..14639f74a08 100644 --- a/src/sage/rings/integer_ring.pyx +++ b/src/sage/rings/integer_ring.pyx @@ -45,13 +45,12 @@ other types will also coerce to the integers, when it makes sense. from __future__ import absolute_import, print_function -include "sage/ext/stdsage.pxi" -include "cysignals/signals.pxi" - from cpython.int cimport * from cpython.list cimport * from cpython.object cimport Py_NE +from cysignals.signals cimport sig_check, sig_on, sig_off + from sage.libs.gmp.mpz cimport * import sage.rings.infinity import sage.rings.rational @@ -474,7 +473,7 @@ cdef class IntegerRing_class(PrincipalIdealDomain): """ if end is None: end = start - start = PY_NEW(Integer) # 0 + start = Integer.__new__(Integer) if step is None: step = 1 if type(step) is not int: @@ -504,7 +503,7 @@ cdef class IntegerRing_class(PrincipalIdealDomain): sig_on() while mpz_cmp(a.value, b.value)*step_sign < 0: last = a - a = PY_NEW(Integer) + a = Integer.__new__(Integer) if type(step) is int: # count on branch prediction... if istep > 0: mpz_add_ui(a.value, last.value, istep) @@ -540,8 +539,7 @@ cdef class IntegerRing_class(PrincipalIdealDomain): n += 1 cdef Integer _coerce_ZZ(self, ZZ_c *z): - cdef integer.Integer i - i = PY_NEW(integer.Integer) + cdef Integer i = Integer.__new__(Integer) sig_on() ZZ_to_mpz(i.value, z) sig_off() @@ -737,8 +735,7 @@ cdef class IntegerRing_class(PrincipalIdealDomain): 5 """ - cdef integer.Integer z - z = PY_NEW(integer.Integer) + cdef Integer z = Integer.__new__(Integer) if x is not None and y is None and x <= 0: raise TypeError("x must be > 0") if x is not None and y is not None and x >= y: diff --git a/src/sage/rings/number_field/number_field_element.pyx b/src/sage/rings/number_field/number_field_element.pyx index ecd6aa17ba6..772ceba3f95 100644 --- a/src/sage/rings/number_field/number_field_element.pyx +++ b/src/sage/rings/number_field/number_field_element.pyx @@ -27,14 +27,15 @@ AUTHORS: # the License, or (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** -from __future__ import absolute_import -from __future__ import print_function + +from __future__ import absolute_import, print_function import operator -include "cysignals/signals.pxi" from cpython.int cimport * -include "sage/ext/stdsage.pxi" + +from cysignals.signals cimport sig_on, sig_off + include "sage/libs/ntl/decl.pxi" from sage.libs.gmp.mpz cimport * @@ -886,8 +887,8 @@ cdef class NumberFieldElement(FieldElement): cdef int _randomize(self, num_bound, den_bound, distribution) except -1: cdef int i - cdef Integer denom_temp = PY_NEW(Integer) - cdef Integer tmp_integer = PY_NEW(Integer) + cdef Integer denom_temp = Integer.__new__(Integer) + cdef Integer tmp_integer = Integer.__new__(Integer) cdef ZZ_c ntl_temp cdef list coeff_list cdef Rational tmp_rational @@ -918,7 +919,7 @@ cdef class NumberFieldElement(FieldElement): else: coeff_list = [] mpz_set_si(denom_temp.value, 1) - tmp_integer = PY_NEW(Integer) + tmp_integer = Integer.__new__(Integer) for i from 0 <= i < ZZX_deg(self.__fld_numerator.x): tmp_rational = (QQ.random_element(num_bound=num_bound, @@ -2501,8 +2502,7 @@ cdef class NumberFieldElement(FieldElement): """ if ZZX_deg(self.__numerator) >= 1: raise TypeError("Unable to coerce %s to a rational"%self) - cdef Integer num - num = PY_NEW(Integer) + cdef Integer num = Integer.__new__(Integer) ZZX_getitem_as_mpz(num.value, &self.__numerator, 0) return num / (ZZ)._coerce_ZZ(&self.__denominator) @@ -2840,7 +2840,7 @@ cdef class NumberFieldElement(FieldElement): cdef Integer numCoeff cdef int i for i from 0 <= i <= ZZX_deg(self.__numerator): - numCoeff = PY_NEW(Integer) + numCoeff = Integer.__new__(Integer) ZZX_getitem_as_mpz(numCoeff.value, &self.__numerator, i) coeffs.append( numCoeff / den ) return coeffs 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 87997c15bfa..7ac8c88236d 100644 --- a/src/sage/rings/number_field/number_field_element_quadratic.pyx +++ b/src/sage/rings/number_field/number_field_element_quadratic.pyx @@ -29,11 +29,11 @@ AUTHORS: #***************************************************************************** from __future__ import absolute_import -include "cysignals/signals.pxi" -include "sage/ext/stdsage.pxi" include "sage/libs/ntl/decl.pxi" from cpython.object cimport Py_EQ, Py_NE, Py_LE, Py_GE, Py_LT, Py_GT +from cysignals.signals cimport sig_on, sig_off + from sage.libs.gmp.mpz cimport * from sage.libs.gmp.mpq cimport * from sage.libs.ntl.ntl_ZZ cimport ntl_ZZ @@ -332,9 +332,9 @@ cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute): sage: loads(dumps(a/3+5)) == a/3+5 True """ - cdef Integer a = PY_NEW(Integer) - cdef Integer b = PY_NEW(Integer) - cdef Integer denom = PY_NEW(Integer) + cdef Integer a = Integer.__new__(Integer) + cdef Integer b = Integer.__new__(Integer) + cdef Integer denom = Integer.__new__(Integer) mpz_set(a.value, self.a) mpz_set(b.value, self.b) mpz_set(denom.value, self.denom) @@ -1399,7 +1399,7 @@ cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute): if mpz_cmp_ui(self.b, 0) != 0 or mpz_cmp_ui(self.denom, 1) != 0: raise TypeError("Unable to coerce %s to an integer" % self) else: - res = PY_NEW(Integer) + res = Integer.__new__(Integer) mpz_set(res.value, self.a) return res @@ -1704,7 +1704,7 @@ cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute): cdef NumberFieldElement_quadratic gen = self.number_field().gen() # should this be cached? cdef Integer denom if gen.is_sqrt_disc(): - denom = PY_NEW(Integer) + denom = Integer.__new__(Integer) mpz_set(denom.value, self.denom) return denom else: @@ -1974,7 +1974,7 @@ cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute): if mpz_sgn(self.b) == 0: mpz_init_set(x,self.a) mpz_fdiv_q(x,x,self.denom) - result = PY_NEW(Integer) + result = Integer.__new__(Integer) mpz_set(result.value,x) mpz_clear(x) return result @@ -1996,7 +1996,7 @@ cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute): mpz_add(x,x,self.a) # here x = a + floor(sqrt(b^2 D)) or a + floor(-sqrt(b^2 D)) mpz_fdiv_q(x,x,self.denom) - result = PY_NEW(Integer) + result = Integer.__new__(Integer) mpz_set(result.value,x) mpz_clear(x) return result diff --git a/src/sage/rings/number_field/totallyreal.pyx b/src/sage/rings/number_field/totallyreal.pyx index 4027eb8baa3..9414c9923d2 100644 --- a/src/sage/rings/number_field/totallyreal.pyx +++ b/src/sage/rings/number_field/totallyreal.pyx @@ -105,9 +105,10 @@ Authors # (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** -from __future__ import print_function -include 'sage/ext/stdsage.pxi' +from __future__ import absolute_import, print_function + +from cysignals.memory cimport check_calloc, sig_free import math import sys @@ -295,7 +296,7 @@ def enumerate_totallyreal_fields_prim(n, B, a = [], verbose=0, return_seqs=False ng = B_pari pari_tmp1 = B_pari - dB = PY_NEW(Integer) + dB = Integer.__new__(Integer) dB_odlyzko = odlyzko_bound_totallyreal(n_int) mpz_set_d(dB.value, dB_odlyzko) dB = 40000*((dB+1)**n_int) @@ -303,10 +304,7 @@ def enumerate_totallyreal_fields_prim(n, B, a = [], verbose=0, return_seqs=False counts[i] = 0 B_pari = pari(B) - f_out = sig_malloc((n_int+1)*sizeof(int)) - if f_out == NULL: raise MemoryError - for i from 0 <= i < n_int: - f_out[i] = 0 + f_out = check_calloc(n_int + 1, sizeof(int)) f_out[n_int] = 1 if keep_fields: diff --git a/src/sage/rings/padics/CA_template.pxi b/src/sage/rings/padics/CA_template.pxi index 047c67f6f65..c1c485892f2 100644 --- a/src/sage/rings/padics/CA_template.pxi +++ b/src/sage/rings/padics/CA_template.pxi @@ -922,7 +922,7 @@ cdef class CAElement(pAdicTemplateElement): sage: R = Zp(7,4,'capped-abs'); a = R(7); a.precision_absolute() 4 """ - cdef Integer ans = PY_NEW(Integer) + cdef Integer ans = Integer.__new__(Integer) mpz_set_si(ans.value, self.absprec) return ans @@ -938,7 +938,7 @@ cdef class CAElement(pAdicTemplateElement): sage: R = Zp(7,4,'capped-abs'); a = R(7); a.precision_relative() 3 """ - cdef Integer ans = PY_NEW(Integer) + cdef Integer ans = Integer.__new__(Integer) mpz_set_si(ans.value, self.absprec - self.valuation_c()) return ans @@ -1007,7 +1007,7 @@ cdef class CAElement(pAdicTemplateElement): (6, O(5^0)) """ cdef CAElement unit = self._new_c() - cdef Integer valuation = PY_NEW(Integer) + cdef Integer valuation = Integer.__new__(Integer) cdef long val = cremove(unit.value, self.value, self.absprec, self.prime_pow) mpz_set_si(valuation.value, val) unit.absprec = self.absprec - val @@ -1214,7 +1214,7 @@ cdef class pAdicConvert_CA_ZZ(RingMap): sage: f(ZpCA(5)(0)) 0 """ - cdef Integer ans = PY_NEW(Integer) + cdef Integer ans = Integer.__new__(Integer) cdef CAElement x = _x cconv_mpz_t_out(ans.value, x.value, 0, x.absprec, x.prime_pow) return ans diff --git a/src/sage/rings/padics/CR_template.pxi b/src/sage/rings/padics/CR_template.pxi index c56fa547179..f1d2ef96d34 100644 --- a/src/sage/rings/padics/CR_template.pxi +++ b/src/sage/rings/padics/CR_template.pxi @@ -1403,7 +1403,7 @@ cdef class CRElement(pAdicTemplateElement): """ if exactzero(self.ordp): return infinity - cdef Integer ans = PY_NEW(Integer) + cdef Integer ans = Integer.__new__(Integer) mpz_set_si(ans.value, self.ordp + self.relprec) return ans @@ -1429,8 +1429,8 @@ cdef class CRElement(pAdicTemplateElement): 0 sage: R(0,7).precision_relative() 0 - """ - cdef Integer ans = PY_NEW(Integer) + """ + cdef Integer ans = Integer.__new__(Integer) mpz_set_si(ans.value, self.relprec) return ans @@ -1528,7 +1528,7 @@ cdef class CRElement(pAdicTemplateElement): raise ValueError('Ring (%s) residue field of the wrong characteristic.'%self.parent()) if exactzero((self).ordp): raise ValueError("unit part of 0 not defined") - cdef Integer val = PY_NEW(Integer) + cdef Integer val = Integer.__new__(Integer) mpz_set_si(val.value, (self).ordp) cdef CRElement unit = (self)._new_c() unit.ordp = 0 @@ -1761,7 +1761,7 @@ cdef class pAdicConvert_CR_ZZ(RingMap): ... ValueError: negative valuation """ - cdef Integer ans = PY_NEW(Integer) + cdef Integer ans = Integer.__new__(Integer) cdef CRElement x = _x if x.relprec != 0: cconv_mpz_t_out(ans.value, x.unit, x.ordp, x.relprec, x.prime_pow) diff --git a/src/sage/rings/padics/FM_template.pxi b/src/sage/rings/padics/FM_template.pxi index 760ad0bebff..e852e9cd0a5 100644 --- a/src/sage/rings/padics/FM_template.pxi +++ b/src/sage/rings/padics/FM_template.pxi @@ -33,7 +33,6 @@ AUTHORS: # http://www.gnu.org/licenses/ #***************************************************************************** -from sage.ext.stdsage cimport PY_NEW include "padic_template_element.pxi" from cpython.int cimport * @@ -721,7 +720,7 @@ cdef class FMElement(pAdicTemplateElement): sage: R = Zp(7,4,'fixed-mod'); a = R(7); a.precision_absolute() 4 """ - cdef Integer ans = PY_NEW(Integer) + cdef Integer ans = Integer.__new__(Integer) mpz_set_si(ans.value, self.prime_pow.prec_cap) return ans @@ -736,7 +735,7 @@ cdef class FMElement(pAdicTemplateElement): sage: a = R(0); a.precision_relative() 0 """ - cdef Integer ans = PY_NEW(Integer) + cdef Integer ans = Integer.__new__(Integer) mpz_set_si(ans.value, self.prime_pow.prec_cap - self.valuation_c()) return ans @@ -813,7 +812,7 @@ cdef class FMElement(pAdicTemplateElement): (5, O(5^5)) """ cdef FMElement unit = self._new_c() - cdef Integer valuation = PY_NEW(Integer) + cdef Integer valuation = Integer.__new__(Integer) mpz_set_si(valuation.value, cremove(unit.value, self.value, self.prime_pow.prec_cap, self.prime_pow)) return valuation, unit @@ -1003,7 +1002,7 @@ cdef class pAdicConvert_FM_ZZ(RingMap): sage: f(ZpFM(5)(0)) 0 """ - cdef Integer ans = PY_NEW(Integer) + cdef Integer ans = Integer.__new__(Integer) cdef FMElement x = _x cconv_mpz_t_out(ans.value, x.value, 0, x.prime_pow.prec_cap, x.prime_pow) return ans 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 176a9cbfccc..d77f6d38f35 100644 --- a/src/sage/rings/padics/padic_ZZ_pX_FM_element.pyx +++ b/src/sage/rings/padics/padic_ZZ_pX_FM_element.pyx @@ -119,8 +119,8 @@ AUTHORS: # http://www.gnu.org/licenses/ #***************************************************************************** -include "sage/ext/stdsage.pxi" -include "cysignals/signals.pxi" +from cysignals.signals cimport sig_on, sig_off + include "sage/libs/ntl/decl.pxi" from sage.structure.element cimport Element @@ -243,13 +243,13 @@ cdef class pAdicZZpXFMElement(pAdicZZpXElement): ctx_prec = ZZ_remove(tmp_z, (x.modulus()).x, self.prime_pow.pow_ZZ_tmp(1)[0]) if ZZ_IsOne(tmp_z): x = x.lift() - tmp_Int = PY_NEW(Integer) + tmp_Int = Integer.__new__(Integer) ZZ_to_mpz(tmp_Int.value, &(x).x) x = tmp_Int else: raise TypeError("cannot coerce the given ntl_ZZ_p (modulus not a power of the same prime)") elif isinstance(x, ntl_ZZ): - tmp_Int = PY_NEW(Integer) + tmp_Int = Integer.__new__(Integer) ZZ_to_mpz(tmp_Int.value, &(x).x) x = tmp_Int elif isinstance(x, (int, long)): @@ -968,11 +968,10 @@ cdef class pAdicZZpXFMElement(pAdicZZpXElement): sage: ZZ(W(5)) 5 """ - cdef Integer ans cdef ZZ_c tmp_z if ZZ_pX_deg(self.value) > 0: raise ValueError("This element not well approximated by an integer.") - ans = PY_NEW(Integer) + cdef Integer ans = Integer.__new__(Integer) tmp_z = ZZ_p_rep(ZZ_pX_ConstTerm(self.value)) ZZ_to_mpz(ans.value, &tmp_z) return ans @@ -1415,7 +1414,7 @@ cdef class pAdicZZpXFMElement(pAdicZZpXElement): sage: a.unit_part() 3 + 2*w^2 + w^4 + w^6 + w^7 + 3*w^8 + 3*w^9 + 2*w^11 + 3*w^12 + 3*w^13 + w^15 + 4*w^16 + 2*w^17 + w^18 + w^22 + 3*w^24 + O(w^25) """ - cdef Integer ans = PY_NEW(Integer) + cdef Integer ans = Integer.__new__(Integer) mpz_set_ui(ans.value, self.prime_pow.ram_prec_cap) return ans @@ -1441,16 +1440,10 @@ cdef class pAdicZZpXFMElement(pAdicZZpXElement): sage: a.unit_part() 3 + 2*w^2 + w^4 + w^6 + w^7 + 3*w^8 + 3*w^9 + 2*w^11 + 3*w^12 + 3*w^13 + w^15 + 4*w^16 + 2*w^17 + w^18 + w^22 + 3*w^24 + O(w^25) """ - cdef Integer ans = PY_NEW(Integer) + cdef Integer ans = Integer.__new__(Integer) mpz_set_ui(ans.value, self.prime_pow.ram_prec_cap - self.valuation_c()) return ans -# def residue(self, n): -# """ -# Reduces this element modulo pi^n. -# """ -# raise NotImplementedError - cpdef pAdicZZpXFMElement unit_part(self): """ Returns the unit part of ``self``, ie diff --git a/src/sage/rings/padics/padic_capped_absolute_element.pyx b/src/sage/rings/padics/padic_capped_absolute_element.pyx index a3b68f8126e..c5454415af8 100644 --- a/src/sage/rings/padics/padic_capped_absolute_element.pyx +++ b/src/sage/rings/padics/padic_capped_absolute_element.pyx @@ -101,7 +101,7 @@ cdef class pAdicCappedAbsoluteElement(CAElement): sage: ZpCA(3,3)(1/4).lift() # indirect doctest 7 """ - cdef Integer ans = PY_NEW(Integer) + cdef Integer ans = Integer.__new__(Integer) mpz_set(ans.value, self.value) return ans @@ -218,7 +218,6 @@ cdef class pAdicCappedAbsoluteElement(CAElement): :meth:`_mod_` """ - cdef Integer selfvalue, modulus if not isinstance(absprec, Integer): absprec = Integer(absprec) if mpz_cmp_si((absprec).value, self.absprec) > 0: @@ -226,9 +225,9 @@ cdef class pAdicCappedAbsoluteElement(CAElement): elif mpz_sgn((absprec).value) < 0: raise ValueError("cannot reduce modulo a negative power of p.") cdef long aprec = mpz_get_ui((absprec).value) - modulus = PY_NEW(Integer) + cdef Integer modulus = Integer.__new__(Integer) mpz_set(modulus.value, self.prime_pow.pow_mpz_t_tmp(aprec)) - selfvalue = PY_NEW(Integer) + cdef Integer selfvalue = Integer.__new__(Integer) mpz_set(selfvalue.value, self.value) return Mod(selfvalue, modulus) @@ -262,13 +261,13 @@ cdef class pAdicCappedAbsoluteElement(CAElement): if mpz_divisible_p(self.value, self.prime_pow.prime.value): return infinity if mpz_cmp_ui(self.value, 1) == 0: - ans = PY_NEW(Integer) + ans = Integer.__new__(Integer) mpz_set_ui(ans.value, 1) return ans mpz_init(ppow_minus_one) mpz_sub_ui(ppow_minus_one, self.prime_pow.pow_mpz_t_tmp(self.absprec), 1) if mpz_cmp(self.value, ppow_minus_one) == 0: - ans = PY_NEW(Integer) + ans = Integer.__new__(Integer) mpz_set_ui(ans.value, 2) mpz_clear(ppow_minus_one) return ans diff --git a/src/sage/rings/padics/pow_computer_ext.pyx b/src/sage/rings/padics/pow_computer_ext.pyx index 01fae2b883f..413e89ab369 100644 --- a/src/sage/rings/padics/pow_computer_ext.pyx +++ b/src/sage/rings/padics/pow_computer_ext.pyx @@ -48,12 +48,13 @@ AUTHORS: # http://www.gnu.org/licenses/ #***************************************************************************** -include "cysignals/signals.pxi" -include "sage/ext/stdsage.pxi" -include "sage/libs/ntl/decl.pxi" from cpython.list cimport * from cpython.dict cimport * +from cysignals.signals cimport sig_on, sig_off + +include "sage/libs/ntl/decl.pxi" + import weakref from sage.misc.misc import cputime from sage.rings.infinity import infinity @@ -562,11 +563,11 @@ cdef class PowComputer_ext(PowComputer_class): PowComputer_ext for 5, with polynomial [9765620 0 1] """ cdef Integer cache_limit, prec_cap, ram_prec_cap - cache_limit = PY_NEW(Integer) + cache_limit = Integer.__new__(Integer) mpz_set_si(cache_limit.value, self.cache_limit) - prec_cap = PY_NEW(Integer) + prec_cap = Integer.__new__(Integer) mpz_set_si(prec_cap.value, self.prec_cap) - ram_prec_cap = PY_NEW(Integer) + ram_prec_cap = Integer.__new__(Integer) mpz_set_si(ram_prec_cap.value, self.ram_prec_cap) return PowComputer_ext_maker, (self.prime, cache_limit, prec_cap, ram_prec_cap, self.in_field, self._poly, self._prec_type, self._ext_type, self._shift_seed) @@ -1103,7 +1104,7 @@ cdef class PowComputer_ZZ_pX(PowComputer_ext): 4 """ cdef Integer _n = Integer(n) - cdef Integer ans = PY_NEW(Integer) + cdef Integer ans = Integer.__new__(Integer) mpz_set_si(ans.value, self.capdiv(mpz_get_si(_n.value))) return ans diff --git a/src/sage/rings/polynomial/polynomial_integer_dense_flint.pyx b/src/sage/rings/polynomial/polynomial_integer_dense_flint.pyx index 23867620a23..9a4f10f55c5 100644 --- a/src/sage/rings/polynomial/polynomial_integer_dense_flint.pyx +++ b/src/sage/rings/polynomial/polynomial_integer_dense_flint.pyx @@ -20,18 +20,22 @@ We check that the buggy gcd is fixed (see :trac:`17816`):: 1 """ -################################################################################ +#***************************************************************************** # Copyright (C) 2007 William Stein # Copyright (C) 2008-2010 Burcin Erocal # -# Distributed under the terms of the GNU General Public License (GPL) -# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. # http://www.gnu.org/licenses/ -################################################################################ -from __future__ import print_function +#***************************************************************************** + +from __future__ import absolute_import, print_function + +from cysignals.memory cimport sig_free +from cysignals.signals cimport sig_on, sig_off -include "sage/ext/stdsage.pxi" -include "cysignals/signals.pxi" include "sage/libs/ntl/decl.pxi" from cpython.int cimport PyInt_AS_LONG @@ -400,7 +404,7 @@ cdef class Polynomial_integer_dense_flint(Polynomial): sig_off() return f if isinstance(x0, int): - z = PY_NEW(Integer) + z = Integer.__new__(Integer) sig_on() fmpz_init(a_fmpz) fmpz_init(z_fmpz) @@ -421,7 +425,7 @@ cdef class Polynomial_integer_dense_flint(Polynomial): if mpz_sgn(a.value) == 0: return self[0] - z = PY_NEW(Integer) + z = Integer.__new__(Integer) sig_on() fmpz_init(a_fmpz) @@ -484,7 +488,7 @@ cdef class Polynomial_integer_dense_flint(Polynomial): fmpz_poly_content(c, self.__poly) - cdef Integer z = PY_NEW(Integer) + cdef Integer z = Integer.__new__(Integer) fmpz_get_mpz(z.value, c) fmpz_clear(c) return z if sign == 1 else -z @@ -529,7 +533,7 @@ cdef class Polynomial_integer_dense_flint(Polynomial): sage: f[:100] 5*x^5 + 4*x^4 + 3*x^3 + 2*x^2 + x + 1 """ - cdef Integer z = PY_NEW(Integer) + cdef Integer z = Integer.__new__(Integer) fmpz_poly_get_coeff_mpz(z.value, self.__poly, n) return z @@ -550,7 +554,7 @@ cdef class Polynomial_integer_dense_flint(Polynomial): if name is None: name = self.parent().variable_name() cdef long i - cdef Integer coef = PY_NEW(Integer) + cdef Integer coef = Integer.__new__(Integer) cdef list all = [] for i from fmpz_poly_degree(self.__poly) >= i >= 0: fmpz_poly_get_coeff_mpz(coef.value, self.__poly, i) @@ -882,7 +886,7 @@ cdef class Polynomial_integer_dense_flint(Polynomial): fmpz_poly_xgcd(r, ss.__poly, tt.__poly, self.__poly, (right).__poly) sig_off() - cdef Integer rr = PY_NEW(Integer) + cdef Integer rr = Integer.__new__(Integer) fmpz_get_mpz(rr.value, r) fmpz_clear(r) @@ -1384,11 +1388,10 @@ cdef class Polynomial_integer_dense_flint(Polynomial): """ cdef ZZX_c ntl_poly cdef ZZ_c* temp - cdef Integer x fmpz_poly_get_ZZX(ntl_poly, self.__poly) temp = ZZX_discriminant(&ntl_poly, proof) - x = PY_NEW(Integer) + cdef Integer x = Integer.__new__(Integer) ZZ_to_mpz(x.value, temp) del temp @@ -1710,7 +1713,7 @@ cdef class Polynomial_integer_dense_flint(Polynomial): cdef fmpz_t res fmpz_init(res) - cdef Integer x = PY_NEW(Integer) + cdef Integer x = Integer.__new__(Integer) sig_on() fmpz_poly_resultant(res, 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 6faf1fe71a7..2b0ed0ced0f 100644 --- a/src/sage/rings/polynomial/polynomial_integer_dense_ntl.pyx +++ b/src/sage/rings/polynomial/polynomial_integer_dense_ntl.pyx @@ -31,10 +31,12 @@ do:: # (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** -from __future__ import print_function -include "sage/ext/stdsage.pxi" -include "cysignals/signals.pxi" +from __future__ import absolute_import, print_function + +from cysignals.memory cimport sig_free +from cysignals.signals cimport sig_on, sig_off + include "sage/libs/ntl/decl.pxi" from sage.rings.polynomial.polynomial_element cimport Polynomial @@ -252,7 +254,7 @@ cdef class Polynomial_integer_dense_ntl(Polynomial): 0 """ cdef ZZ_c y - cdef Integer z = PY_NEW(Integer) + cdef Integer z = Integer.__new__(Integer) ZZX_content(y, self.__poly) ZZ_to_mpz(z.value, &y) return z @@ -356,7 +358,7 @@ cdef class Polynomial_integer_dense_ntl(Polynomial): sage: f[:100] 5*x^5 + 4*x^4 + 3*x^3 + 2*x^2 + x + 1 """ - cdef Integer z = PY_NEW(Integer) + cdef Integer z = Integer.__new__(Integer) ZZ_to_mpz(z.value, &self.__poly.rep.elts()[n]) return z @@ -643,7 +645,7 @@ cdef class Polynomial_integer_dense_ntl(Polynomial): cdef ZZ_c *r ZZX_xgcd(&self.__poly, &(right).__poly, &r, &s, &t, 1) # proof = 1 - cdef Integer rr = PY_NEW(Integer) + cdef Integer rr = Integer.__new__(Integer) ZZ_to_mpz(rr.value, r) cdef Polynomial_integer_dense_ntl ss = self._new() cdef Polynomial_integer_dense_ntl tt = self._new() @@ -836,7 +838,7 @@ cdef class Polynomial_integer_dense_ntl(Polynomial): -339 """ cdef ZZ_c* temp = ZZX_discriminant(&self.__poly, proof) - cdef Integer x = PY_NEW(Integer) + cdef Integer x = Integer.__new__(Integer) ZZ_to_mpz(x.value, temp) del temp return x @@ -1120,7 +1122,7 @@ cdef class Polynomial_integer_dense_ntl(Polynomial): """ cdef Polynomial_integer_dense_ntl _other = (self.parent()._coerce_(other)) cdef ZZ_c* temp = ZZX_resultant(&self.__poly, &_other.__poly, proof) - cdef Integer x = PY_NEW(Integer) + cdef Integer x = Integer.__new__(Integer) ZZ_to_mpz(x.value, temp) del temp return x diff --git a/src/sage/rings/polynomial/polynomial_rational_flint.pyx b/src/sage/rings/polynomial/polynomial_rational_flint.pyx index 731f9851ce8..1d5166272ec 100644 --- a/src/sage/rings/polynomial/polynomial_rational_flint.pyx +++ b/src/sage/rings/polynomial/polynomial_rational_flint.pyx @@ -16,8 +16,8 @@ AUTHOR: # http://www.gnu.org/licenses/ #***************************************************************************** -include "sage/ext/stdsage.pxi" -include "cysignals/signals.pxi" +from cysignals.memory cimport check_allocarray, check_malloc, sig_free +from cysignals.signals cimport sig_on, sig_str, sig_off from cpython.int cimport PyInt_AS_LONG from sage.misc.long cimport pyobject_to_long @@ -240,7 +240,7 @@ cdef class Polynomial_rational_flint(Polynomial): L1 = [e if isinstance(e, Rational) else Rational(e) for e in x] n = len(x) sig_on() - L2 = sig_malloc(n * sizeof(mpq_t)) + L2 = check_allocarray(n, sizeof(mpq_t)) for deg from 0 <= deg < n: mpq_init(L2[deg]) mpq_set(L2[deg], ( L1[deg]).value) @@ -1419,7 +1419,7 @@ cdef class Polynomial_rational_flint(Polynomial): sage: f.denominator() 3 """ - cdef Integer den = PY_NEW(Integer) + cdef Integer den = Integer.__new__(Integer) if fmpq_poly_denref(self.__poly) is NULL: mpz_set_ui(den.value, 1) else: diff --git a/src/sage/rings/rational.pyx b/src/sage/rings/rational.pyx index 27d6a23e6b8..b1acb90b174 100644 --- a/src/sage/rings/rational.pyx +++ b/src/sage/rings/rational.pyx @@ -41,12 +41,13 @@ TESTS:: # the License, or (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** + from __future__ import absolute_import -include "cysignals/signals.pxi" -include "sage/ext/stdsage.pxi" from cpython cimport * +from cysignals.signals cimport sig_on, sig_off + import sys import operator @@ -205,7 +206,7 @@ cpdef Integer integer_rational_power(Integer a, Rational b): sage: integer_rational_power(0, QQ(0)) 1 """ - cdef Integer z = PY_NEW(Integer) + cdef Integer z = Integer.__new__(Integer) if mpz_sgn(mpq_numref(b.value)) < 0: raise ValueError("Only positive exponents supported.") cdef int sgn = mpz_sgn(a.value) @@ -698,21 +699,21 @@ cdef class Rational(sage.structure.element.FieldElement): if type == "std": while mpz_sgn(q) != 0: - z = PY_NEW(Integer) + z = Integer.__new__(Integer) mpz_fdiv_qr(z.value,tmp,p,q) mpz_set(p,q) mpz_set(q,tmp) res.append(z) elif type == "hj": while mpz_sgn(q) != 0: - z = PY_NEW(Integer) + z = Integer.__new__(Integer) mpz_cdiv_qr(z.value,tmp,p,q) mpz_set(p,q) mpz_set(q,tmp) res.append(z) if mpz_sgn(q) == 0: break - z = PY_NEW(Integer) + z = Integer.__new__(Integer) mpz_fdiv_qr(z.value,tmp,p,q) mpz_set(p,q) mpz_set(q,tmp) @@ -1639,7 +1640,6 @@ cdef class Rational(sage.structure.element.FieldElement): sage: (-4/17).val_unit(2) # indirect doctest (2, -1/17) """ - cdef integer.Integer v cdef Rational u if mpz_cmp_ui(p.value, 2) < 0: raise ValueError("p must be at least 2.") @@ -1648,7 +1648,7 @@ cdef class Rational(sage.structure.element.FieldElement): u = Rational.__new__(Rational) mpq_set_ui(u.value, 1, 1) return (sage.rings.infinity.infinity, u) - v = PY_NEW(integer.Integer) + cdef Integer v = Integer.__new__(Integer) u = Rational.__new__(Rational) sig_on() mpz_set_ui(v.value, mpz_remove(mpq_numref(u.value), mpq_numref(self.value), p.value)) @@ -2837,8 +2837,7 @@ cdef class Rational(sage.structure.element.FieldElement): """ if not mpz_cmp_si(mpq_denref(self.value), 1) == 0: raise TypeError("no conversion of this rational to integer") - cdef integer.Integer n - n = PY_NEW(integer.Integer) + cdef Integer n = Integer.__new__(Integer) n.set_from_mpz(mpq_numref(self.value)) return n @@ -2853,8 +2852,7 @@ cdef class Rational(sage.structure.element.FieldElement): sage: x.numer() -5 """ - cdef integer.Integer n - n = PY_NEW(integer.Integer) + cdef Integer n = Integer.__new__(Integer) n.set_from_mpz(mpq_numref(self.value)) return n @@ -2874,8 +2872,7 @@ cdef class Rational(sage.structure.element.FieldElement): sage: x.numerator() 3 """ - cdef integer.Integer n - n = PY_NEW(integer.Integer) + cdef Integer n = Integer.__new__(Integer) n.set_from_mpz(mpq_numref(self.value)) return n @@ -2932,8 +2929,7 @@ cdef class Rational(sage.structure.element.FieldElement): sage: x.denom() 1 """ - cdef integer.Integer n - n = PY_NEW(integer.Integer) + cdef Integer n = Integer.__new__(Integer) n.set_from_mpz(mpq_denref(self.value)) return n @@ -2950,8 +2946,7 @@ cdef class Rational(sage.structure.element.FieldElement): sage: x.denominator() 1 """ - cdef integer.Integer n - n = PY_NEW(integer.Integer) + cdef Integer n = Integer.__new__(Integer) n.set_from_mpz(mpq_denref(self.value)) return n @@ -4009,8 +4004,7 @@ cdef class Q_to_Z(Map): """ if not mpz_cmp_si(mpq_denref((x).value), 1) == 0: raise TypeError("no conversion of this rational to integer") - cdef integer.Integer n - n = PY_NEW(integer.Integer) + cdef Integer n = Integer.__new__(Integer) n.set_from_mpz(mpq_numref((x).value)) return n diff --git a/src/sage/rings/real_double.pyx b/src/sage/rings/real_double.pyx index 8cea6e38e84..a0a7d902a9e 100644 --- a/src/sage/rings/real_double.pyx +++ b/src/sage/rings/real_double.pyx @@ -44,9 +44,11 @@ from __future__ import print_function from cpython.object cimport * from cpython.float cimport * + +from cysignals.signals cimport sig_on, sig_off + include "sage/ext/python_debug.pxi" -include 'sage/ext/stdsage.pxi' -include "cysignals/signals.pxi" +from sage.ext.stdsage cimport PY_NEW from sage.libs.gsl.all cimport * cimport libc.math from libc.string cimport memcpy diff --git a/src/sage/structure/list_clone.pyx b/src/sage/structure/list_clone.pyx index d7d734c52a6..4f7de4deb79 100644 --- a/src/sage/structure/list_clone.pyx +++ b/src/sage/structure/list_clone.pyx @@ -130,21 +130,27 @@ AUTHORS: - Florent Hivert (2010-03): initial revision """ + #***************************************************************************** -# Copyright (C) 2009-2010 Florent Hivert +# Copyright (C) 2009-2010 Florent Hivert # -# Distributed under the terms of the GNU General Public License (GPL) +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** -from __future__ import print_function -include "sage/ext/stdsage.pxi" -include "cysignals/memory.pxi" +from __future__ import absolute_import, print_function + from cpython.list cimport * from cpython.int cimport * from cpython.ref cimport * +from cysignals.memory cimport check_reallocarray, sig_free + import sage +from sage.ext.stdsage cimport HAS_DICTIONARY from sage.structure.element cimport Element from sage.structure.parent cimport Parent from sage.structure.sage_object cimport richcmp @@ -1311,10 +1317,9 @@ cdef class ClonableIntArray(ClonableElement): self._len = size def __dealloc__(self): - if self._list is not NULL: - sig_free(self._list) - self._len = -1 - self._list = NULL + sig_free(self._list) + self._len = -1 + self._list = NULL def _repr_(self): """ diff --git a/src/sage/structure/parent_base.pyx b/src/sage/structure/parent_base.pyx index 7a7543bd687..c5a3cbd7a35 100644 --- a/src/sage/structure/parent_base.pyx +++ b/src/sage/structure/parent_base.pyx @@ -1,16 +1,18 @@ r""" Base class for old-style parent objects with a base ring """ -############################################################################### -# Sage: System for Algebra and Geometry Experimentation + +#***************************************************************************** # Copyright (C) 2006 William Stein -# Distributed under the terms of the GNU General Public License (GPL) -# The full text of the GPL is available at: +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. # http://www.gnu.org/licenses/ -############################################################################### -from __future__ import absolute_import +#***************************************************************************** -include "sage/ext/stdsage.pxi" +from __future__ import absolute_import cimport sage.structure.parent as parent @@ -21,31 +23,6 @@ cdef inline check_old_coerce(parent.Parent p): raise RuntimeError("%s still using old coercion framework" % p) -# TODO: Unpickled parents with base sometimes have their base set to None. -# This causes a segfault in the module arithmetic architecture. -# -# sage: H = HomsetWithBase(QQ, RR, base=ZZ); H -# sage: H0 = loads(dumps(H)) -# sage: H.base_ring(), H0.base_ring() -# (Integer Ring, None) -# -# Perhaps the code below would help (why was it commented out?). - -## def make_parent_with_base_v0(_class, _dict, base, has_coerce_map_from): -## """ -## This should work for any Python class deriving from this, as long -## as it doesn't implement some screwy __new__() method. -## """ -## new_object = _class.__new__(_class) -## if base is None: -## (new_object)._base = new_object -## else: -## (new_object)._base = base -## (new_object)._has_coerce_map_from = has_coerce_map_from -## if not _dict is None: -## new_object.__dict__ = _dict -## return new_object - def is_ParentWithBase(x): """ Return True if x is a parent object with base. @@ -57,10 +34,6 @@ cdef class ParentWithBase(Parent_old): This class is being deprecated, see parent.Parent for the new model. """ def __init__(self, base, coerce_from=[], actions=[], embeddings=[], category=None): - # TODO: SymbolicExpressionRing has base RR, which makes this bad -# print type(self), "base", base, coerce_from -# if base != self and not base in coerce_from: -# coerce_from.append(base) Parent_old.__init__(self, coerce_from=coerce_from, actions=actions, embeddings=embeddings, category=category) self._base = base @@ -71,16 +44,6 @@ cdef class ParentWithBase(Parent_old): else: raise TypeError("No canonical coercion found.") -## def x__reduce__(self): -## if HAS_DICTIONARY(self): -## _dict = self.__dict__ -## else: -## _dict = None -## if self._base is self: -## return (make_parent_with_base_v0, (self.__class__, _dict, None, self._has_coerce_map_from)) -## else: -## return (make_parent_with_base_v0, (self.__class__, _dict, self._base, self._has_coerce_map_from)) - # Derived class *must* define base_extend. def base_extend(self, X): check_old_coerce(self) diff --git a/src/sage/structure/parent_gens.pyx b/src/sage/structure/parent_gens.pyx index 08bf0fc9387..f5c305e3f16 100644 --- a/src/sage/structure/parent_gens.pyx +++ b/src/sage/structure/parent_gens.pyx @@ -67,10 +67,8 @@ This example illustrates generators for a free module over `\ZZ`. # (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** -from __future__ import absolute_import -from __future__ import print_function -include 'sage/ext/stdsage.pxi' +from __future__ import absolute_import, print_function import sage.misc.defaults from sage.misc.latex import latex_variable_name @@ -104,22 +102,6 @@ cdef class ParentWithGens(ParentWithBase): self._assign_names(names=names, normalize=normalize) ParentWithBase.__init__(self, base, category=category) - #if category is not None: - # self._init_category_(category) - -## def x__reduce__(self): -## if self._base is self: -## base = None -## else: -## base = self._base -## if HAS_DICTIONARY(self): -## _dict = self.__dict__ -## else: -## _dict = None -## return (make_parent_gens_v0, (self.__class__, -## _dict, base, -## self._has_coerce_map_from, -## self._names)) # Derived class *must* define ngens method. def ngens(self): diff --git a/src/sage/structure/parent_old.pyx b/src/sage/structure/parent_old.pyx index ca6325bdef6..de671181b47 100644 --- a/src/sage/structure/parent_old.pyx +++ b/src/sage/structure/parent_old.pyx @@ -18,43 +18,32 @@ This came up in some subtle bug once. 5 """ -############################################################################### -# Sage: System for Algebra and Geometry Experimentation +#***************************************************************************** # Copyright (C) 2006 William Stein -# Distributed under the terms of the GNU General Public License (GPL) -# The full text of the GPL is available at: +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. # http://www.gnu.org/licenses/ -############################################################################### -from __future__ import absolute_import -from __future__ import print_function +#***************************************************************************** +from __future__ import absolute_import, print_function cimport sage.structure.sage_object as sage_object import operator from .parent import Set_PythonType, Set_PythonType_class from .coerce import py_scalar_parent +from sage.ext.stdsage cimport HAS_DICTIONARY from sage.structure.coerce_dict import MonoDict, TripleDict from cpython.object cimport * from cpython.bool cimport * -include 'sage/ext/stdsage.pxi' cdef inline check_old_coerce(Parent p): if p._element_constructor is not None: raise RuntimeError("%s still using old coercion framework" % p) -## def make_parent_v0(_class, _dict, has_coerce_map_from): -## """ -## This should work for any Python class deriving from this, as long -## as it doesn't implement some screwy __new__() method. -## """ -## cdef Parent new_object -## new_object = _class.__new__(_class) -## if not _dict is None: -## new_object.__dict__ = _dict -## new_object._has_coerce_map_from = has_coerce_map_from -## return new_object - cdef class Parent(parent.Parent): """ Parents are the SAGE/mathematical analogues of container objects From 01ef9879c85a7d04c82f8cabf49b06fa662748f0 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sat, 29 Apr 2017 01:25:23 -0500 Subject: [PATCH 170/452] Forcing things to be well-ordered. --- src/sage/combinat/crystals/kirillov_reshetikhin.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/combinat/crystals/kirillov_reshetikhin.py b/src/sage/combinat/crystals/kirillov_reshetikhin.py index d3d49b3e560..057bcfd6671 100644 --- a/src/sage/combinat/crystals/kirillov_reshetikhin.py +++ b/src/sage/combinat/crystals/kirillov_reshetikhin.py @@ -1410,11 +1410,11 @@ def highest_weight_dict(self): EXAMPLES:: sage: K = crystals.KirillovReshetikhin(['E',6,1],2,1) - sage: sorted(K.highest_weight_dict().items()) + sage: sorted(K.highest_weight_dict().items(), key=str) [([[(2, -1), (1,)]], ((-2, 0, 1, 0, 0, 0, 0), 1)), ([[(3, -1, -6), (1,)]], ((-1, 0, 0, 1, 0, 0, -1), 1)), - ([[(6, -2), (-6, 2)]], ((0, 0, 0, 0, 0, 0, 0), 1)), ([[(5, -2, -6), (-6, 2)]], ((0, 0, 0, 0, 0, 1, -2), 1)), + ([[(6, -2), (-6, 2)]], ((0, 0, 0, 0, 0, 0, 0), 1)), ([], ((0, 0, 0, 0, 0, 0, 0), 0))] """ hw = [x for x in self.hw_auxiliary() if x.epsilon(1) == 0] @@ -1471,11 +1471,11 @@ def promotion_on_highest_weight_vectors(self): sage: K = crystals.KirillovReshetikhin(['E',6,1],2,1) sage: dic = K.promotion_on_highest_weight_vectors() - sage: sorted(dic.items()) + sage: sorted(dic.items(), key=str) [([[(2, -1), (1,)]], [[(-1,), (-1, 3)]]), ([[(3, -1, -6), (1,)]], [[(5, -3), (-1, 3)]]), - ([[(6, -2), (-6, 2)]], []), ([[(5, -2, -6), (-6, 2)]], [[(2, -1), (1,)]]), + ([[(6, -2), (-6, 2)]], []), ([], [[(1, -3), (-1, 3)]])] """ dic = self.highest_weight_dict() From ffb8e73486805dda6ef145cbf85c7a4612220984 Mon Sep 17 00:00:00 2001 From: David Coudert Date: Sun, 30 Apr 2017 09:53:50 +0200 Subject: [PATCH 171/452] trac #22906: improve add_clique method for (di)graphs --- src/sage/graphs/generic_graph.py | 36 +++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 47740a7c5a4..a45edf6b49c 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -16710,7 +16710,8 @@ def add_clique(self, vertices, loops=False): INPUT: - - ``vertices`` -- a list of vertices for the clique to be added. + - ``vertices`` -- an iterable container of vertices for the clique to be + added, e.g. a list, set, graph, etc. - ``loops`` -- (boolean) whether to add loops or not, i.e., edges from a vertex to itself. Possible only if the (di)graph allows loops. @@ -16735,14 +16736,39 @@ def add_clique(self, vertices, loops=False): False sage: D.is_isomorphic(digraphs.Complete(4, loops=False)) True + + TESTS: + + Using different kinds of iterable container of vertices, :trac:`22906`:: + + sage: G = Graph(4) + sage: G.add_clique(G) + sage: G.is_clique() + True + sage: G = Graph() + sage: G.add_clique(set(range(4))) + sage: G.is_clique() + True + sage: G = Graph() + sage: G.add_clique({i:(i, i+1) for i in range(4)}) + sage: G.is_clique() + True + sage: G.vertices() + [0, 1, 2, 3] + sage: D = DiGraph(4, loops=True) + sage: D.add_clique(range(4), loops=True) + sage: D.is_clique(directed_clique=True) + True """ + import itertools if vertices: - n = len(vertices) - self.add_edges((vertices[i],vertices[j]) for i in range(n-1) for j in range(i+1,n)) + vertices = list(vertices) if self.is_directed(): - self.add_edges((vertices[j],vertices[i]) for i in range(n-1) for j in range(i+1,n)) + self.add_edges(itertools.permutations(vertices, 2)) + else: + self.add_edges(itertools.combinations(vertices, 2)) if loops and self.allows_loops(): - self.add_edges((vertices[i],vertices[i]) for i in range(n)) + self.add_edges((u, u) for u in vertices) def add_cycle(self, vertices): """ From 20cd81e1bee338a47aa5a77906e9747df03d2592 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 30 Apr 2017 11:32:09 +0200 Subject: [PATCH 172/452] phase out lexico comparison in real_mpfi --- src/sage/rings/real_mpfi.pyx | 83 ++++++++++++++++++++---------------- 1 file changed, 46 insertions(+), 37 deletions(-) diff --git a/src/sage/rings/real_mpfi.pyx b/src/sage/rings/real_mpfi.pyx index 439bc2013b6..10b076d0c68 100644 --- a/src/sage/rings/real_mpfi.pyx +++ b/src/sage/rings/real_mpfi.pyx @@ -126,20 +126,12 @@ Comparison operations (``==``, ``!=``, ``<``, ``<=``, ``>``, ``>=``) return ``True`` if every value in the first interval has the given relation to every value in the second interval. -The ``cmp(a, b)`` function works -differently; it compares two intervals lexicographically. (However, the -behavior is not specified if given a non-interval and an interval.) -Note that ``cmp`` will disappear in Python3. - This convention for comparison operators has good and bad points. The good: - Expected transitivity properties hold (if ``a > b`` and ``b == c``, then ``a > c``; etc.) -- if ``a > b``, then ``cmp(a, b) == 1``; if ``a == b``, then ``cmp(a,b) == 0``; - if ``a < b``, then ``cmp(a, b) == -1`` - - ``a == 0`` is true if the interval contains only the floating-point number 0; similarly for ``a == 1`` @@ -151,17 +143,21 @@ The bad: - Trichotomy fails to hold: there are values ``(a,b)`` such that none of ``a < b``, ``a == b``, or ``a > b`` are true -- It is not the case that if ``cmp(a, b) == 0`` then ``a == b``, or that if - ``cmp(a, b) == 1`` then ``a > b``, or that if ``cmp(a, b) == -1`` then - ``a < b`` - - There are values ``a`` and ``b`` such that ``a <= b`` but neither ``a < b`` nor ``a == b`` hold. +- There are values ``a`` and ``b`` such that neither ``a != b`` + nor ``a == b`` hold. + .. NOTE:: Intervals ``a`` and ``b`` overlap iff ``not(a != b)``. +.. WARNING:: + + The ``cmp(a, b)`` function should not be used to compare real + intervals. Note that ``cmp`` will disappear in Python3. + EXAMPLES:: sage: 0 < RIF(1, 2) @@ -176,14 +172,6 @@ EXAMPLES:: True sage: not(0 < RIF(0, 1)) True - sage: cmp(RIF(0), RIF(0, 1)) - -1 - sage: cmp(RIF(0, 1), RIF(0)) - 1 - sage: cmp(RIF(0, 1), RIF(1)) - -1 - sage: cmp(RIF(0, 1), RIF(0, 1)) - 0 Comparison with infinity is defined through coercion to the infinity ring where semi-infinite intervals are sent to their central value @@ -213,6 +201,19 @@ interval coerces to plus infinity:: sage: RIF(-oo,oo) == oo True +If you want to compare two intervals lexicographically, you can use the +method ``lexico_cmp``. However, the behavior of this method is not +specified if given a non-interval and an interval:: + + sage: RIF(0).lexico_cmp(RIF(0, 1)) + -1 + sage: RIF(0, 1).lexico_cmp(RIF(0)) + 1 + sage: RIF(0, 1).lexico_cmp(RIF(1)) + -1 + sage: RIF(0, 1).lexico_cmp(RIF(0, 1)) + 0 + TESTS: Comparisons with numpy types are right (see :trac:`17758` and :trac:`18076`):: @@ -672,7 +673,7 @@ cdef class RealIntervalField_class(sage.rings.ring.Field): Type: RealIntervalField? for more information. """ if not y is None: - x = (x,y) + x = (x, y) return RealIntervalFieldElement(self, x, base) def algebraic_closure(self): @@ -1147,6 +1148,11 @@ cdef class RealIntervalFieldElement(RingElement): TypeError: Cannot convert sage.rings.integer_ring.IntegerRing_class to sage.rings.real_mpfi.RealIntervalField_class sage: RealIntervalFieldElement.__new__(RealIntervalFieldElement, RIF) [.. NaN ..] + + Equality ``x == x`` does not hold unless ``x`` is exact:: + + sage: x = RIF(4.5, 4.6) + sage: TestSuite(x).run(skip=["_test_eq", "_test_pickling"]) """ cdef RealIntervalField_class p = parent mpfi_init2(self.value, p.__prec) @@ -1256,11 +1262,11 @@ cdef class RealIntervalFieldElement(RingElement): EXAMPLES:: sage: a = RIF(5,5.5) - sage: cmp(loads(dumps(a)), a) + sage: loads(dumps(a)).lexico_cmp(a) 0 sage: R = RealIntervalField(sci_not=1, prec=200) sage: b = R('393.39203845902384098234098230948209384028340') - sage: cmp(loads(dumps(b)), b) + sage: loads(dumps(b)).lexico_cmp(b) 0 sage: b = R(1)/R(0); b # R(0) has no particular sign, thus 1/R(0) covers the whole reals [-infinity .. +infinity] @@ -1274,7 +1280,7 @@ cdef class RealIntervalFieldElement(RingElement): True sage: b = R('[2 .. 3]'); b.str(error_digits=1) '2.5?5e0' - sage: cmp(loads(dumps(b)), b) + sage: loads(dumps(b)).lexico_cmp(b) 0 sage: R = RealIntervalField(4000) sage: s = 1/R(3) @@ -3548,10 +3554,10 @@ cdef class RealIntervalFieldElement(RingElement): cpdef _richcmp_(left, right, int op): """ - Implements comparisons between intervals. + Implement comparisons between intervals. - (See the file header - comment for more information on interval comparison.) + See the file header comment for more information on interval + comparison. EXAMPLES:: @@ -3761,32 +3767,35 @@ cdef class RealIntervalFieldElement(RingElement): """ return not (mpfr_zero_p(&self.value.left) and mpfr_zero_p(&self.value.right)) - cpdef int _cmp_(left, right) except -2: + def lexico_cmp(left, right): """ Compare two intervals lexicographically. + This means that the left bounds are compared first and then + the right bounds are compared if the left bounds coincide. + Return 0 if they are the same interval, -1 if the second is larger, or 1 if the first is larger. EXAMPLES:: - sage: cmp(RIF(0), RIF(1)) + sage: RIF(0).lexico_cmp(RIF(1)) -1 - sage: cmp(RIF(0, 1), RIF(1)) + sage: RIF(0, 1).lexico_cmp(RIF(1)) -1 - sage: cmp(RIF(0, 1), RIF(1, 2)) + sage: RIF(0, 1).lexico_cmp(RIF(1, 2)) -1 - sage: cmp(RIF(0, 0.99999), RIF(1, 2)) + sage: RIF(0, 0.99999).lexico_cmp(RIF(1, 2)) -1 - sage: cmp(RIF(1, 2), RIF(0, 1)) + sage: RIF(1, 2).lexico_cmp(RIF(0, 1)) 1 - sage: cmp(RIF(1, 2), RIF(0)) + sage: RIF(1, 2).lexico_cmp(RIF(0)) 1 - sage: cmp(RIF(0, 1), RIF(0, 2)) + sage: RIF(0, 1).lexico_cmp(RIF(0, 2)) -1 - sage: cmp(RIF(0, 1), RIF(0, 1)) + sage: RIF(0, 1).lexico_cmp(RIF(0, 1)) 0 - sage: cmp(RIF(0, 1), RIF(0, 1/2)) + sage: RIF(0, 1).lexico_cmp(RIF(0, 1/2)) 1 """ cdef RealIntervalFieldElement lt, rt From 1521d8e4e677f11ea2b76307b9c7cf643cdebead Mon Sep 17 00:00:00 2001 From: David Coudert Date: Sun, 30 Apr 2017 16:47:11 +0200 Subject: [PATCH 173/452] trac #22911: reorder loop related methods --- src/sage/graphs/generic_graph.py | 146 +++++++++++++++---------------- 1 file changed, 73 insertions(+), 73 deletions(-) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 47740a7c5a4..1aa2c7b0bd0 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -26,6 +26,10 @@ :meth:`~GenericGraph.allows_loops` | Return whether loops are permitted in the (di)graph. :meth:`~GenericGraph.allow_loops` | Change whether loops are permitted in the (di)graph. :meth:`~GenericGraph.loops` | Return any loops in the (di)graph. + :meth:`~GenericGraph.loop_edges` | Returns a list of all loops in the graph. + :meth:`~GenericGraph.number_of_loops` | Return the number of edges that are loops. + :meth:`~GenericGraph.loop_vertices` | Return a list of vertices with loops. + :meth:`~GenericGraph.remove_loops` | Remove loops on vertices in vertices. If vertices is None, removes all loops. :meth:`~GenericGraph.has_multiple_edges` | Return whether there are multiple edges in the (di)graph. :meth:`~GenericGraph.allows_multiple_edges` | Return whether multiple edges are permitted in the (di)graph. :meth:`~GenericGraph.allow_multiple_edges` | Change whether multiple edges are permitted in the (di)graph. @@ -51,7 +55,6 @@ :meth:`~GenericGraph.set_vertex` | Associate an arbitrary object with a vertex. :meth:`~GenericGraph.get_vertex` | Retrieve the object associated with a given vertex. :meth:`~GenericGraph.get_vertices` | Return a dictionary of the objects associated to each vertex. - :meth:`~GenericGraph.loop_vertices` | Return a list of vertices with loops. :meth:`~GenericGraph.vertex_iterator` | Return an iterator over the vertices. :meth:`~GenericGraph.neighbor_iterator` | Return an iterator over neighbors of vertex. :meth:`~GenericGraph.vertices` | Return a list of the vertices. @@ -73,9 +76,6 @@ :meth:`~GenericGraph.edge_label` | Return the label of an edge. :meth:`~GenericGraph.edge_labels` | Return a list of edge labels. :meth:`~GenericGraph.remove_multiple_edges` | Remove all multiple edges, retaining one edge for each. - :meth:`~GenericGraph.remove_loops` | Remove loops on vertices in vertices. If vertices is None, removes all loops. - :meth:`~GenericGraph.loop_edges` | Returns a list of all loops in the graph. - :meth:`~GenericGraph.number_of_loops` | Return the number of edges that are loops. :meth:`~GenericGraph.clear` | Empty the graph of vertices and edges and removes name, associated objects, and position information. :meth:`~GenericGraph.degree` | Return the degree (in + out for digraphs) of a vertex or of vertices. :meth:`~GenericGraph.average_degree` | Return the average degree of the graph. @@ -2474,6 +2474,75 @@ def loops(self, labels=True): loops += self.edge_boundary([v], [v], labels) return loops + def loop_edges(self): + """ + Returns a list of all loops in the graph. + + EXAMPLES:: + + sage: G = Graph(4, loops=True) + sage: G.add_edges( [ (0,0), (1,1), (2,2), (3,3), (2,3) ] ) + sage: G.loop_edges() + [(0, 0, None), (1, 1, None), (2, 2, None), (3, 3, None)] + + :: + + sage: D = DiGraph(4, loops=True) + sage: D.add_edges( [ (0,0), (1,1), (2,2), (3,3), (2,3) ] ) + sage: D.loop_edges() + [(0, 0, None), (1, 1, None), (2, 2, None), (3, 3, None)] + + :: + + sage: G = Graph(4, loops=True, multiedges=True, sparse=True) + sage: G.add_edges([(i,i) for i in range(4)]) + sage: G.loop_edges() + [(0, 0, None), (1, 1, None), (2, 2, None), (3, 3, None)] + """ + if self.allows_multiple_edges(): + return [(v,v,l) for v in self.loop_vertices() for l in self.edge_label(v,v)] + else: + return [(v,v,self.edge_label(v,v)) for v in self.loop_vertices()] + + def number_of_loops(self): + """ + Returns the number of edges that are loops. + + EXAMPLES:: + + sage: G = Graph(4, loops=True) + sage: G.add_edges( [ (0,0), (1,1), (2,2), (3,3), (2,3) ] ) + sage: G.edges(labels=False) + [(0, 0), (1, 1), (2, 2), (2, 3), (3, 3)] + sage: G.number_of_loops() + 4 + + :: + + sage: D = DiGraph(4, loops=True) + sage: D.add_edges( [ (0,0), (1,1), (2,2), (3,3), (2,3) ] ) + sage: D.edges(labels=False) + [(0, 0), (1, 1), (2, 2), (2, 3), (3, 3)] + sage: D.number_of_loops() + 4 + """ + return len(self.loop_edges()) + + def loop_vertices(self): + """ + Returns a list of vertices with loops. + + EXAMPLES:: + + sage: G = Graph({0 : [0], 1: [1,2,3], 2: [3]}, loops=True) + sage: G.loop_vertices() + [0, 1] + """ + if self.allows_loops(): + return [v for v in self if self.has_edge(v,v)] + else: + return [] + def has_multiple_edges(self, to_undirected=False): """ Returns whether there are multiple edges in the (di)graph. @@ -9891,21 +9960,6 @@ def get_vertices(self, verts=None): return output - def loop_vertices(self): - """ - Returns a list of vertices with loops. - - EXAMPLES:: - - sage: G = Graph({0 : [0], 1: [1,2,3], 2: [3]}, loops=True) - sage: G.loop_vertices() - [0, 1] - """ - if self.allows_loops(): - return [v for v in self if self.has_edge(v,v)] - else: - return [] - def vertex_iterator(self, vertices=None): """ Returns an iterator over the given vertices. @@ -11077,60 +11131,6 @@ def remove_loops(self, vertices=None): if self.has_edge(v,v): self.delete_multiedge(v,v) - def loop_edges(self): - """ - Returns a list of all loops in the graph. - - EXAMPLES:: - - sage: G = Graph(4, loops=True) - sage: G.add_edges( [ (0,0), (1,1), (2,2), (3,3), (2,3) ] ) - sage: G.loop_edges() - [(0, 0, None), (1, 1, None), (2, 2, None), (3, 3, None)] - - :: - - sage: D = DiGraph(4, loops=True) - sage: D.add_edges( [ (0,0), (1,1), (2,2), (3,3), (2,3) ] ) - sage: D.loop_edges() - [(0, 0, None), (1, 1, None), (2, 2, None), (3, 3, None)] - - :: - - sage: G = Graph(4, loops=True, multiedges=True, sparse=True) - sage: G.add_edges([(i,i) for i in range(4)]) - sage: G.loop_edges() - [(0, 0, None), (1, 1, None), (2, 2, None), (3, 3, None)] - """ - if self.allows_multiple_edges(): - return [(v,v,l) for v in self.loop_vertices() for l in self.edge_label(v,v)] - else: - return [(v,v,self.edge_label(v,v)) for v in self.loop_vertices()] - - def number_of_loops(self): - """ - Returns the number of edges that are loops. - - EXAMPLES:: - - sage: G = Graph(4, loops=True) - sage: G.add_edges( [ (0,0), (1,1), (2,2), (3,3), (2,3) ] ) - sage: G.edges(labels=False) - [(0, 0), (1, 1), (2, 2), (2, 3), (3, 3)] - sage: G.number_of_loops() - 4 - - :: - - sage: D = DiGraph(4, loops=True) - sage: D.add_edges( [ (0,0), (1,1), (2,2), (3,3), (2,3) ] ) - sage: D.edges(labels=False) - [(0, 0), (1, 1), (2, 2), (2, 3), (3, 3)] - sage: D.number_of_loops() - 4 - """ - return len(self.loop_edges()) - ### Modifications def clear(self): From fd7bf7ff53ea457128b02c24b893ec5448ea6c49 Mon Sep 17 00:00:00 2001 From: David Coudert Date: Sun, 30 Apr 2017 17:00:19 +0200 Subject: [PATCH 174/452] trac #22911: add parameter labels to loop_edges --- src/sage/graphs/generic_graph.py | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 1aa2c7b0bd0..91434698902 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -2474,16 +2474,31 @@ def loops(self, labels=True): loops += self.edge_boundary([v], [v], labels) return loops - def loop_edges(self): + def loop_edges(self, labels=True): """ Returns a list of all loops in the graph. + INPUT: + + - ``labels`` -- whether returned edges have labels ((u,v,l)) or not ((u,v)). + EXAMPLES:: sage: G = Graph(4, loops=True) sage: G.add_edges( [ (0,0), (1,1), (2,2), (3,3), (2,3) ] ) sage: G.loop_edges() [(0, 0, None), (1, 1, None), (2, 2, None), (3, 3, None)] + sage: G.loop_edges(labels=False) + [(0, 0), (1, 1), (2, 2), (3, 3)] + sage: G.allows_loops() + True + sage: G.has_loops() + True + sage: G.allow_loops(False) + sage: G.has_loops() + False + sage: G.loop_edges() + [] :: @@ -2498,11 +2513,19 @@ def loop_edges(self): sage: G.add_edges([(i,i) for i in range(4)]) sage: G.loop_edges() [(0, 0, None), (1, 1, None), (2, 2, None), (3, 3, None)] + sage: G.add_edges([(0, 0), (1, 1)]) + sage: G.loop_edges(labels=False) + [(0, 0), (0, 0), (1, 1), (1, 1), (2, 2), (3, 3)] """ if self.allows_multiple_edges(): - return [(v,v,l) for v in self.loop_vertices() for l in self.edge_label(v,v)] - else: + if labels: + return [(v,v,l) for v in self.loop_vertices() for l in self.edge_label(v,v)] + else: + return [(v,v) for v in self.loop_vertices() for l in self.edge_label(v,v)] + elif labels: return [(v,v,self.edge_label(v,v)) for v in self.loop_vertices()] + else: + return [(v,v) for v in self.loop_vertices()] def number_of_loops(self): """ From ea97bfce2d685fffcb7c17ac5967be875385806a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 30 Apr 2017 18:46:29 +0200 Subject: [PATCH 175/452] py3 deprecation of call to cmp on RIF elements --- src/sage/rings/real_mpfi.pyx | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/sage/rings/real_mpfi.pyx b/src/sage/rings/real_mpfi.pyx index 10b076d0c68..3bad4a6f4ea 100644 --- a/src/sage/rings/real_mpfi.pyx +++ b/src/sage/rings/real_mpfi.pyx @@ -3817,6 +3817,22 @@ cdef class RealIntervalFieldElement(RingElement): else: return 0 + cpdef int _cmp_(self, other) except -2: + """ + Deprecated method (:trac:`22907`) + + EXAMPLES:: + + sage: a = RIF(1) + sage: a.__cmp__(a) + doctest:...: DeprecationWarning: for RIF elements, do not use cmp + See http://trac.sagemath.org/22907 for details. + 0 + """ + from sage.misc.superseded import deprecation + deprecation(22907, 'for RIF elements, do not use cmp') + return self.lexico_cmp(other) + def __contains__(self, other): """ Test whether one interval (or real number) is totally contained in From 85b7ef5915b0ac3d2dac5aba1d32155af6361b04 Mon Sep 17 00:00:00 2001 From: David Coudert Date: Sun, 30 Apr 2017 19:02:43 +0200 Subject: [PATCH 176/452] trac #22911: make loops an alias for loop_edges and fix doc strings --- src/sage/graphs/generic_graph.py | 88 +++++++------------------------- 1 file changed, 18 insertions(+), 70 deletions(-) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 91434698902..5b63a2dda95 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -22,13 +22,13 @@ :meth:`~GenericGraph.distance_matrix` | Return the distance matrix of the (strongly) connected (di)graph :meth:`~GenericGraph.weighted_adjacency_matrix` | Return the weighted adjacency matrix of the graph :meth:`~GenericGraph.kirchhoff_matrix` | Return the Kirchhoff matrix (a.k.a. the Laplacian) of the graph. - :meth:`~GenericGraph.has_loops` | Return whether there are loops in the (di)graph. - :meth:`~GenericGraph.allows_loops` | Return whether loops are permitted in the (di)graph. - :meth:`~GenericGraph.allow_loops` | Change whether loops are permitted in the (di)graph. - :meth:`~GenericGraph.loops` | Return any loops in the (di)graph. - :meth:`~GenericGraph.loop_edges` | Returns a list of all loops in the graph. - :meth:`~GenericGraph.number_of_loops` | Return the number of edges that are loops. - :meth:`~GenericGraph.loop_vertices` | Return a list of vertices with loops. + :meth:`~GenericGraph.has_loops` | Return whether there are loops in the (di)graph + :meth:`~GenericGraph.allows_loops` | Return whether loops are permitted in the (di)graph + :meth:`~GenericGraph.allow_loops` | Change whether loops are permitted in the (di)graph + :meth:`~GenericGraph.loops` | Return a list of all loops in the (di)graph + :meth:`~GenericGraph.loop_edges` | Return a list of all loops in the (di)graph + :meth:`~GenericGraph.number_of_loops` | Return the number of edges that are loops + :meth:`~GenericGraph.loop_vertices` | Return a list of vertices with loops :meth:`~GenericGraph.remove_loops` | Remove loops on vertices in vertices. If vertices is None, removes all loops. :meth:`~GenericGraph.has_multiple_edges` | Return whether there are multiple edges in the (di)graph. :meth:`~GenericGraph.allows_multiple_edges` | Return whether multiple edges are permitted in the (di)graph. @@ -2278,7 +2278,7 @@ def _check_embedding_validity(self, embedding=None, boolean=True): def has_loops(self): """ - Returns whether there are loops in the (di)graph. + Return whether there are loops in the (di)graph EXAMPLES:: @@ -2326,7 +2326,7 @@ def has_loops(self): def allows_loops(self): """ - Returns whether loops are permitted in the (di)graph. + Return whether loops are permitted in the (di)graph EXAMPLES:: @@ -2370,7 +2370,7 @@ def allows_loops(self): def allow_loops(self, new, check=True): """ - Changes whether loops are permitted in the (di)graph. + Change whether loops are permitted in the (di)graph INPUT: @@ -2418,69 +2418,14 @@ def allow_loops(self, new, check=True): self.remove_loops() self._backend.loops(new) - def loops(self, labels=True): - """ - Returns any loops in the (di)graph. - - INPUT: - - - ``labels`` -- whether returned edges have labels ((u,v,l)) or not ((u,v)). - - EXAMPLES:: - - sage: G = Graph(loops=True); G - Looped graph on 0 vertices - sage: G.has_loops() - False - sage: G.allows_loops() - True - sage: G.add_edge((0,0)) - sage: G.has_loops() - True - sage: G.loops() - [(0, 0, None)] - sage: G.allow_loops(False); G - Graph on 1 vertex - sage: G.has_loops() - False - sage: G.edges() - [] - - sage: D = DiGraph(loops=True); D - Looped digraph on 0 vertices - sage: D.has_loops() - False - sage: D.allows_loops() - True - sage: D.add_edge((0,0)) - sage: D.has_loops() - True - sage: D.loops() - [(0, 0, None)] - sage: D.allow_loops(False); D - Digraph on 1 vertex - sage: D.has_loops() - False - sage: D.edges() - [] - - sage: G = graphs.PetersenGraph() - sage: G.loops() - [] - - """ - loops = [] - for v in self: - loops += self.edge_boundary([v], [v], labels) - return loops - def loop_edges(self, labels=True): """ - Returns a list of all loops in the graph. + Return a list of all loops in the (di)graph INPUT: - - ``labels`` -- whether returned edges have labels ((u,v,l)) or not ((u,v)). + - ``labels`` -- whether returned edges have labels (``(u,v,l)``) or not + (``(u,v)``). EXAMPLES:: @@ -2527,9 +2472,12 @@ def loop_edges(self, labels=True): else: return [(v,v) for v in self.loop_vertices()] + # As discussed in trac 22911, we make method loops an alias for loop_edges + loops = loop_edges + def number_of_loops(self): """ - Returns the number of edges that are loops. + Return the number of edges that are loops EXAMPLES:: @@ -2553,7 +2501,7 @@ def number_of_loops(self): def loop_vertices(self): """ - Returns a list of vertices with loops. + Return a list of vertices with loops EXAMPLES:: From c22c50553ceed2fb3ac391648f78927279885980 Mon Sep 17 00:00:00 2001 From: David Coudert Date: Sun, 30 Apr 2017 19:25:00 +0200 Subject: [PATCH 177/452] trac #22911: merge doctests --- src/sage/graphs/generic_graph.py | 31 ++++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 5b63a2dda95..d5523b61b0f 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -2429,7 +2429,12 @@ def loop_edges(self, labels=True): EXAMPLES:: - sage: G = Graph(4, loops=True) + sage: G = Graph(loops=True); G + Looped graph on 0 vertices + sage: G.has_loops() + False + sage: G.allows_loops() + True sage: G.add_edges( [ (0,0), (1,1), (2,2), (3,3), (2,3) ] ) sage: G.loop_edges() [(0, 0, None), (1, 1, None), (2, 2, None), (3, 3, None)] @@ -2444,6 +2449,30 @@ def loop_edges(self, labels=True): False sage: G.loop_edges() [] + sage: G.edges() + [(2, 3, None)] + + sage: D = DiGraph(loops=True); D + Looped digraph on 0 vertices + sage: D.has_loops() + False + sage: D.allows_loops() + True + sage: D.add_edge((0,0)) + sage: D.has_loops() + True + sage: D.loops() + [(0, 0, None)] + sage: D.allow_loops(False); D + Digraph on 1 vertex + sage: D.has_loops() + False + sage: D.edges() + [] + + sage: G = graphs.PetersenGraph() + sage: G.loops() + [] :: From fc65b8ce08248f28497f35ae4d13f7f47513a6d5 Mon Sep 17 00:00:00 2001 From: David Coudert Date: Sun, 30 Apr 2017 19:53:01 +0200 Subject: [PATCH 178/452] trac #22911: remove period in input --- src/sage/graphs/generic_graph.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index d5523b61b0f..672ea25e8fa 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -2425,7 +2425,7 @@ def loop_edges(self, labels=True): INPUT: - ``labels`` -- whether returned edges have labels (``(u,v,l)``) or not - (``(u,v)``). + (``(u,v)``) EXAMPLES:: From 66c21bae27cf5f92bc8ab888db9e75013106d1bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 30 Apr 2017 21:17:58 +0200 Subject: [PATCH 179/452] py3: using six.string_types in a few places --- src/sage/databases/findstat.py | 6 +++--- src/sage/misc/sage_input.py | 4 ++-- src/sage/symbolic/function_factory.py | 3 ++- src/sage/typeset/character_art_factory.py | 5 +++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/sage/databases/findstat.py b/src/sage/databases/findstat.py index aec5a624702..b855648fc85 100644 --- a/src/sage/databases/findstat.py +++ b/src/sage/databases/findstat.py @@ -168,7 +168,7 @@ def increasing_tree_shape(elt, compare=min): #***************************************************************************** from __future__ import print_function from six.moves import range -from six import iteritems, add_metaclass +from six import iteritems, add_metaclass, string_types from sage.misc.inherit_comparison import InheritComparisonClasscallMetaclass from sage.structure.element import Element @@ -2441,7 +2441,7 @@ def _element_constructor_(self, entry): if isinstance(entry, FindStatCollection): return entry - if isinstance(entry, (str, unicode)): + if isinstance(entry, string_types): # find by name in _findstat_collections for (id, c) in iteritems(self._findstat_collections): if entry.upper() in (c[0].upper(), c[1].upper(), c[2].upper()): @@ -2837,7 +2837,7 @@ def _element_constructor_(self, entry): elif entry in self._findstat_maps: return self.element_class(self, entry) - elif isinstance(entry, (str, unicode)): + elif isinstance(entry, string_types): # find by name in _findstat_maps for c in self._findstat_maps: if entry.upper() == c[FINDSTAT_MAP_NAME].upper(): diff --git a/src/sage/misc/sage_input.py b/src/sage/misc/sage_input.py index aeadc0ec94b..0e33d257cce 100644 --- a/src/sage/misc/sage_input.py +++ b/src/sage/misc/sage_input.py @@ -174,7 +174,7 @@ from __future__ import print_function, absolute_import -from six import itervalues, iteritems +from six import itervalues, iteritems, string_types def sage_input(x, preparse=True, verify=False, allow_locals=False): @@ -536,7 +536,7 @@ def __call__(self, x, coerced=False): return self.name('float')(self.int(ZZ(rrx))) return self.name('float')(RR(x)) - if isinstance(x, (str, unicode)): + if isinstance(x, string_types): return SIE_literal_stringrep(self, repr(x)) if isinstance(x, tuple): diff --git a/src/sage/symbolic/function_factory.py b/src/sage/symbolic/function_factory.py index 5687c0d40cb..c78c3b171b2 100644 --- a/src/sage/symbolic/function_factory.py +++ b/src/sage/symbolic/function_factory.py @@ -10,6 +10,7 @@ # http://www.gnu.org/licenses/ ############################################################################### from __future__ import print_function +from six import string_types from sage.symbolic.function import SymbolicFunction, sfunctions_funcs, \ unpickle_wrapper @@ -311,7 +312,7 @@ def function(s, *args, **kwds): sage: E E """ - if not isinstance(s, (str, unicode)): + if not isinstance(s, string_types): raise TypeError("expect string as first argument") # create the function diff --git a/src/sage/typeset/character_art_factory.py b/src/sage/typeset/character_art_factory.py index e13ab8d0541..bff5bbb65ab 100644 --- a/src/sage/typeset/character_art_factory.py +++ b/src/sage/typeset/character_art_factory.py @@ -16,10 +16,11 @@ # # http://www.gnu.org/licenses/ #******************************************************************************* -from six import iteritems +from six import iteritems, string_types from sage.structure.sage_object import SageObject + class CharacterArtFactory(SageObject): def __init__(self, @@ -60,7 +61,7 @@ def __init__(self, """ self.art_type = art_type - assert string_type in [str, unicode] + assert string_type in string_types self.string_type = string_type assert magic_method_name in ['_ascii_art_', '_unicode_art_'] self.magic_method_name = magic_method_name From ef99d57bfddb66ad3bc24a4d57309fb9e99c7658 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Mon, 1 May 2017 11:19:33 +0100 Subject: [PATCH 180/452] update to 1.2.11 --- build/pkgs/zlib/checksums.ini | 8 ++++---- build/pkgs/zlib/package-version.txt | 2 +- build/pkgs/zlib/patches/cygwin_symbols.patch | 18 ++++++++---------- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/build/pkgs/zlib/checksums.ini b/build/pkgs/zlib/checksums.ini index 51f394e2518..4b1b46adcaa 100644 --- a/build/pkgs/zlib/checksums.ini +++ b/build/pkgs/zlib/checksums.ini @@ -1,4 +1,4 @@ -tarball=zlib-VERSION.tar.bz2 -sha1=e63277b761e138a75f8c6a9ededb8d95198739a7 -md5=72106d8198c120d46676dd2f15cf3685 -cksum=3965901566 +tarball=zlib-VERSION.tar.gz +sha1=e6d119755acdf9104d7ba236b1242696940ed6dd +md5=1c9f62f0778697a09d36121ead88e08e +cksum=2150653187 diff --git a/build/pkgs/zlib/package-version.txt b/build/pkgs/zlib/package-version.txt index f09a5d00bfb..624c12b0260 100644 --- a/build/pkgs/zlib/package-version.txt +++ b/build/pkgs/zlib/package-version.txt @@ -1 +1 @@ -1.2.8.p0 +1.2.11.p0 diff --git a/build/pkgs/zlib/patches/cygwin_symbols.patch b/build/pkgs/zlib/patches/cygwin_symbols.patch index c611accae4f..97754e4e53f 100644 --- a/build/pkgs/zlib/patches/cygwin_symbols.patch +++ b/build/pkgs/zlib/patches/cygwin_symbols.patch @@ -1,10 +1,8 @@ -diff -druN src.orig/win32/zlib.def src/win32/zlib.def ---- src.orig/win32/zlib.def 2013-08-06 23:12:37.370530629 +0200 -+++ src/win32/zlib.def 2013-08-06 23:13:09.034279643 +0200 -@@ -83,4 +83,5 @@ - inflateUndermine - inflateResetKeep - deflateResetKeep -- gzopen_w -+; disable the following for Cygwin -+; gzopen_w +from https://github.com/cygwinports/zlib/blob/master/1.2.11-gzopen_w.patch +--- origsrc/zlib-1.2.11/win32/zlib.def 2017-01-01 01:37:10.000000000 -0600 ++++ src/win32/zlib.def 2017-03-03 15:41:32.326386500 -0600 +@@ -91,4 +91,3 @@ EXPORTS + inflateCodesUsed + inflateResetKeep + deflateResetKeep +- gzopen_w From 464754af35bf09eb4eaea18503597dd12345ff54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 1 May 2017 14:21:33 +0200 Subject: [PATCH 181/452] py3: do not use basestring but six.string_types --- src/sage/combinat/posets/poset_examples.py | 4 +- src/sage/crypto/mq/rijndael_gf.py | 44 +++++++++++----------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/sage/combinat/posets/poset_examples.py b/src/sage/combinat/posets/poset_examples.py index 1454a4b71f9..a11bb9ea81a 100644 --- a/src/sage/combinat/posets/poset_examples.py +++ b/src/sage/combinat/posets/poset_examples.py @@ -72,7 +72,7 @@ # http://www.gnu.org/licenses/ #***************************************************************************** from __future__ import print_function -from six import add_metaclass +from six import add_metaclass, string_types from sage.misc.classcall_metaclass import ClasscallMetaclass import sage.categories.posets @@ -703,7 +703,7 @@ def RandomLattice(n, p, properties=None): D.relabel([i-1 for i in Permutations(n).random_element()]) return LatticePoset(D, cover_relations=True) - if isinstance(properties, basestring): + if isinstance(properties, string_types): properties = set([properties]) else: properties = set(properties) diff --git a/src/sage/crypto/mq/rijndael_gf.py b/src/sage/crypto/mq/rijndael_gf.py index a19ec833efc..0eaecd2bb44 100644 --- a/src/sage/crypto/mq/rijndael_gf.py +++ b/src/sage/crypto/mq/rijndael_gf.py @@ -422,6 +422,7 @@ # http://www.gnu.org/licenses/ #***************************************************************************** from __future__ import print_function, division +from six import string_types from sage.matrix.constructor import matrix from sage.matrix.constructor import column_matrix @@ -487,10 +488,10 @@ def __init__(self, Nb, Nk, state_chr='a', key_chr='k'): if Nk not in range(4, 9): msg = "Key length Nk must be in the range 4 - 8, not {0}" raise ValueError(msg.format(Nk)) - if not isinstance(state_chr, basestring): + if not isinstance(state_chr, string_types): msg = "state_chr must be a string, not {0}" raise TypeError(msg.format(state_chr)) - if not isinstance(key_chr, basestring): + if not isinstance(key_chr, string_types): msg = "key_chr must be a string, not {0}" raise TypeError(msg.format(key_chr)) @@ -707,8 +708,8 @@ def _hex_to_GF(self, H, matrix=True): sage: rgf._hex_to_GF('1a2b0f', matrix=False) [x^4 + x^3 + x, x^5 + x^3 + x + 1, x^3 + x^2 + x + 1] """ - if not isinstance(H, basestring) or \ - any([c not in '0123456789abcdefABCDEF' for c in H]): + if not isinstance(H, string_types) or \ + any(c not in '0123456789abcdefABCDEF' for c in H): raise TypeError("keyword 'H' must be a hex string") def hx_to_gf(h): @@ -835,8 +836,7 @@ def _bin_to_GF(self, B, matrix=True): x^7 + x^6 + x^4 + x^2 + x + 1, x^5 + x^4 + x^2 + 1] """ - if not isinstance(B, basestring) or \ - any([c not in '01' for c in B]): + if not isinstance(B, string_types) or any(c not in '01' for c in B): raise TypeError("keyword 'B' must be a binary string") def bn_to_gf(b): @@ -953,14 +953,14 @@ def encrypt(self, plain, key, format='hex'): True """ if format == 'hex': - if not isinstance(plain, basestring) or \ - any([c not in '0123456789abcdefABCDEF' for c in plain]): + if not isinstance(plain, string_types) or \ + any(c not in '0123456789abcdefABCDEF' for c in plain): raise TypeError("'plain' keyword must be a hex string") if len(plain) != 8 * self._Nb: msg = "'plain' keyword\'s length must be {0}, not{1}" raise ValueError(msg.format(8 * self._Nb, len(plain))) - if not isinstance(key, basestring) or \ - any([c not in '0123456789abcdefABCDEF' for c in key]): + if not isinstance(key, string_types) or \ + any(c not in '0123456789abcdefABCDEF' for c in key): raise TypeError("'key' keyword must be a hex string") if len(key) != 8 * self._Nk: msg = "'key' keyword's length must be {0}, not {1}" @@ -969,14 +969,14 @@ def encrypt(self, plain, key, format='hex'): key_state = self._hex_to_GF(key) roundKeys = self.expand_key(key_state) elif format == 'binary': - if not isinstance(plain, basestring) or \ - any([c not in '01' for c in plain]): + if not isinstance(plain, string_types) or \ + any(c not in '01' for c in plain): raise TypeError("'plain' keyword must be a binary string") if len(plain) != 32 * self._Nb: msg = "'plain' keyword's length must be {0}, not {1}" raise ValueError(msg.format(32 * self._Nb, len(plain))) - if not isinstance(key, basestring) or \ - any([c not in '01' for c in key]): + if not isinstance(key, string_types) or \ + any(c not in '01' for c in key): raise TypeError("'key' keyword must be a binary string") if len(key) != 32 * self._Nk: msg = "'key' keyword's length must be {0}, not {1}" @@ -1043,14 +1043,14 @@ def decrypt(self, ciphertext, key, format='hex'): True """ if format == 'hex': - if not isinstance(ciphertext, basestring) or \ - any([c not in '0123456789abcdefABCDEF' for c in ciphertext]): + if not isinstance(ciphertext, string_types) or \ + any(c not in '0123456789abcdefABCDEF' for c in ciphertext): raise TypeError("'ciphertext' keyword must be a hex string") if len(ciphertext) != 8 * self._Nb: msg = "'ciphertext' keyword's length must be {0}, not{1}" raise ValueError(msg.format(8 * self._Nb, len(ciphertext))) - if not isinstance(key, basestring) or \ - any([c not in '0123456789abcdefABCDEF' for c in key]): + if not isinstance(key, string_types) or \ + any(c not in '0123456789abcdefABCDEF' for c in key): raise TypeError("'key' keyword must be a hex string") if len(key) != 8 * self._Nk: msg = "'key' keyword's length must be {0}, not {1}" @@ -1059,15 +1059,15 @@ def decrypt(self, ciphertext, key, format='hex'): key_state = self._hex_to_GF(key) roundKeys = self.expand_key(key_state) elif format == 'binary': - if not isinstance(ciphertext, basestring) or \ - any([c not in '01' for c in ciphertext]): + if not isinstance(ciphertext, string_types) or \ + any(c not in '01' for c in ciphertext): raise TypeError(("'ciphertext' keyword must be a binary " "string")) if len(ciphertext) != 32 * self._Nb: msg = "'ciphertext' keyword's length must be {0}, not {1}" raise ValueError(msg.format(32 * self._Nb, len(ciphertext))) - if not isinstance(key, basestring) or \ - any([c not in '01' for c in key]): + if not isinstance(key, string_types) or \ + any(c not in '01' for c in key): raise TypeError("'key' keyword must be a binary string") if len(key) != 32 * self._Nk: msg = "'key' keyword\'s length must be {0}, not {1}" From 4572a6ad6fe20e8979cb1c3f32cfba0a5afa6ffb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 1 May 2017 14:49:09 +0200 Subject: [PATCH 182/452] another little change --- src/sage/misc/sageinspect.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/misc/sageinspect.py b/src/sage/misc/sageinspect.py index 130addd2958..6962a9ac74e 100644 --- a/src/sage/misc/sageinspect.py +++ b/src/sage/misc/sageinspect.py @@ -114,7 +114,7 @@ def foo(unsigned int x=1, a=')"', b={not (2+1==3):'bar'}, *args, **kwds): return """ from __future__ import print_function, absolute_import from six.moves import range -from six import iteritems +from six import iteritems, class_types import ast import inspect @@ -1707,7 +1707,7 @@ def sage_getdoc_original(obj): """ # typ is the type corresponding to obj, which is obj itself if # that was a type or old-style class - if isinstance(obj, (type, types.ClassType) ): + if isinstance(obj, class_types): typ = obj else: typ = type(obj) From 2232799d273183c1a08a56faff8af06fa4483c9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 1 May 2017 15:01:44 +0200 Subject: [PATCH 183/452] trac 22918 some more details --- src/sage/misc/sageinspect.py | 2 +- src/sage/symbolic/expression.pyx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/misc/sageinspect.py b/src/sage/misc/sageinspect.py index 6962a9ac74e..045ed056782 100644 --- a/src/sage/misc/sageinspect.py +++ b/src/sage/misc/sageinspect.py @@ -409,7 +409,7 @@ def visit_Name(self, node): sage: [vis(n) for n in ['True', 'False', 'None', 'foo', 'bar']] [True, False, None, 'foo', 'bar'] sage: [type(vis(n)) for n in ['True', 'False', 'None', 'foo', 'bar']] - [<... 'bool'>, <... 'bool'>, , <... 'str'>, <... 'str'>] + [<... 'bool'>, <... 'bool'>, <... 'NoneType'>, <... 'str'>, <... 'str'>] """ what = node.id if what == 'None': diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 314317ae7d6..82f2dd0e8dd 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -3737,11 +3737,11 @@ cdef class Expression(CommutativeRingElement): sage: None^pi Traceback (most recent call last): ... - TypeError: no canonical coercion from to Symbolic Ring + TypeError: no canonical coercion from <... 'NoneType'> to Symbolic Ring sage: sin(x)^None Traceback (most recent call last): ... - TypeError: no canonical coercion from to Symbolic Ring + TypeError: no canonical coercion from <... 'NoneType'> to Symbolic Ring Check that :trac:`18088` is fixed:: From 52cb60a9146b7d3eccfac8f8f3ac5226f1bd81b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 1 May 2017 15:16:15 +0200 Subject: [PATCH 184/452] py3: some care for cmp in monoids --- src/sage/monoids/free_monoid.py | 23 ++++++++++++++++------- src/sage/monoids/string_monoid_element.py | 8 +++++--- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/sage/monoids/free_monoid.py b/src/sage/monoids/free_monoid.py index 1715753f9fd..d24b848462c 100644 --- a/src/sage/monoids/free_monoid.py +++ b/src/sage/monoids/free_monoid.py @@ -201,14 +201,23 @@ def __init__(self, n, names=None): #self._assign_names(names) Monoid_class.__init__(self,names) - def __cmp__(self, other): + def __eq__(self, other): + """ + Test for equality. + """ if not isinstance(other, FreeMonoid_class): - return -1 - c = cmp(self.__ngens, other.__ngens) - if c: return c - if self.variable_names() == other.variable_names(): - return 0 - return 1 + return False + if self.__ngens != other.__ngens: + return False + if self.variable_names() != other.variable_names(): + return False + return True + + def __ne__(self, other): + """ + Test for unequality. + """ + return not (self == other) def _repr_(self): return "Free monoid on %s generators %s"%(self.__ngens,self.gens()) diff --git a/src/sage/monoids/string_monoid_element.py b/src/sage/monoids/string_monoid_element.py index 44a65a62a89..d1b2b13342d 100644 --- a/src/sage/monoids/string_monoid_element.py +++ b/src/sage/monoids/string_monoid_element.py @@ -26,6 +26,8 @@ from sage.rings.integer import Integer from sage.rings.all import RealField from .free_monoid_element import FreeMonoidElement +from sage.structure.sage_object import richcmp + def is_StringMonoidElement(x): r""" @@ -100,12 +102,12 @@ def __init__(self, S, x, check=True): else: raise TypeError("Argument x (= %s) is of the wrong type." % x) - def __cmp__(left, right): + def _richcmp_(left, right, op): """ Compare two free monoid elements with the same parents. The ordering is the one on the underlying sorted list of - (monomial,coefficients) pairs. + (monomial, coefficients) pairs. EXAMPLES:: @@ -116,7 +118,7 @@ def __cmp__(left, right): sage: S("01") < S("10") True """ - return cmp(left._element_list, right._element_list) + return richcmp(left._element_list, right._element_list, op) def _repr_(self): """ From 7b4ec6cf444e2f89ae77ea6f6a8670743c47ff18 Mon Sep 17 00:00:00 2001 From: Nils Bruin Date: Mon, 1 May 2017 13:03:40 -0700 Subject: [PATCH 185/452] Add sys.version_info as "PYTHON_VERSION" to cython compile-time environment --- src/setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/setup.py b/src/setup.py index c9e3fd7ea04..2215379c955 100755 --- a/src/setup.py +++ b/src/setup.py @@ -417,6 +417,7 @@ def run(self): force=self.force, aliases=aliases, compiler_directives=self.cython_directives, + compile_time_env={'PY_VERSION_HEX':sys.hexversion}, create_extension=sage_create_extension, # Debugging gdb_debug=self.debug, From 71b68d22215182fa7700ddb73ecd1bf82fda84f4 Mon Sep 17 00:00:00 2001 From: Nils Bruin Date: Mon, 1 May 2017 14:59:20 -0700 Subject: [PATCH 186/452] tract #22305 -- split off del_dictitem_by_exact_value and compile conditionally based on Py2/Py3 --- src/sage/misc/dict_del_by_value.pxd | 10 + src/sage/misc/dict_del_by_value.pyx | 443 ++++++++++++++++++++++++++++ src/sage/misc/weak_dict.pyx | 195 +----------- 3 files changed, 456 insertions(+), 192 deletions(-) create mode 100644 src/sage/misc/dict_del_by_value.pxd create mode 100644 src/sage/misc/dict_del_by_value.pyx diff --git a/src/sage/misc/dict_del_by_value.pxd b/src/sage/misc/dict_del_by_value.pxd new file mode 100644 index 00000000000..5e6eeb57a3b --- /dev/null +++ b/src/sage/misc/dict_del_by_value.pxd @@ -0,0 +1,10 @@ +from cpython.object cimport PyObject +cdef extern from "Python.h": + ctypedef struct PyDictObject + +cdef del_dictitem_by_exact_value(PyDictObject *mp, PyObject *value, Py_hash_t hash) + +#This is for compatibility: this routine is available in Py3 and we +#implement it ourselves in Py2. +IF PY_VERSION_HEX<=0x02ffffff: + cdef PyObject* PyDict_GetItemWithError(dict op, object key) except? NULL diff --git a/src/sage/misc/dict_del_by_value.pyx b/src/sage/misc/dict_del_by_value.pyx new file mode 100644 index 00000000000..967a67348a2 --- /dev/null +++ b/src/sage/misc/dict_del_by_value.pyx @@ -0,0 +1,443 @@ +""" +Delete item from PyDict by exact value and hash + +Beware that the implementation of the routine here relies on implementation +details of CPython's dict that go beyond the published API. This file depends +on python version when cythonized. It expects PY_VERSION_HEX to be available +in the cythonization and the result depends on it (and needs to match the +python version the C-compiler compiles it against). Usage should do something +along the lines of + + cythonize("dict_del_by_value.pyx", + compile_time_env({"PY_VERSION_HEX": sys.hexversion})) + +AUTHORS: + +- Nils Bruin (2017-05) +""" +######################################################################## +# Copyright (C) 2017 Nils Bruin +# +# Distributed under the terms of the GNU General Public License (GPL) +# +# http://www.gnu.org/licenses/ +######################################################################## +from __future__ import print_function + +import weakref +from weakref import KeyedRef +from copy import deepcopy + +from cpython.list cimport PyList_New +from cpython cimport Py_XINCREF, Py_XDECREF + +IF PY_VERSION_HEX<=0x02ffffff: + cdef extern from "Python.h": + ctypedef struct PyDictEntry: + Py_ssize_t me_hash + PyObject* me_key + PyObject* me_value + ctypedef struct PyDictObject: + Py_ssize_t ma_fill + Py_ssize_t ma_used + Py_ssize_t ma_mask + PyDictEntry* ma_table + PyDictEntry* (*ma_lookup)(PyDictObject *mp, PyObject *key, Py_hash_t hash) except NULL + + PyObject* Py_None + #we need this redefinition because we want to be able to call + #PyWeakref_GetObject with borrowed references. This is the recommended + #strategy according to Cython/Includes/cpython/__init__.pxd + PyObject* PyWeakref_GetObject(PyObject * wr) + int PyList_SetItem(object list, Py_ssize_t index, PyObject * item) except -1 + + from cpython.object cimport PyObject_Hash + cdef PyObject* PyDict_GetItemWithError(dict op, object key) except? NULL: + cdef PyDictEntry* ep + cdef PyDictObject* mp = op + ep = mp.ma_lookup(mp, key, PyObject_Hash(key)) + if ep: + return ep.me_value + else: + return NULL + + #this routine extracts the "dummy" sentinel value that is used in dicts to mark + #"freed" slots. We need that to delete things ourselves. + + cdef PyObject* init_dummy() except NULL: + cdef dict D = dict() + cdef PyDictObject* mp = D + cdef size_t mask + cdef PyDictEntry* ep0 = mp.ma_table + cdef PyDictEntry* ep + cdef size_t i + global dummy + + D[0]=0; del D[0] #ensure that there is a "deleted" entry in the dict + mask = mp.ma_mask + #since our entry had hash 0, we should really succeed on the first iteration + for i in range(mask+1): + ep = &(ep0[i]) + if ep.me_key != NULL: + return ep.me_key + raise RuntimeError("Problem initializing dummy") + + #note that dummy here is a borrowed reference. That's not a problem because + #we're never giving it up and dictobject.c is also holding a permanent reference + #to this object + cdef PyObject* dummy = init_dummy() + + #this routine looks for the first entry in dict D with given hash of the + #key and given (identical!) value and deletes that entry. + cdef del_dictitem_by_exact_value(PyDictObject *mp, PyObject *value, Py_hash_t hash): + """ + This is used in callbacks for the weak values of :class:`WeakValueDictionary`. + + INPUT: + + - ``PyDictObject *mp`` -- pointer to a dict + - ``PyObject *value`` -- pointer to a value of the dictionary + - ``Py_hash_t hash`` -- hash of the key by which the value is stored in the dict + + The hash bucket determined by the given hash is searched for the item + containing the given value. If this item cannot be found, the function is + silently returning. Otherwise, the item is removed from the dict. + + TESTS: + + The following is an indirect doctest, as discussed on :trac:`13394`. + :: + + sage: from sage.misc.weak_dict import WeakValueDictionary + sage: V = [set(range(n)) for n in range(5)] + sage: D = WeakValueDictionary(enumerate(V)) + + The line ``V[k] = None`` triggers execution of the callback functions of + the dict values. However, the actual deletion is postponed till after the + iteration over the dictionary has finished. Hence, when the callbacks are + executed, the values which the callback belongs to has already been + overridded by a new value. Therefore, the callback does not delete the + item:: + + sage: for k in D: # indirect doctest + ....: V[k] = None + ....: D[k] = ZZ + sage: len(D) + 5 + sage: D[1] + Integer Ring + + TESTS: + + The following shows that the deletion of deeply nested structures does not + result in an error, by :trac:`15506`:: + + sage: class A: pass + sage: a = A(); prev = a + sage: M = WeakValueDictionary() + sage: for i in range(10^3+10): newA = A(); M[newA] = prev; prev = newA + sage: del a + + """ + cdef size_t i + cdef size_t perturb + cdef size_t mask = mp.ma_mask + cdef PyDictEntry* ep0 = mp.ma_table + cdef PyDictEntry* ep + i = hash & mask + ep = &(ep0[i]) + + if ep.me_key == NULL: + # key not found + return + + perturb = hash + while ((ep.me_value) != value or ep.me_hash != hash): + i = (i << 2) + i + perturb +1 + ep = &ep0[i & mask] + if ep.me_key == NULL: + # key not found + return + perturb = perturb >> 5 #this is the value of PERTURB_SHIFT + + T=PyList_New(2) + PyList_SetItem(T, 0, ep.me_key) + if dummy == NULL: + raise RuntimeError("dummy needs to be initialized") + Py_XINCREF(dummy) + ep.me_key = dummy + PyList_SetItem(T, 1, ep.me_value) + ep.me_value = NULL + mp.ma_used -= 1 + #We have transferred the to-be-deleted references to the list T + #we now delete the list so that the actual decref happens through a + #deallocation routine that uses the Python Trashcan macros to + #avoid stack overflow in deleting deep structures. + del T + +ELIF PY_VERSION_HEX>=0x03060000: + + from libc.stdint cimport int8_t,int16_t,int32_t,int64_t + cdef extern from "Python.h": + ctypedef struct PyDictObject: + Py_ssize_t ma_used + PyDictKeysObject * ma_keys + PyObject ** ma_values + + PyObject* Py_None + #we need this redefinition because we want to be able to call + #PyWeakref_GetObject with borrowed references. This is the recommended + #strategy according to Cython/Includes/cpython/__init__.pxd + PyObject* PyWeakref_GetObject(PyObject * wr) + int PyList_SetItem(object list, Py_ssize_t index, PyObject * item) except -1 + PyObject* PyDict_GetItemWithError(dict op, object key) except? NULL + int PyWeakref_Check(PyObject * ob) + + ctypedef struct PyDictKeysObject + #### + #definitions replicated from CPython's Objects/dict-common.h + #(this file is not exported fron CPython, so we need to be + #careful the definitions are in step with what happens there. + ctypedef union IndexBlock: + int8_t as_1[8] + int16_t as_2[4] + int32_t as_4[2] + int64_t as_8[1] + + ctypedef struct MyPyDictKeysObject: + Py_ssize_t dk_refcnt + Py_ssize_t dk_size + Py_ssize_t (*dk_lookup)(PyDictObject *mp, PyObject *key, Py_hash_t hash, PyObject ** value_addr, Py_ssize_t *hashpos) + Py_ssize_t dk_usable + Py_ssize_t dk_nentries + IndexBlock dk_indices + + ctypedef struct PyDictKeyEntry: + Py_hash_t me_hash + PyObject * me_key + PyObject * me_value + + cdef Py_ssize_t DKIX_EMPTY = -1 + cdef Py_ssize_t DKIX_DUMMY = -2 + cdef Py_ssize_t DKIX_ERROR = -3 + + ##### + #These routines are copied from CPython's Object/dictobject.c + #in order to access PyDictKeysObject fields + + cdef inline int DK_IXSIZE(MyPyDictKeysObject *keys): + cdef Py_ssize_t s = keys.dk_size + cdef int i + if s <= 0xff: + i = 1 + elif s <= 0xffff: + i = 2 + elif s <= 0xffffffff: + i = 4 + else: + i = 8 + return i + + cdef inline PyDictKeyEntry * DK_ENTRIES(MyPyDictKeysObject *keys): + return &(keys.dk_indices.as_1[keys.dk_size * DK_IXSIZE(keys)]) + + cdef inline Py_ssize_t dk_get_index(MyPyDictKeysObject *keys, Py_ssize_t i): + cdef Py_ssize_t s = keys.dk_size + cdef Py_ssize_t ix + if s <= 0xff: + ix = keys.dk_indices.as_1[i] + elif s <= 0xffff: + ix = keys.dk_indices.as_2[i] + elif s <= 0xffffffff: + ix = keys.dk_indices.as_4[i] + else: + ix = keys.dk_indices.as_8[i] + return ix + + cdef inline dk_set_index(MyPyDictKeysObject *keys, Py_ssize_t i, Py_ssize_t ix): + cdef Py_ssize_t s = keys.dk_size + if s <= 0xff: + keys.dk_indices.as_1[i] = ix + elif s <= 0xffff: + keys.dk_indices.as_2[i] = ix + elif s <= 0xffffffff: + keys.dk_indices.as_4[i] = ix + else: + keys.dk_indices.as_8[i] = ix + return ix + #End of replication of Object/dictobject.c + ###### + + cdef void * lookdict + + cdef void * DK_LOOKUP(PyDictObject *mp): + return (((mp.ma_keys)).dk_lookup) + + def init_lookdict(): + global lookdict + cdef dict D={} + #this should trigger the initialization of the general + #lookup function on the dict. + PyDict_GetItemWithError(D,None) + #which we store in a global variable + lookdict=DK_LOOKUP(D) + + init_lookdict() + + cdef ensure_allows_deletions(PyDictObject *mp): + if DK_LOOKUP(mp) != lookdict: + #on normal dictionaries (non-split table), looking up a key + #that is not a unicode object triggers installation of the + #general lookup function (which can deal with DKIX_DUMMY) + PyDict_GetItemWithError(mp,None) + #this can actually fail if mp is a dictionary with split table + assert DK_LOOKUP(mp) == lookdict + + cdef del_dictitem_by_exact_value(PyDictObject *mp, PyObject *value, Py_hash_t hash): + """ + This is used in callbacks for the weak values of :class:`WeakValueDictionary`. + + INPUT: + + - ``PyDictObject *mp`` -- pointer to a dict + - ``PyObject *value`` -- pointer to a value of the dictionary + - ``Py_hash_t hash`` -- hash of the key by which the value is stored in the dict + + The hash bucket determined by the given hash is searched for the item + containing the given value. If this item cannot be found, the function is + silently returning. Otherwise, the item is removed from the dict. + + TESTS: + + The following is an indirect doctest, as discussed on :trac:`13394`. + :: + + sage: from sage.misc.weak_dict import WeakValueDictionary + sage: V = [set(range(n)) for n in range(5)] + sage: D = WeakValueDictionary(enumerate(V)) + + The line ``V[k] = None`` triggers execution of the callback functions of + the dict values. However, the actual deletion is postponed till after the + iteration over the dictionary has finished. Hence, when the callbacks are + executed, the values which the callback belongs to has already been + overridded by a new value. Therefore, the callback does not delete the + item:: + + sage: for k in D: # indirect doctest + ....: V[k] = None + ....: D[k] = ZZ + sage: len(D) + 5 + sage: D[1] + Integer Ring + + TESTS: + + The following shows that the deletion of deeply nested structures does not + result in an error, by :trac:`15506`:: + + sage: class A: pass + sage: a = A(); prev = a + sage: M = WeakValueDictionary() + sage: for i in range(10^3+10): newA = A(); M[newA] = prev; prev = newA + sage: del a + + """ + cdef size_t i + cdef MyPyDictKeysObject * keys = (mp.ma_keys) + cdef size_t perturb + cdef size_t mask = keys.dk_size-1 + cdef PyDictKeyEntry *entries, *ep + entries = DK_ENTRIES(keys) + + if mp.ma_values != NULL: + print ("del_dictitem_by_exact_value cannot be applied to a shared key dict") + return + + i = hash & mask + ix = dk_get_index(keys, i) + + if ix == DKIX_EMPTY: + # key not found + return + + ep = &(entries[ix]) + perturb = hash + while (ep.me_value != value or ep.me_hash != hash): + perturb = perturb >> 5 #this is the value of PERTURB_SHIFT + i = ((i << 2) + i + perturb +1) & mask + ix = dk_get_index(keys, i) + if ix == DKIX_EMPTY: + # key not found + return + ep = &(entries[ix]) + + ensure_allows_deletions(mp) + T=PyList_New(2) + PyList_SetItem(T, 0, ep.me_key) + PyList_SetItem(T, 1, ep.me_value) + ep.me_key = NULL + ep.me_value = NULL + mp.ma_used -= 1 + dk_set_index(keys, i, DKIX_DUMMY) + #We have transferred the to-be-deleted references to the list T + #we now delete the list so that the actual decref happens through a + #deallocation routine that uses the Python Trashcan macros to + #avoid stack overflow in deleting deep structures. + del T + +#END IF PY_VERSION_HEX + +def test_del_dictitem_by_exact_value(D, value, h): + """ + This function helps testing some cdef function used to delete dictionary items. + + INPUT: + + - ``D`` -- a Python ````. + - ``value`` -- an object that is value ``D``. + - ``h`` -- the hash of the key under which to find ``value`` in ``D``. + + The underlying cdef function deletes an item from ``D`` that is in the + hash bucket determined by ``h`` and whose value is identic with + ``value``. Of course, this only makes sense if the pairs ``(h, value)`` + corresponding to items in ``D`` are pair-wise distinct. + + If a matching item can not be found, the function does nothing and + silently returns. + + TESTS: + + See :trac:`13394` for a discussion. + :: + + sage: from sage.misc.dict_del_by_value import test_del_dictitem_by_exact_value + sage: B=1000 + sage: L=list(range(B)) + sage: D1=dict() + sage: D2=dict() + sage: for i in range(100000): # long time + ....: ki=L[floor(random()*B)] + ....: vi=L[floor(random()*B)] + ....: D1[ki]=vi + ....: D2[ki]=vi + ....: ko=L[floor(random()*B)] + ....: if ko in D1: + ....: vo=D1[ko] + ....: del D1[ko] + ....: test_del_dictitem_by_exact_value(D2,vo,hash(ko)) + ....: assert D1 == D2 + + No action is taken if the item prescribed by key hash and value does not + exist in the dictionary:: + + sage: D = {1: ZZ} + sage: test_del_dictitem_by_exact_value(D, ZZ, 2) + sage: D + {1: Integer Ring} + sage: test_del_dictitem_by_exact_value(D, QQ, 1) + sage: D + {1: Integer Ring} + + """ + return del_dictitem_by_exact_value(D, value, h) diff --git a/src/sage/misc/weak_dict.pyx b/src/sage/misc/weak_dict.pyx index 3de8f54edde..3103c4977f5 100644 --- a/src/sage/misc/weak_dict.pyx +++ b/src/sage/misc/weak_dict.pyx @@ -123,22 +123,11 @@ from copy import deepcopy from cpython.dict cimport * from cpython.weakref cimport PyWeakref_NewRef -from cpython.list cimport PyList_New from cpython.object cimport PyObject_Hash from cpython cimport Py_XINCREF, Py_XDECREF +from dict_del_by_value cimport * cdef extern from "Python.h": - ctypedef struct PyDictEntry: - Py_ssize_t me_hash - PyObject* me_key - PyObject* me_value - ctypedef struct PyDictObject: - Py_ssize_t ma_fill - Py_ssize_t ma_used - Py_ssize_t ma_mask - PyDictEntry* ma_table - PyDictEntry* (*ma_lookup)(PyDictObject *mp, PyObject *key, long hash) except NULL - PyObject* Py_None #we need this redefinition because we want to be able to call #PyWeakref_GetObject with borrowed references. This is the recommended @@ -146,183 +135,6 @@ cdef extern from "Python.h": PyObject* PyWeakref_GetObject(PyObject * wr) int PyList_SetItem(object list, Py_ssize_t index, PyObject * item) except -1 -cdef PyObject* PyDict_GetItemWithError(dict op, object key) except? NULL: - cdef PyDictEntry* ep - cdef PyDictObject* mp = op - ep = mp.ma_lookup(mp, key, PyObject_Hash(key)) - if ep: - return ep.me_value - else: - return NULL - -#this routine extracts the "dummy" sentinel value that is used in dicts to mark -#"freed" slots. We need that to delete things ourselves. - -cdef PyObject* init_dummy() except NULL: - cdef dict D = dict() - cdef PyDictObject* mp = D - cdef size_t mask - cdef PyDictEntry* ep0 = mp.ma_table - cdef PyDictEntry* ep - cdef size_t i - global dummy - - D[0]=0; del D[0] #ensure that there is a "deleted" entry in the dict - mask = mp.ma_mask - #since our entry had hash 0, we should really succeed on the first iteration - for i in range(mask+1): - ep = &(ep0[i]) - if ep.me_key != NULL: - return ep.me_key - raise RuntimeError("Problem initializing dummy") - -#note that dummy here is a borrowed reference. That's not a problem because -#we're never giving it up and dictobject.c is also holding a permanent reference -#to this object -cdef PyObject* dummy = init_dummy() - -#this routine looks for the first entry in dict D with given hash of the -#key and given (identical!) value and deletes that entry. -cdef del_dictitem_by_exact_value(PyDictObject *mp, PyObject *value, long hash): - """ - This is used in callbacks for the weak values of :class:`WeakValueDictionary`. - - INPUT: - - - ``PyDictObject *mp`` -- pointer to a dict - - ``PyObject *value`` -- pointer to a value of the dictionary - - ``long hash`` -- hash of the key by which the value is stored in the dict - - The hash bucket determined by the given hash is searched for the item - containing the given value. If this item cannot be found, the function is - silently returning. Otherwise, the item is removed from the dict. - - TESTS: - - The following is an indirect doctest, as discussed on :trac:`13394`. - :: - - sage: from sage.misc.weak_dict import WeakValueDictionary - sage: V = [set(range(n)) for n in range(5)] - sage: D = WeakValueDictionary(enumerate(V)) - - The line ``V[k] = None`` triggers execution of the callback functions of - the dict values. However, the actual deletion is postponed till after the - iteration over the dictionary has finished. Hence, when the callbacks are - executed, the values which the callback belongs to has already been - overridded by a new value. Therefore, the callback does not delete the - item:: - - sage: for k in D: # indirect doctest - ....: V[k] = None - ....: D[k] = ZZ - sage: len(D) - 5 - sage: D[1] - Integer Ring - - TESTS: - - The following shows that the deletion of deeply nested structures does not - result in an error, by :trac:`15506`:: - - sage: class A: pass - sage: a = A(); prev = a - sage: M = WeakValueDictionary() - sage: for i in range(10^3+10): newA = A(); M[newA] = prev; prev = newA - sage: del a - - """ - cdef size_t i - cdef size_t perturb - cdef size_t mask = mp.ma_mask - cdef PyDictEntry* ep0 = mp.ma_table - cdef PyDictEntry* ep - i = hash & mask - ep = &(ep0[i]) - - if ep.me_key == NULL: - # key not found - return - - perturb = hash - while ((ep.me_value) != value or ep.me_hash != hash): - i = (i << 2) + i + perturb +1 - ep = &ep0[i & mask] - if ep.me_key == NULL: - # key not found - return - perturb = perturb >> 5 #this is the value of PERTURB_SHIFT - - T=PyList_New(2) - PyList_SetItem(T, 0, ep.me_key) - if dummy == NULL: - raise RuntimeError("dummy needs to be initialized") - Py_XINCREF(dummy) - ep.me_key = dummy - PyList_SetItem(T, 1, ep.me_value) - ep.me_value = NULL - mp.ma_used -= 1 - #We have transferred the to-be-deleted references to the list T - #we now delete the list so that the actual decref happens through a - #deallocation routine that uses the Python Trashcan macros to - #avoid stack overflow in deleting deep structures. - del T - -def test_del_dictitem_by_exact_value(D, value, h): - """ - This function helps testing some cdef function used to delete dictionary items. - - INPUT: - - - ``D`` -- a Python ````. - - ``value`` -- an object that is value ``D``. - - ``h`` -- the hash of the key under which to find ``value`` in ``D``. - - The underlying cdef function deletes an item from ``D`` that is in the - hash bucket determined by ``h`` and whose value is identic with - ``value``. Of course, this only makes sense if the pairs ``(h, value)`` - corresponding to items in ``D`` are pair-wise distinct. - - If a matching item can not be found, the function does nothing and - silently returns. - - TESTS: - - See :trac:`13394` for a discussion. - :: - - sage: from sage.misc.weak_dict import test_del_dictitem_by_exact_value - sage: B=1000 - sage: L=list(range(B)) - sage: D1=dict() - sage: D2=dict() - sage: for i in range(100000): # long time - ....: ki=L[floor(random()*B)] - ....: vi=L[floor(random()*B)] - ....: D1[ki]=vi - ....: D2[ki]=vi - ....: ko=L[floor(random()*B)] - ....: if ko in D1: - ....: vo=D1[ko] - ....: del D1[ko] - ....: test_del_dictitem_by_exact_value(D2,vo,hash(ko)) - ....: assert D1 == D2 - - No action is taken if the item prescribed by key hash and value does not - exist in the dictionary:: - - sage: D = {1: ZZ} - sage: test_del_dictitem_by_exact_value(D, ZZ, 2) - sage: D - {1: Integer Ring} - sage: test_del_dictitem_by_exact_value(D, QQ, 1) - sage: D - {1: Integer Ring} - - """ - return del_dictitem_by_exact_value(D, value, h) - cdef class WeakValueDictEraser: """ Erases items from a :class:`sage.misc.weak_dict.WeakValueDictionary` when @@ -924,9 +736,8 @@ cdef class WeakValueDictionary(dict): TypeError: mutable matrices are unhashable """ - cdef PyDictObject* mp=self - cdef PyDictEntry* ep=mp.ma_lookup(mp,k, PyObject_Hash(k)) - return (ep.me_value != NULL) and (PyWeakref_GetObject(ep.me_value) != Py_None) + cdef PyObject* wr = PyDict_GetItemWithError(self, k) + return (wr != NULL) and (PyWeakref_GetObject(wr) != Py_None) #def __len__(self): #since GC is not deterministic, neither is the length of a WeakValueDictionary, From 4a298e3a2950d48dca09a2f40a456e7082b14be4 Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Mon, 1 May 2017 15:19:49 -0700 Subject: [PATCH 187/452] trac 22923: fix docstrings and comments re caching in algebra/steenrod/ --- .../steenrod/steenrod_algebra_bases.py | 3 --- .../steenrod/steenrod_algebra_mult.py | 20 +++---------------- 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/src/sage/algebras/steenrod/steenrod_algebra_bases.py b/src/sage/algebras/steenrod/steenrod_algebra_bases.py index 9476c44c3d9..bf04407ada0 100644 --- a/src/sage/algebras/steenrod/steenrod_algebra_bases.py +++ b/src/sage/algebras/steenrod/steenrod_algebra_bases.py @@ -1124,9 +1124,6 @@ def steenrod_basis_error_check(dim, p, **kwds): import sage.misc.misc as misc generic = kwds.get('generic', False if p==2 else True ) - # In this test function, we don't want to use caching. - # Hence, the uncached versions of steenrod_algebra_basis - # and of convert_to_milnor_matrix are used. if not generic: bases = ('adem','woody', 'woodz', 'wall', 'arnona', 'arnonc', 'pst_rlex', 'pst_llex', 'pst_deg', 'pst_revz', diff --git a/src/sage/algebras/steenrod/steenrod_algebra_mult.py b/src/sage/algebras/steenrod/steenrod_algebra_mult.py index a00d9647120..329e624809e 100644 --- a/src/sage/algebras/steenrod/steenrod_algebra_mult.py +++ b/src/sage/algebras/steenrod/steenrod_algebra_mult.py @@ -7,7 +7,7 @@ multiplication. - John H. Palmieri (2010-06-30: version 1.0) multiplication of Serre-Cartan basis elements using the Adem relations. - - Simon King (2011-10-25): Fix the use of cached functions. +- Simon King (2011-10-25): Fix the use of cached functions. .. rubric:: Milnor multiplication, `p=2` @@ -187,9 +187,8 @@ where `s_k \geq \epsilon_{k+1} + p s_{k+1}` for all `k`. As at the prime 2, these form a basis for the Steenrod algebra. -The main function for this is :func:`make_mono_admissible_` (and in -practice, one should use the cached version, -``make_mono_admissible``), which converts a product of Steenrod +The main function for this is :func:`make_mono_admissible`, +which converts a product of Steenrod squares or pth power operations and Bocksteins into a dictionary representing a sum of admissible monomials. """ @@ -707,12 +706,6 @@ def adem(a, b, c=0, p=2, generic=None): a dictionary representing the mod `p` Adem relations applied to `P^a P^b` or (if `c` present) to `P^a \beta^b P^c`. - .. note:: - - Users should use :func:`adem` instead of this function (which - has a trailing underscore in its name): :func:`adem` - is the cached version of this one, and so will be faster. - The mod `p` Adem relations for the mod `p` Steenrod algebra are as follows: if `p=2`, then if `a < 2b`, @@ -876,13 +869,6 @@ def make_mono_admissible(mono, p=2, generic=None): tuples `(i_1, ..., i_{j-1}, NEW, i_{j+2}, ...)`, keeping track of the coefficients. - .. note:: - - Users should use :func:`make_mono_admissible` instead of this - function (which has a trailing underscore in its name): - :func:`make_mono_admissible` is the cached version of this - one, and so will be faster. - EXAMPLES:: sage: from sage.algebras.steenrod.steenrod_algebra_mult import make_mono_admissible From 54d8c2da8ad19e610fe9939b90bc23202c5b5525 Mon Sep 17 00:00:00 2001 From: Nils Bruin Date: Mon, 1 May 2017 15:27:23 -0700 Subject: [PATCH 188/452] Correction: Py3 does provide PyDict_GetItemWithError but Cython doesn't provide it yet --- src/sage/misc/dict_del_by_value.pxd | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/sage/misc/dict_del_by_value.pxd b/src/sage/misc/dict_del_by_value.pxd index 5e6eeb57a3b..5d83af20d5d 100644 --- a/src/sage/misc/dict_del_by_value.pxd +++ b/src/sage/misc/dict_del_by_value.pxd @@ -8,3 +8,6 @@ cdef del_dictitem_by_exact_value(PyDictObject *mp, PyObject *value, Py_hash_t ha #implement it ourselves in Py2. IF PY_VERSION_HEX<=0x02ffffff: cdef PyObject* PyDict_GetItemWithError(dict op, object key) except? NULL +ELSE: + cdef extern from "Python.h": + PyObject* PyDict_GetItemWithError(dict op, object key) except? NULL From 143f133690a95a8ac514b7c9226b94e8a953550b Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Tue, 2 May 2017 09:02:07 +0200 Subject: [PATCH 189/452] 22925: Fix Cython interface to Pynac's find_function --- src/sage/libs/pynac/pynac.pxd | 2 +- src/sage/symbolic/function.pyx | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/libs/pynac/pynac.pxd b/src/sage/libs/pynac/pynac.pxd index 17c9a355a22..20907bbdf84 100644 --- a/src/sage/libs/pynac/pynac.pxd +++ b/src/sage/libs/pynac/pynac.pxd @@ -421,7 +421,7 @@ cdef extern from "sage/libs/pynac/wrap.h": unsigned g_register_new "GiNaC::function::register_new" (GFunctionOpt opt) unsigned find_function "GiNaC::function::find_function" (char* name, - unsigned nargs) except +ValueError + unsigned nargs) except + bint has_symbol "GiNaC::has_symbol" (GEx ex) bint has_symbol_or_function "GiNaC::has_symbol_or_function" (GEx ex) diff --git a/src/sage/symbolic/function.pyx b/src/sage/symbolic/function.pyx index c37de13a637..976960b7b02 100644 --- a/src/sage/symbolic/function.pyx +++ b/src/sage/symbolic/function.pyx @@ -806,7 +806,7 @@ cdef class GinacFunction(BuiltinFunction): # get serial try: self._serial = find_function(fname, self._nargs) - except ValueError as err: + except RuntimeError as err: raise ValueError("cannot find GiNaC function with name %s and %s arguments" % (fname, self._nargs)) global sfunction_serial_dict @@ -1061,7 +1061,7 @@ cdef class BuiltinFunction(Function): # search ginac registry for name and nargs try: serial = find_function(self._name, self._nargs) - except ValueError as err: + except RuntimeError as err: pass # if match, get operator from function table From 49979fcf0bc9af2869c20c6dc767080003499ccb Mon Sep 17 00:00:00 2001 From: Vincent Delecroix <20100.delecroix@gmail.com> Date: Wed, 29 Apr 2015 19:18:56 +0200 Subject: [PATCH 190/452] Trac 18303: comparison of algebraic numbers (new tentative) --- src/sage/rings/qqbar.py | 479 ++++++++++++++---- .../schemes/elliptic_curves/period_lattice.py | 2 +- 2 files changed, 371 insertions(+), 110 deletions(-) diff --git a/src/sage/rings/qqbar.py b/src/sage/rings/qqbar.py index aa41659cbba..16e9c9593cd 100644 --- a/src/sage/rings/qqbar.py +++ b/src/sage/rings/qqbar.py @@ -510,7 +510,9 @@ import sage.rings.ring from sage.misc.fast_methods import Singleton from sage.misc.cachefunc import cached_method -from sage.structure.sage_object import SageObject +from sage.structure.sage_object import (SageObject, richcmp, rich_to_bool, + op_EQ, op_NE, op_LE, op_LT, + op_GE, op_GT) from sage.rings.real_mpfr import RR from sage.rings.real_mpfi import RealIntervalField, RIF, is_RealIntervalFieldElement, RealIntervalField_class from sage.rings.complex_field import ComplexField @@ -2054,6 +2056,79 @@ def mk_algebraic(x): QQxy_x = QQxy.gen(0) QQxy_y = QQxy.gen(1) + +def cmp_elements_with_same_minpoly(a, b, p): + r""" + Compare the algebraic elements ``a`` and ``b`` knowing that they have the + same minimal polynomial ``p``. + + This is an helper function for comparison of algebraic elements (i.e. the + methods :meth:`AlgebraicNumber._richcmp_` and + :meth:`AlgebraicReal._richcmp_`). + + INPUT: + + - ``a`` and ``b`` -- elements of the algebraic or the real algebraic field + with same minimal polynomial + + - ``p`` -- the minmial polynomial + + OUTPUT: + + `-1`, `0`, `1`, `None` depending on whether `a < b`, `a = b` or `a > b` or + the function did not succeed with the given precision of `a` and `b`. + + EXAMPLES:: + + sage: from sage.rings.qqbar import cmp_elements_with_same_minpoly + sage: x = polygen(ZZ) + sage: p = x^2 - 2 + sage: a = AA.polynomial_root(p, RIF(1,2)) + sage: b = AA.polynomial_root(p, RIF(-2,-1)) + sage: cmp_elements_with_same_minpoly(a, b, p) + 1 + sage: cmp_elements_with_same_minpoly(-a, b, p) + 0 + """ + ar = a._value.real() + br = b._value.real() + if not ar.overlaps(br): + return -1 if richcmp(ar, br, op_LT) else 1 + + ai = a._value.imag() + bi = b._value.imag() + + if a.parent() is AA or b.parent() is AA: + ring = AA + else: + ring = QQbar + roots = p.roots(ring, False) + + real = ar.union(br) + imag = ai.union(bi) + roots = [r for r in roots if r._value.real().overlaps(real) + and r._value.imag().abs().overlaps(imag)] + if len(roots) == 1: + # There is only a single (real) root matching both descriptors + # so they both must be that root and therefore equal. + return 0 + if (len(roots) == 2 and + not roots[0]._value.imag().contains_zero()): + # There is a complex conjugate pair of roots matching both + # descriptors, so compare by imaginary value. + while ai.contains_zero(): + a._more_precision() + ai = a._value.imag() + while bi.contains_zero(): + b._more_precision() + bi = b._value.imag() + if ai.overlaps(bi): + return 0 + return -1 if richcmp(ai, bi, op_LT) else 1 + + return None + + class AlgebraicGeneratorRelation(SageObject): """ A simple class for maintaining relations in the lattice of algebraic @@ -2172,7 +2247,13 @@ def __cmp__(self, other): sage: gen.__cmp__(qq_generator) 1 """ - return cmp(self._index, other._index) + si = self._index + oi = other._index + if si < oi: + return -1 + if si > oi: + return 1 + return 0 def is_complex(self): r""" @@ -3022,6 +3103,106 @@ def __hash__(self): else: return hash((self + QQbar_hash_offset).interval_exact(CIF)) + def __bool__(self): + """ + Check whether self is equal is nonzero. + + This is fast if interval arithmetic proves and in many other cases. + Though, it might be slow in very particular cases where the number is + actually zero or very close to zero. + + EXAMPLES:: + + sage: bool(QQbar.zeta(2) + 1) + False + sage: bool(QQbar.zeta(7) / (2^500)) + True + + sage: bool(QQbar(I).imag()) + True + sage: bool(QQbar(I).real()) + False + + The following is very fast, even though the number is really small:: + + sage: a1 = QQbar(2).sqrt() - 16616132878186749607/11749380235262596085 + sage: a2 = QQbar(2).sqrt() - 16616132878186749607/11749380235262596085 + sage: bool(a1 + a2) + True + sage: bool(a1 - a2) + False + + sage: a = QQbar(2).sqrt() - 16616132878186749607/11749380235262596085 + sage: b = QQbar(2).sqrt() - 6882627592338442563/4866752642924153522 + sage: c = QQbar(3).sqrt() - 142437039878091970439/82236063316189858921 + sage: d = (59/2)**(1000/7) + sage: e = (a + b + c) * (a + b - c) * (a - b) * (a - b - c) / d + sage: bool(e) + True + sage: bool(e.abs() < 2**-500) + True + """ + # case 0: trivial test + if not self._value.contains_zero(): + return True + elif self._value.is_zero(): + if not type(self._descr) is ANRational: + self._set_descr(ANRational(QQ.zero())) + return False + + # case 1: cheap tests + sd = self._descr + if type(sd) is ANExtensionElement or type(sd) is ANRootOfUnity: + # The ANExtensionElement and ANRootOfUnity returns an ANRational + # instead, if the number is zero. + return True + elif type(sd) is ANRational: + return sd._value.__nonzero__() + elif type(sd) is ANUnaryExpr and sd._op != 'real' and sd._op != 'imag': + ans = sd._arg.__nonzero__() + if not ans: + self._set_descr(ANRational(QQ.zero())) + return ans + elif type(sd) is ANBinaryExpr and sd._op == '*': + ans = sd._left.__nonzero__() and sd._right.__nonzero__() + if not ans: + self._set_descr(ANRational(QQ.zero())) + return ans + elif type(sd) is ANBinaryExpr and sd._op == '/': + ans = sd._left.__nonzero__() + if not ans: + self._set_descr(ANRational(QQ.zero())) + return ans + + # case 2: try more precision + if self._value.prec() < 128: + self._more_precision() + if not self._value.contains_zero(): + return True + + # case 3: try with minpoly in case of x+y or x-y + if type(sd) is ANBinaryExpr: + op = sd._op + left = sd._left + right = sd._right if op == '-' else -sd._right + + lp = left.minpoly() + rp = right.minpoly() + if lp != rp: + return True + + c = cmp_elements_with_same_minpoly(left, right, left.minpoly()) + if c is not None: + if c == 0: + self._set_descr(ANRational(QQ.zero())) + return bool(c) + + # Sigh... + self.exactify() + return self.__nonzero__() + + __nonzero__ = __bool__ + def is_square(self): """ Return whether or not this number is square. @@ -3613,11 +3794,14 @@ def radical_expression(self): roots = candidates interval_field = interval_field.to_prec(interval_field.prec()*2) + class AlgebraicNumber(AlgebraicNumber_base): r""" The class for algebraic numbers (complex numbers which are the roots of a polynomial with integer coefficients). Much of its functionality is inherited from ``AlgebraicNumber_base``. + + .. automethod:: _richcmp_ """ def __init__(self, x): r""" @@ -3643,8 +3827,8 @@ def __reduce__(self): """ return (AlgebraicNumber, (self._descr, )) - def __cmp__(self, other): - """ + def _richcmp_(self, other, op): + r""" Compare two algebraic numbers, lexicographically. (That is, first compare the real components; if the real components are equal, compare the imaginary components.) @@ -3707,63 +3891,8 @@ def __cmp__(self, other): 1.000000000000000? + 3.390564396412898?*I, 1.000000000000000? + 3.850538755978243?*I, 1.000000000000000? + 4.016778562562223?*I] - """ - # case 0: same object - if self is other: return 0 - - # case 1: real parts are clearly distinct - ri1 = self._value.real() - ri2 = other._value.real() - if not ri1.overlaps(ri2): - return cmp(ri1, ri2) - - # case 2: possibly equal or conjugate values - # (this case happen a lot when sorting the roots of a real polynomial) - if is_RealIntervalFieldElement(self._value): - ci1 = ri1.parent().zero() - else: - ci1 = self._value.imag().abs() - if is_RealIntervalFieldElement(other._value): - ci2 = ri2.parent().zero() - else: - ci2 = other._value.imag().abs() - if ci1.overlaps(ci2) and self.minpoly() == other.minpoly(): - ri = ri1.union(ri2) - ci = ci1.union(ci2) - roots = self.minpoly().roots(QQbar, False) - roots = [r for r in roots if r._value.real().overlaps(ri) - and r._value.imag().abs().overlaps(ci)] - if len(roots) == 1: - # There is only a single (real) root matching both descriptors - # so they both must be that root and therefore equal. - return 0 - if (len(roots) == 2 and - not roots[0]._value.imag().contains_zero()): - # There is a complex conjugate pair of roots matching both - # descriptors, so compare by imaginary value. - ii1 = self._value.imag() - while ii1.contains_zero(): - self._more_precision() - ii1 = self._value.imag() - ii2 = other._value.imag() - while ii2.contains_zero(): - other._more_precision() - ii2 = other._value.imag() - if ii1.overlaps(ii2): - return 0 - return cmp(ii1, ii2) - - # case 3: try hard to compare real parts and imaginary parts - rcmp = cmp(self.real(), other.real()) - if rcmp != 0: - return rcmp - return cmp(self.imag(), other.imag()) - def __eq__(self, other): - """ - Test two algebraic numbers for equality. - - EXAMPLES:: + TESTS:: sage: QQbar.zeta(6) == QQbar(1/2 + I*sqrt(3)/2) True @@ -3775,25 +3904,6 @@ def __eq__(self, other): False sage: GF(7)(2) in QQbar False - """ - if not isinstance(other, AlgebraicNumber): - try: - self, other = canonical_coercion(self, other) - return self == other - except TypeError: - return False - if self is other: return True - if isinstance(other._descr, ANRational) and other._descr._value.is_zero(): - return not self - if isinstance(self._descr, ANRational) and self._descr._value.is_zero(): - return not other - return not self._sub_(other) - - def __ne__(self, other): - r""" - Test two algebraic numbers for inequality. - - EXAMPLES:: sage: QQbar.zeta(6) != QQbar(1/2 + I*sqrt(3)/2) False @@ -3803,8 +3913,58 @@ def __ne__(self, other): False sage: QQbar(2) != GF(7)(2) True + + sage: QQbar.zeta(3).real() == -1/2 + True """ - return not self == other + # note: we can assume that self is not other here + sd = self._descr + od = other._descr + + if isinstance(sd, ANRational) and isinstance(od, ANRational): + return richcmp(sd._value, od._value, op) + + if op == op_EQ or op == op_NE: + # some cheap and quite common tests where we can decide + # equality or difference + if not (self._value.real().overlaps(other._value.real()) and + self._value.imag().overlaps(other._value.imag())): + return op == op_NE + if type(sd) is ANRational and not sd._value: + return bool(other) == (op == op_NE) + elif type(od) is ANRational and not od._value: + return bool(self) == (op == op_NE) + elif (isinstance(sd, ANExtensionElement) and + isinstance(od, ANExtensionElement) and + sd._generator is od._generator): + return sd._value == od._value if op == op_EQ else sd._value != od._value + + # case 0: real parts are clearly distinct + ri1 = self._value.real() + ri2 = other._value.real() + if not ri1.overlaps(ri2): + return richcmp(ri1, ri2, op) + + # case 1: rationals + sd = self._descr + od = other._descr + if type(sd) is ANRational and type(od) is ANRational: + return richcmp(sd._value, od._value, op) + + # case 2: possibly equal or conjugate values + # (this case happen a lot when sorting the roots of a real polynomial) + ci1 = self._value.imag().abs() + ci2 = other._value.imag().abs() + if ci1.overlaps(ci2) and self.minpoly() == other.minpoly(): + c = cmp_elements_with_same_minpoly(self, other, self.minpoly()) + if c is not None: + return rich_to_bool(op, c) + + # case 3: try hard to compare real parts and imaginary parts + rcmp = richcmp(self.real(), other.real(), op) + if rcmp != 0: + return rcmp + return richcmp(self.imag(), other.imag(), op) def __bool__(self): """ @@ -3879,7 +4039,7 @@ def __pow__(self, e): sage: QQbar.zeta(7)^6 0.6234898018587335? - 0.7818314824680299?*I sage: (QQbar.zeta(7)^6)^(1/3) * QQbar.zeta(21) - 1.000000000000000? + 0.?e-18*I + 1.000000000000000? + 0.?e-17*I TESTS: @@ -4311,6 +4471,11 @@ def rational_argument(self): return self._descr.rational_argument(self) class AlgebraicReal(AlgebraicNumber_base): + r""" + A real algebraic number. + + .. automethod:: _richcmp_ + """ def __init__(self, x): """ Create an algebraic real from x, possibly taking the real part of x. @@ -4388,26 +4553,68 @@ def __reduce__(self): """ return (AlgebraicReal, (self._descr, )) - def __cmp__(self, other): + def _richcmp_(self, other, op): """ Compare two algebraic reals. EXAMPLES:: - sage: cmp(AA(golden_ratio), AA(sqrt(5))) - -1 - sage: cmp(AA(golden_ratio), AA((sqrt(5)+1)/2)) - 0 - sage: cmp(AA(7), AA(50/7)) - -1 + sage: AA(2).sqrt() < AA(3).sqrt() + True + sage: ((5+AA(5).sqrt())/2).sqrt() == 2*QQbar.zeta(5).imag() + True + sage: AA(3).sqrt() + AA(2).sqrt() < 3 + False + + TESTS:: + + sage: AA(golden_ratio) < AA(sqrt(5)) + True + sage: AA(golden_ratio) == AA((sqrt(5)+1)/2) + True + sage: AA(7) >= AA(50/7) + False """ - if self is other: return 0 - if isinstance(other._descr, ANRational) and other._descr._value.is_zero(): - return self.sign() - elif isinstance(self._descr, ANRational) and self._descr._value.is_zero(): - return -other.sign() - else: - return self._sub_(other).sign() + # note: we can assume that self is not other here + sd = self._descr + od = other._descr + + if type(sd) is ANRational and type(od) is ANRational: + return richcmp(sd._value, od._value, op) + + if op == op_EQ or op == op_NE: + # some cheap and quite common tests where we can decide equality or difference + if not self._value.real().overlaps(other._value.real()): + return op == op_NE + if type(sd) is ANRational and not sd._value: + return bool(other) == (op == op_NE) + elif type(od) is ANRational and not od._value: + return bool(self) == (op == op_NE) + elif (type(sd) is ANExtensionElement and + type(od) is ANExtensionElement and + sd._generator is od._generator): + return sd._value == od._value if op == op_EQ else sd._value != od._value + elif self.minpoly() != other.minpoly(): + return op == op_NE + + # case 0: real parts are clearly distinct + if not self._value.overlaps(other._value): + return richcmp(self._value, other._value, op) + + # case 1: rationals + sd = self._descr + od = other._descr + if type(sd) is ANRational and type(od) is ANRational: + return richcmp(sd._value, od._value, op) + + if self._value.prec() < 128: + self._more_precision() + if other._value.prec() < 128: + other._more_precision() + if not self._value.overlaps(other._value): + return richcmp(self._value, other._value, op) + + return rich_to_bool(op, (self-other).sign()) def __pow__(self, e): """ @@ -4719,28 +4926,82 @@ def sign(self): -1 sage: (AA(2).sqrt() - AA(2).sqrt()).sign() 0 + + sage: a = AA(2).sqrt() + AA(3).sqrt() - 58114382797550084497/18470915334626475921 + sage: a.sign() + 1 + sage: b = AA(2).sqrt() + AA(3).sqrt() - 2602510228533039296408/827174681630786895911 + sage: b.sign() + -1 + + sage: c = AA(5)**(1/3) - 1437624125539676934786/840727688792155114277 + sage: c.sign() + 1 + + sage: (((a+b)*(a+c)*(b+c))**9 / (a*b*c)).sign() + 1 + sage: (a-b).sign() + 1 + sage: (b-a).sign() + -1 + sage: (a*b).sign() + -1 + sage: ((a*b).abs() + a).sign() + 1 + sage: (a*b - b*a).sign() + 0 """ - if self._value.lower() > 0: - return 1 - elif self._value.upper() < 0: - return -1 - elif isinstance(self._descr, ANRational): - return self._descr._value.sign() + if not self._value.contains_zero(): + return self._value.unique_sign() + + sd = self._descr + if isinstance(self._descr, ANRational): + return sd._value.sign() elif isinstance(self._descr, ANExtensionElement): # All field elements are irrational by construction # (the ANExtensionElement constructor will return an ANRational # instead, if the number is actually rational). # An irrational number must eventually be different from 0 - self._more_precision() - return self.sign() - elif self._value.prec() < 128: + while self._value.contains_zero(): + self._more_precision() + return self._value.unique_sign() + elif type(sd) is ANBinaryExpr: + ls = sd._left.sign() + rs = sd._right.sign() + if sd._op == '*' or sd._op == '/': + return sd._left.sign() * sd._right.sign() + elif sd._op == '+': + if ls == rs: + return ls + else: + if ls == -rs: + return ls + elif not ls: + self._set_descr((-sd._right)._descr) + return -rs + elif not rs: + self._set_descr(sd._left._descr) + return ls + elif type(sd) is ANUnaryExpr: + if sd._op == 'abs': + c = 1 if bool(sd._arg) else 0 + if not c: + self._set_descr(ANRational(QQ.zero())) + return c + elif sd._op == '-': + return -(sd._arg.sign()) + elif sd._op == '~': + return sd._arg.sign() + + if self._value.prec() < 128: # OK, we'll try adding precision one more time self._more_precision() - return self.sign() - else: - # Sigh... - self.exactify() - return self.sign() + if not self._value.contains_zero(): + return self._value.unique_sign() + + # Sigh... + self.exactify() + return self.sign() def _interval_fast(self, prec): r""" diff --git a/src/sage/schemes/elliptic_curves/period_lattice.py b/src/sage/schemes/elliptic_curves/period_lattice.py index e51fc13758a..eb6ae832954 100644 --- a/src/sage/schemes/elliptic_curves/period_lattice.py +++ b/src/sage/schemes/elliptic_curves/period_lattice.py @@ -1051,7 +1051,7 @@ def ei(self): sage: abs(x1.real())+abs(x2.real())<1e-14 True sage: x1.imag(),x2.imag(),x3 - (-1.122462048309373?, 1.122462048309373?, -1) + (-1.122462048309373?, 1.122462048309373?, -1.000000000000000?) :: From 7481c2b546713e7c310394b2a24f3557bb4b0573 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 30 Apr 2017 19:30:36 +0200 Subject: [PATCH 191/452] trac 18303 some details --- src/sage/rings/qqbar.py | 52 ++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/src/sage/rings/qqbar.py b/src/sage/rings/qqbar.py index 16e9c9593cd..8f9e8858252 100644 --- a/src/sage/rings/qqbar.py +++ b/src/sage/rings/qqbar.py @@ -510,7 +510,8 @@ import sage.rings.ring from sage.misc.fast_methods import Singleton from sage.misc.cachefunc import cached_method -from sage.structure.sage_object import (SageObject, richcmp, rich_to_bool, +from sage.structure.sage_object import (SageObject, richcmp, + rich_to_bool, richcmp_not_equal, op_EQ, op_NE, op_LE, op_LT, op_GE, op_GT) from sage.rings.real_mpfr import RR @@ -2093,7 +2094,7 @@ def cmp_elements_with_same_minpoly(a, b, p): ar = a._value.real() br = b._value.real() if not ar.overlaps(br): - return -1 if richcmp(ar, br, op_LT) else 1 + return -1 if richcmp_not_equal(ar, br, op_LT) else 1 ai = a._value.imag() bi = b._value.imag() @@ -2124,7 +2125,7 @@ def cmp_elements_with_same_minpoly(a, b, p): bi = b._value.imag() if ai.overlaps(bi): return 0 - return -1 if richcmp(ai, bi, op_LT) else 1 + return -1 if richcmp_not_equal(ai, bi, op_LT) else 1 return None @@ -3105,9 +3106,9 @@ def __hash__(self): def __bool__(self): """ - Check whether self is equal is nonzero. + Check whether ``self`` is nonzero. - This is fast if interval arithmetic proves and in many other cases. + This is fast if interval arithmetic proves it and in many other cases. Though, it might be slow in very particular cases where the number is actually zero or very close to zero. @@ -3152,23 +3153,23 @@ def __bool__(self): # case 1: cheap tests sd = self._descr - if type(sd) is ANExtensionElement or type(sd) is ANRootOfUnity: + if isinstance(sd, ANExtensionElement) or isinstance(sd, ANRootOfUnity): # The ANExtensionElement and ANRootOfUnity returns an ANRational # instead, if the number is zero. return True - elif type(sd) is ANRational: + elif isinstance(sd, ANRational): return sd._value.__nonzero__() - elif type(sd) is ANUnaryExpr and sd._op != 'real' and sd._op != 'imag': + elif isinstance(sd, ANUnaryExpr) and sd._op != 'real' and sd._op != 'imag': ans = sd._arg.__nonzero__() if not ans: self._set_descr(ANRational(QQ.zero())) return ans - elif type(sd) is ANBinaryExpr and sd._op == '*': + elif isinstance(sd, ANBinaryExpr) and sd._op == '*': ans = sd._left.__nonzero__() and sd._right.__nonzero__() if not ans: self._set_descr(ANRational(QQ.zero())) return ans - elif type(sd) is ANBinaryExpr and sd._op == '/': + elif isinstance(sd, ANBinaryExpr) and sd._op == '/': ans = sd._left.__nonzero__() if not ans: self._set_descr(ANRational(QQ.zero())) @@ -3181,7 +3182,7 @@ def __bool__(self): return True # case 3: try with minpoly in case of x+y or x-y - if type(sd) is ANBinaryExpr: + if isinstance(sd, ANBinaryExpr): op = sd._op left = sd._left right = sd._right if op == '-' else -sd._right @@ -3199,7 +3200,7 @@ def __bool__(self): # Sigh... self.exactify() - return self.__nonzero__() + return self.__bool__() __nonzero__ = __bool__ @@ -3857,8 +3858,8 @@ def _richcmp_(self, other, op): [-0.0221204634374361? - 1.090991904211621?*I, -0.0221204634374361? + 1.090991904211621?*I, -0.8088604911480535?*I, - 0.?e-215 - 0.7598602580415435?*I, - 0.?e-229 + 0.7598602580415435?*I, + 0.?e-79 - 0.7598602580415435?*I, + 0.?e-79 + 0.7598602580415435?*I, 0.8088604911480535?*I, 0.0221204634374361? - 1.090991904211621?*I, 0.0221204634374361? + 1.090991904211621?*I] @@ -3930,9 +3931,9 @@ def _richcmp_(self, other, op): if not (self._value.real().overlaps(other._value.real()) and self._value.imag().overlaps(other._value.imag())): return op == op_NE - if type(sd) is ANRational and not sd._value: + if isinstance(sd, ANRational) and not sd._value: return bool(other) == (op == op_NE) - elif type(od) is ANRational and not od._value: + elif isinstance(od, ANRational) and not od._value: return bool(self) == (op == op_NE) elif (isinstance(sd, ANExtensionElement) and isinstance(od, ANExtensionElement) and @@ -3943,12 +3944,12 @@ def _richcmp_(self, other, op): ri1 = self._value.real() ri2 = other._value.real() if not ri1.overlaps(ri2): - return richcmp(ri1, ri2, op) + return richcmp_not_equal(ri1, ri2, op) # case 1: rationals sd = self._descr od = other._descr - if type(sd) is ANRational and type(od) is ANRational: + if isinstance(sd, ANRational) and isinstance(od, ANRational): return richcmp(sd._value, od._value, op) # case 2: possibly equal or conjugate values @@ -3961,16 +3962,19 @@ def _richcmp_(self, other, op): return rich_to_bool(op, c) # case 3: try hard to compare real parts and imaginary parts - rcmp = richcmp(self.real(), other.real(), op) - if rcmp != 0: - return rcmp + srp = self.real() + orp = other.real() + if srp != orp: + return richcmp_not_equal(srp, orp, op) return richcmp(self.imag(), other.imag(), op) def __bool__(self): """ - Check whether self is equal is nonzero. This is fast if - interval arithmetic proves that self is nonzero, but may be - slow if the number actually is very close to zero. + Check whether ``self`` is nonzero. + + This is fast if interval arithmetic proves that ``self`` is + nonzero, but may be slow if the number actually is very close + to zero. EXAMPLES:: From 9f553cd56c65cd474e6d120990b187e68e279c32 Mon Sep 17 00:00:00 2001 From: "Erik M. Bray" Date: Tue, 2 May 2017 15:21:53 +0200 Subject: [PATCH 192/452] Fix this patch, which was incorrectly changed in https://trac.sagemath.org/ticket/22666 --- build/pkgs/python3/patches/3.4.5-struct.patch | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/build/pkgs/python3/patches/3.4.5-struct.patch b/build/pkgs/python3/patches/3.4.5-struct.patch index 3b677a72e90..6138b1359b4 100644 --- a/build/pkgs/python3/patches/3.4.5-struct.patch +++ b/build/pkgs/python3/patches/3.4.5-struct.patch @@ -3,6 +3,15 @@ as been fixed upstream for Python 3.7; see https://bugs.python.org/issue21124 diff -r b244bf74b638 Modules/_struct.c --- a/Modules/_struct.c Sun Oct 02 13:49:05 2016 +0300 +++ b/Modules/_struct.c Sun Oct 02 19:54:56 2016 +0900 +@@ -1627,7 +1627,7 @@ unpackiter_iternext(unpackiterobject *self) + } + + static PyTypeObject unpackiter_type = { +- PyVarObject_HEAD_INIT(&PyType_Type, 0) ++ PyVarObject_HEAD_INIT(NULL, 0) + "unpack_iterator", /* tp_name */ + sizeof(unpackiterobject), /* tp_basicsize */ + 0, @@ -2301,6 +2301,9 @@ if (PyType_Ready(&PyStructType) < 0) return NULL; From cb9623f5a813a9a1351ad3bcb4315b9741e9db2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 2 May 2017 16:15:23 +0200 Subject: [PATCH 193/452] py3: remove one call to unicode --- src/sage_setup/docbuild/__init__.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/sage_setup/docbuild/__init__.py b/src/sage_setup/docbuild/__init__.py index daa7dc6a556..70c3ef405ce 100644 --- a/src/sage_setup/docbuild/__init__.py +++ b/src/sage_setup/docbuild/__init__.py @@ -1208,7 +1208,8 @@ def get_builder(name): print("of documents, or 'sage --docbuild --help' for more help.") sys.exit(1) -def format_columns(lst, align='<', cols=None, indent=4, pad=3, width=80): + +def format_columns(lst, align=u'<', cols=None, indent=4, pad=3, width=80): """ Utility function that formats a list as a simple table and returns a Unicode string representation. The number of columns is @@ -1223,13 +1224,14 @@ def format_columns(lst, align='<', cols=None, indent=4, pad=3, width=80): if cols is None: import math cols = math.trunc((width - indent) / size) - s = " " * indent + s = u" " * indent for i in range(len(lst)): if i != 0 and i % cols == 0: - s += "\n" + " " * indent - s += "{0:{1}{2}}".format(lst[i], align, size) - s += "\n" - return unicode(s) + s += u"\n" + u" " * indent + s += u"{0:{1}{2}}".format(lst[i], align, size) + s += u"\n" + return s + def help_usage(s=u"", compact=False): """ From f9291c573de501553996af6845e098bad0f5cfdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=2E=20Thi=C3=A9ry?= Date: Tue, 2 May 2017 10:27:00 -0400 Subject: [PATCH 194/452] 22931: added missing Sphinx labels to prep tutorials --- src/doc/en/prep/Advanced-2DPlotting.rst | 2 ++ src/doc/en/prep/Calculus.rst | 2 ++ src/doc/en/prep/Intro-Tutorial.rst | 2 ++ src/doc/en/prep/Programming.rst | 2 ++ src/doc/en/prep/Quickstarts/Abstract-Algebra.rst | 2 ++ src/doc/en/prep/Quickstarts/Differential-Equations.rst | 2 ++ src/doc/en/prep/Quickstarts/Graphs-and-Discrete.rst | 2 ++ src/doc/en/prep/Quickstarts/Interact.rst | 2 ++ src/doc/en/prep/Quickstarts/Linear-Algebra.rst | 2 ++ src/doc/en/prep/Quickstarts/Multivariable-Calculus.rst | 2 ++ src/doc/en/prep/Quickstarts/NumAnalysis.rst | 2 ++ src/doc/en/prep/Quickstarts/Number-Theory.rst | 2 ++ src/doc/en/prep/Quickstarts/Statistics-and-Distributions.rst | 2 ++ src/doc/en/prep/Symbolics-and-Basic-Plotting.rst | 2 ++ src/doc/en/prep/index.rst | 2 ++ src/doc/en/prep/quickstart.rst | 2 ++ 16 files changed, 32 insertions(+) diff --git a/src/doc/en/prep/Advanced-2DPlotting.rst b/src/doc/en/prep/Advanced-2DPlotting.rst index 00967b9e683..4f3c77540de 100644 --- a/src/doc/en/prep/Advanced-2DPlotting.rst +++ b/src/doc/en/prep/Advanced-2DPlotting.rst @@ -2,6 +2,8 @@ .. linkall +.. _Advanced_2DPlotting: + Tutorial for Advanced 2d Plotting ================================= diff --git a/src/doc/en/prep/Calculus.rst b/src/doc/en/prep/Calculus.rst index 81b0fed4346..72667d8059e 100644 --- a/src/doc/en/prep/Calculus.rst +++ b/src/doc/en/prep/Calculus.rst @@ -2,6 +2,8 @@ .. linkall +.. _calculus: + Tutorial for Calculus ===================== diff --git a/src/doc/en/prep/Intro-Tutorial.rst b/src/doc/en/prep/Intro-Tutorial.rst index 82aef6ad728..18d374182ce 100644 --- a/src/doc/en/prep/Intro-Tutorial.rst +++ b/src/doc/en/prep/Intro-Tutorial.rst @@ -2,6 +2,8 @@ .. linkall +.. _intro-tutorial: + Introductory Sage Tutorial ========================== diff --git a/src/doc/en/prep/Programming.rst b/src/doc/en/prep/Programming.rst index 595216d4411..2bc3ebab544 100644 --- a/src/doc/en/prep/Programming.rst +++ b/src/doc/en/prep/Programming.rst @@ -2,6 +2,8 @@ .. linkall +.. _programming: + Sage Introductory Programming Tutorial ====================================== diff --git a/src/doc/en/prep/Quickstarts/Abstract-Algebra.rst b/src/doc/en/prep/Quickstarts/Abstract-Algebra.rst index dfe894a4602..7ebd64ebf42 100644 --- a/src/doc/en/prep/Quickstarts/Abstract-Algebra.rst +++ b/src/doc/en/prep/Quickstarts/Abstract-Algebra.rst @@ -2,6 +2,8 @@ .. linkall +.. _quickstart-abstract-algebra: + Sage Quickstart for Abstract Algebra ==================================== diff --git a/src/doc/en/prep/Quickstarts/Differential-Equations.rst b/src/doc/en/prep/Quickstarts/Differential-Equations.rst index 539b21344fa..bc151b7ce4a 100644 --- a/src/doc/en/prep/Quickstarts/Differential-Equations.rst +++ b/src/doc/en/prep/Quickstarts/Differential-Equations.rst @@ -2,6 +2,8 @@ .. linkall +.. _quickstart-differential-equations: + Sage Quickstart for Differential Equations ========================================== diff --git a/src/doc/en/prep/Quickstarts/Graphs-and-Discrete.rst b/src/doc/en/prep/Quickstarts/Graphs-and-Discrete.rst index aa7a308854a..39cf5eb8cef 100644 --- a/src/doc/en/prep/Quickstarts/Graphs-and-Discrete.rst +++ b/src/doc/en/prep/Quickstarts/Graphs-and-Discrete.rst @@ -2,6 +2,8 @@ .. linkall +.. _quickstart-graphs-and-discrete: + Sage Quickstart for Graph Theory and Discrete Mathematics ========================================================= diff --git a/src/doc/en/prep/Quickstarts/Interact.rst b/src/doc/en/prep/Quickstarts/Interact.rst index 9898017ee22..32b082d5d28 100644 --- a/src/doc/en/prep/Quickstarts/Interact.rst +++ b/src/doc/en/prep/Quickstarts/Interact.rst @@ -2,6 +2,8 @@ .. linkall +.. _quickstart-interact: + Sage Interact Quickstart ======================== diff --git a/src/doc/en/prep/Quickstarts/Linear-Algebra.rst b/src/doc/en/prep/Quickstarts/Linear-Algebra.rst index e14d7896b41..e20ca9d1d4f 100644 --- a/src/doc/en/prep/Quickstarts/Linear-Algebra.rst +++ b/src/doc/en/prep/Quickstarts/Linear-Algebra.rst @@ -2,6 +2,8 @@ .. linkall +.. _quickstart-linear-algebra: + Sage Quickstart for Linear Algebra ================================== diff --git a/src/doc/en/prep/Quickstarts/Multivariable-Calculus.rst b/src/doc/en/prep/Quickstarts/Multivariable-Calculus.rst index dc534d0eef7..6eefd070764 100644 --- a/src/doc/en/prep/Quickstarts/Multivariable-Calculus.rst +++ b/src/doc/en/prep/Quickstarts/Multivariable-Calculus.rst @@ -2,6 +2,8 @@ .. linkall +.. _quickstart-multivariate-calculus: + Sage Quickstart for Multivariable Calculus ========================================== diff --git a/src/doc/en/prep/Quickstarts/NumAnalysis.rst b/src/doc/en/prep/Quickstarts/NumAnalysis.rst index 69e27e51b9b..8f40f6e4a5d 100644 --- a/src/doc/en/prep/Quickstarts/NumAnalysis.rst +++ b/src/doc/en/prep/Quickstarts/NumAnalysis.rst @@ -2,6 +2,8 @@ .. linkall +.. _quickstart-numerical-analysis: + Sage Quickstart for Numerical Analysis ====================================== diff --git a/src/doc/en/prep/Quickstarts/Number-Theory.rst b/src/doc/en/prep/Quickstarts/Number-Theory.rst index d9596ee7e47..eb63dca106d 100644 --- a/src/doc/en/prep/Quickstarts/Number-Theory.rst +++ b/src/doc/en/prep/Quickstarts/Number-Theory.rst @@ -2,6 +2,8 @@ .. linkall +.. _quickstart-number-theory: + Sage Quickstart for Number Theory ================================= diff --git a/src/doc/en/prep/Quickstarts/Statistics-and-Distributions.rst b/src/doc/en/prep/Quickstarts/Statistics-and-Distributions.rst index 419d3b121eb..437898873f8 100644 --- a/src/doc/en/prep/Quickstarts/Statistics-and-Distributions.rst +++ b/src/doc/en/prep/Quickstarts/Statistics-and-Distributions.rst @@ -2,6 +2,8 @@ .. linkall +.. _quickstart-statistics-and-distributions: + Sage Quickstart for Statistics ============================== diff --git a/src/doc/en/prep/Symbolics-and-Basic-Plotting.rst b/src/doc/en/prep/Symbolics-and-Basic-Plotting.rst index f6494f40da6..f22d874812e 100644 --- a/src/doc/en/prep/Symbolics-and-Basic-Plotting.rst +++ b/src/doc/en/prep/Symbolics-and-Basic-Plotting.rst @@ -2,6 +2,8 @@ .. linkall +.. _symbolics-and-basic-plotting: + Tutorial for Symbolics and Plotting =================================== diff --git a/src/doc/en/prep/index.rst b/src/doc/en/prep/index.rst index be762634ec1..8cc6fb1bb11 100644 --- a/src/doc/en/prep/index.rst +++ b/src/doc/en/prep/index.rst @@ -3,6 +3,8 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. +.. _prep_tutorials: + PREP Tutorials ============== diff --git a/src/doc/en/prep/quickstart.rst b/src/doc/en/prep/quickstart.rst index 336d2b7b92c..38167a8ca11 100644 --- a/src/doc/en/prep/quickstart.rst +++ b/src/doc/en/prep/quickstart.rst @@ -3,6 +3,8 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. +.. _prep-quickstart-tutorials: + PREP Quickstart Tutorials ========================= From ba996ea23e0f49240c938fd1fe2944e66f0c2575 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=2E=20Thi=C3=A9ry?= Date: Tue, 2 May 2017 10:35:23 -0400 Subject: [PATCH 195/452] 22931: add Sphinx labels to the root of all documents --- src/doc/en/a_tour_of_sage/index.rst | 2 ++ src/doc/en/constructions/index.rst | 2 ++ src/doc/en/developer/index.rst | 2 ++ src/doc/en/faq/index.rst | 2 ++ src/doc/en/installation/index.rst | 2 ++ src/doc/en/reference/index.rst | 2 ++ src/doc/en/thematic_tutorials/index.rst | 2 ++ src/doc/en/tutorial/index.rst | 2 ++ 8 files changed, 16 insertions(+) diff --git a/src/doc/en/a_tour_of_sage/index.rst b/src/doc/en/a_tour_of_sage/index.rst index ef3222ef4c1..d998c42b836 100644 --- a/src/doc/en/a_tour_of_sage/index.rst +++ b/src/doc/en/a_tour_of_sage/index.rst @@ -1,3 +1,5 @@ +.. _a-tour-of-sage: + ============== A Tour of Sage ============== diff --git a/src/doc/en/constructions/index.rst b/src/doc/en/constructions/index.rst index 6051fcafdcc..b6e660c245c 100644 --- a/src/doc/en/constructions/index.rst +++ b/src/doc/en/constructions/index.rst @@ -2,6 +2,8 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. +.. _constructions: + Welcome to the Sage Constructions documentation! ================================================ diff --git a/src/doc/en/developer/index.rst b/src/doc/en/developer/index.rst index 8726af7f7ae..6647e3a06f0 100644 --- a/src/doc/en/developer/index.rst +++ b/src/doc/en/developer/index.rst @@ -1,3 +1,5 @@ +.. _developers-guide: + ====================================== Welcome to the Sage Developer's Guide! ====================================== diff --git a/src/doc/en/faq/index.rst b/src/doc/en/faq/index.rst index 5ccf5ddbbaa..31d5cb59040 100644 --- a/src/doc/en/faq/index.rst +++ b/src/doc/en/faq/index.rst @@ -3,6 +3,8 @@ .. your liking, but it should at least contain the root `toctree` .. directive. +.. _faq: + Welcome to the Sage FAQ! ======================== diff --git a/src/doc/en/installation/index.rst b/src/doc/en/installation/index.rst index ec1ce3d302c..06ebb3d7a26 100644 --- a/src/doc/en/installation/index.rst +++ b/src/doc/en/installation/index.rst @@ -1,3 +1,5 @@ +.. _installation-guide: + Welcome to the Sage Installation Guide ====================================== diff --git a/src/doc/en/reference/index.rst b/src/doc/en/reference/index.rst index 3607297d28e..e50991aa506 100644 --- a/src/doc/en/reference/index.rst +++ b/src/doc/en/reference/index.rst @@ -1,3 +1,5 @@ +.. _reference-manual: + ******** Contents ******** diff --git a/src/doc/en/thematic_tutorials/index.rst b/src/doc/en/thematic_tutorials/index.rst index 8f73b34ffc1..bcae758a13e 100644 --- a/src/doc/en/thematic_tutorials/index.rst +++ b/src/doc/en/thematic_tutorials/index.rst @@ -2,6 +2,8 @@ .. Aug 21 20:15:55 2008. You can adapt this file completely to your .. liking, but it should at least contain the root `toctree` directive. +.. _thematic-tutorials: + Welcome to the Sage Thematic Tutorials! ======================================= diff --git a/src/doc/en/tutorial/index.rst b/src/doc/en/tutorial/index.rst index 72b80ad2b5d..858cbb1f2c8 100644 --- a/src/doc/en/tutorial/index.rst +++ b/src/doc/en/tutorial/index.rst @@ -2,6 +2,8 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. +.. _tutorial: + Welcome to the Sage Tutorial! ============================= From 7a7928a50cf0f1280a840587819e3c74bd06e6c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 2 May 2017 16:44:31 +0200 Subject: [PATCH 196/452] trac 22919 more permissive test --- src/sage/monoids/free_monoid.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/sage/monoids/free_monoid.py b/src/sage/monoids/free_monoid.py index d24b848462c..e5422337a69 100644 --- a/src/sage/monoids/free_monoid.py +++ b/src/sage/monoids/free_monoid.py @@ -205,12 +205,17 @@ def __eq__(self, other): """ Test for equality. """ + if self is other: + return True if not isinstance(other, FreeMonoid_class): return False if self.__ngens != other.__ngens: return False - if self.variable_names() != other.variable_names(): - return False + try: + if self.variable_names() != other.variable_names(): + return False + except ValueError: + pass return True def __ne__(self, other): From 515fb996026d21645e6fe0bc0aca5b58935899a3 Mon Sep 17 00:00:00 2001 From: Vincent Delecroix <20100.delecroix@gmail.com> Date: Tue, 2 May 2017 16:47:07 +0200 Subject: [PATCH 197/452] Trac 18303: a simplification, some fixes and more tests --- src/sage/rings/qqbar.py | 103 +++++++++++++++++++++------------------- 1 file changed, 54 insertions(+), 49 deletions(-) diff --git a/src/sage/rings/qqbar.py b/src/sage/rings/qqbar.py index 8f9e8858252..dc8e53931a7 100644 --- a/src/sage/rings/qqbar.py +++ b/src/sage/rings/qqbar.py @@ -3104,7 +3104,7 @@ def __hash__(self): else: return hash((self + QQbar_hash_offset).interval_exact(CIF)) - def __bool__(self): + def __nonzero__(self): """ Check whether ``self`` is nonzero. @@ -3142,8 +3142,48 @@ def __bool__(self): True sage: bool(e.abs() < 2**-500) True + + An identity between roots of unity:: + + sage: z3 = QQbar.zeta(3) + sage: z4 = QQbar.zeta(4) + sage: z5 = QQbar.zeta(5) + sage: p1 = (z3 + z4 + z5)**2 + sage: p2 = (z3 - z4 - z5)**2 + sage: p3 = (z3 - z4 + z5)**2 + sage: p4 = (z3 + z4 - z5)**2 + sage: bool(p1 - p2 + p3 - p4 - 8 * QQbar.zeta(15)**8) + False + + The following are non-trivially zeros (though no exactification occur):: + + sage: x = polygen(ZZ) + sage: a = (AA(2).sqrt() + AA(3).sqrt() + AA(5).sqrt())^2 + sage: b = 10 + 2*max((x^4 - 62*x^2 - 240*x - 239).roots(AA, False)) + sage: bool(a - b) + False + + sage: d = sum(AA(k)**(1/k) for k in [2..100]) + sage: bool(d * (a - b)) + False + sage: bool((a - b) * d) + False + sage: bool(d * (a - b) * d) + False + sage: bool((a - b) / d) + False + + sage: d = sum(QQbar(-k)**(1/k) for k in [2..100]) + sage: bool(d * (a - b)) + False + sage: bool((a - b) * d) + False + sage: bool(d * (a - b) * d) + False + sage: bool((a - b) / d) + False """ - # case 0: trivial test + # case 0: trivial tests if not self._value.contains_zero(): return True elif self._value.is_zero(): @@ -3153,24 +3193,24 @@ def __bool__(self): # case 1: cheap tests sd = self._descr - if isinstance(sd, ANExtensionElement) or isinstance(sd, ANRootOfUnity): - # The ANExtensionElement and ANRootOfUnity returns an ANRational + if isinstance(sd, ANExtensionElement): + # The ANExtensionElement returns an ANRational # instead, if the number is zero. return True elif isinstance(sd, ANRational): - return sd._value.__nonzero__() + return bool(sd._value) elif isinstance(sd, ANUnaryExpr) and sd._op != 'real' and sd._op != 'imag': - ans = sd._arg.__nonzero__() + ans = bool(sd._arg) if not ans: self._set_descr(ANRational(QQ.zero())) return ans - elif isinstance(sd, ANBinaryExpr) and sd._op == '*': - ans = sd._left.__nonzero__() and sd._right.__nonzero__() + elif isinstance(sd, ANBinaryExpr) and sd._op is operator.mul: + ans = bool(sd._left) and bool(sd._right) if not ans: self._set_descr(ANRational(QQ.zero())) return ans - elif isinstance(sd, ANBinaryExpr) and sd._op == '/': - ans = sd._left.__nonzero__() + elif isinstance(sd, ANBinaryExpr) and sd._op is operator.div: + ans = bool(sd._left) if not ans: self._set_descr(ANRational(QQ.zero())) return ans @@ -3185,7 +3225,7 @@ def __bool__(self): if isinstance(sd, ANBinaryExpr): op = sd._op left = sd._left - right = sd._right if op == '-' else -sd._right + right = sd._right if op is operator.sub else -sd._right lp = left.minpoly() rp = right.minpoly() @@ -3200,10 +3240,8 @@ def __bool__(self): # Sigh... self.exactify() - return self.__bool__() + return bool(self) - __nonzero__ = __bool__ - def is_square(self): """ Return whether or not this number is square. @@ -3968,39 +4006,6 @@ def _richcmp_(self, other, op): return richcmp_not_equal(srp, orp, op) return richcmp(self.imag(), other.imag(), op) - def __bool__(self): - """ - Check whether ``self`` is nonzero. - - This is fast if interval arithmetic proves that ``self`` is - nonzero, but may be slow if the number actually is very close - to zero. - - EXAMPLES:: - - sage: bool(QQbar.zeta(2) + 1) - False - sage: bool(QQbar.zeta(7) / (2^500)) - True - """ - val = self._value - d = self._descr - if not val.contains_zero() or isinstance(d, ANExtensionElement): - return True - elif isinstance(d, ANRational): - return bool(d._value) - - while self._value.prec() < 128: - self._more_precision() - if not self._value.contains_zero(): - return True - - # Sigh... - self.exactify() - return self.__bool__() - - __nonzero__ = __bool__ - def __pow__(self, e): r""" ``self**p`` returns the `p`'th power of self (where `p` can be an arbitrary rational). If `p` is `(a/b)`, takes the principal @@ -4972,9 +4977,9 @@ def sign(self): elif type(sd) is ANBinaryExpr: ls = sd._left.sign() rs = sd._right.sign() - if sd._op == '*' or sd._op == '/': + if sd._op is operator.mul or sd._op is operator.div: return sd._left.sign() * sd._right.sign() - elif sd._op == '+': + elif sd._op is operator.add: if ls == rs: return ls else: From 9c853e72dd6252e90f5532fb767f1ab6ea5003e9 Mon Sep 17 00:00:00 2001 From: Bruno Grenet Date: Tue, 2 May 2017 16:58:15 +0200 Subject: [PATCH 198/452] is_field catches NotImplementedError when proof=False --- .../polynomial/polynomial_quotient_ring.py | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/sage/rings/polynomial/polynomial_quotient_ring.py b/src/sage/rings/polynomial/polynomial_quotient_ring.py index 28fa62bc430..504263471ce 100644 --- a/src/sage/rings/polynomial/polynomial_quotient_ring.py +++ b/src/sage/rings/polynomial/polynomial_quotient_ring.py @@ -823,8 +823,27 @@ def is_field(self, proof = True): sage: S = R.quotient(x^2 - 2) sage: S.is_field() True + + If proof is True, requires the `is_irreducible` method of the modulus to + be implemented:: + + sage: R1. = GF(5)[] + sage: F1 = R1.quotient_ring(x^2+x+1) + sage: R2. = F1[] + sage: F2 = R2.quotient_ring(x^2+x+1) + sage: F2.is_field() + Traceback (most recent call last): + ... + NotImplementedError + sage: F2.is_field(proof = False) + False """ - return self.base_ring().is_field(proof) and self.modulus().is_irreducible() + if proof: + return self.base_ring().is_field(True) and self.modulus().is_irreducible() + try: + return self.base_ring().is_field(False) and self.modulus().is_irreducible() + except NotImplementedError: + return False def krull_dimension(self): return self.base_ring().krull_dimension() From 88e55d16a99c9f6767bd57472d185b6dff3c9631 Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Tue, 2 May 2017 17:27:42 +0200 Subject: [PATCH 199/452] 22877: Wrong atan2 of complex arguments --- src/sage/libs/pynac/pynac.pyx | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/sage/libs/pynac/pynac.pyx b/src/sage/libs/pynac/pynac.pyx index 68eff58c2cf..bbb98813190 100644 --- a/src/sage/libs/pynac/pynac.pyx +++ b/src/sage/libs/pynac/pynac.pyx @@ -1791,19 +1791,36 @@ cdef py_atan2(x, y): 2.284887025407... sage: atan2(2.1000000000000000000000000000000000000, -1.20000000000000000000000000000000) 2.089942441041419571002776071... + + Check that :trac:`22877` is fixed:: + + sage: atan2(CC(I), CC(I+1)) + 0.553574358897045 + 0.402359478108525*I + sage: atan2(CBF(I), CBF(I+1)) + [0.55357435889705 +/- 5.75e-15] + [0.40235947810852 +/- 6.01e-15]*I """ from sage.symbolic.constants import pi, NaN P = coercion_model.common_parent(x, y) + is_real = False if P is ZZ: P = RR + if P in (float, RR, RBF): + is_real = True if y != 0: - if x > 0: - res = py_atan(abs(y/x)) - elif x < 0: - res = P(pi) - py_atan(abs(y/x)) + try: + is_real = is_real or (x.is_real() and y.is_real()) + except AttributeError: + is_real = False + if is_real: + if x > 0: + res = py_atan(abs(y/x)) + elif x < 0: + res = P(pi) - py_atan(abs(y/x)) + else: + res = P(pi)/2 + return res if y > 0 else -res else: - res = P(pi)/2 - return res if y > 0 else -res + return -I*py_log((x + I*y)/py_sqrt(x**2 + y**2)) else: if x > 0: return P(0) From eeae1078e76f7e28da4c3a10bdb2c5e52e7e780b Mon Sep 17 00:00:00 2001 From: Bruno Grenet Date: Tue, 2 May 2017 18:09:48 +0200 Subject: [PATCH 200/452] 22910: Forward flag proof to is_field in is_integral_domain --- src/sage/rings/ring.pyx | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/sage/rings/ring.pyx b/src/sage/rings/ring.pyx index 22ac471cc12..15ed9bee00c 100644 --- a/src/sage/rings/ring.pyx +++ b/src/sage/rings/ring.pyx @@ -994,8 +994,17 @@ cdef class Ring(ParentWithGens): Traceback (most recent call last): ... NotImplementedError + + Forward the proof flag to `is_field`, see :trac:`22910`:: + + sage: R1. = GF(5)[] + sage: F1 = R1.quotient_ring(x^2+x+1) + sage: R2. = F1[] + sage: F2 = R2.quotient_ring(x^2+x+1) + sage: F2.is_integral_domain(False) + False """ - if self.is_field(): + if self.is_field(proof): return True if self.is_zero(): From aafb6c828b5d4e54ef2d65d4684d8f1e6f449ddd Mon Sep 17 00:00:00 2001 From: Bruno Grenet Date: Tue, 2 May 2017 18:14:00 +0200 Subject: [PATCH 201/452] 22910: add possibility for is_field to get flags --- src/sage/rings/polynomial/plural.pyx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/sage/rings/polynomial/plural.pyx b/src/sage/rings/polynomial/plural.pyx index 39631f0cccf..eec261aaefc 100644 --- a/src/sage/rings/polynomial/plural.pyx +++ b/src/sage/rings/polynomial/plural.pyx @@ -636,7 +636,7 @@ cdef class NCPolynomialRing_plural(Ring): """ return False - def is_field(self): + def is_field(self, *args, **kwargs): """ Return ``False``. @@ -646,6 +646,14 @@ cdef class NCPolynomialRing_plural(Ring): sage: P = A.g_algebra(relations={y*x:-x*y}, order = 'lex') sage: P.is_field() False + + TESTS: + + Make the method accept additional parameters, such as the flag `proof`. + See :trac:`22910`:: + + sage: P.is_field(proof=False) + False """ return False From 643e829eb731c754ae5f67e0772125b204a82615 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=2E=20Thi=C3=A9ry?= Date: Tue, 2 May 2017 17:25:13 -0400 Subject: [PATCH 202/452] 22931: normalize the new labels for the prep documents with a prep- prefix. --- src/doc/en/prep/Advanced-2DPlotting.rst | 2 +- src/doc/en/prep/Calculus.rst | 2 +- src/doc/en/prep/Intro-Tutorial.rst | 2 +- src/doc/en/prep/Logging-On.rst | 1 + src/doc/en/prep/Programming.rst | 2 +- src/doc/en/prep/Quickstarts/Abstract-Algebra.rst | 2 +- src/doc/en/prep/Quickstarts/Differential-Equations.rst | 2 +- src/doc/en/prep/Quickstarts/Graphs-and-Discrete.rst | 2 +- src/doc/en/prep/Quickstarts/Interact.rst | 2 +- src/doc/en/prep/Quickstarts/Linear-Algebra.rst | 2 +- src/doc/en/prep/Quickstarts/Multivariable-Calculus.rst | 2 +- src/doc/en/prep/Quickstarts/NumAnalysis.rst | 2 +- src/doc/en/prep/Quickstarts/Number-Theory.rst | 2 +- src/doc/en/prep/Quickstarts/Statistics-and-Distributions.rst | 2 +- src/doc/en/prep/Symbolics-and-Basic-Plotting.rst | 2 +- src/doc/en/prep/index.rst | 2 +- 16 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/doc/en/prep/Advanced-2DPlotting.rst b/src/doc/en/prep/Advanced-2DPlotting.rst index 4f3c77540de..5d2042684ca 100644 --- a/src/doc/en/prep/Advanced-2DPlotting.rst +++ b/src/doc/en/prep/Advanced-2DPlotting.rst @@ -2,7 +2,7 @@ .. linkall -.. _Advanced_2DPlotting: +.. _prep-advanced-2dplotting: Tutorial for Advanced 2d Plotting ================================= diff --git a/src/doc/en/prep/Calculus.rst b/src/doc/en/prep/Calculus.rst index 72667d8059e..53e90de0764 100644 --- a/src/doc/en/prep/Calculus.rst +++ b/src/doc/en/prep/Calculus.rst @@ -2,7 +2,7 @@ .. linkall -.. _calculus: +.. _prep-calculus: Tutorial for Calculus ===================== diff --git a/src/doc/en/prep/Intro-Tutorial.rst b/src/doc/en/prep/Intro-Tutorial.rst index 18d374182ce..2def3bef370 100644 --- a/src/doc/en/prep/Intro-Tutorial.rst +++ b/src/doc/en/prep/Intro-Tutorial.rst @@ -2,7 +2,7 @@ .. linkall -.. _intro-tutorial: +.. _prep-intro-tutorial: Introductory Sage Tutorial ========================== diff --git a/src/doc/en/prep/Logging-On.rst b/src/doc/en/prep/Logging-On.rst index b9216cc69f4..24c356b3eba 100644 --- a/src/doc/en/prep/Logging-On.rst +++ b/src/doc/en/prep/Logging-On.rst @@ -2,6 +2,7 @@ .. linkall +.. _prep-logging-on: .. _logging-on: Logging on to a Sage Server and Creating a Worksheet diff --git a/src/doc/en/prep/Programming.rst b/src/doc/en/prep/Programming.rst index 2bc3ebab544..cafca74b2d5 100644 --- a/src/doc/en/prep/Programming.rst +++ b/src/doc/en/prep/Programming.rst @@ -2,7 +2,7 @@ .. linkall -.. _programming: +.. _prep-programming: Sage Introductory Programming Tutorial ====================================== diff --git a/src/doc/en/prep/Quickstarts/Abstract-Algebra.rst b/src/doc/en/prep/Quickstarts/Abstract-Algebra.rst index 7ebd64ebf42..042b786420c 100644 --- a/src/doc/en/prep/Quickstarts/Abstract-Algebra.rst +++ b/src/doc/en/prep/Quickstarts/Abstract-Algebra.rst @@ -2,7 +2,7 @@ .. linkall -.. _quickstart-abstract-algebra: +.. _prep-quickstart-abstract-algebra: Sage Quickstart for Abstract Algebra ==================================== diff --git a/src/doc/en/prep/Quickstarts/Differential-Equations.rst b/src/doc/en/prep/Quickstarts/Differential-Equations.rst index bc151b7ce4a..3c023424db8 100644 --- a/src/doc/en/prep/Quickstarts/Differential-Equations.rst +++ b/src/doc/en/prep/Quickstarts/Differential-Equations.rst @@ -2,7 +2,7 @@ .. linkall -.. _quickstart-differential-equations: +.. _prep-quickstart-differential-equations: Sage Quickstart for Differential Equations ========================================== diff --git a/src/doc/en/prep/Quickstarts/Graphs-and-Discrete.rst b/src/doc/en/prep/Quickstarts/Graphs-and-Discrete.rst index 39cf5eb8cef..9406595ddec 100644 --- a/src/doc/en/prep/Quickstarts/Graphs-and-Discrete.rst +++ b/src/doc/en/prep/Quickstarts/Graphs-and-Discrete.rst @@ -2,7 +2,7 @@ .. linkall -.. _quickstart-graphs-and-discrete: +.. _prep-quickstart-graphs-and-discrete: Sage Quickstart for Graph Theory and Discrete Mathematics ========================================================= diff --git a/src/doc/en/prep/Quickstarts/Interact.rst b/src/doc/en/prep/Quickstarts/Interact.rst index 32b082d5d28..666ad9023ce 100644 --- a/src/doc/en/prep/Quickstarts/Interact.rst +++ b/src/doc/en/prep/Quickstarts/Interact.rst @@ -2,7 +2,7 @@ .. linkall -.. _quickstart-interact: +.. _prep-quickstart-interact: Sage Interact Quickstart ======================== diff --git a/src/doc/en/prep/Quickstarts/Linear-Algebra.rst b/src/doc/en/prep/Quickstarts/Linear-Algebra.rst index e20ca9d1d4f..d9ad58c1f45 100644 --- a/src/doc/en/prep/Quickstarts/Linear-Algebra.rst +++ b/src/doc/en/prep/Quickstarts/Linear-Algebra.rst @@ -2,7 +2,7 @@ .. linkall -.. _quickstart-linear-algebra: +.. _prep-quickstart-linear-algebra: Sage Quickstart for Linear Algebra ================================== diff --git a/src/doc/en/prep/Quickstarts/Multivariable-Calculus.rst b/src/doc/en/prep/Quickstarts/Multivariable-Calculus.rst index 6eefd070764..c5db7bfd4d1 100644 --- a/src/doc/en/prep/Quickstarts/Multivariable-Calculus.rst +++ b/src/doc/en/prep/Quickstarts/Multivariable-Calculus.rst @@ -2,7 +2,7 @@ .. linkall -.. _quickstart-multivariate-calculus: +.. _prep-quickstart-multivariate-calculus: Sage Quickstart for Multivariable Calculus ========================================== diff --git a/src/doc/en/prep/Quickstarts/NumAnalysis.rst b/src/doc/en/prep/Quickstarts/NumAnalysis.rst index 8f40f6e4a5d..70fc163fed8 100644 --- a/src/doc/en/prep/Quickstarts/NumAnalysis.rst +++ b/src/doc/en/prep/Quickstarts/NumAnalysis.rst @@ -2,7 +2,7 @@ .. linkall -.. _quickstart-numerical-analysis: +.. _prep-quickstart-numerical-analysis: Sage Quickstart for Numerical Analysis ====================================== diff --git a/src/doc/en/prep/Quickstarts/Number-Theory.rst b/src/doc/en/prep/Quickstarts/Number-Theory.rst index eb63dca106d..5b1f73d8138 100644 --- a/src/doc/en/prep/Quickstarts/Number-Theory.rst +++ b/src/doc/en/prep/Quickstarts/Number-Theory.rst @@ -2,7 +2,7 @@ .. linkall -.. _quickstart-number-theory: +.. _prep-quickstart-number-theory: Sage Quickstart for Number Theory ================================= diff --git a/src/doc/en/prep/Quickstarts/Statistics-and-Distributions.rst b/src/doc/en/prep/Quickstarts/Statistics-and-Distributions.rst index 437898873f8..1192d8d84b9 100644 --- a/src/doc/en/prep/Quickstarts/Statistics-and-Distributions.rst +++ b/src/doc/en/prep/Quickstarts/Statistics-and-Distributions.rst @@ -2,7 +2,7 @@ .. linkall -.. _quickstart-statistics-and-distributions: +.. _prep-quickstart-statistics-and-distributions: Sage Quickstart for Statistics ============================== diff --git a/src/doc/en/prep/Symbolics-and-Basic-Plotting.rst b/src/doc/en/prep/Symbolics-and-Basic-Plotting.rst index f22d874812e..a7236d450d2 100644 --- a/src/doc/en/prep/Symbolics-and-Basic-Plotting.rst +++ b/src/doc/en/prep/Symbolics-and-Basic-Plotting.rst @@ -2,7 +2,7 @@ .. linkall -.. _symbolics-and-basic-plotting: +.. _prep-symbolics-and-basic-plotting: Tutorial for Symbolics and Plotting =================================== diff --git a/src/doc/en/prep/index.rst b/src/doc/en/prep/index.rst index 8cc6fb1bb11..33c3f3aaf26 100644 --- a/src/doc/en/prep/index.rst +++ b/src/doc/en/prep/index.rst @@ -3,7 +3,7 @@ You can adapt this file completely to your liking, but it should at least contain the root `toctree` directive. -.. _prep_tutorials: +.. _prep-tutorials: PREP Tutorials ============== From d4b7838d5c80190468797faabea032eb93f5690d Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Tue, 2 May 2017 22:27:21 +0100 Subject: [PATCH 203/452] removed lazy_imports with deprecations also cleaned up most deprecations, except sandlib; indeed, there is no direct equivalent for sandlib('gor'), used in tests --- src/sage/sandpiles/all.py | 7 ------ src/sage/sandpiles/sandpile.py | 46 +++++++++------------------------- 2 files changed, 12 insertions(+), 41 deletions(-) diff --git a/src/sage/sandpiles/all.py b/src/sage/sandpiles/all.py index 4e746e78966..380502025ee 100644 --- a/src/sage/sandpiles/all.py +++ b/src/sage/sandpiles/all.py @@ -4,10 +4,3 @@ from .sandpile import Sandpile, SandpileDivisor, SandpileConfig, firing_graph, parallel_firing_graph, wilmes_algorithm, random_digraph, random_DAG, triangle_sandpile lazy_import('sage.sandpiles.examples', 'sandpiles') - -lazy_import('sage.sandpiles.sandpile', 'sandlib', deprecation=(18618,'sandlib() will soon be removed. Use sandpile() instead.')) -lazy_import('sage.sandpiles.sandpile', 'grid_sandpile', deprecation=(18618,'grid_sandpile() will soon be removed. Use sandpile.Grid() instead.')) -lazy_import('sage.sandpiles.sandpile', 'complete_sandpile', deprecation=(18618,'complete_sandpile() will soon be removed. Use sandpile.Complete() instead.')) -lazy_import('sage.sandpiles.sandpile', 'firing_vector', deprecation=(18618,'firing_vector() will soon be removed. Use SandpileDivisor.is_linearly_equivalent() instead.')) - -lazy_import('sage.sandpiles.sandpile', ['admissible_partitions','partition_sandpile','min_cycles','glue_graphs','aztec_sandpile','triangle_sandpile'], deprecation=18618) diff --git a/src/sage/sandpiles/sandpile.py b/src/sage/sandpiles/sandpile.py index ea1762268a2..cf795672161 100644 --- a/src/sage/sandpiles/sandpile.py +++ b/src/sage/sandpiles/sandpile.py @@ -28,7 +28,7 @@ DEPRECATED -SandpileDivisor.linear_system, SandpileDivisor.r_of_D, sandlib method, complete_sandpile, grid_sandpile, triangle_sandpile, aztec_sandpile, random_digraph, random_tree, glue_graphs, admissible_partitions, firing_vector, min_cycles. +SandpileDivisor.linear_system, SandpileDivisor.r_of_D. MINOR CHANGES @@ -6203,10 +6203,8 @@ def sandlib(selector=None): EXAMPLES:: + sage: from sage.sandpiles.sandpile import sandlib sage: sandlib() - doctest:...: DeprecationWarning: sandlib() will soon be removed. Use sandpile() instead. - See http://trac.sagemath.org/18618 for details. - Sandpiles in the sandlib: kite : generic undirected graphs with 5 vertices generic : generic digraph with 6 vertices @@ -6302,10 +6300,8 @@ def triangle_sandpile(n): EXAMPLES:: + sage: from sage.sandpiles.sandpile import triangle_sandpile sage: T = triangle_sandpile(5) - doctest:...: DeprecationWarning: - Importing triangle_sandpile from here is deprecated. If you need to use it, please import it directly from sage.sandpiles.sandpile - See http://trac.sagemath.org/18618 for details. sage: T.group_order() 135418115000 """ @@ -6349,10 +6345,8 @@ def aztec_sandpile(n): EXAMPLES:: + sage: from sage.sandpiles.sandpile import aztec_sandpile sage: aztec_sandpile(2) - doctest:...: DeprecationWarning: - Importing aztec_sandpile from here is deprecated. If you need to use it, please import it directly from sage.sandpiles.sandpile - See http://trac.sagemath.org/18618 for details. {'sink': {(-3/2, -1/2): 2, (-3/2, 1/2): 2, (-1/2, -3/2): 2, @@ -6438,10 +6432,8 @@ def random_digraph(num_verts, p=0.5, directed=True, weight_max=1): EXAMPLES:: + sage: from sage.sandpiles.sandpile import random_digraph sage: g = random_digraph(6,0.2,True,3) - doctest:...: DeprecationWarning: random_digraph will be removed soon. Use any of the Random* methods - from graphs() and from digraphs() instead. - See http://trac.sagemath.org/18618 for details. sage: S = Sandpile(g,0) sage: S.show(edge_labels = True) @@ -6453,7 +6445,6 @@ def random_digraph(num_verts, p=0.5, directed=True, weight_max=1): sage: random_digraph(5) Digraph on 5 vertices """ - deprecation(18618,'random_digraph will be removed soon. Use any of the Random* methods from graphs() and from digraphs() instead.') a = digraphs.RandomDirectedGN(num_verts) b = graphs.RandomGNP(num_verts,p) a.add_edges(b.edges()) @@ -6547,16 +6538,12 @@ def glue_graphs(g, h, glue_g, glue_h): EXAMPLES:: + sage: from sage.sandpiles.sandpile import glue_graphs sage: x = {0: {}, 1: {0: 1}, 2: {0: 1, 1: 1}, 3: {0: 1, 1: 1, 2: 1}} sage: y = {0: {}, 1: {0: 2}, 2: {1: 2}, 3: {0: 1, 2: 1}} sage: glue_x = {1: 1, 3: 2} sage: glue_y = {0: 1, 1: 2, 3: 1} - sage: z = glue_graphs(x,y,glue_x,glue_y) - doctest:...: DeprecationWarning: - Importing glue_graphs from here is deprecated. If you need to use it, - please import it directly from sage.sandpiles.sandpile - See http://trac.sagemath.org/18618 for details. - sage: z + sage: z = glue_graphs(x,y,glue_x,glue_y); z {0: {}, 'x0': {0: 1, 'x1': 1, 'x3': 2, 'y1': 2, 'y3': 1}, 'x1': {'x0': 1}, @@ -6709,11 +6696,10 @@ def admissible_partitions(S, k): EXAMPLES:: + sage: from sage.sandpiles.sandpile import admissible_partitions + sage: from sage.sandpiles.sandpile import partition_sandpile sage: S = sandpiles.Cycle(4) sage: P = [admissible_partitions(S, i) for i in [2,3,4]] - doctest:...: DeprecationWarning: - Importing admissible_partitions from here is deprecated. If you need to use it, please import it directly from sage.sandpiles.sandpile - See http://trac.sagemath.org/18618 for details. sage: P [[{{0}, {1, 2, 3}}, {{0, 2, 3}, {1}}, @@ -6728,9 +6714,6 @@ def admissible_partitions(S, k): [{{0}, {1}, {2}, {3}}]] sage: for p in P: ....: sum([partition_sandpile(S, i).betti(verbose=False)[-1] for i in p]) - doctest:...: DeprecationWarning: - Importing partition_sandpile from here is deprecated. If you need to use it, please import it directly from sage.sandpiles.sandpile - See http://trac.sagemath.org/18618 for details. 6 8 3 @@ -6771,6 +6754,7 @@ def partition_sandpile(S, p): EXAMPLES:: + sage: from sage.sandpiles.sandpile import admissible_partitions, partition_sandpile sage: S = sandpiles.Cycle(4) sage: P = [admissible_partitions(S, i) for i in [2,3,4]] sage: for p in P: @@ -6816,14 +6800,11 @@ def firing_vector(S, D, E): EXAMPLES:: + sage: from sage.sandpiles.sandpile import firing_vector sage: S = sandpiles.Complete(4) sage: D = SandpileDivisor(S, {0: 0, 1: 0, 2: 8, 3: 0}) sage: E = SandpileDivisor(S, {0: 2, 1: 2, 2: 2, 3: 2}) sage: v = firing_vector(S, D, E) - doctest:...: DeprecationWarning: firing_vector() will soon be removed. Use SandpileDivisor.is_linearly_equivalent() instead. - See http://trac.sagemath.org/18618 for details. - doctest:...: DeprecationWarning: May 25, 2015: Replaced by SandpileDivisor.is_linearly_equivalent. - See http://trac.sagemath.org/18618 for details. sage: v (0, 0, 2, 0) @@ -6834,7 +6815,6 @@ def firing_vector(S, D, E): sage: firing_vector(S, D, S.zero_div()) Error. Are the divisors linearly equivalent? """ - deprecation(18618,'May 25, 2015: Replaced by SandpileDivisor.is_linearly_equivalent.') try: v = vector(D.values()) w = vector(E.values()) @@ -6859,11 +6839,9 @@ def min_cycles(G, v): EXAMPLES:: + sage: from sage.sandpiles.sandpile import min_cycles, sandlib sage: T = sandlib('gor') sage: [min_cycles(T, i) for i in T.vertices()] - doctest:...: DeprecationWarning: - Importing min_cycles from here is deprecated. If you need to use it, please import it directly from sage.sandpiles.sandpile - See http://trac.sagemath.org/18618 for details. [[], [[1, 3]], [[2, 3, 1], [2, 3]], [[3, 1], [3, 2]]] """ pr = G.neighbors_in(v) From ab7ca3ff21168dd65d06c81d1cf983d502df5a67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=2E=20Thi=C3=A9ry?= Date: Tue, 2 May 2017 17:38:42 -0400 Subject: [PATCH 204/452] 22931: Changed title (and intro) for the reference manual for consistency with the other documents --- src/doc/en/reference/index.rst | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/doc/en/reference/index.rst b/src/doc/en/reference/index.rst index e50991aa506..0f740f4533d 100644 --- a/src/doc/en/reference/index.rst +++ b/src/doc/en/reference/index.rst @@ -1,14 +1,13 @@ .. _reference-manual: -******** -Contents -******** - -Welcome to Sage's Reference Manual! - -This manual is a thematic index of all of `Sage's `_ -features. It also contains many examples that illustrate their use, all of them -systematically tested with each release. +**************** +Reference Manual +**************** + +Welcome to Sage's Reference Manual! It contains documentation for +(almost) all of `Sage's `_ features, each +illustrated with examples that are systematically tested with each +release. A thematic index is available below. Enjoy Sage! From 30610b440d0dda03fff897a7d4aee67ddbbada03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=2E=20Thi=C3=A9ry?= Date: Tue, 2 May 2017 17:51:12 -0400 Subject: [PATCH 205/452] 22931: Changed title (and intro) for the reference manual for consistency with the other documents (cont'd) --- src/doc/en/reference/index.rst | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/doc/en/reference/index.rst b/src/doc/en/reference/index.rst index 0f740f4533d..9554e151a80 100644 --- a/src/doc/en/reference/index.rst +++ b/src/doc/en/reference/index.rst @@ -1,15 +1,13 @@ .. _reference-manual: -**************** -Reference Manual -**************** - -Welcome to Sage's Reference Manual! It contains documentation for -(almost) all of `Sage's `_ features, each -illustrated with examples that are systematically tested with each -release. A thematic index is available below. - -Enjoy Sage! +************************************ +Welcome to the Sage Reference Manual +************************************ + +This manual contains documentation for (almost) all of `Sage's +`_ features, each illustrated with examples +that are systematically tested with each release. A thematic index is +available below. User Interface ============== From 58408447206956771a85f92e0b73d89dbd1041e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=2E=20Thi=C3=A9ry?= Date: Tue, 2 May 2017 17:51:24 -0400 Subject: [PATCH 206/452] 22931: added one crossref for illustration purposes --- src/doc/en/prep/Symbolics-and-Basic-Plotting.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/en/prep/Symbolics-and-Basic-Plotting.rst b/src/doc/en/prep/Symbolics-and-Basic-Plotting.rst index a7236d450d2..e8e74915cfd 100644 --- a/src/doc/en/prep/Symbolics-and-Basic-Plotting.rst +++ b/src/doc/en/prep/Symbolics-and-Basic-Plotting.rst @@ -488,6 +488,6 @@ We close this tutorial with a cool plot that we define *implicitly* as a Graphics3d Object The next tutorial will use all that you have learned about Sage basics, -symbolics, and plotting in a specific mathematical venue \- the calculus -sequence! +symbolics, and plotting in a specific mathematical venue \- the +:ref:`calculus sequence `! From f86a9105329748f287ac5c888e05a74424dae1e9 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Wed, 3 May 2017 00:12:59 +0100 Subject: [PATCH 207/452] removed previously deprecated firing_vector and random_digraph --- src/sage/sandpiles/all.py | 2 +- src/sage/sandpiles/sandpile.py | 91 ---------------------------------- 2 files changed, 1 insertion(+), 92 deletions(-) diff --git a/src/sage/sandpiles/all.py b/src/sage/sandpiles/all.py index 380502025ee..ea997043368 100644 --- a/src/sage/sandpiles/all.py +++ b/src/sage/sandpiles/all.py @@ -1,6 +1,6 @@ from __future__ import absolute_import from sage.misc.lazy_import import lazy_import -from .sandpile import Sandpile, SandpileDivisor, SandpileConfig, firing_graph, parallel_firing_graph, wilmes_algorithm, random_digraph, random_DAG, triangle_sandpile +from .sandpile import Sandpile, SandpileDivisor, SandpileConfig, firing_graph, parallel_firing_graph, wilmes_algorithm, random_DAG, triangle_sandpile lazy_import('sage.sandpiles.examples', 'sandpiles') diff --git a/src/sage/sandpiles/sandpile.py b/src/sage/sandpiles/sandpile.py index cf795672161..d49850317cf 100644 --- a/src/sage/sandpiles/sandpile.py +++ b/src/sage/sandpiles/sandpile.py @@ -6409,57 +6409,6 @@ def aztec_sandpile(n): aztec_sandpile['sink'][vert] = out_degree return aztec_sandpile -def random_digraph(num_verts, p=0.5, directed=True, weight_max=1): - """ - A random weighted digraph with a directed spanning tree rooted at `0`. If - ``directed = False``, the only difference is that if `(i,j,w)` is an edge with - tail `i`, head `j`, and weight `w`, then `(j,i,w)` appears also. The result - is returned as a Sage digraph. - - INPUT: - - - ``num_verts`` -- number of vertices - - - ``p`` -- (default: 0.5) probability edges occur - - - ``directed`` -- (default: ``True``) if directed - - - ``weight_max`` -- (default: 1) integer maximum for random weights - - OUTPUT: - - random graph - - EXAMPLES:: - - sage: from sage.sandpiles.sandpile import random_digraph - sage: g = random_digraph(6,0.2,True,3) - sage: S = Sandpile(g,0) - sage: S.show(edge_labels = True) - - TESTS: - - Check that we can construct a random digraph with the - default arguments (:trac:`12181`):: - - sage: random_digraph(5) - Digraph on 5 vertices - """ - a = digraphs.RandomDirectedGN(num_verts) - b = graphs.RandomGNP(num_verts,p) - a.add_edges(b.edges()) - if directed: - c = graphs.RandomGNP(num_verts,p) - # reverse the edges of c and add them in - a.add_edges([(j,i,None) for i,j,k in c.edges()]) - else: - a.add_edges([(j,i,None) for i,j,k in a.edges()]) - a.add_edges([(j,i,None) for i,j,k in b.edges()]) - # now handle the weights - for i,j,k in a.edge_iterator(): - a.set_edge_label(i,j,ZZ.random_element(weight_max)+1) - return a - def random_DAG(num_verts, p=0.5, weight_max=1): r""" A random directed acyclic graph with ``num_verts`` vertices. @@ -6783,46 +6732,6 @@ def partition_sandpile(S, p): if S.sink() in i: return Sandpile(g,i) -def firing_vector(S, D, E): - r""" - If `D` and `E` are linearly equivalent divisors, find the firing vector - taking `D` to `E`. - - INPUT: - - - ``S`` -- Sandpile - - - ``D``, ``E`` -- tuples (representing linearly equivalent divisors) - - OUTPUT: - - tuple (representing a firing vector from ``D`` to ``E``) - - EXAMPLES:: - - sage: from sage.sandpiles.sandpile import firing_vector - sage: S = sandpiles.Complete(4) - sage: D = SandpileDivisor(S, {0: 0, 1: 0, 2: 8, 3: 0}) - sage: E = SandpileDivisor(S, {0: 2, 1: 2, 2: 2, 3: 2}) - sage: v = firing_vector(S, D, E) - sage: v - (0, 0, 2, 0) - - The divisors must be linearly equivalent:: - - sage: vector(D.values()) - S.laplacian()*vector(v) == vector(E.values()) - True - sage: firing_vector(S, D, S.zero_div()) - Error. Are the divisors linearly equivalent? - """ - try: - v = vector(D.values()) - w = vector(E.values()) - return tuple(S.laplacian().solve_left(v-w)) - except ValueError: - print("Error. Are the divisors linearly equivalent?") - return - def min_cycles(G, v): r""" Minimal length cycles in the digraph `G` starting at vertex `v`. From 81e89598c69e6f3affe099e2958e8f9c47c9a398 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Wed, 3 May 2017 00:17:02 +0100 Subject: [PATCH 208/452] fix a typo in a message --- src/sage/sandpiles/examples.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/sandpiles/examples.py b/src/sage/sandpiles/examples.py index 3e8c158898b..eb38b711700 100644 --- a/src/sage/sandpiles/examples.py +++ b/src/sage/sandpiles/examples.py @@ -65,11 +65,11 @@ def __call__(self): EXAMPLES:: sage: sandpiles() - Try sandpile.FOO() where FOO is in the list: + Try sandpiles.FOO() where FOO is in the list: Complete, Cycle, Diamond, Fan, Grid, House, Wheel """ - print('Try sandpile.FOO() where FOO is in the list:\n') + print('Try sandpiles.FOO() where FOO is in the list:\n') print(" " + ", ".join([str(i) for i in dir(sandpiles) if i[0] != '_'])) From a962ee3fc6405a5915da98048f9120980e29dc95 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 2 May 2017 20:22:54 -0500 Subject: [PATCH 209/452] Simple doc fixes and renaming free_module -> module. --- src/sage/homology/hochschild_complex.py | 98 ++++++++++++++++--------- 1 file changed, 63 insertions(+), 35 deletions(-) diff --git a/src/sage/homology/hochschild_complex.py b/src/sage/homology/hochschild_complex.py index cbbe859b392..e8579947801 100644 --- a/src/sage/homology/hochschild_complex.py +++ b/src/sage/homology/hochschild_complex.py @@ -22,6 +22,8 @@ from sage.combinat.free_module import CombinatorialFreeModule from sage.homology.chain_complex import ChainComplex, Chain_class +from sage.misc.superseded import deprecated_function_alias + class HochschildComplex(UniqueRepresentation, Parent): r""" The Hochschild complex. @@ -96,8 +98,6 @@ def __init__(self, A, M): sage: H in ChainComplexes(QQ) True - Some methods required by the category are not implemented:: - sage: TestSuite(H).run() """ self._A = A @@ -164,21 +164,21 @@ def coefficients(self): """ return self._M - def free_module(self, d): + def module(self, d): """ - Return the free module in degree ``d``. + Return the module in degree ``d``. EXAMPLES:: sage: SGA = SymmetricGroupAlgebra(QQ, 3) sage: T = SGA.trivial_representation() sage: H = SGA.hochschild_complex(T) - sage: H.free_module(0) + sage: H.module(0) Trivial representation of Standard permutations of 3 over Rational Field - sage: H.free_module(1) + sage: H.module(1) Trivial representation of Standard permutations of 3 over Rational Field # Symmetric group algebra of order 3 over Rational Field - sage: H.free_module(2) + sage: H.module(2) Trivial representation of Standard permutations of 3 over Rational Field # Symmetric group algebra of order 3 over Rational Field # Symmetric group algebra of order 3 over Rational Field @@ -187,6 +187,8 @@ def free_module(self, d): raise ValueError("only defined for non-negative degree") return tensor([self._M] + [self._A]*d) + free_module = deprecated_function_alias(21386, module) + @cached_method def trivial_module(self): """ @@ -240,8 +242,8 @@ def boundary(self, d): ....: phi = H.boundary(n) ....: psi = H.boundary(n+1) ....: comp = phi * psi - ....: zero = H.free_module(n-1).zero() - ....: return all(comp(b) == zero for b in H.free_module(n+1).basis()) + ....: zero = H.module(n-1).zero() + ....: return all(comp(b) == zero for b in H.module(n+1).basis()) sage: SGA = SymmetricGroupAlgebra(QQ, 3) sage: H = SGA.hochschild_complex(SGA) @@ -266,9 +268,9 @@ def boundary(self, d): if d == 0: t = self.trivial_module() zero = t.zero() - return self.free_module(0).module_morphism(lambda x: zero, codomain=t) - Fd = self.free_module(d-1) - Fd1 = self.free_module(d) + return self.module(0).module_morphism(lambda x: zero, codomain=t) + Fd = self.module(d-1) + Fd1 = self.module(d) mone = -one def on_basis(k): p = self._M.monomial(k[0]) * self._A.monomial(k[1]) @@ -320,8 +322,8 @@ def coboundary(self, d): ....: phi = H.coboundary(n) ....: psi = H.coboundary(n+1) ....: comp = psi * phi - ....: zero = H.free_module(n+1).zero() - ....: return all(comp(b) == zero for b in H.free_module(n-1).basis()) + ....: zero = H.module(n+1).zero() + ....: return all(comp(b) == zero for b in H.module(n-1).basis()) sage: SGA = SymmetricGroupAlgebra(QQ, 3) sage: H = SGA.hochschild_complex(SGA) @@ -466,11 +468,11 @@ def _element_constructor_(self, vectors): Trivial chain sage: H(x+2*y) Chain(0: x + 2*y) - sage: H({0: H.free_module(0).an_element()}) + sage: H({0: H.module(0).an_element()}) Chain(0: 2 + 2*x + 3*y) - sage: H({2: H.free_module(2).an_element()}) + sage: H({2: H.module(2).an_element()}) Chain(2: 2*1 # 1 # 1 + 2*1 # 1 # x + 3*1 # 1 # y) - sage: H({0:x-y, 2: H.free_module(2).an_element()}) + sage: H({0:x-y, 2: H.module(2).an_element()}) Chain with 2 nonzero terms over Rational Field """ if not vectors: # special case: the zero chain @@ -478,7 +480,7 @@ def _element_constructor_(self, vectors): # special case: an element of the defining module if isinstance(vectors, self._M.element_class) and vectors.parent() is self._M: mc = vectors.monomial_coefficients(copy=False) - vec = self.free_module(0)._from_dict({(k,): mc[k] for k in mc}) + vec = self.module(0)._from_dict({(k,): mc[k] for k in mc}) return self.element_class(self, {0: vec}) if isinstance(vectors, (Chain_class, self.element_class)): vectors = vectors._vec @@ -489,11 +491,11 @@ def _element_constructor_(self, vectors): vec = vectors.pop(0) if vec.parent() is self._M: mc = vec.monomial_coefficients(copy=False) - data[0] = self.free_module(0)._from_dict({(k,): mc[k] for k in mc}) + data[0] = self.module(0)._from_dict({(k,): mc[k] for k in mc}) else: - data[0] = self.free_module(0)(vec) + data[0] = self.module(0)(vec) for degree in vectors: - vec = self.free_module(degree)(vectors[degree]) + vec = self.module(degree)(vectors[degree]) if not vec: continue data[degree] = vec @@ -517,10 +519,36 @@ def _an_element_(self): 0, 0] """ - return self.element_class(self, {d: self.free_module(d).an_element() + return self.element_class(self, {d: self.module(d).an_element() for d in range(4)}) class Element(ModuleElement): + """ + A chain of the Hochschild complex. + + EXAMPLES:: + + sage: SGA = SymmetricGroupAlgebra(QQ, 3) + sage: T = SGA.trivial_representation() + sage: H = SGA.hochschild_complex(T) + sage: H(T.an_element()) + Chain(0: 2*B['v']) + sage: H({0: T.an_element()}) + Chain(0: 2*B['v']) + sage: H({1: H.module(1).an_element()}) + Chain(1: 2*B['v'] # [1, 2, 3] + 2*B['v'] # [1, 3, 2] + 3*B['v'] # [2, 1, 3]) + sage: H({0: H.module(0).an_element(), 3: H.module(3).an_element()}) + Chain with 2 nonzero terms over Rational Field + + sage: F. = FreeAlgebra(ZZ) + sage: H = F.hochschild_complex(F) + sage: H(x + 2*y^2) + Chain(0: F[x] + 2*F[y^2]) + sage: H({0: x*y - x}) + Chain(0: -F[x] + F[x*y]) + sage: H({0: x-y, 2: H.module(2).basis().an_element()}) + Chain with 2 nonzero terms over Integer Ring + """ def __init__(self, parent, vectors): """ Initialize ``self``. @@ -529,7 +557,7 @@ def __init__(self, parent, vectors): sage: F. = FreeAlgebra(ZZ) sage: H = F.hochschild_complex(F) - sage: a = H({0: x-y, 2: H.free_module(2).basis().an_element()}) + sage: a = H({0: x-y, 2: H.module(2).basis().an_element()}) sage: TestSuite(a).run() """ self._vec = vectors @@ -543,14 +571,14 @@ def vector(self, degree): sage: F. = FreeAlgebra(ZZ) sage: H = F.hochschild_complex(F) - sage: a = H({0: x-y, 2: H.free_module(2).basis().an_element()}) + sage: a = H({0: x-y, 2: H.module(2).basis().an_element()}) sage: [a.vector(i) for i in range(3)] [F[x] - F[y], 0, F[1] # F[1] # F[1]] """ try: return self._vec[degree] except KeyError: - return self.parent().free_module(degree).zero() + return self.parent().module(degree).zero() def _repr_(self): """ @@ -564,9 +592,9 @@ def _repr_(self): Trivial chain sage: H(x+2*y) Chain(0: x + 2*y) - sage: H({2: H.free_module(2).an_element()}) + sage: H({2: H.module(2).an_element()}) Chain(2: 2*1 # 1 # 1 + 2*1 # 1 # x + 3*1 # 1 # y) - sage: H({0:x-y, 2: H.free_module(2).an_element()}) + sage: H({0:x-y, 2: H.module(2).an_element()}) Chain with 2 nonzero terms over Rational Field """ n = len(self._vec) @@ -592,8 +620,8 @@ def _ascii_art_(self): sage: F. = FreeAlgebra(ZZ) sage: H = F.hochschild_complex(F) sage: a = H({0: x - y, - ....: 1: H.free_module(1).basis().an_element(), - ....: 2: H.free_module(2).basis().an_element()}) + ....: 1: H.module(1).basis().an_element(), + ....: 2: H.module(2).basis().an_element()}) sage: ascii_art(a) d_0 d_1 d_2 d_3 0 <---- F - F <---- 1 # 1 <---- 1 # 1 # 1 <---- 0 @@ -627,8 +655,8 @@ def _add_(self, other): sage: F. = FreeAlgebra(ZZ) sage: H = F.hochschild_complex(F) sage: a = H({0: x - y, - ....: 1: H.free_module(1).basis().an_element(), - ....: 2: H.free_module(2).basis().an_element()}) + ....: 1: H.module(1).basis().an_element(), + ....: 2: H.module(2).basis().an_element()}) sage: [a.vector(i) for i in range(3)] [F[x] - F[y], F[1] # F[1], F[1] # F[1] # F[1]] sage: [H.an_element().vector(i) for i in range(3)] @@ -662,8 +690,8 @@ def _lmul_(self, scalar): sage: F. = FreeAlgebra(ZZ) sage: H = F.hochschild_complex(F) sage: a = H({0: x - y, - ....: 1: H.free_module(1).basis().an_element(), - ....: 2: H.free_module(2).basis().an_element()}) + ....: 1: H.module(1).basis().an_element(), + ....: 2: H.module(2).basis().an_element()}) sage: v = 3*a sage: [v.vector(i) for i in range(3)] [3*F[x] - 3*F[y], 3*F[1] # F[1], 3*F[1] # F[1] # F[1]] @@ -686,8 +714,8 @@ def _richcmp_(self, other, op): sage: F. = FreeAlgebra(ZZ) sage: H = F.hochschild_complex(F) sage: a = H({0: x - y, - ....: 1: H.free_module(1).basis().an_element(), - ....: 2: H.free_module(2).basis().an_element()}) + ....: 1: H.module(1).basis().an_element(), + ....: 2: H.module(2).basis().an_element()}) sage: a == 3*a False sage: a + a == 2*a From d4bc6c8ce967ffcc4c55ca1952248c0fd9656e58 Mon Sep 17 00:00:00 2001 From: Bruno Grenet Date: Wed, 3 May 2017 10:07:32 +0200 Subject: [PATCH 210/452] 22910: Docstring fixes --- src/sage/rings/polynomial/plural.pyx | 2 +- src/sage/rings/polynomial/polynomial_quotient_ring.py | 6 +++--- src/sage/rings/ring.pyx | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sage/rings/polynomial/plural.pyx b/src/sage/rings/polynomial/plural.pyx index eec261aaefc..525dd2462b2 100644 --- a/src/sage/rings/polynomial/plural.pyx +++ b/src/sage/rings/polynomial/plural.pyx @@ -649,7 +649,7 @@ cdef class NCPolynomialRing_plural(Ring): TESTS: - Make the method accept additional parameters, such as the flag `proof`. + Make the method accept additional parameters, such as the flag ``proof``. See :trac:`22910`:: sage: P.is_field(proof=False) diff --git a/src/sage/rings/polynomial/polynomial_quotient_ring.py b/src/sage/rings/polynomial/polynomial_quotient_ring.py index 504263471ce..71db491b116 100644 --- a/src/sage/rings/polynomial/polynomial_quotient_ring.py +++ b/src/sage/rings/polynomial/polynomial_quotient_ring.py @@ -824,9 +824,9 @@ def is_field(self, proof = True): sage: S.is_field() True - If proof is True, requires the `is_irreducible` method of the modulus to - be implemented:: - + If proof is ``True``, requires the ``is_irreducible`` method of the + modulus to be implemented:: + sage: R1. = GF(5)[] sage: F1 = R1.quotient_ring(x^2+x+1) sage: R2. = F1[] diff --git a/src/sage/rings/ring.pyx b/src/sage/rings/ring.pyx index 15ed9bee00c..383935431f4 100644 --- a/src/sage/rings/ring.pyx +++ b/src/sage/rings/ring.pyx @@ -995,7 +995,7 @@ cdef class Ring(ParentWithGens): ... NotImplementedError - Forward the proof flag to `is_field`, see :trac:`22910`:: + Forward the proof flag to ``is_field``, see :trac:`22910`:: sage: R1. = GF(5)[] sage: F1 = R1.quotient_ring(x^2+x+1) From 86e541d7697cb0bdc2b4ecbe7c3fc4bec7a26816 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 3 May 2017 10:30:34 +0200 Subject: [PATCH 211/452] trac 18303 fix failing doctests --- src/sage/geometry/polyhedron/backend_field.py | 8 ++++---- src/sage/schemes/projective/projective_morphism.py | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sage/geometry/polyhedron/backend_field.py b/src/sage/geometry/polyhedron/backend_field.py index ca49decf889..7aac890ba42 100644 --- a/src/sage/geometry/polyhedron/backend_field.py +++ b/src/sage/geometry/polyhedron/backend_field.py @@ -210,9 +210,9 @@ def _init_Vrepresentation_backend(self, Vrep): An inequality (-0.1419794359520263?, -1.698172434277148?) x + 1.200789243901438? >= 0, An inequality (0.3001973109753594?, 0.600394621950719?) x - 0.4245431085692869? >= 0) sage: p.Vrepresentation() - (A vertex at (0, 0.7071067811865475?), + (A vertex at (0.?e-15, 0.707106781186548?), A vertex at (1.414213562373095?, 0), - A vertex at (4, 0.372677996249965?)) + A vertex at (4.000000000000000?, 0.372677996249965?)) """ self._Vrepresentation = [] parent = self.parent() @@ -237,9 +237,9 @@ def _init_Hrepresentation_backend(self, Hrep): An inequality (-0.1419794359520263?, -1.698172434277148?) x + 1.200789243901438? >= 0, An inequality (0.3001973109753594?, 0.600394621950719?) x - 0.4245431085692869? >= 0) sage: p.Vrepresentation() - (A vertex at (0, 0.7071067811865475?), + (A vertex at (0.?e-15, 0.707106781186548?), A vertex at (1.414213562373095?, 0), - A vertex at (4, 0.372677996249965?)) + A vertex at (4.000000000000000?, 0.372677996249965?)) """ self._Hrepresentation = [] parent = self.parent() diff --git a/src/sage/schemes/projective/projective_morphism.py b/src/sage/schemes/projective/projective_morphism.py index 2b78e621507..0b3a76726fd 100644 --- a/src/sage/schemes/projective/projective_morphism.py +++ b/src/sage/schemes/projective/projective_morphism.py @@ -3597,7 +3597,7 @@ def multiplier_spectra(self, n, formal=True, embedding=None): sage: f = H([x^2 - w/4*y^2, y^2]) sage: f.multiplier_spectra(2, False, embedding=K.embeddings(QQbar)[0]) [0, - 5.931851652578137? + 0.?e-49*I, + 5.931851652578137? + 0.?e-47*I, 0.0681483474218635? - 1.930649271699173?*I, 0.0681483474218635? + 1.930649271699173?*I] From f1a684897f6a2305e4b44c4ec190a7193c205f44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 3 May 2017 10:44:57 +0200 Subject: [PATCH 212/452] trac 18303 one typo --- 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 dc8e53931a7..7d20602ba61 100644 --- a/src/sage/rings/qqbar.py +++ b/src/sage/rings/qqbar.py @@ -2072,7 +2072,7 @@ def cmp_elements_with_same_minpoly(a, b, p): - ``a`` and ``b`` -- elements of the algebraic or the real algebraic field with same minimal polynomial - - ``p`` -- the minmial polynomial + - ``p`` -- the minimal polynomial OUTPUT: From 58ff8a20916adf6482e2cde50e2398987d80fc22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 3 May 2017 17:31:05 +0200 Subject: [PATCH 213/452] trac 22815 remove one call to cmp --- .../groups/perm_gps/symgp_conjugacy_class.py | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/src/sage/groups/perm_gps/symgp_conjugacy_class.py b/src/sage/groups/perm_gps/symgp_conjugacy_class.py index e5272d56ffe..65673006106 100644 --- a/src/sage/groups/perm_gps/symgp_conjugacy_class.py +++ b/src/sage/groups/perm_gps/symgp_conjugacy_class.py @@ -16,6 +16,7 @@ from sage.sets.set import Set import itertools + class SymmetricGroupConjugacyClassMixin(object): r""" Mixin class which contains methods for conjugacy classes of @@ -51,7 +52,7 @@ def _repr_(self): """ return "Conjugacy class of cycle type %s in %s"%(self._part, self._parent) - def __cmp__(self, other): + def __eq__(self, other): r""" Comparison of conjugacy classes is done by comparing the defining cycle types. @@ -65,10 +66,24 @@ def __cmp__(self, other): sage: C == Cp True """ - c = cmp(type(self), type(other)) - if c: - return c - return cmp(self._part, other._part) + if not isinstance(other, SymmetricGroupConjugacyClassMixin): + return False + return self._part == other._part + + def __ne__(self, other): + """ + Test for unequality. + + EXAMPLES:: + + sage: G = SymmetricGroup(5) + sage: g = G([(1,3), (2,4,5)]) + sage: C = G.conjugacy_class(Partition([3,2])) + sage: Cp = G.conjugacy_class(g) + sage: C != Cp + False + """ + return not (self == other) def partition(self): """ @@ -82,6 +97,7 @@ def partition(self): """ return self._part + class SymmetricGroupConjugacyClass(SymmetricGroupConjugacyClassMixin, ConjugacyClassGAP): """ A conjugacy class of the symmetric group. From aa9f25855b6d72f7010c2f6241f0737d306b7237 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 3 May 2017 10:48:30 -0500 Subject: [PATCH 214/452] Fixing integral points for a non-empty polytope with trivial integral hull. --- src/sage/geometry/polyhedron/backend_normaliz.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/sage/geometry/polyhedron/backend_normaliz.py b/src/sage/geometry/polyhedron/backend_normaliz.py index 6c29099d45f..1380cb22778 100644 --- a/src/sage/geometry/polyhedron/backend_normaliz.py +++ b/src/sage/geometry/polyhedron/backend_normaliz.py @@ -551,6 +551,20 @@ def integral_points(self, threshold=10000): sage: P = Polyhedron([[]], backend='normaliz') # optional - pynormaliz sage: P.integral_points() # optional - pynormaliz ((),) + + A polytope with no integral points (:trac:`22938`):: + + sage: ieqs = [[1, 2, -1, 0], [0, -1, 2, -1], [0, 0, -1, 2], + ....: [0, -1, 0, 0], [0, 0, -1, 0], [0, 0, 0, -1], + ....: [-1, -1, -1, -1], [1, 1, 0, 0], [1, 0, 1, 0], + ....: [1, 0, 0, 1]] + sage: P = Polyhedron(ieqs=ieqs, backend='normaliz') # optional - pynormaliz + sage: P.bounding_box() # optional - pynormaliz + ((-3/4, -1/2, -1/4), (-1/2, -1/4, 0)) + sage: P.bounding_box(integral_hull=True) # optional - pynormaliz + (None, None) + sage: P.integral_points() # optional - pynormaliz + () """ import PyNormaliz if not self.is_compact(): @@ -567,6 +581,8 @@ def integral_points(self, threshold=10000): # for small bounding boxes, it is faster to naively iterate over the points of the box if threshold > 1: box_min, box_max = self.bounding_box(integral_hull=True) + if box_min is None: + return () box_points = prod(max_coord-min_coord+1 for min_coord, max_coord in zip(box_min, box_max)) if box_points Date: Wed, 3 May 2017 11:04:18 -0500 Subject: [PATCH 215/452] Fixing bad latex code. --- src/sage/combinat/crystals/mv_polytopes.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/crystals/mv_polytopes.py b/src/sage/combinat/crystals/mv_polytopes.py index 35cc0e1fab9..7a0729f036b 100644 --- a/src/sage/combinat/crystals/mv_polytopes.py +++ b/src/sage/combinat/crystals/mv_polytopes.py @@ -259,7 +259,7 @@ class MVPolytopes(PBWCrystal): \langle \alpha, \gamma \rangle \geq M_{\gamma} \text{ for all } \gamma \in \Gamma \}. - The vertices `\(\mu_w\)_{w \in W}` are given by + The vertices `\{\mu_w\}_{w \in W}` are given by .. MATH:: @@ -280,7 +280,7 @@ class MVPolytopes(PBWCrystal): \\ \mu_{w_k} - \mu_{w_{k-1}} & = n_k w_{k-1} \alpha_{i_k}, \end{aligned} - where `w_k = s_{i_1} \cdots s_{i_k}` and `(a_{ji)` is the Cartan matrix. + where `w_k = s_{i_1} \cdots s_{i_k}` and `(a_{ji})` is the Cartan matrix. MV polytopes have a crystal structure that corresponds to the crystal structure, which is isomorphic to `\mathcal{B}(\infty)` From 99113f1d434a846d322100a919023c3437c551ad Mon Sep 17 00:00:00 2001 From: Vincent Delecroix <20100.delecroix@gmail.com> Date: Wed, 3 May 2017 18:11:32 +0200 Subject: [PATCH 216/452] trac 18303: bool vs nonzero + doc --- src/sage/rings/qqbar.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/sage/rings/qqbar.py b/src/sage/rings/qqbar.py index 7d20602ba61..0502086cd0c 100644 --- a/src/sage/rings/qqbar.py +++ b/src/sage/rings/qqbar.py @@ -3104,7 +3104,7 @@ def __hash__(self): else: return hash((self + QQbar_hash_offset).interval_exact(CIF)) - def __nonzero__(self): + def __bool__(self): """ Check whether ``self`` is nonzero. @@ -3155,7 +3155,7 @@ def __nonzero__(self): sage: bool(p1 - p2 + p3 - p4 - 8 * QQbar.zeta(15)**8) False - The following are non-trivially zeros (though no exactification occur):: + Test some non-trivial zeros:: sage: x = polygen(ZZ) sage: a = (AA(2).sqrt() + AA(3).sqrt() + AA(5).sqrt())^2 @@ -3187,7 +3187,7 @@ def __nonzero__(self): if not self._value.contains_zero(): return True elif self._value.is_zero(): - if not type(self._descr) is ANRational: + if not isinstance(self._descr, ANRational): self._set_descr(ANRational(QQ.zero())) return False @@ -3242,6 +3242,8 @@ def __nonzero__(self): self.exactify() return bool(self) + __nonzero__ = __bool__ + def is_square(self): """ Return whether or not this number is square. From a44343c8726bfcc8ecdec5f0ac159d4e44ddf81a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 3 May 2017 20:56:06 +0200 Subject: [PATCH 217/452] fixing a typo --- src/sage/symbolic/expression.pyx | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 314317ae7d6..a0a51d7a391 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -9481,8 +9481,6 @@ cdef class Expression(CommutativeRingElement): else: return self - - def simplify_real(self): r""" Simplify the given expression over the real numbers. This allows @@ -9791,7 +9789,7 @@ cdef class Expression(CommutativeRingElement): TESTS: - Check that the problem with applying `full_simplify()` to gamma + Check that the problem with applying ``full_simplify()`` to gamma functions (:trac:`9240`) has been fixed:: sage: gamma(1/3) From 35d3fb325ffd6bef4d93e62bd1cd513e3428215d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 3 May 2017 21:38:01 +0200 Subject: [PATCH 218/452] another little typo --- src/sage/rings/polynomial/multi_polynomial_sequence.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/sage/rings/polynomial/multi_polynomial_sequence.py b/src/sage/rings/polynomial/multi_polynomial_sequence.py index f872cd0c3f9..c66c9d01529 100644 --- a/src/sage/rings/polynomial/multi_polynomial_sequence.py +++ b/src/sage/rings/polynomial/multi_polynomial_sequence.py @@ -267,8 +267,8 @@ def PolynomialSequence(arg1, arg2=None, immutable=False, cr=False, cr_str=None): TESTS: - A PolynomialSequence can exist with elements in a infinite field of - characteristic 2 that is not (see :trac:`19452`):: + A PolynomialSequence can exist with elements in an infinite field of + characteristic 2 (see :trac:`19452`):: sage: from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence sage: F = GF(2) @@ -277,7 +277,6 @@ def PolynomialSequence(arg1, arg2=None, immutable=False, cr=False, cr_str=None): sage: PolynomialSequence([0], R) [0] """ - from sage.matrix.matrix import is_Matrix from sage.rings.polynomial.pbori import BooleanMonomialMonoid, BooleanMonomial From e337da411113eb62eda31e7e19388bc5b76851e2 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 3 May 2017 20:55:20 -0500 Subject: [PATCH 219/452] Adding some more documentation and allowing coercion to the coefficient module. --- src/sage/homology/hochschild_complex.py | 26 ++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/src/sage/homology/hochschild_complex.py b/src/sage/homology/hochschild_complex.py index e8579947801..bd5f04b703a 100644 --- a/src/sage/homology/hochschild_complex.py +++ b/src/sage/homology/hochschild_complex.py @@ -15,7 +15,7 @@ from sage.misc.cachefunc import cached_method from sage.structure.unique_representation import UniqueRepresentation from sage.structure.parent import Parent -from sage.structure.element import ModuleElement +from sage.structure.element import ModuleElement, parent from sage.structure.sage_object import richcmp from sage.categories.category_types import ChainComplexes from sage.categories.tensor import tensor @@ -466,6 +466,8 @@ def _element_constructor_(self, vectors): sage: H = E.hochschild_complex(E) sage: H(0) Trivial chain + sage: H(2) + Chain(0: 2) sage: H(x+2*y) Chain(0: x + 2*y) sage: H({0: H.module(0).an_element()}) @@ -474,22 +476,30 @@ def _element_constructor_(self, vectors): Chain(2: 2*1 # 1 # 1 + 2*1 # 1 # x + 3*1 # 1 # y) sage: H({0:x-y, 2: H.module(2).an_element()}) Chain with 2 nonzero terms over Rational Field + sage: H([2]) + Traceback (most recent call last): + ... + ValueError: cannot construct an element from [2] """ if not vectors: # special case: the zero chain return self.element_class(self, {}) # special case: an element of the defining module - if isinstance(vectors, self._M.element_class) and vectors.parent() is self._M: + if self._M.has_coerce_map_from(parent(vectors)): + vectors = self._M(vectors) + if parent(vectors) is self._M: mc = vectors.monomial_coefficients(copy=False) vec = self.module(0)._from_dict({(k,): mc[k] for k in mc}) return self.element_class(self, {0: vec}) if isinstance(vectors, (Chain_class, self.element_class)): vectors = vectors._vec data = dict() + if not isinstance(vectors, dict): + raise ValueError("cannot construct an element from {}".format(vectors)) # Special handling for the 0 free module # FIXME: Allow coercions between the 0 free module and the defining module if 0 in vectors: vec = vectors.pop(0) - if vec.parent() is self._M: + if parent(vec) is self._M: mc = vec.monomial_coefficients(copy=False) data[0] = self.module(0)._from_dict({(k,): mc[k] for k in mc}) else: @@ -526,6 +536,14 @@ class Element(ModuleElement): """ A chain of the Hochschild complex. + INPUT: + + Can be one of the following: + + - A dictionary whose keys are the degree and whose `d`-th + value is an element in the degree `d` module. + - An element in the coefficient module `M`. + EXAMPLES:: sage: SGA = SymmetricGroupAlgebra(QQ, 3) @@ -546,6 +564,8 @@ class Element(ModuleElement): Chain(0: F[x] + 2*F[y^2]) sage: H({0: x*y - x}) Chain(0: -F[x] + F[x*y]) + sage: H(2) + Chain(0: 2*F[1]) sage: H({0: x-y, 2: H.module(2).basis().an_element()}) Chain with 2 nonzero terms over Integer Ring """ From 4ea51346546103ed01d7d64f6b93645082caff00 Mon Sep 17 00:00:00 2001 From: Daniel Krenn Date: Thu, 4 May 2017 07:45:12 +0200 Subject: [PATCH 220/452] Trac #22944: remove experimental-decorator --- .../asymptotic_expansion_generators.py | 17 ---------------- src/sage/rings/asymptotic/asymptotic_ring.py | 20 ------------------- src/sage/rings/asymptotic/growth_group.py | 20 ------------------- .../asymptotic/growth_group_cartesian.py | 15 -------------- src/sage/rings/asymptotic/misc.py | 1 - src/sage/rings/asymptotic/term_monoid.py | 18 ----------------- 6 files changed, 91 deletions(-) diff --git a/src/sage/rings/asymptotic/asymptotic_expansion_generators.py b/src/sage/rings/asymptotic/asymptotic_expansion_generators.py index ce474cf83da..0b87be89c8b 100644 --- a/src/sage/rings/asymptotic/asymptotic_expansion_generators.py +++ b/src/sage/rings/asymptotic/asymptotic_expansion_generators.py @@ -1,23 +1,6 @@ r""" Common Asymptotic Expansions -.. WARNING:: - - As this code is experimental, a warning is thrown when an - asymptotic ring (or an associated structure) is created for the - first time in a session (see - :class:`sage.misc.superseded.experimental`). - - TESTS:: - - sage: AsymptoticRing(growth_group='z^ZZ * log(z)^QQ', coefficient_ring=ZZ) - doctest:...: FutureWarning: This class/method/function is marked as - experimental. It, its functionality or its interface might change - without a formal deprecation. - See http://trac.sagemath.org/17601 for details. - Asymptotic Ring over Integer Ring - - Asymptotic expansions in SageMath can be built through the ``asymptotic_expansions`` object. It contains generators for common asymptotic expressions. For example, diff --git a/src/sage/rings/asymptotic/asymptotic_ring.py b/src/sage/rings/asymptotic/asymptotic_ring.py index c630c5570ca..8ac348e5438 100644 --- a/src/sage/rings/asymptotic/asymptotic_ring.py +++ b/src/sage/rings/asymptotic/asymptotic_ring.py @@ -89,23 +89,6 @@ see the top of the module :doc:`growth group `. -.. WARNING:: - - As this code is experimental, a warning is thrown when an - asymptotic ring (or an associated structure) is created for the - first time in a session (see - :class:`sage.misc.superseded.experimental`). - - TESTS:: - - sage: from sage.rings.asymptotic.growth_group import GrowthGroup - sage: G = GrowthGroup('x^ZZ') - doctest:...: FutureWarning: This class/method/function is marked as - experimental. It, its functionality or its interface might change - without a formal deprecation. - See http://trac.sagemath.org/17601 for details. - - .. _asymptotic_ring_intro: Introductory Examples @@ -469,7 +452,6 @@ from sage.structure.element import CommutativeAlgebraElement from sage.structure.unique_representation import UniqueRepresentation from sage.misc.defaults import series_precision -from sage.misc.superseded import experimental from sage.rings.all import RIF @@ -3494,8 +3476,6 @@ def format_names(N): category=category, default_prec=default_prec) - - @experimental(trac_number=17601) def __init__(self, growth_group, coefficient_ring, category, default_prec): r""" See :class:`AsymptoticRing` for more information. diff --git a/src/sage/rings/asymptotic/growth_group.py b/src/sage/rings/asymptotic/growth_group.py index 9f171d7afca..584f6b532eb 100644 --- a/src/sage/rings/asymptotic/growth_group.py +++ b/src/sage/rings/asymptotic/growth_group.py @@ -13,23 +13,6 @@ examples of growth groups and elements are given as well. -.. WARNING:: - - As this code is experimental, warnings are thrown when a growth - group is created for the first time in a session (see - :class:`sage.misc.superseded.experimental`). - - TESTS:: - - sage: from sage.rings.asymptotic.growth_group import \ - ....: GenericGrowthGroup, GrowthGroup - sage: GenericGrowthGroup(ZZ) - doctest:...: FutureWarning: This class/method/function is marked as - experimental. It, its functionality or its interface might change - without a formal deprecation. - See http://trac.sagemath.org/17601 for details. - Growth Group Generic(ZZ) - .. _growth_group_description: Description of Growth Groups @@ -251,7 +234,6 @@ lazy_import('sage.rings.asymptotic.growth_group_cartesian', 'CartesianProductGrowthGroups') from sage.categories.pushout import ConstructionFunctor -from sage.misc.superseded import experimental from sage.structure.element import MultiplicativeGroupElement from sage.structure.factory import UniqueFactory from sage.structure.parent import Parent @@ -1672,8 +1654,6 @@ def __classcall__(cls, base, var=None, category=None, ignore_variables=None): return super(GenericGrowthGroup, cls).__classcall__( cls, base, var, category) - - @experimental(trac_number=17601) def __init__(self, base, var, category): r""" See :class:`GenericGrowthElement` for more information. diff --git a/src/sage/rings/asymptotic/growth_group_cartesian.py b/src/sage/rings/asymptotic/growth_group_cartesian.py index 39aa8e0e97e..6e725460c89 100644 --- a/src/sage/rings/asymptotic/growth_group_cartesian.py +++ b/src/sage/rings/asymptotic/growth_group_cartesian.py @@ -16,21 +16,6 @@ - Benjamin Hackl is supported by the Google Summer of Code 2015. -.. WARNING:: - - As this code is experimental, warnings are thrown when a growth - group is created for the first time in a session (see - :class:`sage.misc.superseded.experimental`). - - TESTS:: - - sage: from sage.rings.asymptotic.growth_group import GenericGrowthGroup, GrowthGroup - sage: GenericGrowthGroup(ZZ) - doctest:...: FutureWarning: This class/method/function is marked as - experimental. It, its functionality or its interface might change - without a formal deprecation. - See http://trac.sagemath.org/17601 for details. - Growth Group Generic(ZZ) TESTS:: diff --git a/src/sage/rings/asymptotic/misc.py b/src/sage/rings/asymptotic/misc.py index f66c0225348..e04fdf97cf4 100644 --- a/src/sage/rings/asymptotic/misc.py +++ b/src/sage/rings/asymptotic/misc.py @@ -609,7 +609,6 @@ def __init__(self, data=None, var=None): TESTS:: sage: A = AsymptoticRing('n^ZZ', ZZ) - doctest:...: FutureWarning: ... sage: from sage.rings.asymptotic.misc import NotImplementedOZero sage: raise NotImplementedOZero(A) Traceback (most recent call last): diff --git a/src/sage/rings/asymptotic/term_monoid.py b/src/sage/rings/asymptotic/term_monoid.py index 2e98af599eb..cda4ca42d90 100644 --- a/src/sage/rings/asymptotic/term_monoid.py +++ b/src/sage/rings/asymptotic/term_monoid.py @@ -31,21 +31,6 @@ `x^5`). Essentially, absorption can be interpreted as the addition of "compatible" terms (partial addition). -.. WARNING:: - - As this code is experimental, a warning is thrown when a term - monoid is created for the first time in a session (see - :class:`sage.misc.superseded.experimental`). - - TESTS:: - - sage: from sage.rings.asymptotic.growth_group import GrowthGroup - sage: from sage.rings.asymptotic.term_monoid import GenericTermMonoid - sage: G = GrowthGroup('x^ZZ * log(x)^ZZ') - doctest:...: FutureWarning: This class/method/function is marked as - experimental. It, its functionality or its interface might change - without a formal deprecation. - See http://trac.sagemath.org/17601 for details. .. _term_absorption: @@ -222,7 +207,6 @@ # http://www.gnu.org/licenses/ # ***************************************************************************** -from sage.misc.superseded import experimental from sage.rings.big_oh import O from sage.structure.element import MultiplicativeGroupElement from sage.structure.factory import UniqueFactory @@ -1446,8 +1430,6 @@ def __classcall__(cls, growth_group, coefficient_ring, category=None): return super(GenericTermMonoid, cls).__classcall__( cls, growth_group, coefficient_ring, category) - - @experimental(trac_number=17601) def __init__(self, growth_group, coefficient_ring, category): r""" See :class:`GenericTermMonoid` for more information. From 78bbc5d791b06db26a54d845a49f0c7be7455621 Mon Sep 17 00:00:00 2001 From: Daniel Krenn Date: Thu, 4 May 2017 07:45:32 +0200 Subject: [PATCH 221/452] Trac #22944: remove "(experimental)" from docs --- src/doc/en/reference/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/en/reference/index.rst b/src/doc/en/reference/index.rst index 3607297d28e..01b1f87875b 100644 --- a/src/doc/en/reference/index.rst +++ b/src/doc/en/reference/index.rst @@ -56,7 +56,7 @@ Calculus and Analysis * :doc:`Symbolic Calculus ` * :doc:`Mathematical Constants ` * :doc:`Elementary and Special Functions ` -* :doc:`Asymptotic Expansions ` (experimental) +* :doc:`Asymptotic Expansions ` * :doc:`Numerical Optimization ` Probability and Statistics From 55bdc0a6c1d6e24666329258df947875c7ee7d56 Mon Sep 17 00:00:00 2001 From: Vincent Delecroix <20100.delecroix@gmail.com> Date: Mon, 1 May 2017 20:13:36 +0200 Subject: [PATCH 222/452] Cleaning linbox interface of Matrix_integer_dense --- src/doc/en/reference/libs/index.rst | 1 + src/sage/libs/linbox/linbox.pyx | 35 ++ .../libs/linbox/linbox_flint_interface.pxd | 16 + .../libs/linbox/linbox_flint_interface.pyx | 240 ++++++++++ src/sage/matrix/matrix_integer_dense.pxd | 9 +- src/sage/matrix/matrix_integer_dense.pyx | 443 ++++++++++-------- 6 files changed, 546 insertions(+), 198 deletions(-) create mode 100644 src/sage/libs/linbox/linbox_flint_interface.pxd create mode 100644 src/sage/libs/linbox/linbox_flint_interface.pyx diff --git a/src/doc/en/reference/libs/index.rst b/src/doc/en/reference/libs/index.rst index 9b0b6e96d9e..9339004c54b 100644 --- a/src/doc/en/reference/libs/index.rst +++ b/src/doc/en/reference/libs/index.rst @@ -41,6 +41,7 @@ to be aware of the modules described in this chapter. sage/libs/singular/groebner_strategy sage/libs/ppl sage/libs/linbox/linbox + sage/libs/linbox/linbox_flint_interface sage/libs/flint/flint sage/libs/flint/fmpz_poly sage/libs/flint/arith diff --git a/src/sage/libs/linbox/linbox.pyx b/src/sage/libs/linbox/linbox.pyx index c31d1fc8779..60f12b5ae6d 100644 --- a/src/sage/libs/linbox/linbox.pyx +++ b/src/sage/libs/linbox/linbox.pyx @@ -5,6 +5,9 @@ r""" Linbox interface + +The interface :class:`Linbox_integer_dense` to dense matrices is deprecated. One +would better use :mod:`~sage.libs.linbox.linbox_flint_interface` """ ## NOTE: The sig_on()/sig_off() stuff can't go in here -- it has to be in the @@ -83,17 +86,30 @@ cdef extern from "linbox/linbox-sage.h": size_t nrows, size_t ncols) cdef class Linbox_integer_dense: + r""" + .. WARNING:: + + deprecated class + """ cdef set(self, mpz_t** matrix, size_t nrows, size_t ncols): + from sage.misc.superseded import deprecation + deprecation(111111, "sage.libs.linbox.linbox.Linbox_integer_dense is deprecated, use sage.libs.linbox.linbox_flint_interface instead") + self.nrows = nrows self.ncols = ncols self.matrix = matrix def minpoly(self): """ + Deprecated + OUTPUT: coefficients of minpoly as a Python list """ + from sage.misc.superseded import deprecation + deprecation(111111, "sage.libs.linbox.linbox.Linbox_integer_dense is deprecated, use sage.libs.linbox.linbox_flint_interface instead") + cdef mpz_t* poly cdef size_t degree verbose("using linbox poly comp") @@ -113,10 +129,15 @@ cdef class Linbox_integer_dense: def charpoly(self): """ + Deprecated + OUTPUT: coefficients of charpoly or minpoly as a Python list """ + from sage.misc.superseded import deprecation + deprecation(111111, "sage.libs.linbox.linbox.Linbox_integer_dense is deprecated, use sage.libs.linbox.linbox_flint_interface instead") + cdef mpz_t* poly cdef size_t degree verbose("using linbox poly comp") @@ -138,6 +159,9 @@ cdef class Linbox_integer_dense: mpz_t **ans, mpz_t **B, size_t B_nr, size_t B_nc): + from sage.misc.superseded import deprecation + deprecation(111111, "sage.libs.linbox.linbox.Linbox_integer_dense is deprecated, use sage.libs.linbox.linbox_flint_interface instead") + cdef int e e = linbox_integer_dense_matrix_matrix_multiply(ans, self.matrix, B, self.nrows, self.ncols, B_nc) if e: @@ -145,20 +169,31 @@ cdef class Linbox_integer_dense: cdef unsigned long rank(self) except -1: + from sage.misc.superseded import deprecation + deprecation(111111, "sage.libs.linbox.linbox.Linbox_integer_dense is deprecated, use sage.libs.linbox.linbox_flint_interface instead") + return linbox_integer_dense_rank(self.matrix, self.nrows, self.ncols) def det(self): """ + Deprecated + OUTPUT: determinant as a sage Integer """ + from sage.misc.superseded import deprecation + deprecation(111111, "sage.libs.linbox.linbox.Linbox_integer_dense is deprecated, use sage.libs.linbox.linbox_flint_interface instead") + cdef Integer z z = Integer() linbox_integer_dense_det(z.value, self.matrix, self.nrows, self.ncols) return z def smithform(self): + from sage.misc.superseded import deprecation + deprecation(111111, "sage.libs.linbox.linbox.Linbox_integer_dense is deprecated, use sage.libs.linbox.linbox_flint_interface instead") + raise NotImplementedError #cdef mpz_t* v #linbox_integer_dense_smithform(&v, self.matrix, self.nrows, self.ncols) diff --git a/src/sage/libs/linbox/linbox_flint_interface.pxd b/src/sage/libs/linbox/linbox_flint_interface.pxd new file mode 100644 index 00000000000..853fab63cbe --- /dev/null +++ b/src/sage/libs/linbox/linbox_flint_interface.pxd @@ -0,0 +1,16 @@ +from sage.libs.flint.types cimport fmpz_t, fmpz_mat_t, fmpz_poly_t + +# set C <- A * B +cdef void linbox_fmpz_mat_mul(fmpz_mat_t C, fmpz_mat_t A, fmpz_mat_t B) + +# set cp to the characteristic polynomial of A +cdef void linbox_fmpz_mat_charpoly(fmpz_poly_t cp, fmpz_mat_t A) + +# set mp to the minimal polynomial of A +cdef void linbox_fmpz_mat_minpoly(fmpz_poly_t mp, fmpz_mat_t A) + +# return the rank of A +cdef unsigned long linbox_fmpz_mat_rank(fmpz_mat_t A) + +# set det to the determinant of A +cdef void linbox_fmpz_mat_det(fmpz_t det, fmpz_mat_t A) diff --git a/src/sage/libs/linbox/linbox_flint_interface.pyx b/src/sage/libs/linbox/linbox_flint_interface.pyx new file mode 100644 index 00000000000..8d3995abecd --- /dev/null +++ b/src/sage/libs/linbox/linbox_flint_interface.pyx @@ -0,0 +1,240 @@ +# distutils: extra_compile_args = LINBOX_CFLAGS +# distutils: libraries = LINBOX_LIBRARIES +# distutils: library_dirs = LINBOX_LIBDIR +# distutils: language = c++ +r""" +Interface between flint matrices and linbox + +This module only contains C++ code (and the interface is fully C +compatible). It basically contains what used to be in the LinBox +source code under interfaces/sage/linbox-Sage.C written by M. Albrecht +and C. Pernet. The functions available are: + +- ``void linbox_fmpz_mat_mul(fmpz_mat_t C, fmpz_mat_t A, fmpz_mat_t B)``: set + ``C`` to be the result of the multiplication ``A * B`` + +- ``void linbox_fmpz_mat_charpoly(fmpz_poly_t cp, fmpz_mat_t A)``: set ``cp`` + to be the characteristic polynomial of the square matrix ``A`` + +- ``void linbox_fmpz_mat_minpoly(fmpz_poly_t mp, fmpz_mat_t A)``: set ``mp`` + to be the minimal polynomial of the square matrix ``A`` + +- ``unsigned long linbox_fmpz_mat_rank(fmpz_mat_t A)``: return the rank of the + matrix ``A`` + +- ``void linbox_fmpz_mat_det(fmpz_t det, fmpz_mat_t A)``: set ``det`` to the + determinat of the square matrix ``A`` +""" +#***************************************************************************** +# Copyright (C) 2007 Martin Albrecht +# Copyright (C) 2008 Clement Pernet +# Copyright (C) 2017 Vincent Delecroix +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# http://www.gnu.org/licenses/ +#***************************************************************************** + +from sage.libs.gmp.types cimport mpz_t, mpz_srcptr, mpz_ptr +from sage.libs.gmp.mpz cimport mpz_set +from sage.libs.flint.types cimport fmpz, fmpz_t +from sage.libs.flint.fmpz cimport fmpz_get_mpz, fmpz_set_mpz +from sage.libs.flint.fmpz_mat cimport fmpz_mat_entry, fmpz_mat_nrows, fmpz_mat_ncols +from sage.libs.flint.fmpz_poly cimport fmpz_poly_set_coeff_mpz, fmpz_poly_fit_length, _fmpz_poly_set_length + +cdef extern from "givaro/givconfig.h": + pass +cdef extern from "linbox/linbox-config.h": + pass + +cdef extern from "gmp++/gmp++.h": + cdef cppclass GivaroInteger "Givaro::Integer": + mpz_srcptr get_mpz() + +cdef extern from "linbox/matrix/dense-matrix.h": + ## template + ## using DenseMatrix = BlasMatrix<_Field> ; + ## + # indirect include from linbox/matrix/densematrix/blas-matrix.h + ## + ## template + ## class BlasMatrix + cdef cppclass LinBoxIntegerDenseMatrix "LinBox::DenseMatrix>": + ctypedef GivaroIntegerRing Field + ctypedef GivaroInteger Element + size_t rowdim() + size_t coldim() + LinBoxIntegerDenseMatrix(Field &F, size_t m, size_t n) + void setEntry(size_t i, size_t j, Element &a) + Element &getEntry(size_t i, size_t j) + +cdef extern from "givaro/zring.h": + cdef cppclass GivaroIntegerRing "Givaro::ZRing": + ctypedef GivaroInteger Element + +cdef extern from "givaro/givspyinteger.h": + cdef cppclass GivaroSpyInteger "Givaro::SpyInteger": + mpz_ptr get_mpz(GivaroInteger& i) + mpz_srcptr get_mpz_const(const GivaroInteger& i) + +cdef extern from "givaro/givpoly1.h": + ## template < typename T, typename A=std::allocator > + ## class givvector : public __GIV_STANDARD_VECTOR + cdef cppclass givvector "Givaro::givvector" [T,ALLOCATOR=*]: + T& operator[](size_t i) + size_t size() + +cdef extern from "linbox/ring/givaro-polynomial.h": + ## template + ## class GivPolynomialRing : public Givaro::Poly1FactorDom< Domain,StorageTag> + cdef cppclass LinBoxIntegerPolynomialRing "LinBox::GivPolynomialRing, Givaro::Dense>": + ctypedef givvector[GivaroInteger] Element + ctypedef givvector[GivaroInteger] Polynomial + +cdef extern from "linbox/matrix/matrix-domain.h": + ## template + ## class MatrixDomain : public MVProductDomain { + cdef cppclass LinBoxIntegerDenseMatrixDomain "LinBox::MatrixDomain>": + LinBoxIntegerDenseMatrixDomain(GivaroIntegerRing&) + LinBoxIntegerDenseMatrix& mul(LinBoxIntegerDenseMatrix ans, + LinBoxIntegerDenseMatrix left, + LinBoxIntegerDenseMatrix right) + +cdef extern from "linbox/solutions/charpoly.h": + ## template + ## Polynomial &charpoly (Polynomial & P, const Blackbox & A) + LinBoxIntegerPolynomialRing.Element& LinBoxIntegerDense_charpoly "LinBox::charpoly" (LinBoxIntegerPolynomialRing.Element&, LinBoxIntegerDenseMatrix&) + +cdef extern from "linbox/solutions/minpoly.h": + ## template + ## Polynomial &minpoly (Polynomial & P, const Blackbox & A) + LinBoxIntegerPolynomialRing.Element& LinBoxIntegerDense_minpoly "LinBox::minpoly" (LinBoxIntegerPolynomialRing.Element&, LinBoxIntegerDenseMatrix&) + +cdef extern from "linbox/solutions/rank.h": + ## template + ## inline unsigned long &rank (unsigned long &r, const Blackbox &A, + ## const DomainCategory &tag, const Method &M); + unsigned long & LinBoxIntegerDense_rank "LinBox::rank" (unsigned long &, LinBoxIntegerDenseMatrix) + +cdef extern from "linbox/solutions/det.h": + GivaroInteger& LinBoxIntegerDense_det "LinBox::det" (GivaroInteger&, LinBoxIntegerDenseMatrix) + + + +############################################################################### +# end of LinBox declarations -- begining of the code # +############################################################################### + + +cdef GivaroSpyInteger spy + +# set the entries of A from m (no allocation preformed) +# NOTE: this function is not part of the interface (ie the .pxd file) to keep the +# module C-compatible +cdef void fmpz_mat_get_linbox(LinBoxIntegerDenseMatrix * A, fmpz_mat_t m): + "Set the entries of A to m" + cdef size_t i,j + cdef GivaroInteger t + + for i in range(fmpz_mat_nrows(m)): + for j in range(fmpz_mat_ncols(m)): + fmpz_get_mpz( spy.get_mpz(t), fmpz_mat_entry(m, i, j)) + A.setEntry(i, j, t) + + +# set the entries of m from A (no allocation performed) +# NOTE: this function is not part of the interface (ie the .pxd file) to keep the +# module C-compatible +cdef void fmpz_mat_set_linbox(fmpz_mat_t m, LinBoxIntegerDenseMatrix *A): + "Set the entries of m to A" + cdef size_t i,j + for i in range(A.rowdim()): + for j in range(A.coldim()): + fmpz_set_mpz(fmpz_mat_entry(m, i, j), spy.get_mpz(A.getEntry(i, j))) + + +# set C <- A * B +cdef void linbox_fmpz_mat_mul(fmpz_mat_t C, fmpz_mat_t A, fmpz_mat_t B): + cdef GivaroIntegerRing ZZ + cdef LinBoxIntegerDenseMatrix *LBA + cdef LinBoxIntegerDenseMatrix *LBB + cdef LinBoxIntegerDenseMatrix *LBC + + LBA = new LinBoxIntegerDenseMatrix(ZZ, fmpz_mat_nrows(A), fmpz_mat_ncols(A)) + fmpz_mat_get_linbox(LBA, A) + + LBB = new LinBoxIntegerDenseMatrix(ZZ, fmpz_mat_nrows(B), fmpz_mat_ncols(B)) + fmpz_mat_get_linbox(LBB, B) + + LBC = new LinBoxIntegerDenseMatrix(ZZ, fmpz_mat_nrows(A), fmpz_mat_ncols(B)) + + cdef LinBoxIntegerDenseMatrixDomain * MD + MD = new LinBoxIntegerDenseMatrixDomain(ZZ) + MD.mul(LBC[0], LBA[0], LBB[0]) + del MD + + fmpz_mat_set_linbox(C, LBC) + + +# set p to the minpoly or the charpoly of A +cdef inline void linbox_fmpz_mat_poly(fmpz_poly_t p, fmpz_mat_t A, int minpoly): + cdef GivaroIntegerRing ZZ + cdef LinBoxIntegerDenseMatrix * LBA + + LBA = new LinBoxIntegerDenseMatrix(ZZ, fmpz_mat_nrows(A), fmpz_mat_ncols(A)) + fmpz_mat_get_linbox(LBA, A) + + cdef LinBoxIntegerPolynomialRing.Element m_A + if minpoly: + LinBoxIntegerDense_minpoly(m_A, LBA[0]) + else: + LinBoxIntegerDense_charpoly(m_A, LBA[0]) + + del LBA + + fmpz_poly_fit_length(p, m_A.size()) + _fmpz_poly_set_length(p, m_A.size()) + + cdef size_t i + for i in range(m_A.size()): + fmpz_poly_set_coeff_mpz(p, i, spy.get_mpz(m_A[i])) + + +# set cp to the characteristic polynomial of A +cdef void linbox_fmpz_mat_charpoly(fmpz_poly_t cp, fmpz_mat_t A): + linbox_fmpz_mat_poly(cp, A, False) + + +# set mp to the minimal polynomial of A +cdef void linbox_fmpz_mat_minpoly(fmpz_poly_t mp, fmpz_mat_t A): + linbox_fmpz_mat_poly(mp, A, True) + + +# return the rank of A +cdef unsigned long linbox_fmpz_mat_rank(fmpz_mat_t A): + cdef GivaroIntegerRing ZZ + cdef LinBoxIntegerDenseMatrix * LBA + + LBA = new LinBoxIntegerDenseMatrix(ZZ, fmpz_mat_nrows(A), fmpz_mat_ncols(A)) + fmpz_mat_get_linbox(LBA, A) + cdef unsigned long r = 0 + LinBoxIntegerDense_rank(r, LBA[0]) + del LBA + return r + + +# set det to the determinant of A +cdef void linbox_fmpz_mat_det(fmpz_t det, fmpz_mat_t A): + cdef GivaroIntegerRing ZZ + cdef LinBoxIntegerDenseMatrix * LBA + + LBA = new LinBoxIntegerDenseMatrix(ZZ, fmpz_mat_nrows(A), fmpz_mat_ncols(A)) + fmpz_mat_get_linbox(LBA, A) + cdef GivaroInteger d + LinBoxIntegerDense_det(d, LBA[0]) + del LBA + + fmpz_set_mpz(det, spy.get_mpz(d)) + diff --git a/src/sage/matrix/matrix_integer_dense.pxd b/src/sage/matrix/matrix_integer_dense.pxd index 90fc6922f87..03119c03584 100644 --- a/src/sage/matrix/matrix_integer_dense.pxd +++ b/src/sage/matrix/matrix_integer_dense.pxd @@ -8,10 +8,7 @@ from sage.ext.mod_int cimport * ctypedef long* GEN cdef class Matrix_integer_dense(Matrix_dense): - cdef fmpz_mat_t _matrix # Always initialized in __cinit__ - cdef bint _initialized_mpz - cdef mpz_t * _entries # Only used if _initialized_mpz - cdef mpz_t ** _rows # Only used if _initialized_mpz + cdef fmpz_mat_t _matrix cdef object _pivots cdef int mpz_height(self, mpz_t height) except -1 cdef _mod_int_c(self, mod_int modulus) @@ -19,10 +16,6 @@ cdef class Matrix_integer_dense(Matrix_dense): cdef _pickle_version0(self) cdef _unpickle_version0(self, data) cpdef _export_as_string(self, int base=?) - cdef inline int _init_mpz(self) except -1 - cdef int _init_mpz_impl(self) except -1 - cdef inline int _init_linbox(self) except -1 - cdef void _dealloc_mpz(self) cdef void set_unsafe_mpz(self, Py_ssize_t i, Py_ssize_t j, const mpz_t value) cdef void set_unsafe_si(self, Py_ssize_t i, Py_ssize_t j, long value) cdef void set_unsafe_double(self, Py_ssize_t i, Py_ssize_t j, double value) diff --git a/src/sage/matrix/matrix_integer_dense.pyx b/src/sage/matrix/matrix_integer_dense.pyx index 5ef68fd7d2b..2b475d40ea5 100644 --- a/src/sage/matrix/matrix_integer_dense.pyx +++ b/src/sage/matrix/matrix_integer_dense.pyx @@ -15,6 +15,9 @@ AUTHORS: - Vincent Delecroix (February 2015): make it faster, see :trac:`17822`. +- Vincent Delecroix (May 2017): removed duplication of entries and + cleaner linbox interface + EXAMPLES:: sage: a = matrix(ZZ, 3,3, range(9)); a @@ -46,7 +49,7 @@ TESTS:: # Copyright (C) 2006,2007 William Stein # Copyright (C) 2014 Marc Masdeu # Copyright (C) 2014 Jeroen Demeyer -# Copyright (C) 2015,2016 Vincent Delecroix +# Copyright (C) 2015,2016,2017 Vincent Delecroix # # 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 @@ -82,13 +85,15 @@ from cypari2.stack cimport clear_stack from cypari2.paridecl cimport * ######################################################### -include "cysignals/signals.pxi" -include "sage/ext/stdsage.pxi" - +from sage.ext.stdsage cimport PY_NEW +from cysignals.signals cimport sig_on, sig_off, sig_str, sig_check +from cysignals.memory cimport sig_malloc, sig_free, check_malloc from sage.arith.multi_modular cimport MultiModularBasis + from sage.libs.flint.fmpz cimport * from sage.libs.flint.fmpz_mat cimport * + from sage.rings.integer cimport Integer from sage.rings.rational_field import QQ from sage.rings.real_double import RDF @@ -123,10 +128,7 @@ from sage.rings.fast_arith cimport arith_int cdef arith_int ai = arith_int() ######### linbox interface ########## -from sage.libs.linbox.linbox cimport Linbox_integer_dense -cdef Linbox_integer_dense linbox = Linbox_integer_dense() -USE_LINBOX_POLY = True - +from sage.libs.linbox.linbox_flint_interface cimport * ########## iml -- integer matrix library ########### from sage.libs.iml cimport * @@ -137,7 +139,24 @@ fplll_fp_map = {None: None, 'xd': 'dpe', 'rr': 'mpfr'} -cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse +cdef inline mpz_t * fmpz_mat_to_mpz_array(fmpz_mat_t m): + cdef mpz_t * entries = check_malloc(sizeof(mpz_t) * fmpz_mat_nrows(m) * fmpz_mat_ncols(m)) + cdef size_t i, j + cdef size_t k = 0 + for i in range(fmpz_mat_nrows(m)): + for j in range(fmpz_mat_ncols(m)): + mpz_init(entries[k]) + fmpz_get_mpz(entries[k], fmpz_mat_entry(m, i, j)) + k += 1 + return entries + +cdef inline void mpz_array_clear(mpz_t * a, size_t length): + cdef size_t i + for i in range(length): + mpz_clear(a[i]) + sig_free(a) + +cdef class Matrix_integer_dense(Matrix_dense): r""" Matrix over the integers, implemented using FLINT. @@ -200,57 +219,10 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse self._nrows = parent.nrows() self._ncols = parent.ncols() self._pivots = None - self._initialized_mpz = False - self._entries = NULL - self._rows = NULL sig_str("FLINT exception") fmpz_mat_init(self._matrix, self._nrows, self._ncols) sig_off() - cdef inline int _init_mpz(self) except -1: - if self._initialized_mpz: - return 0 - else: - return self._init_mpz_impl() - - cdef inline int _init_linbox(self) except -1: - if not self._initialized_mpz: - self._init_mpz_impl() - linbox.set(self._rows, self._nrows, self._ncols) - return 0 - - cdef int _init_mpz_impl(self) except -1: - cdef Py_ssize_t i, j, k - - sig_on() - self._rows = sig_malloc(sizeof(mpz_t*) * self._nrows) - if not self._rows: - raise MemoryError - self._entries = sig_malloc(sizeof(mpz_t) * self._nrows * self._ncols) - if not self._entries: - sig_free(self._rows) - raise MemoryError - k = 0 - for i in range(self._nrows): - self._rows[i] = self._entries + k - for j in range(self._ncols): - mpz_init(self._entries[k]) - fmpz_get_mpz(self._entries[k],fmpz_mat_entry(self._matrix,i,j)) - k += 1 - sig_off() - self._initialized_mpz = True - return 1 - - cdef void _dealloc_mpz(self): - if not self._initialized_mpz: - return - cdef Py_ssize_t k - for k in range(self._nrows * self._ncols): - mpz_clear(self._entries[k]) - sig_free(self._rows) - sig_free(self._entries) - self._initialized_mpz = False - def __hash__(self): r""" Returns hash of self. @@ -283,7 +255,6 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse sage: del a """ fmpz_mat_clear(self._matrix) - self._dealloc_mpz() def __init__(self, parent, entries, copy, coerce): r""" @@ -463,24 +434,18 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse [ 3 4 5] """ fmpz_set_mpz(fmpz_mat_entry(self._matrix,i,j), value) - if self._initialized_mpz: - mpz_set(self._entries[i*self._ncols + j], value) cdef void set_unsafe_si(self, Py_ssize_t i, Py_ssize_t j, long value): """ Set position i,j of this matrix to ``value``. """ fmpz_set_si(fmpz_mat_entry(self._matrix,i,j), value) - if self._initialized_mpz: - mpz_set_si(self._entries[i*self._ncols + j], value) cdef void set_unsafe_double(self, Py_ssize_t i, Py_ssize_t j, double value): """ Set position i,j of this matrix to ``value``. """ fmpz_set_d(fmpz_mat_entry(self._matrix,i,j), value) - if self._initialized_mpz: - mpz_set_d(self._entries[i*self._ncols + j], value) cdef get_unsafe(self, Py_ssize_t i, Py_ssize_t j): """ @@ -796,8 +761,8 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse EXAMPLES:: - sage: A = matrix(ZZ,2,3,range(6)) - sage: A*A.transpose() + sage: A = matrix(ZZ, 2, 3, range(6)) + sage: A * A.transpose() [ 5 14] [14 50] sage: A._multiply_linbox(A.transpose()) @@ -808,38 +773,21 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse This fixes a bug found in :trac:`17094`:: - sage: A = identity_matrix(ZZ,3) + sage: A = identity_matrix(ZZ, 3) sage: A._multiply_linbox(A) [1 0 0] [0 1 0] [0 0 1] """ - cdef int e - cdef long int i,j cdef Matrix_integer_dense ans - cdef Matrix_integer_dense left = self - - if self._nrows == right._nrows: - # self acts on the space of right - parent = right.parent() - if self._ncols == right._ncols: - # right acts on the space of self - parent = self.parent() - else: - parent = self.matrix_space(left._nrows, right._ncols) - - ans = self._new(parent.nrows(),parent.ncols()) + cdef Matrix_integer_dense left = self - left._init_linbox() - right._init_mpz() - ans._init_mpz() + ans = self._new(left._nrows, right._ncols) sig_on() - linbox.matrix_matrix_multiply(ans._rows, right._rows, right._nrows, right._ncols) - for i from 0 <= i < ans._nrows: - for j from 0 <= j < ans._ncols: - fmpz_set_mpz(fmpz_mat_entry(ans._matrix,i,j),ans._rows[i][j]) + linbox_fmpz_mat_mul(ans._matrix, left._matrix, right._matrix) sig_off() + return ans def _multiply_classical(self, Matrix_integer_dense right): @@ -853,6 +801,24 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse [ 18 21 24] [ 54 66 78] [ 90 111 132] + + TESTS:: + + sage: for _ in range(100): + ....: nrows = randint(0, 10) + ....: nmid = randint(0, 10) + ....: ncols = randint(0, 10) + ....: m1 = random_matrix(ZZ, nrows, nmid) + ....: m2 = random_matrix(ZZ, nmid, ncols) + ....: ans_flint = m1 * m2 + ....: ans_classical = m1._multiply_classical(m2) + ....: ans_linbox = m1._multiply_linbox(m2) + ....: if ans_flint != ans_classical: + ....: raise RuntimeError("ERROR\nm1=\n{}\nm2=\n{}\nans_flint=\n{}\nans_classical=\n{}".format( + ....: m1.str(), m2.str(), ans_flint.str(), ans_classical.str())) + ....: if ans_flint != ans_linbox: + ....: raise RuntimeError("ERROR\nm1=\n{}\nm2=\n{}\nans_flint=\n{}\nans_linbox=\n{}".format( + ....: m1.str(), m2.str(), ans_flint.str(), ans_linbox.str())) """ if self._ncols != right._nrows: raise IndexError("Number of columns of self must equal number of rows of right.") @@ -1237,6 +1203,16 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse sage: A._cache['charpoly_linbox'] x^2 - 3*x - 2 + Check consistency between the various algorithms:: + + sage: for _ in range(100): + ....: dim = randint(1, 20) + ....: m = random_matrix(ZZ, dim) + ....: ans_flint = m.charpoly(algorithm='flint') + ....: ans_linbox = m.charpoly(algorithm='linbox') + ....: if ans_flint != ans_linbox: + ....: raise RuntimeError("ans_flint = {} and ans_linbox = {} for\n{}".format( + ....: ans_flint, ans_linbox, m.str())) """ cdef long i,n cdef Integer z @@ -1248,13 +1224,13 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse if g is not None: return g.change_variable_name(var) - if algorithm == 'flint' or (algorithm == 'linbox' and not USE_LINBOX_POLY): + if algorithm == 'flint': g = ((PolynomialRing(ZZ,names = var).gen()))._new() sig_on() fmpz_mat_charpoly(g.__poly,self._matrix) sig_off() elif algorithm == 'linbox': - g = self._charpoly_linbox(var) + g = self._poly_linbox('charpoly', var) else: raise ValueError("no algorithm '%s'"%algorithm) self.cache(cache_key, g) @@ -1267,7 +1243,7 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse - ``var`` - a variable name - - ``algorithm`` - 'linbox' (default) 'generic' + - ``algorithm`` - 'linbox' (default) or 'generic' .. NOTE:: @@ -1277,66 +1253,69 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse EXAMPLES:: - sage: A = matrix(ZZ,6, range(36)) + sage: A = matrix(ZZ, 6, range(36)) sage: A.minpoly() x^3 - 105*x^2 - 630*x - sage: n=6; A = Mat(ZZ,n)([k^2 for k in range(n^2)]) - sage: A.minpoly() + + sage: A = Mat(ZZ, 6)([k^2 for k in range(36)]) + sage: A.minpoly(algorithm='linbox') + x^4 - 2695*x^3 - 257964*x^2 + 1693440*x + sage: A.minpoly(algorithm='generic') x^4 - 2695*x^3 - 257964*x^2 + 1693440*x + """ key = 'minpoly_%s_%s'%(algorithm, var) x = self.fetch(key) if x: return x - if algorithm == 'linbox' and not USE_LINBOX_POLY: - algorithm = 'generic' if algorithm == 'linbox': - g = self._minpoly_linbox(var) + g = self._poly_linbox('minpoly', var) elif algorithm == 'generic': g = Matrix_dense.minpoly(self, var) else: raise ValueError("no algorithm '%s'"%algorithm) + self.cache(key, g) return g - def _minpoly_linbox(self, var='x'): - return self._poly_linbox(var=var, typ='minpoly') + def _poly_linbox(self, typ, var='x'): + r""" + Return the minimal or characteristic polynomial of this matrix - def _charpoly_linbox(self, var='x'): - if self.is_zero(): # program around a bug in linbox on 32-bit linux - x = self.base_ring()[var].gen() - return x ** self._nrows - return self._poly_linbox(var=var, typ='charpoly') + EXAMPLES:: - def _poly_linbox(self, var='x', typ='minpoly'): + sage: matrix(1, [5])._poly_linbox('minpoly', 'z') + z - 5 + sage: matrix(1, [5])._poly_linbox('charpoly', 't') + t - 5 """ - INPUT: - + if self._nrows != self._ncols: + raise ArithmeticError("self must be a square matrix") - - ``var`` - 'x' + cdef Polynomial_integer_dense_flint x = ZZ[var].gen() - - ``typ`` - 'minpoly' or 'charpoly' + if self.is_zero(): + if typ == 'minpoly': + return x + elif typ == 'charpoly': + return x ** self._nrows + else: + raise ValueError("typ must either be 'minpoly' or 'charpoly'") - """ - time = verbose('computing %s of %s x %s matrix using linbox'%(typ, self._nrows, self._ncols)) - if self._nrows != self._ncols: - raise ArithmeticError("self must be a square matrix") - if self._nrows <= 1: - return Matrix_dense.charpoly(self, var) - self._init_linbox() + ans = x._new() if typ == 'minpoly': sig_on() - v = linbox.minpoly() + linbox_fmpz_mat_minpoly(ans.__poly, self._matrix) sig_off() - else: + elif typ == 'charpoly': sig_on() - v = linbox.charpoly() + linbox_fmpz_mat_charpoly(ans.__poly, self._matrix) sig_off() - R = self._base_ring[var] - verbose('finished computing %s'%typ, time) - return R(v) + else: + raise ValueError("typ must either be 'minpoly' or 'charpoly'") + return ans def height(self): """ @@ -1547,7 +1526,6 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse def _echelon_in_place_classical(self): cdef Matrix_integer_dense E - self._dealloc_mpz() E = self.echelon_form() sig_on() fmpz_mat_set(self._matrix,E._matrix) @@ -1840,9 +1818,9 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse [ 0 0 0 0 0 0 0 200 0 0] [ 0 0 0 0 0 0 0 0 200 0] [ 0 0 0 0 0 0 0 0 0 200] - + Check that the output is correct in corner cases, see :trac:`18613`:: - + sage: m = matrix(2, 0) sage: m.parent() Full MatrixSpace of 2 by 0 dense matrices over Integer Ring @@ -1915,7 +1893,6 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse U = U[:r] elif algorithm == "padic": from . import matrix_integer_dense_hnf - self._init_mpz() if transformation: H_m, U = matrix_integer_dense_hnf.hnf_with_transformation(self, proof=proof) if not include_zero_rows: @@ -2219,31 +2196,24 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse :meth:`smith_form` """ d = self.fetch('elementary_divisors') - if not d is None: + if d is not None: return d[:] if self._nrows == 0 or self._ncols == 0: d = [] + elif algorithm == 'linbox': + raise ValueError("linbox too broken -- currently Linbox SNF is disabled.") + elif algorithm == 'pari': + d = self.__pari__().matsnf(0).sage() + i = d.count(0) + d.sort() + if i > 0: + d = d[i:] + [d[0]]*i else: - if algorithm == 'linbox': - raise ValueError("linbox too broken -- currently Linbox SNF is disabled.") - if algorithm == 'pari': - d = self.__pari__().matsnf(0).sage() - i = d.count(0) - d.sort() - if i > 0: - d = d[i:] + [d[0]]*i - elif not (algorithm in ['pari', 'linbox']): - raise ValueError("algorithm (='%s') unknown"%algorithm) + raise ValueError("algorithm (='%s') unknown"%algorithm) + self.cache('elementary_divisors', d) return d[:] - def _elementary_divisors_linbox(self): - self._init_linbox() - sig_on() - d = linbox.smithform() - sig_off() - return d - def smith_form(self): r""" Returns matrices S, U, and V such that S = U\*self\*V, and S is in @@ -3458,10 +3428,18 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse def _rank_linbox(self): """ Compute the rank of this matrix using Linbox. + + TESTS:: + + sage: matrix(ZZ, 4, 6, 0)._rank_linbox() + 0 + sage: matrix(ZZ, 3, 4, range(12))._rank_linbox() + 2 + sage: matrix(ZZ, 5, 10, [1+i+i^2 for i in range(50)])._rank_linbox() + 3 """ - self._init_linbox() sig_on() - cdef unsigned long r = linbox.rank() + cdef unsigned long r = linbox_fmpz_mat_rank(self._matrix) sig_off() return Integer(r) @@ -3542,12 +3520,23 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse Traceback (most recent call last): ... RuntimeError: you must pass the proof=False option to the determinant command to use LinBox's det algorithm - sage: A.determinant(algorithm='linbox',proof=False) + sage: A.determinant(algorithm='linbox', proof=False) -21 sage: A._clear_cache() sage: A.determinant() -21 + Try the other algorithms on the same example:: + + sage: A._clear_cache(); A.determinant(algorithm='padic') + -21 + sage: A._clear_cache(); A.determinant(algorithm='pari') + -21 + sage: A._clear_cache(); A.determinant(algorithm='ntl') + -21 + sage: A._clear_cache(); A.determinant(algorithm='padic') + -21 + A bigger example:: sage: A = random_matrix(ZZ,30) @@ -3559,13 +3548,36 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse TESTS: This shows that we can compute determinants for all sizes up to - 80. The check that the determinant of a squared matrix is a + 80. The check that the determinant of a squared matrix is a square is a sanity check that the result is probably correct:: sage: for s in [1..80]: # long time ....: M = random_matrix(ZZ, s) ....: d = (M*M).determinant() ....: assert d.is_square() + + Check consistency:: + + sage: all(matrix(ZZ, 0).det(algorithm=algo).is_one() for algo in ['flint', 'padic', 'pari', 'ntl']) + True + sage: for _ in range(100): + ....: dim = randint(1, 10) + ....: m = random_matrix(ZZ, dim) + ....: det_flint = m.__copy__().det(algorithm='flint') + ....: det_padic = m.__copy__().det(algorithm='padic') + ....: det_pari = m.__copy__().det(algorithm='pari') + ....: det_ntl = m.__copy__().det(algorithm='ntl') + ....: if type(det_flint) is not Integer: + ....: raise RuntimeError("type(det_flint) = {}".format(type(det_flint))) + ....: if type(det_padic) is not Integer: + ....: raise RuntimeError("type(det_padic) = {}".format(type(det_padic))) + ....: if type(det_pari) is not Integer: + ....: raise RuntimeError("type(det_pari) = {}".format(type(det_pari))) + ....: if type(det_ntl) is not Integer: + ....: raise RuntimeError("type(det_ntl) = {}".format(type(det_ntl))) + ....: if det_flint != det_padic or det_flint != det_pari or det_flint != det_ntl: + ....: raise RuntimeError("ERROR\ndet_flint = {}\ndet_padic={}\ndet_pari={}\ndet_ntl={}\n{}".format( + ....: det_flint, det_padic, det_pari, det_ntl, self.str())) """ d = self.fetch('det') if d is not None: @@ -3589,7 +3601,7 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse fmpz_clear(e) d = det elif algorithm == 'padic': - import matrix_integer_dense_hnf + from . import matrix_integer_dense_hnf d = matrix_integer_dense_hnf.det_padic(self, proof=proof, stabilize=stabilize) elif algorithm == 'linbox': if proof: @@ -3609,12 +3621,27 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse def _det_linbox(self): """ Compute the determinant of this matrix using Linbox. + + TESTS:: + + sage: matrix(ZZ, 0)._det_linbox() + 1 """ - self._init_linbox() + if self._nrows != self._ncols: + raise ArithmeticError("self must be a square matrix") + if self._nrows == 0: + return ZZ.one() + + cdef fmpz_t tmp + fmpz_init(tmp) sig_on() - d = linbox.det() + linbox_fmpz_mat_det(tmp, self._matrix) sig_off() - return Integer(d) + + cdef Integer ans = PY_NEW(Integer) + fmpz_get_mpz(ans.value, tmp) + fmpz_clear(tmp) + return ans def _det_pari(self, int flag=0): """ @@ -3622,14 +3649,18 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse flag is set to 1, use classical Gaussian elimination. For efficiency purposes, this det is computed entirely on the - PARI stack then the PARI stack is cleared. This function is + PARI stack then the PARI stack is cleared. This function is most useful for very small matrices. EXAMPLES:: - sage: matrix(ZZ,3,[1..9])._det_pari() + sage: matrix(ZZ, 0)._det_pari() + 1 + sage: matrix(ZZ, 0)._det_pari(1) + 1 + sage: matrix(ZZ, 3, [1..9])._det_pari() 0 - sage: matrix(ZZ,3,[1..9])._det_pari(1) + sage: matrix(ZZ, 3, [1..9])._det_pari(1) 0 """ sig_on() @@ -3643,23 +3674,43 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse def _det_ntl(self): """ Compute the determinant of this matrix using NTL. + + EXAMPLES:: + + sage: matrix(ZZ, 0)._det_ntl() + 1 + sage: matrix(ZZ, 3, [1..9])._det_ntl() + 0 + sage: matrix(ZZ, 3, [1,3,6,2,7,8,2,1,0])._det_ntl() + -32 """ sig_on() d = self._ntl_().determinant() sig_off() return Integer(d) - #### Rational kernel, via IML def _rational_kernel_iml(self): """ - IML: Return the rational kernel of this matrix (acting from the - left), considered as a matrix over QQ. I.e., returns a matrix K - such that self\*K = 0, and the number of columns of K equals the - nullity of self. + Return the rational (left) kernel of this matrix - AUTHORS: + OUTPUT: - - William Stein + A matrix ``K`` such that ``self * K = 0``, and the number of columns of + K equals the nullity of self. + + EXAMPLES:: + + sage: m = matrix(ZZ, 5, 5, [1+i+i^2 for i in range(25)]) + sage: m._rational_kernel_iml() + [ 1 3] + [-3 -8] + [ 3 6] + [-1 0] + [ 0 -1] + + sage: V1 = m._rational_kernel_iml().column_space().change_ring(QQ) + sage: V2 = m._rational_kernel_flint().column_space().change_ring(QQ) + sage: assert V1 == V2 """ if self._nrows == 0 or self._ncols == 0: return self.matrix_space(self._ncols, 0).zero_matrix() @@ -3668,34 +3719,46 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse cdef unsigned long i,j,k cdef mpz_t *mp_N time = verbose('computing null space of %s x %s matrix using IML'%(self._nrows, self._ncols)) - self._init_mpz() + cdef mpz_t * m = fmpz_mat_to_mpz_array(self._matrix) sig_on() - dim = nullspaceMP(self._nrows, self._ncols, self._entries, &mp_N) + dim = nullspaceMP(self._nrows, self._ncols, m, &mp_N) sig_off() # Now read the answer as a matrix. cdef Matrix_integer_dense M - M = self._new(self._ncols,dim) + M = self._new(self._ncols, dim) k = 0 - for i from 0 <= i < self._ncols: - for j from 0 <= j < dim: - fmpz_set_mpz(fmpz_mat_entry(M._matrix,i,j), mp_N[k]) - mpz_clear(mp_N[k]) + for i in range(self._ncols): + for j in range(dim): + fmpz_set_mpz(fmpz_mat_entry(M._matrix, i, j), mp_N[k]) k += 1 - sig_free(mp_N) + mpz_array_clear(m, self._nrows * self._ncols) + mpz_array_clear(mp_N, dim * self._ncols) verbose("finished computing null space", time) return M - #### Rational kernel, via flint def _rational_kernel_flint(self): """ - Return the rational kernel of this matrix (acting from the - left), considered as a matrix over QQ. I.e., returns a matrix K - such that self\*K = 0, and the number of columns of K equals the - nullity of self. + Return the rational (left) kernel of this matrix - AUTHORS: + OUTPUT: + + A matrix ``K`` such that ``self * K = 0``, and the number of columns of + K equals the nullity of self. + + EXAMPLES:: - - Marc Masdeu + sage: m = matrix(ZZ, 4, 6, [i^2-2*i for i in range(24)]) + sage: m._rational_kernel_flint() + [ 1728 5184 10368] + [ -5184 -13824 -25920] + [ 5184 10368 17280] + [ -1728 0 0] + [ 0 -1728 0] + [ 0 0 -1728] + + sage: V1 = m._rational_kernel_iml().column_space().change_ring(QQ) + sage: V2 = m._rational_kernel_flint().column_space().change_ring(QQ) + sage: assert V1 == V2 """ if self._nrows == 0 or self._ncols == 0: return self.matrix_space(self._ncols, 0).zero_matrix() @@ -3703,15 +3766,15 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse cdef long dim cdef fmpz_mat_t M0 sig_on() - fmpz_mat_init(M0,self._ncols,self._ncols) + fmpz_mat_init(M0, self._ncols, self._ncols) dim = fmpz_mat_nullspace(M0, self._matrix) sig_off() # Now read the answer as a matrix. - cdef Matrix_integer_dense M - M = self._new(self._ncols,dim) - for i from 0 <= i < M._nrows: - for j from 0 <= j < M._ncols: - fmpz_set(fmpz_mat_entry(M._matrix,i,j),fmpz_mat_entry(M0,i,j)) + cdef Matrix_integer_dense M = self._new(self._ncols, dim) + cdef size_t i,j + for i in range(self._ncols): + for j in range(dim): + fmpz_set(fmpz_mat_entry(M._matrix, i, j), fmpz_mat_entry(M0, i, j)) fmpz_mat_clear(M0) return M @@ -4190,18 +4253,18 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse sig_check() verbose("Initializing mp_N and mp_D") mp_N = sig_malloc( n * m * sizeof(mpz_t) ) - for i from 0 <= i < n * m: + for i in range(n * m): mpz_init(mp_N[i]) mpz_init(mp_D) verbose("Done with initializing mp_N and mp_D") - self._init_mpz() - B._init_mpz() + cdef mpz_t * mself = fmpz_mat_to_mpz_array(self._matrix) + cdef mpz_t * mB = fmpz_mat_to_mpz_array(B._matrix) try: verbose('Calling solver n = %s, m = %s'%(n,m)) sig_on() - nonsingSolvLlhsMM(solu_pos, n, m, self._entries, B._entries, mp_N, mp_D) + nonsingSolvLlhsMM(solu_pos, n, m, mself, mB, mp_N, mp_D) sig_off() - M = self._new(P.nrows(),P.ncols()) + M = self._new(P.nrows(), P.ncols()) k = 0 for i from 0 <= i < M._nrows: for j from 0 <= j < M._ncols: @@ -4212,9 +4275,9 @@ cdef class Matrix_integer_dense(Matrix_dense): # dense or sparse return M, D finally: mpz_clear(mp_D) - for i from 0 <= i < n*m: - mpz_clear(mp_N[i]) - sig_free(mp_N) + mpz_array_clear(mself, self.nrows() * self.ncols()) + mpz_array_clear(mB, B.nrows() * B.ncols()) + mpz_array_clear(mp_N, n*m) def _solve_flint(self, Matrix_integer_dense B, right=True): """ From c8b95de65ca3e430835af831040b68924d41bf3b Mon Sep 17 00:00:00 2001 From: Vincent Delecroix <20100.delecroix@gmail.com> Date: Wed, 3 May 2017 07:51:38 +0200 Subject: [PATCH 223/452] 22924: remove (instead of deprecate) code from linbox.pyx --- src/sage/libs/linbox/linbox.pxd | 12 --- src/sage/libs/linbox/linbox.pyx | 152 -------------------------------- 2 files changed, 164 deletions(-) diff --git a/src/sage/libs/linbox/linbox.pxd b/src/sage/libs/linbox/linbox.pxd index 09035553f1a..6903e89dafa 100644 --- a/src/sage/libs/linbox/linbox.pxd +++ b/src/sage/libs/linbox/linbox.pxd @@ -13,15 +13,3 @@ cdef class Linbox_modn_sparse: cdef object rank(self, int gauss) cdef void solve(self, c_vector_modint **x, c_vector_modint *b, int method) - -cdef class Linbox_integer_dense: - cdef mpz_t** matrix - cdef size_t nrows, ncols - - cdef set(self, mpz_t** matrix, size_t nrows, size_t ncols) - cdef matrix_matrix_multiply(self, - mpz_t **ans, - mpz_t **B, - size_t B_nr, size_t B_nc) - cdef unsigned long rank(self) except -1 - diff --git a/src/sage/libs/linbox/linbox.pyx b/src/sage/libs/linbox/linbox.pyx index 60f12b5ae6d..a0335d5e760 100644 --- a/src/sage/libs/linbox/linbox.pyx +++ b/src/sage/libs/linbox/linbox.pyx @@ -56,155 +56,3 @@ cdef class Linbox_modn_sparse: for i from 0 <= i < X.size(): set_entry(x[0], i, X.get(i)) - -########################################################################## -## Sparse matrices over ZZ -########################################################################## - - -########################################################################## -## Dense matrices over ZZ -########################################################################## - -cdef extern from "linbox/linbox-sage.h": - void linbox_integer_dense_minpoly(mpz_t* &minpoly, size_t °ree, size_t n, mpz_t** matrix) - - void linbox_integer_dense_charpoly(mpz_t* &charpoly, size_t °ree, size_t n, mpz_t** matrix) - - void linbox_integer_dense_delete_array(mpz_t* f) - - int linbox_integer_dense_matrix_matrix_multiply(mpz_t** ans, mpz_t **A, mpz_t **B, size_t A_nr, size_t A_nc, size_t B_nc) - - unsigned long linbox_integer_dense_rank(mpz_t** matrix, size_t nrows, - size_t ncols) - - void linbox_integer_dense_det(mpz_t ans, mpz_t** matrix, - size_t nrows, size_t ncols) - - void linbox_integer_dense_smithform(mpz_t **v, - mpz_t **matrix, - size_t nrows, size_t ncols) - -cdef class Linbox_integer_dense: - r""" - .. WARNING:: - - deprecated class - """ - cdef set(self, mpz_t** matrix, size_t nrows, size_t ncols): - from sage.misc.superseded import deprecation - deprecation(111111, "sage.libs.linbox.linbox.Linbox_integer_dense is deprecated, use sage.libs.linbox.linbox_flint_interface instead") - - self.nrows = nrows - self.ncols = ncols - self.matrix = matrix - - def minpoly(self): - """ - Deprecated - - OUTPUT: - - coefficients of minpoly as a Python list - """ - from sage.misc.superseded import deprecation - deprecation(111111, "sage.libs.linbox.linbox.Linbox_integer_dense is deprecated, use sage.libs.linbox.linbox_flint_interface instead") - - cdef mpz_t* poly - cdef size_t degree - verbose("using linbox poly comp") - linbox_integer_dense_minpoly(poly, degree, self.nrows, self.matrix) - verbose("computed poly -- now converting back to Sage") - - v = [] - cdef Integer k - cdef size_t n - for n from 0 <= n <= degree: - k = Integer() - mpz_set(k.value, poly[n]) - mpz_clear(poly[n]) - v.append(k) - linbox_integer_dense_delete_array(poly) - return v - - def charpoly(self): - """ - Deprecated - - OUTPUT: - - coefficients of charpoly or minpoly as a Python list - """ - from sage.misc.superseded import deprecation - deprecation(111111, "sage.libs.linbox.linbox.Linbox_integer_dense is deprecated, use sage.libs.linbox.linbox_flint_interface instead") - - cdef mpz_t* poly - cdef size_t degree - verbose("using linbox poly comp") - linbox_integer_dense_charpoly(poly, degree, self.nrows, self.matrix) - verbose("computed poly -- now converting back to Sage") - - v = [] - cdef Integer k - cdef size_t n - for n from 0 <= n <= degree: - k = Integer() - mpz_set(k.value, poly[n]) - mpz_clear(poly[n]) - v.append(k) - linbox_integer_dense_delete_array(poly) - return v - - cdef matrix_matrix_multiply(self, - mpz_t **ans, - mpz_t **B, - size_t B_nr, size_t B_nc): - from sage.misc.superseded import deprecation - deprecation(111111, "sage.libs.linbox.linbox.Linbox_integer_dense is deprecated, use sage.libs.linbox.linbox_flint_interface instead") - - cdef int e - e = linbox_integer_dense_matrix_matrix_multiply(ans, self.matrix, B, self.nrows, self.ncols, B_nc) - if e: - raise RuntimeError("error doing matrix matrix multiply over ZZ using linbox") - - - cdef unsigned long rank(self) except -1: - from sage.misc.superseded import deprecation - deprecation(111111, "sage.libs.linbox.linbox.Linbox_integer_dense is deprecated, use sage.libs.linbox.linbox_flint_interface instead") - - return linbox_integer_dense_rank(self.matrix, self.nrows, self.ncols) - - def det(self): - """ - Deprecated - - OUTPUT: - - determinant as a sage Integer - """ - from sage.misc.superseded import deprecation - deprecation(111111, "sage.libs.linbox.linbox.Linbox_integer_dense is deprecated, use sage.libs.linbox.linbox_flint_interface instead") - - cdef Integer z - z = Integer() - linbox_integer_dense_det(z.value, self.matrix, self.nrows, self.ncols) - return z - - def smithform(self): - from sage.misc.superseded import deprecation - deprecation(111111, "sage.libs.linbox.linbox.Linbox_integer_dense is deprecated, use sage.libs.linbox.linbox_flint_interface instead") - - raise NotImplementedError - #cdef mpz_t* v - #linbox_integer_dense_smithform(&v, self.matrix, self.nrows, self.ncols) - #z = [] - #cdef Integer k - #cdef size_t n - #for n from 0 <= n < self.ncols: - # k = Integer() - # mpz_set(k.value, v[n]) - # mpz_clear(v[n]) - # z.append(k) - #linbox_integer_dense_delete_array(v) - #return z - From fcafa60b4d7331fa832557ae1919df166d84b62c Mon Sep 17 00:00:00 2001 From: Vincent Delecroix <20100.delecroix@gmail.com> Date: Wed, 3 May 2017 13:31:32 +0200 Subject: [PATCH 224/452] 22924: get rid of spies --- src/sage/libs/linbox/linbox.pyx | 3 --- .../libs/linbox/linbox_flint_interface.pyx | 19 ++++++------------- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/src/sage/libs/linbox/linbox.pyx b/src/sage/libs/linbox/linbox.pyx index a0335d5e760..8c6f34a4bb1 100644 --- a/src/sage/libs/linbox/linbox.pyx +++ b/src/sage/libs/linbox/linbox.pyx @@ -5,9 +5,6 @@ r""" Linbox interface - -The interface :class:`Linbox_integer_dense` to dense matrices is deprecated. One -would better use :mod:`~sage.libs.linbox.linbox_flint_interface` """ ## NOTE: The sig_on()/sig_off() stuff can't go in here -- it has to be in the diff --git a/src/sage/libs/linbox/linbox_flint_interface.pyx b/src/sage/libs/linbox/linbox_flint_interface.pyx index 8d3995abecd..d9b528a9b69 100644 --- a/src/sage/libs/linbox/linbox_flint_interface.pyx +++ b/src/sage/libs/linbox/linbox_flint_interface.pyx @@ -51,7 +51,8 @@ cdef extern from "linbox/linbox-config.h": cdef extern from "gmp++/gmp++.h": cdef cppclass GivaroInteger "Givaro::Integer": - mpz_srcptr get_mpz() + mpz_ptr get_mpz() + mpz_srcptr get_mpz_const() cdef extern from "linbox/matrix/dense-matrix.h": ## template @@ -74,10 +75,6 @@ cdef extern from "givaro/zring.h": cdef cppclass GivaroIntegerRing "Givaro::ZRing": ctypedef GivaroInteger Element -cdef extern from "givaro/givspyinteger.h": - cdef cppclass GivaroSpyInteger "Givaro::SpyInteger": - mpz_ptr get_mpz(GivaroInteger& i) - mpz_srcptr get_mpz_const(const GivaroInteger& i) cdef extern from "givaro/givpoly1.h": ## template < typename T, typename A=std::allocator > @@ -128,19 +125,16 @@ cdef extern from "linbox/solutions/det.h": ############################################################################### -cdef GivaroSpyInteger spy - # set the entries of A from m (no allocation preformed) # NOTE: this function is not part of the interface (ie the .pxd file) to keep the # module C-compatible cdef void fmpz_mat_get_linbox(LinBoxIntegerDenseMatrix * A, fmpz_mat_t m): - "Set the entries of A to m" cdef size_t i,j cdef GivaroInteger t for i in range(fmpz_mat_nrows(m)): for j in range(fmpz_mat_ncols(m)): - fmpz_get_mpz( spy.get_mpz(t), fmpz_mat_entry(m, i, j)) + fmpz_get_mpz(t.get_mpz(), fmpz_mat_entry(m, i, j)) A.setEntry(i, j, t) @@ -148,11 +142,10 @@ cdef void fmpz_mat_get_linbox(LinBoxIntegerDenseMatrix * A, fmpz_mat_t m): # NOTE: this function is not part of the interface (ie the .pxd file) to keep the # module C-compatible cdef void fmpz_mat_set_linbox(fmpz_mat_t m, LinBoxIntegerDenseMatrix *A): - "Set the entries of m to A" cdef size_t i,j for i in range(A.rowdim()): for j in range(A.coldim()): - fmpz_set_mpz(fmpz_mat_entry(m, i, j), spy.get_mpz(A.getEntry(i, j))) + fmpz_set_mpz(fmpz_mat_entry(m, i, j), A.getEntry(i, j).get_mpz_const()) # set C <- A * B @@ -199,7 +192,7 @@ cdef inline void linbox_fmpz_mat_poly(fmpz_poly_t p, fmpz_mat_t A, int minpoly): cdef size_t i for i in range(m_A.size()): - fmpz_poly_set_coeff_mpz(p, i, spy.get_mpz(m_A[i])) + fmpz_poly_set_coeff_mpz(p, i, m_A[i].get_mpz_const()) # set cp to the characteristic polynomial of A @@ -236,5 +229,5 @@ cdef void linbox_fmpz_mat_det(fmpz_t det, fmpz_mat_t A): LinBoxIntegerDense_det(d, LBA[0]) del LBA - fmpz_set_mpz(det, spy.get_mpz(d)) + fmpz_set_mpz(det, d.get_mpz_const()) From 637fd872a78a7aec0781998a281d4dbbbc0fd7af Mon Sep 17 00:00:00 2001 From: Vincent Delecroix <20100.delecroix@gmail.com> Date: Thu, 4 May 2017 09:28:30 +0200 Subject: [PATCH 225/452] 22924: cleaning in linbox_flint_interface.pyx --- .../libs/linbox/linbox_flint_interface.pyx | 78 +++++++++++-------- 1 file changed, 44 insertions(+), 34 deletions(-) diff --git a/src/sage/libs/linbox/linbox_flint_interface.pyx b/src/sage/libs/linbox/linbox_flint_interface.pyx index d9b528a9b69..52406982be1 100644 --- a/src/sage/libs/linbox/linbox_flint_interface.pyx +++ b/src/sage/libs/linbox/linbox_flint_interface.pyx @@ -128,7 +128,7 @@ cdef extern from "linbox/solutions/det.h": # set the entries of A from m (no allocation preformed) # NOTE: this function is not part of the interface (ie the .pxd file) to keep the # module C-compatible -cdef void fmpz_mat_get_linbox(LinBoxIntegerDenseMatrix * A, fmpz_mat_t m): +cdef void fmpz_mat_get_linbox(LinBoxIntegerDenseMatrix& A, fmpz_mat_t m): cdef size_t i,j cdef GivaroInteger t @@ -141,80 +141,91 @@ cdef void fmpz_mat_get_linbox(LinBoxIntegerDenseMatrix * A, fmpz_mat_t m): # set the entries of m from A (no allocation performed) # NOTE: this function is not part of the interface (ie the .pxd file) to keep the # module C-compatible -cdef void fmpz_mat_set_linbox(fmpz_mat_t m, LinBoxIntegerDenseMatrix *A): +cdef void fmpz_mat_set_linbox(fmpz_mat_t m, LinBoxIntegerDenseMatrix& A): cdef size_t i,j for i in range(A.rowdim()): for j in range(A.coldim()): fmpz_set_mpz(fmpz_mat_entry(m, i, j), A.getEntry(i, j).get_mpz_const()) +# set the entries of the polynomial p from q (no allocation performed) +# NOTE: this function is not part of the interface (ie the .pxd file) to keep the +# module C-compatible +cdef void fmpz_poly_set_linbox(fmpz_poly_t p, LinBoxIntegerPolynomialRing.Element& q): + cdef size_t i + + fmpz_poly_fit_length(p, q.size()) + + for i in range(q.size()): + fmpz_poly_set_coeff_mpz(p, i, q[i].get_mpz_const()) + + _fmpz_poly_set_length(p, q.size()) + + # set C <- A * B cdef void linbox_fmpz_mat_mul(fmpz_mat_t C, fmpz_mat_t A, fmpz_mat_t B): cdef GivaroIntegerRing ZZ cdef LinBoxIntegerDenseMatrix *LBA cdef LinBoxIntegerDenseMatrix *LBB cdef LinBoxIntegerDenseMatrix *LBC + cdef LinBoxIntegerDenseMatrixDomain * MD LBA = new LinBoxIntegerDenseMatrix(ZZ, fmpz_mat_nrows(A), fmpz_mat_ncols(A)) - fmpz_mat_get_linbox(LBA, A) + fmpz_mat_get_linbox(LBA[0], A) LBB = new LinBoxIntegerDenseMatrix(ZZ, fmpz_mat_nrows(B), fmpz_mat_ncols(B)) - fmpz_mat_get_linbox(LBB, B) + fmpz_mat_get_linbox(LBB[0], B) LBC = new LinBoxIntegerDenseMatrix(ZZ, fmpz_mat_nrows(A), fmpz_mat_ncols(B)) - cdef LinBoxIntegerDenseMatrixDomain * MD MD = new LinBoxIntegerDenseMatrixDomain(ZZ) MD.mul(LBC[0], LBA[0], LBB[0]) + del MD - fmpz_mat_set_linbox(C, LBC) + fmpz_mat_set_linbox(C, LBC[0]) -# set p to the minpoly or the charpoly of A -cdef inline void linbox_fmpz_mat_poly(fmpz_poly_t p, fmpz_mat_t A, int minpoly): +# set cp to the characteristic polynomial of A +cdef void linbox_fmpz_mat_charpoly(fmpz_poly_t cp, fmpz_mat_t A): cdef GivaroIntegerRing ZZ cdef LinBoxIntegerDenseMatrix * LBA + cdef LinBoxIntegerPolynomialRing.Element m_A LBA = new LinBoxIntegerDenseMatrix(ZZ, fmpz_mat_nrows(A), fmpz_mat_ncols(A)) - fmpz_mat_get_linbox(LBA, A) - - cdef LinBoxIntegerPolynomialRing.Element m_A - if minpoly: - LinBoxIntegerDense_minpoly(m_A, LBA[0]) - else: - LinBoxIntegerDense_charpoly(m_A, LBA[0]) + fmpz_mat_get_linbox(LBA[0], A) + LinBoxIntegerDense_charpoly(m_A, LBA[0]) + fmpz_poly_set_linbox(cp, m_A) del LBA - fmpz_poly_fit_length(p, m_A.size()) - _fmpz_poly_set_length(p, m_A.size()) - - cdef size_t i - for i in range(m_A.size()): - fmpz_poly_set_coeff_mpz(p, i, m_A[i].get_mpz_const()) - - -# set cp to the characteristic polynomial of A -cdef void linbox_fmpz_mat_charpoly(fmpz_poly_t cp, fmpz_mat_t A): - linbox_fmpz_mat_poly(cp, A, False) - # set mp to the minimal polynomial of A cdef void linbox_fmpz_mat_minpoly(fmpz_poly_t mp, fmpz_mat_t A): - linbox_fmpz_mat_poly(mp, A, True) + cdef GivaroIntegerRing ZZ + cdef LinBoxIntegerDenseMatrix * LBA + cdef LinBoxIntegerPolynomialRing.Element m_A + + LBA = new LinBoxIntegerDenseMatrix(ZZ, fmpz_mat_nrows(A), fmpz_mat_ncols(A)) + fmpz_mat_get_linbox(LBA[0], A) + LinBoxIntegerDense_minpoly(m_A, LBA[0]) + fmpz_poly_set_linbox(mp, m_A) + + del LBA # return the rank of A cdef unsigned long linbox_fmpz_mat_rank(fmpz_mat_t A): cdef GivaroIntegerRing ZZ cdef LinBoxIntegerDenseMatrix * LBA + cdef unsigned long r = 0 LBA = new LinBoxIntegerDenseMatrix(ZZ, fmpz_mat_nrows(A), fmpz_mat_ncols(A)) - fmpz_mat_get_linbox(LBA, A) - cdef unsigned long r = 0 + fmpz_mat_get_linbox(LBA[0], A) LinBoxIntegerDense_rank(r, LBA[0]) + del LBA + return r @@ -222,12 +233,11 @@ cdef unsigned long linbox_fmpz_mat_rank(fmpz_mat_t A): cdef void linbox_fmpz_mat_det(fmpz_t det, fmpz_mat_t A): cdef GivaroIntegerRing ZZ cdef LinBoxIntegerDenseMatrix * LBA + cdef GivaroInteger d LBA = new LinBoxIntegerDenseMatrix(ZZ, fmpz_mat_nrows(A), fmpz_mat_ncols(A)) - fmpz_mat_get_linbox(LBA, A) - cdef GivaroInteger d + fmpz_mat_get_linbox(LBA[0], A) LinBoxIntegerDense_det(d, LBA[0]) - del LBA - fmpz_set_mpz(det, d.get_mpz_const()) + del LBA From fde1353a5c22bd3ff3fe50c9df982264b30d505e Mon Sep 17 00:00:00 2001 From: Vincent Delecroix <20100.delecroix@gmail.com> Date: Thu, 4 May 2017 10:10:07 +0200 Subject: [PATCH 226/452] 22924: clean minpoly/charpoly in Matrix_integer_dense --- .../libs/linbox/linbox_flint_interface.pyx | 14 +- src/sage/matrix/matrix_integer_dense.pyx | 165 +++++++++++------- 2 files changed, 118 insertions(+), 61 deletions(-) diff --git a/src/sage/libs/linbox/linbox_flint_interface.pyx b/src/sage/libs/linbox/linbox_flint_interface.pyx index 52406982be1..7809d86eb65 100644 --- a/src/sage/libs/linbox/linbox_flint_interface.pyx +++ b/src/sage/libs/linbox/linbox_flint_interface.pyx @@ -42,7 +42,7 @@ from sage.libs.gmp.mpz cimport mpz_set from sage.libs.flint.types cimport fmpz, fmpz_t from sage.libs.flint.fmpz cimport fmpz_get_mpz, fmpz_set_mpz from sage.libs.flint.fmpz_mat cimport fmpz_mat_entry, fmpz_mat_nrows, fmpz_mat_ncols -from sage.libs.flint.fmpz_poly cimport fmpz_poly_set_coeff_mpz, fmpz_poly_fit_length, _fmpz_poly_set_length +from sage.libs.flint.fmpz_poly cimport fmpz_poly_set_coeff_mpz, fmpz_poly_fit_length, _fmpz_poly_set_length, fmpz_poly_one cdef extern from "givaro/givconfig.h": pass @@ -192,6 +192,12 @@ cdef void linbox_fmpz_mat_charpoly(fmpz_poly_t cp, fmpz_mat_t A): cdef LinBoxIntegerDenseMatrix * LBA cdef LinBoxIntegerPolynomialRing.Element m_A + # FIXME: looks like a bug in LinBox + # see https://trac.sagemath.org/ticket/22924#comment:17 + if fmpz_mat_nrows(A) == 0: + fmpz_poly_one(cp) + return + LBA = new LinBoxIntegerDenseMatrix(ZZ, fmpz_mat_nrows(A), fmpz_mat_ncols(A)) fmpz_mat_get_linbox(LBA[0], A) LinBoxIntegerDense_charpoly(m_A, LBA[0]) @@ -206,6 +212,12 @@ cdef void linbox_fmpz_mat_minpoly(fmpz_poly_t mp, fmpz_mat_t A): cdef LinBoxIntegerDenseMatrix * LBA cdef LinBoxIntegerPolynomialRing.Element m_A + # FIXME: looks like a bug in LinBox + # see https://trac.sagemath.org/ticket/22924#comment:17 + if fmpz_mat_nrows(A) == 0: + fmpz_poly_one(mp) + return + LBA = new LinBoxIntegerDenseMatrix(ZZ, fmpz_mat_nrows(A), fmpz_mat_ncols(A)) fmpz_mat_get_linbox(LBA[0], A) LinBoxIntegerDense_minpoly(m_A, LBA[0]) diff --git a/src/sage/matrix/matrix_integer_dense.pyx b/src/sage/matrix/matrix_integer_dense.pyx index 2b475d40ea5..595f79a0d54 100644 --- a/src/sage/matrix/matrix_integer_dense.pyx +++ b/src/sage/matrix/matrix_integer_dense.pyx @@ -1160,14 +1160,15 @@ cdef class Matrix_integer_dense(Matrix_dense): """ return self, ZZ(1) - def charpoly(self, var='x', algorithm='generic'): + def charpoly(self, var='x', algorithm=None): """ INPUT: - ``var`` - a variable name - - ``algorithm`` - 'generic' (default), 'flint' or 'linbox' + - ``algorithm`` - (optional) either 'generic', 'flint' or 'linbox'. + Default is set to 'linbox'. EXAMPLES:: @@ -1185,6 +1186,13 @@ cdef class Matrix_integer_dense(Matrix_dense): sage: A.minpoly() x^3 - 3990*x^2 - 266000*x + On non square matrices, this method raises an ArithmeticError:: + + sage: matrix(ZZ, 2, 1).charpoly() + Traceback (most recent call last): + ... + ArithmeticError: only valid for square matrix + TESTS: The cached polynomial should be independent of the ``var`` @@ -1203,53 +1211,81 @@ cdef class Matrix_integer_dense(Matrix_dense): sage: A._cache['charpoly_linbox'] x^2 - 3*x - 2 - Check consistency between the various algorithms:: + Test corner cases:: + + sage: matrix([5]).charpoly('z', 'flint') + z - 5 + sage: matrix([5]).charpoly('z', 'linbox') + z - 5 + sage: matrix([5]).charpoly('z', 'generic') + z - 5 + + + sage: matrix([]).charpoly('y', 'flint') + 1 + sage: matrix([]).charpoly('y', 'linbox') + 1 + sage: matrix([]).charpoly('y', 'generic') + 1 + + sage: matrix([0]).charpoly('x', 'flint') + x + sage: matrix([0]).charpoly('x', 'linbox') + x + sage: matrix([0]).charpoly('x', 'generic') + x + + Consistency on random inputs:: sage: for _ in range(100): ....: dim = randint(1, 20) ....: m = random_matrix(ZZ, dim) - ....: ans_flint = m.charpoly(algorithm='flint') - ....: ans_linbox = m.charpoly(algorithm='linbox') - ....: if ans_flint != ans_linbox: - ....: raise RuntimeError("ans_flint = {} and ans_linbox = {} for\n{}".format( - ....: ans_flint, ans_linbox, m.str())) + ....: m._clear_cache(); ans_flint = m.charpoly(algorithm='flint') + ....: m._clear_cache(); ans_linbox = m.charpoly(algorithm='linbox') + ....: m._clear_cache(); ans_generic = m.charpoly(algorithm='generic') + ....: if ans_flint != ans_linbox or ans_flint != ans_generic: + ....: raise RuntimeError("ans_flint = {}, ans_linbox = {} and ans_generic = {} for\n{}".format( + ....: ans_flint, ans_linbox, ans_generic, m.str())) """ - cdef long i,n - cdef Integer z + if self._nrows != self._ncols: + raise ArithmeticError("only valid for square matrix") + cdef Polynomial_integer_dense_flint g - if algorithm == 'generic': + + if algorithm is None: algorithm = 'linbox' + cache_key = 'charpoly_%s' % algorithm g = self.fetch(cache_key) if g is not None: return g.change_variable_name(var) if algorithm == 'flint': - g = ((PolynomialRing(ZZ,names = var).gen()))._new() + g = ( PolynomialRing(ZZ, names=var).gen())._new() sig_on() - fmpz_mat_charpoly(g.__poly,self._matrix) + fmpz_mat_charpoly(g.__poly, self._matrix) sig_off() elif algorithm == 'linbox': - g = self._poly_linbox('charpoly', var) + g = ( PolynomialRing(ZZ, names=var).gen())._new() + sig_on() + linbox_fmpz_mat_charpoly(g.__poly, self._matrix) + sig_off() + elif algorithm == 'generic': + g = Matrix_dense.charpoly(self, var) else: raise ValueError("no algorithm '%s'"%algorithm) + self.cache(cache_key, g) return g - def minpoly(self, var='x', algorithm = 'linbox'): + def minpoly(self, var='x', algorithm=None): """ INPUT: - ``var`` - a variable name - - ``algorithm`` - 'linbox' (default) or 'generic' - - - .. NOTE:: - - Linbox charpoly disabled on 64-bit machines, since it hangs - in many cases. + - ``algorithm`` - (optional) either 'linbox' (default) or 'generic' EXAMPLES:: @@ -1263,59 +1299,68 @@ cdef class Matrix_integer_dense(Matrix_dense): sage: A.minpoly(algorithm='generic') x^4 - 2695*x^3 - 257964*x^2 + 1693440*x - """ - key = 'minpoly_%s_%s'%(algorithm, var) - x = self.fetch(key) - if x: return x + On non square matrices, this method raises an ArithmeticError:: + sage: matrix(ZZ, 2, 1).minpoly() + Traceback (most recent call last): + ... + ArithmeticError: only valid for square matrix - if algorithm == 'linbox': - g = self._poly_linbox('minpoly', var) - elif algorithm == 'generic': - g = Matrix_dense.minpoly(self, var) - else: - raise ValueError("no algorithm '%s'"%algorithm) + TESTS: - self.cache(key, g) - return g + Corner cases:: - def _poly_linbox(self, typ, var='x'): - r""" - Return the minimal or characteristic polynomial of this matrix + sage: matrix([5]).minpoly('z', 'linbox') + z - 5 + sage: matrix([5]).minpoly('z', 'generic') + z - 5 - EXAMPLES:: + sage: matrix([]).minpoly('y', 'linbox') + 1 + sage: matrix([]).minpoly('y', 'generic') + 1 - sage: matrix(1, [5])._poly_linbox('minpoly', 'z') - z - 5 - sage: matrix(1, [5])._poly_linbox('charpoly', 't') - t - 5 + sage: matrix(ZZ, 2).minpoly('x', 'linbox') + x + sage: matrix(ZZ, 2).minpoly('x', 'generic') + x + + Consistency on random inputs:: + + sage: for _ in range(100): + ....: dim = randint(1, 20) + ....: m = random_matrix(ZZ, dim) + ....: m._clear_cache(); ans_generic = m.minpoly(algorithm='generic') + ....: m._clear_cache(); ans_linbox = m.minpoly(algorithm='linbox') + ....: if ans_generic != ans_linbox: + ....: raise RuntimeError("ans_generic = {} and ans_linbox = {} for\n{}".format( + ....: ans_generic, ans_linbox, m.str())) """ if self._nrows != self._ncols: - raise ArithmeticError("self must be a square matrix") + raise ArithmeticError("only valid for square matrix") - cdef Polynomial_integer_dense_flint x = ZZ[var].gen() + cdef Polynomial_integer_dense_flint g - if self.is_zero(): - if typ == 'minpoly': - return x - elif typ == 'charpoly': - return x ** self._nrows - else: - raise ValueError("typ must either be 'minpoly' or 'charpoly'") + if algorithm is None: + algorithm = 'linbox' - ans = x._new() - if typ == 'minpoly': - sig_on() - linbox_fmpz_mat_minpoly(ans.__poly, self._matrix) - sig_off() - elif typ == 'charpoly': + key = 'minpoly_%s'%(algorithm) + g = self.fetch(key) + if g is not None: + return g.change_variable_name(var) + + if algorithm == 'linbox': + g = ( PolynomialRing(ZZ, names=var).gen())._new() sig_on() - linbox_fmpz_mat_charpoly(ans.__poly, self._matrix) + linbox_fmpz_mat_minpoly(g.__poly, self._matrix) sig_off() + elif algorithm == 'generic': + g = Matrix_dense.minpoly(self, var) else: - raise ValueError("typ must either be 'minpoly' or 'charpoly'") + raise ValueError("no algorithm '%s'"%algorithm) - return ans + self.cache(key, g) + return g def height(self): """ From 644e94497a0c38c6e79068511bfd9471fb31d61f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 4 May 2017 10:52:38 +0200 Subject: [PATCH 227/452] python3 update to 3.6.1 --- build/pkgs/python3/checksums.ini | 6 +++--- build/pkgs/python3/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/python3/checksums.ini b/build/pkgs/python3/checksums.ini index 2f96cb3d1ad..e8a071a8610 100644 --- a/build/pkgs/python3/checksums.ini +++ b/build/pkgs/python3/checksums.ini @@ -1,4 +1,4 @@ tarball=Python-VERSION.tar.gz -sha1=b7f832e6d84b406db4c854e3eb46411e6931bc98 -md5=be78e48cdfc1a7ad90efff146dce6cfe -cksum=667413425 +sha1=6e91434cf22414af8240dfa1bf8ab2d043b04998 +md5=2d0fc9f3a5940707590e07f03ecb08b9 +cksum=1747228928 diff --git a/build/pkgs/python3/package-version.txt b/build/pkgs/python3/package-version.txt index d5c0c991428..9575d51bad2 100644 --- a/build/pkgs/python3/package-version.txt +++ b/build/pkgs/python3/package-version.txt @@ -1 +1 @@ -3.5.1 +3.6.1 From 0223fd9ec603f9ec9436ef42d6d2f0d6e3200fe5 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 4 May 2017 09:50:06 -0500 Subject: [PATCH 228/452] Do not create all highest weight elements for type B spin RC bijection. --- src/sage/combinat/rigged_configurations/bij_type_B.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sage/combinat/rigged_configurations/bij_type_B.py b/src/sage/combinat/rigged_configurations/bij_type_B.py index 21dab1dead1..20bf132e306 100644 --- a/src/sage/combinat/rigged_configurations/bij_type_B.py +++ b/src/sage/combinat/rigged_configurations/bij_type_B.py @@ -123,7 +123,9 @@ def run(self, verbose=False): self.ret_rig_con[-1] = RiggedPartition(self.ret_rig_con[-1]._list, self.ret_rig_con[-1].rigging, self.ret_rig_con[-1].vacancy_numbers) - bij = KRTToRCBijectionTypeA2Odd(KRT.module_generators[0]) # Placeholder element + # Placeholder element + elt = KRT(*[C.module_generators[0] for C in KRT.crystals]) + bij = KRTToRCBijectionTypeA2Odd(elt) bij.ret_rig_con = KRT.rigged_configurations()(*self.ret_rig_con, use_vacancy_numbers=True) bij.cur_path = self.cur_path bij.cur_dims = self.cur_dims From 26617dd78d7230f73872841046713e3d9eed057d Mon Sep 17 00:00:00 2001 From: Vincent Delecroix <20100.delecroix@gmail.com> Date: Thu, 4 May 2017 17:26:49 +0200 Subject: [PATCH 229/452] 22948: del absolute_import at the end of catalogs --- src/sage/coding/channels_catalog.py | 2 + src/sage/coding/codes_catalog.py | 43 +++++++++++-------- src/sage/combinat/crystals/catalog.py | 7 +++ .../crystals/catalog_elementary_crystals.py | 6 +++ .../crystals/catalog_infinity_crystals.py | 6 +++ .../crystals/catalog_kirillov_reshetikhin.py | 8 ++++ src/sage/combinat/designs/design_catalog.py | 7 ++- src/sage/game_theory/catalog.py | 7 +++ src/sage/groups/affine_gps/catalog.py | 8 ++++ src/sage/groups/finitely_presented_catalog.py | 8 +++- src/sage/groups/matrix_gps/catalog.py | 7 +++ .../perm_gps/permutation_groups_catalog.py | 8 ++++ 12 files changed, 97 insertions(+), 20 deletions(-) diff --git a/src/sage/coding/channels_catalog.py b/src/sage/coding/channels_catalog.py index e2fa3d82b4e..1ee638e949c 100644 --- a/src/sage/coding/channels_catalog.py +++ b/src/sage/coding/channels_catalog.py @@ -28,3 +28,5 @@ _lazy_import('sage.coding.channel_constructions', ['ErrorErasureChannel', 'QarySymmetricChannel', 'StaticErrorRateChannel']) +# We don't want this to appear in tab completion +del absolute_import diff --git a/src/sage/coding/codes_catalog.py b/src/sage/coding/codes_catalog.py index 0f2c006ee8e..6a1bd4bdac4 100644 --- a/src/sage/coding/codes_catalog.py +++ b/src/sage/coding/codes_catalog.py @@ -11,6 +11,11 @@ sage: from sage.coding.codes_catalog import * +TESTS:: + + sage: import sage.coding.codes_catalog + sage: 'absolute_import' in dir(sage.coding.codes_catalog) + False """ #***************************************************************************** # Copyright (C) 2009 David Lucas @@ -28,12 +33,12 @@ # in the global namespace. from __future__ import absolute_import -from sage.misc.lazy_import import lazy_import as _lazy_import +from sage.misc.lazy_import import lazy_import from .linear_code import LinearCode from sage.coding.linear_code import LinearCode -_lazy_import('sage.coding.code_constructions', +lazy_import('sage.coding.code_constructions', ['BCHCode', 'BinaryGolayCode', 'CyclicCodeFromGeneratingPolynomial', 'CyclicCode', 'CyclicCodeFromCheckPolynomial', 'DuadicCodeEvenPair', 'DuadicCodeOddPair', 'ExtendedBinaryGolayCode', @@ -47,27 +52,29 @@ 'ReedSolomonCode', 'TernaryGolayCode', 'ToricCode', 'WalshCode']) -_lazy_import('sage.coding.bch', 'BCHCode') -_lazy_import('sage.coding.cyclic_code', 'CyclicCode') -_lazy_import('sage.coding.extended_code', 'ExtendedCode') -_lazy_import('sage.coding.golay_code', 'GolayCode') -_lazy_import('sage.coding.grs', 'GeneralizedReedSolomonCode') -_lazy_import('sage.coding.guava', ['QuasiQuadraticResidueCode', +lazy_import('sage.coding.bch', 'BCHCode') +lazy_import('sage.coding.cyclic_code', 'CyclicCode') +lazy_import('sage.coding.extended_code', 'ExtendedCode') +lazy_import('sage.coding.golay_code', 'GolayCode') +lazy_import('sage.coding.grs', 'GeneralizedReedSolomonCode') +lazy_import('sage.coding.guava', ['QuasiQuadraticResidueCode', 'RandomLinearCodeGuava']) -_lazy_import('sage.coding.hamming_code', 'HammingCode') -_lazy_import('sage.coding.parity_check_code', 'ParityCheckCode') -_lazy_import('sage.coding.punctured_code', 'PuncturedCode') -_lazy_import('sage.coding.reed_muller_code', ['BinaryReedMullerCode', +lazy_import('sage.coding.hamming_code', 'HammingCode') +lazy_import('sage.coding.parity_check_code', 'ParityCheckCode') +lazy_import('sage.coding.punctured_code', 'PuncturedCode') +lazy_import('sage.coding.reed_muller_code', ['BinaryReedMullerCode', 'ReedMullerCode']) -_lazy_import('sage.coding.subfield_subcode', 'SubfieldSubcode') +lazy_import('sage.coding.subfield_subcode', 'SubfieldSubcode') from . import decoders_catalog as decoders from . import encoders_catalog as encoders from . import bounds_catalog as bounds -_lazy_import('sage.coding','databases') +lazy_import('sage.coding','databases') + +from sage.misc.rest_index_of_methods import gen_rest_table_index +import sys +__doc__ = __doc__.format(INDEX_OF_FUNCTIONS=gen_rest_table_index(sys.modules[__name__], only_local_functions=False)) -del _lazy_import -from sage.misc.rest_index_of_methods import gen_rest_table_index as _gen_rest_table_index -import sys as _sys -__doc__ = __doc__.format(INDEX_OF_FUNCTIONS=_gen_rest_table_index(_sys.modules[__name__], only_local_functions=False)) +# We don't want this to appear in tab completion +del absolute_import, lazy_import, sys, gen_rest_table_index diff --git a/src/sage/combinat/crystals/catalog.py b/src/sage/combinat/crystals/catalog.py index d6e9cab5e7d..1141ed64bfc 100644 --- a/src/sage/combinat/crystals/catalog.py +++ b/src/sage/combinat/crystals/catalog.py @@ -45,6 +45,11 @@ * :class:`DirectSum ` * :class:`TensorProduct ` + +TESTS:: + + sage: 'absolute_import' in dir(crystals) + False """ from __future__ import absolute_import @@ -78,3 +83,5 @@ from . import catalog_infinity_crystals as infinity from . import catalog_elementary_crystals as elementary +# We don't want this to appear in tab completion +del absolute_import diff --git a/src/sage/combinat/crystals/catalog_elementary_crystals.py b/src/sage/combinat/crystals/catalog_elementary_crystals.py index ed330816b43..5e83fe5fdb8 100644 --- a/src/sage/combinat/crystals/catalog_elementary_crystals.py +++ b/src/sage/combinat/crystals/catalog_elementary_crystals.py @@ -8,6 +8,11 @@ or :class:`B ` * :class:`R ` * :class:`T ` + +TESTS:: + + sage: 'absolute_import' in dir(crystals.elementary) + False """ from __future__ import absolute_import @@ -17,3 +22,4 @@ from .elementary_crystals import ElementaryCrystal as B from .elementary_crystals import ComponentCrystal as Component +del absolute_import diff --git a/src/sage/combinat/crystals/catalog_infinity_crystals.py b/src/sage/combinat/crystals/catalog_infinity_crystals.py index 16543788962..5d506234826 100644 --- a/src/sage/combinat/crystals/catalog_infinity_crystals.py +++ b/src/sage/combinat/crystals/catalog_infinity_crystals.py @@ -15,6 +15,11 @@ ` * :class:`Star ` * :class:`Tableaux ` + +TESTS:: + + sage: 'absolute_import' in dir(crystals.infinity) + False """ from __future__ import absolute_import @@ -28,3 +33,4 @@ from sage.combinat.crystals.littelmann_path import InfinityCrystalOfLSPaths as LSPaths from sage.combinat.crystals.alcove_path import InfinityCrystalOfAlcovePaths as AlcovePaths +del absolute_import diff --git a/src/sage/combinat/crystals/catalog_kirillov_reshetikhin.py b/src/sage/combinat/crystals/catalog_kirillov_reshetikhin.py index 3d5d99a95de..00dd6ed9223 100644 --- a/src/sage/combinat/crystals/catalog_kirillov_reshetikhin.py +++ b/src/sage/combinat/crystals/catalog_kirillov_reshetikhin.py @@ -9,6 +9,11 @@ * :func:`LSPaths ` * :func:`RiggedConfigurations ` + +TESTS:: + + sage: 'absolute_import' in dir(crystals.kirillov_reshetikhin) + False """ from __future__ import absolute_import @@ -16,3 +21,6 @@ from .kirillov_reshetikhin import KirillovReshetikhinCrystalFromLSPaths as LSPaths from sage.combinat.rigged_configurations.kr_tableaux import KirillovReshetikhinTableaux from sage.combinat.rigged_configurations.rigged_configurations import KirillovReshetikhinCrystal as RiggedConfigurations + +# remove from tab completion +del absolute_import diff --git a/src/sage/combinat/designs/design_catalog.py b/src/sage/combinat/designs/design_catalog.py index c3f7d71bb63..796d4f0f45b 100644 --- a/src/sage/combinat/designs/design_catalog.py +++ b/src/sage/combinat/designs/design_catalog.py @@ -71,6 +71,11 @@ .. [1] La Jolla Covering Repository, http://www.ccrwest.org/cover.html + +TESTS:: + + sage: 'absolute_import' in dir(designs) or 'deprecated_callable_import' in dir(designs) + False """ from __future__ import absolute_import from sage.combinat.designs.block_design import (BlockDesign, @@ -123,4 +128,4 @@ ("This function will soon be removed. Use the designs.orthogonal_arrays.* functions instead")) # We don't want this to appear in designs. -del deprecated_callable_import +del deprecated_callable_import, absolute_import diff --git a/src/sage/game_theory/catalog.py b/src/sage/game_theory/catalog.py index aaefe760fba..9e47ab0c4bc 100644 --- a/src/sage/game_theory/catalog.py +++ b/src/sage/game_theory/catalog.py @@ -1,6 +1,13 @@ r""" Catalog Of Games + +TESTS:: + + sage: 'absolute_import' in dir(game_theory) + False """ from __future__ import absolute_import from . import catalog_normal_form_games as normal_form_games + +del absolute_import diff --git a/src/sage/groups/affine_gps/catalog.py b/src/sage/groups/affine_gps/catalog.py index 3ff92fe86a5..d78a1bdb2c4 100644 --- a/src/sage/groups/affine_gps/catalog.py +++ b/src/sage/groups/affine_gps/catalog.py @@ -1,6 +1,11 @@ r""" Type ``groups.affine.`` to access examples of groups implemented as affine groups. + +TESTS:: + + sage: 'absolute_import' in dir(groups.affine) + False """ from __future__ import absolute_import @@ -15,3 +20,6 @@ from .affine_group import AffineGroup as Affine from .euclidean_group import EuclideanGroup as Euclidean + +# We don't want this to appear in tab completion +del absolute_import diff --git a/src/sage/groups/finitely_presented_catalog.py b/src/sage/groups/finitely_presented_catalog.py index acb1609e01a..dc934864556 100644 --- a/src/sage/groups/finitely_presented_catalog.py +++ b/src/sage/groups/finitely_presented_catalog.py @@ -2,6 +2,11 @@ Type ``groups.presentation.`` to access examples of groups implemented as finite presentations (quotients of free groups). + +TESTS:: + + sage: 'absolute_import' in dir(groups.presentation) + False """ from __future__ import absolute_import @@ -24,4 +29,5 @@ from .finitely_presented_named import AlternatingPresentation as Alternating from .finitely_presented_named import BinaryDihedralPresentation as BinaryDihedral - +# We don't want this to appear in tab completion +del absolute_import diff --git a/src/sage/groups/matrix_gps/catalog.py b/src/sage/groups/matrix_gps/catalog.py index 525cb0248af..9febc470765 100644 --- a/src/sage/groups/matrix_gps/catalog.py +++ b/src/sage/groups/matrix_gps/catalog.py @@ -3,6 +3,11 @@ Type ``groups.matrix.`` to access examples of groups implemented as permutation groups. + +TESTS:: + + sage: 'absolute_import' in dir(groups.matrix) + False """ from __future__ import absolute_import @@ -19,3 +24,5 @@ from .all import QuaternionMatrixGroupGF3 as QuaternionGF3 from sage.groups.matrix_gps.binary_dihedral import BinaryDihedralGroup as BinaryDihedral +# We don't want this to appear tab completion +del absolute_import diff --git a/src/sage/groups/perm_gps/permutation_groups_catalog.py b/src/sage/groups/perm_gps/permutation_groups_catalog.py index b9ad040de7e..5c015376b49 100644 --- a/src/sage/groups/perm_gps/permutation_groups_catalog.py +++ b/src/sage/groups/perm_gps/permutation_groups_catalog.py @@ -3,6 +3,11 @@ Type ``groups.permutation.`` to access examples of groups implemented as permutation groups. + +TESTS:: + + sage: 'absolute_import' in dir(groups.permutation) + False """ from __future__ import absolute_import @@ -29,3 +34,6 @@ from .permgroup_named import (PGL, PSL, PSp,PSU,PGU,) from .permgroup_named import TransitiveGroup as Transitive from .cubegroup import CubeGroup as RubiksCube + +# We don't want this to appear in tab completion +del absolute_import From bd0a226c693a793ada956d045ae898e88b271972 Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Thu, 4 May 2017 17:28:06 +0200 Subject: [PATCH 230/452] 22844: latex conversion, direction arg, interface cleanup --- src/sage/calculus/calculus.py | 70 ------------------------------ src/sage/functions/other.py | 80 ++++++++++++++++++++++++++++++++++- 2 files changed, 79 insertions(+), 71 deletions(-) diff --git a/src/sage/calculus/calculus.py b/src/sage/calculus/calculus.py index e0ae5df1739..4085e0ab6da 100644 --- a/src/sage/calculus/calculus.py +++ b/src/sage/calculus/calculus.py @@ -1702,21 +1702,6 @@ def at(ex, *args, **kwds): return ex.subs(**kwds) - -def dummy_limit(*args): - """ - This function is called to create formal wrappers of limits that - Maxima can't compute: - - EXAMPLES:: - - sage: a = lim(exp(x^2)*(1-erf(x)), x=infinity); a - -limit((erf(x) - 1)*e^(x^2), x, +Infinity) - sage: a = sage.calculus.calculus.dummy_limit(sin(x)/x, x, 0);a - limit(sin(x)/x, x, 0) - """ - return _limit(args[0], var(repr(args[1])), SR(args[2])) - def dummy_diff(*args): """ This function is called when 'diff' appears in a Maxima string. @@ -1797,59 +1782,6 @@ def dummy_inverse_laplace(*args): # ####################################################### -def _limit_latex_(self, f, x, a, direction=None): - r""" - Return latex expression for limit of a symbolic function. - - EXAMPLES:: - - sage: from sage.calculus.calculus import _limit_latex_ - sage: var('x,a') - (x, a) - sage: f = function('f') - sage: _limit_latex_(0, f(x), x, a) - '\\lim_{x \\to a}\\, f\\left(x\\right)' - sage: latex(limit(f(x), x=oo)) - \lim_{x \to +\infty}\, f\left(x\right) - - TESTS: - - When one-sided limits are converted back from maxima, the direction - argument becomes a symbolic variable. We check if typesetting these works:: - - sage: var('minus,plus') - (minus, plus) - sage: _limit_latex_(0, f(x), x, a, minus) - '\\lim_{x \\to a^-}\\, f\\left(x\\right)' - sage: _limit_latex_(0, f(x), x, a, plus) - '\\lim_{x \\to a^+}\\, f\\left(x\\right)' - sage: latex(limit(f(x),x=a,dir='+')) - \lim_{x \to a^+}\, f\left(x\right) - sage: latex(limit(f(x),x=a,dir='right')) - \lim_{x \to a^+}\, f\left(x\right) - sage: latex(limit(f(x),x=a,dir='-')) - \lim_{x \to a^-}\, f\left(x\right) - sage: latex(limit(f(x),x=a,dir='left')) - \lim_{x \to a^-}\, f\left(x\right) - - Check if :trac:`13181` is fixed:: - - sage: t = var('t') - sage: latex(limit(exp_integral_e(1/2, I*t - I*x)*sqrt(-t + x),t=x,dir='-')) - \lim_{t \to x^-}\, \sqrt{-t + x} exp_integral_e\left(\frac{1}{2}, i \, t - i \, x\right) - sage: latex(limit(exp_integral_e(1/2, I*t - I*x)*sqrt(-t + x),t=x,dir='+')) - \lim_{t \to x^+}\, \sqrt{-t + x} exp_integral_e\left(\frac{1}{2}, i \, t - i \, x\right) - sage: latex(limit(exp_integral_e(1/2, I*t - I*x)*sqrt(-t + x),t=x)) - \lim_{t \to x}\, \sqrt{-t + x} exp_integral_e\left(\frac{1}{2}, i \, t - i \, x\right) - """ - if repr(direction) == 'minus': - dir_str = '^-' - elif repr(direction) == 'plus': - dir_str = '^+' - else: - dir_str = '' - return "\\lim_{%s \\to %s%s}\\, %s"%(latex(x), latex(a), dir_str, latex(f)) - def _laplace_latex_(self, *args): r""" Return LaTeX expression for Laplace transform of a symbolic function. @@ -1887,7 +1819,6 @@ def _inverse_laplace_latex_(self, *args): return "\\mathcal{L}^{-1}\\left(%s\\right)"%(', '.join([latex(x) for x in args])) # Return un-evaluated expression as instances of SFunction class -_limit = function_factory('limit', print_latex_func=_limit_latex_) _laplace = function_factory('laplace', print_latex_func=_laplace_latex_) _inverse_laplace = function_factory('ilt', print_latex_func=_inverse_laplace_latex_) @@ -2090,7 +2021,6 @@ def symbolic_expression_from_maxima_string(x, equals_sub=False, maxima=maxima): search = sci_not.search(s) # have to do this here, otherwise maxima_tick catches it - syms['limit'] = dummy_limit syms['diff'] = dummy_diff syms['integrate'] = dummy_integrate syms['laplace'] = dummy_laplace diff --git a/src/sage/functions/other.py b/src/sage/functions/other.py index df831ea2f94..5ef60203c04 100644 --- a/src/sage/functions/other.py +++ b/src/sage/functions/other.py @@ -2613,11 +2613,25 @@ class Function_limit(BuiltinFunction): """ Placeholder symbolic limit function that is only accessible internally. + This function is called to create formal wrappers of limits that + Maxima can't compute:: + + sage: a = lim(exp(x^2)*(1-erf(x)), x=infinity); a + -limit((erf(x) - 1)*e^(x^2), x, +Infinity) + EXAMPLES:: sage: from sage.functions.other import symbolic_limit as slimit sage: slimit(1/x, x, +oo) limit(1/x, x, +Infinity) + sage: var('minus,plus') + (minus, plus) + sage: slimit(1/x, x, +oo) + limit(1/x, x, +Infinity) + sage: slimit(1/x, x, 0, plus) + limit(1/x, x, 0, plus) + sage: slimit(1/x, x, 0, minus) + limit(1/x, x, 0, minus) """ def __init__(self): """ @@ -2627,7 +2641,71 @@ def __init__(self): sage: maxima(slimit(1/x, x, +oo)) 0 """ - BuiltinFunction.__init__(self, "limit", nargs=3, + BuiltinFunction.__init__(self, "limit", nargs=0, conversions=dict(maxima='limit')) + def _latex_(self): + r""" + EXAMPLES:: + + sage: from sage.functions.other import symbolic_limit as slimit + sage: latex(slimit) + \lim + """ + return r'\lim' + + def _print_latex_(self, ex, var, to, direction=''): + r""" + EXAMPLES:: + + sage: from sage.functions.other import symbolic_limit as slimit + sage: var('x,a') + (x, a) + sage: f = function('f') + sage: latex(slimit(f(x), x, a)) + \lim_{x \to a}\, f\left(x\right) + sage: latex(limit(f(x), x=oo)) + \lim_{x \to +\infty}\, f\left(x\right) + + TESTS: + + When one-sided limits are converted back from maxima, the direction + argument becomes a symbolic variable. We check if typesetting these works:: + + sage: from sage.functions.other import symbolic_limit as slimit + sage: var('minus,plus') + (minus, plus) + sage: latex(slimit(f(x), x, a, minus)) + \lim_{x \to a^-}\, f\left(x\right) + sage: latex(slimit(f(x), x, a, plus)) + \lim_{x \to a^+}\, f\left(x\right) + sage: latex(limit(f(x),x=a,dir='+')) + \lim_{x \to a^+}\, f\left(x\right) + sage: latex(limit(f(x),x=a,dir='right')) + \lim_{x \to a^+}\, f\left(x\right) + sage: latex(limit(f(x),x=a,dir='-')) + \lim_{x \to a^-}\, f\left(x\right) + sage: latex(limit(f(x),x=a,dir='left')) + \lim_{x \to a^-}\, f\left(x\right) + + Check if :trac:`13181` is fixed:: + + sage: t = var('t') + sage: latex(limit(exp_integral_e(1/2, I*t - I*x)*sqrt(-t + x),t=x,dir='-')) + \lim_{t \to x^-}\, \sqrt{-t + x} exp_integral_e\left(\frac{1}{2}, i \, t - i \, x\right) + sage: latex(limit(exp_integral_e(1/2, I*t - I*x)*sqrt(-t + x),t=x,dir='+')) + \lim_{t \to x^+}\, \sqrt{-t + x} exp_integral_e\left(\frac{1}{2}, i \, t - i \, x\right) + sage: latex(limit(exp_integral_e(1/2, I*t - I*x)*sqrt(-t + x),t=x)) + \lim_{t \to x}\, \sqrt{-t + x} exp_integral_e\left(\frac{1}{2}, i \, t - i \, x\right) + """ + if repr(direction) == 'minus': + dir_str = '^-' + elif repr(direction) == 'plus': + dir_str = '^+' + else: + dir_str = '' + return r"\lim_{{{} \to {}{}}}\, {}".format(latex(var), + latex(to), dir_str, latex(ex)) + symbolic_limit = Function_limit() + From a24030bfed5149b7b1998d68ff4273dbf02e0992 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 4 May 2017 21:02:33 +0200 Subject: [PATCH 231/452] trac 21668 make sure the mode is sorted --- src/sage/stats/basic_stats.py | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/sage/stats/basic_stats.py b/src/sage/stats/basic_stats.py index 634ef4333b8..3572d0833e9 100644 --- a/src/sage/stats/basic_stats.py +++ b/src/sage/stats/basic_stats.py @@ -85,20 +85,24 @@ def mean(v): def mode(v): """ - Return the mode of `v`. The mode is the sorted list of the most - frequently occuring elements in `v`. If `n` is the most times - that any element occurs in `v`, then the mode is the sorted list - of elements of `v` that occur `n` times. + Return the mode of `v`. - NOTE: The elements of `v` must be hashable and comparable. + The mode is the sorted list of the most frequently occuring + elements in `v`. If `n` is the most times that any element occurs + in `v`, then the mode is the sorted list of elements of `v` that + occur `n` times. + + .. NOTE:: + + The elements of `v` must be hashable and comparable. INPUT: - - `v` -- a list + - `v` -- a list OUTPUT: - - a list + - a list EXAMPLES:: @@ -113,6 +117,8 @@ def mode(v): [1, 2, 3, 4, 5] sage: mode([3,1,2,1,2,3]) [1, 2, 3] + sage: mode([0, 2, 7, 7, 13, 20, 2, 13]) + [2, 7, 13] sage: mode(['sage', 4, I, 3/5, 'sage', pi]) ['sage'] sage: class MyClass: @@ -121,8 +127,11 @@ def mode(v): sage: stats.mode(MyClass()) [1] """ - if hasattr(v, 'mode'): return v.mode() - from operator import itemgetter + if hasattr(v, 'mode'): + return v.mode() + + if not v: + return v freq = {} for i in v: @@ -131,8 +140,9 @@ def mode(v): else: freq[i] = 1 - s = sorted(freq.items(), key=itemgetter(1), reverse=True) - return [i[0] for i in s if i[1]==s[0][1]] + n = max(freq.values()) + return sorted(u for u, f in freq.items() if f == n) + def std(v, bias=False): """ From 3dc06b7b8948469daf71ca755c83c86a12dfb2f1 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 4 May 2017 14:33:05 -0500 Subject: [PATCH 232/452] Fixing latex typo. --- src/sage/combinat/crystals/kirillov_reshetikhin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/crystals/kirillov_reshetikhin.py b/src/sage/combinat/crystals/kirillov_reshetikhin.py index 4510bd516f3..547bce2f308 100644 --- a/src/sage/combinat/crystals/kirillov_reshetikhin.py +++ b/src/sage/combinat/crystals/kirillov_reshetikhin.py @@ -3047,7 +3047,7 @@ class KR_type_Dn_twistedElement(KirillovReshetikhinGenericCrystalElement): def e0(self): r""" Return `e_0` on ``self`` by going to the `\pm`-diagram corresponding - to the `\{2,\lots,n\}`-highest weight vector in the component of + to the `\{2,\ldots,n\}`-highest weight vector in the component of ``self``, then applying [Definition 6.2, 4], and pulling back from `\pm`-diagrams. From 693fad3c9e970546edab54df76157f5a4d5d13e7 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 4 May 2017 20:44:52 -0500 Subject: [PATCH 233/452] Change category name to LoopCrystals. --- ...e_derived_crystals.py => loop_crystals.py} | 59 +++++++++++-------- src/sage/combinat/crystals/affine.py | 4 +- src/sage/combinat/crystals/alcove_path.py | 4 +- .../combinat/crystals/kirillov_reshetikhin.py | 2 +- src/sage/combinat/crystals/littelmann_path.py | 6 +- .../rigged_configurations/kr_tableaux.py | 2 +- .../rigged_configurations.py | 2 +- 7 files changed, 43 insertions(+), 36 deletions(-) rename src/sage/categories/{affine_derived_crystals.py => loop_crystals.py} (95%) diff --git a/src/sage/categories/affine_derived_crystals.py b/src/sage/categories/loop_crystals.py similarity index 95% rename from src/sage/categories/affine_derived_crystals.py rename to src/sage/categories/loop_crystals.py index 0fdd3ff5ae5..02a32370a8d 100644 --- a/src/sage/categories/affine_derived_crystals.py +++ b/src/sage/categories/loop_crystals.py @@ -1,12 +1,15 @@ r""" -Affine Derived Subalgebra Crystals +Loop Crystals """ #***************************************************************************** -# Copyright (C) 2015 Travis Scrimshaw +# Copyright (C) 2015 Travis Scrimshaw # -# Distributed under the terms of the GNU General Public License (GPL) +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. # http://www.gnu.org/licenses/ -#****************************************************************************** +#***************************************************************************** from __future__ import print_function, division, absolute_import @@ -24,17 +27,21 @@ from sage.rings.all import ZZ -class AffineDerivedSubalgebraCrystals(Category_singleton): +class LoopCrystals(Category_singleton): r""" The category of `U_q'(\mathfrak{g})`-crystals, where `\mathfrak{g}` is of affine type. + The category is called loop crystals as we can also consider them + as crystals corresponding to the loop algebra `\mathfrak{g}_0[t]`, + where `\mathfrak{g}_0` is the corresponding classical type. + EXAMPLES:: - sage: from sage.categories.affine_derived_crystals import AffineDerivedSubalgebraCrystals - sage: C = AffineDerivedSubalgebraCrystals() + sage: from sage.categories.loop_crystals import LoopCrystals + sage: C = LoopCrystals() sage: C - Category of affine derived subalgebra crystals + Category of loop crystals sage: C.super_categories() [Category of crystals] sage: C.example() @@ -51,8 +58,8 @@ def super_categories(self): r""" EXAMPLES:: - sage: from sage.categories.affine_derived_crystals import AffineDerivedSubalgebraCrystals - sage: AffineDerivedSubalgebraCrystals().super_categories() + sage: from sage.categories.loop_crystals import LoopCrystals + sage: LoopCrystals().super_categories() [Category of crystals] """ return [Crystals()] @@ -64,8 +71,8 @@ def example(self, n = 3): EXAMPLES:: - sage: from sage.categories.affine_derived_crystals import AffineDerivedSubalgebraCrystals - sage: B = AffineDerivedSubalgebraCrystals().example(); B + sage: from sage.categories.loop_crystals import LoopCrystals + sage: B = LoopCrystals().example(); B Kirillov-Reshetikhin crystal of type ['A', 3, 1] with (r,s)=(1,1) """ from sage.combinat.crystals.kirillov_reshetikhin import KirillovReshetikhinCrystal @@ -122,7 +129,7 @@ def digraph(self, subset=None, index_set=None): return G # TODO: Should we make "regular" an axiom? -class RegularAffineDerivedSubalgebraCrystals(Category_singleton): +class RegularLoopCrystals(Category_singleton): r""" The category of regular `U_q'(\mathfrak{g})`-crystals, where `\mathfrak{g}` is of affine type. @@ -132,12 +139,12 @@ def super_categories(self): """ EXAMPLES:: - sage: from sage.categories.affine_derived_crystals import RegularAffineDerivedSubalgebraCrystals - sage: RegularAffineDerivedSubalgebraCrystals().super_categories() + sage: from sage.categories.loop_crystals import RegularLoopCrystals + sage: RegularLoopCrystals().super_categories() [Category of regular crystals, - Category of affine derived subalgebra crystals] + Category of loop crystals] """ - return [RegularCrystals(), AffineDerivedSubalgebraCrystals()] + return [RegularCrystals(), LoopCrystals()] class ElementMethods: def classical_weight(self): @@ -168,11 +175,11 @@ def super_categories(self): r""" EXAMPLES:: - sage: from sage.categories.affine_derived_crystals import KirillovReshetikhinCrystals + sage: from sage.categories.loop_crystals import KirillovReshetikhinCrystals sage: KirillovReshetikhinCrystals().super_categories() - [Category of finite regular affine derived subalgebra crystals] + [Category of finite regular loop crystals] """ - return [RegularAffineDerivedSubalgebraCrystals().Finite()] + return [RegularLoopCrystals().Finite()] class ParentMethods: @abstract_method @@ -373,7 +380,7 @@ def local_energy_function(self, B): Return the local energy function of ``self`` and ``B``. See - :class:`~sage.categories.affine_derived_crystals.LocalEnergyFunction` + :class:`~sage.categories.loop_crystals.LocalEnergyFunction` for a definition. EXAMPLES:: @@ -524,7 +531,7 @@ def level(self): .. SEEALSO:: - :meth:`~sage.categories.affine_derived_crystals.KirillovReshetikhinCrystals.ParentMethods.is_perfect` + :meth:`~sage.categories.loop_crystals.KirillovReshetikhinCrystals.ParentMethods.is_perfect` EXAMPLES:: @@ -605,7 +612,7 @@ def energy_function(self): D(b) = H(b \otimes b^{\sharp}) - H(u_B \otimes b^{\sharp}), where `H` is the :meth:`local energy function - `. + `. EXAMPLES:: @@ -637,11 +644,11 @@ def extra_super_categories(self): """ EXAMPLES:: - sage: from sage.categories.affine_derived_crystals import KirillovReshetikhinCrystals + sage: from sage.categories.loop_crystals import KirillovReshetikhinCrystals sage: KirillovReshetikhinCrystals().TensorProducts().extra_super_categories() - [Category of finite regular affine derived subalgebra crystals] + [Category of finite regular loop crystals] """ - return [RegularAffineDerivedSubalgebraCrystals().Finite()] + return [RegularLoopCrystals().Finite()] class ParentMethods: @cached_method diff --git a/src/sage/combinat/crystals/affine.py b/src/sage/combinat/crystals/affine.py index 45b9c892c62..286784f5174 100644 --- a/src/sage/combinat/crystals/affine.py +++ b/src/sage/combinat/crystals/affine.py @@ -13,7 +13,7 @@ #**************************************************************************** from sage.misc.abstract_method import abstract_method -from sage.categories.affine_derived_crystals import RegularAffineDerivedSubalgebraCrystals +from sage.categories.loop_crystals import RegularLoopCrystals from sage.structure.element import parent from sage.structure.parent import Parent from sage.structure.unique_representation import UniqueRepresentation @@ -112,7 +112,7 @@ def __init__(self, cartan_type, classical_crystal, category=None): sage: TestSuite(A).run() """ if category is None: - category = RegularAffineDerivedSubalgebraCrystals() + category = RegularLoopCrystals() self._cartan_type = cartan_type Parent.__init__(self, category = category) self.classical_crystal = classical_crystal; diff --git a/src/sage/combinat/crystals/alcove_path.py b/src/sage/combinat/crystals/alcove_path.py index 86a3bc4647b..3a766a82c72 100644 --- a/src/sage/combinat/crystals/alcove_path.py +++ b/src/sage/combinat/crystals/alcove_path.py @@ -30,7 +30,7 @@ from sage.structure.sage_object import richcmp from sage.categories.finite_crystals import FiniteCrystals from sage.categories.classical_crystals import ClassicalCrystals -from sage.categories.affine_derived_crystals import AffineDerivedSubalgebraCrystals +from sage.categories.loop_crystals import LoopCrystals from sage.graphs.all import DiGraph from sage.combinat.root_system.cartan_type import CartanType from sage.combinat.root_system.root_system import RootSystem @@ -334,7 +334,7 @@ def __init__(self, starting_weight, highest_weight_crystal): self._R = RootsWithHeight(starting_weight) self._finite_cartan_type = True elif cartan_type.is_finite() and not highest_weight_crystal: - Parent.__init__(self, category=AffineDerivedSubalgebraCrystals().Finite()) + Parent.__init__(self, category=LoopCrystals().Finite()) self._R = RootsWithHeight(starting_weight) self._finite_cartan_type = True self._cartan_type = cartan_type.affine() diff --git a/src/sage/combinat/crystals/kirillov_reshetikhin.py b/src/sage/combinat/crystals/kirillov_reshetikhin.py index 8c8b1ac1b02..7a89b97b5ca 100644 --- a/src/sage/combinat/crystals/kirillov_reshetikhin.py +++ b/src/sage/combinat/crystals/kirillov_reshetikhin.py @@ -32,7 +32,7 @@ from sage.combinat.combinat import CombinatorialObject from sage.structure.parent import Parent from sage.categories.crystals import CrystalMorphism -from sage.categories.affine_derived_crystals import KirillovReshetikhinCrystals +from sage.categories.loop_crystals import KirillovReshetikhinCrystals from sage.categories.homset import Hom from sage.categories.map import Map from sage.rings.integer import Integer diff --git a/src/sage/combinat/crystals/littelmann_path.py b/src/sage/combinat/crystals/littelmann_path.py index 87c532d07d0..81082335e48 100644 --- a/src/sage/combinat/crystals/littelmann_path.py +++ b/src/sage/combinat/crystals/littelmann_path.py @@ -34,8 +34,8 @@ from sage.categories.regular_crystals import RegularCrystals from sage.categories.classical_crystals import ClassicalCrystals from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets -from sage.categories.affine_derived_crystals import (RegularAffineDerivedSubalgebraCrystals, - KirillovReshetikhinCrystals) +from sage.categories.loop_crystals import (RegularLoopCrystals, + KirillovReshetikhinCrystals) from sage.combinat.root_system.cartan_type import CartanType from sage.combinat.root_system.weyl_group import WeylGroup from sage.rings.integer import Integer @@ -222,7 +222,7 @@ def __init__(self, starting_weight, starting_weight_parent): if sum(self.weight[i] for i in cl) == 1: cat = KirillovReshetikhinCrystals() else: - cat = RegularAffineDerivedSubalgebraCrystals().Finite() + cat = RegularLoopCrystals().Finite() Parent.__init__(self, category=cat) else: Parent.__init__(self, category=ClassicalCrystals()) diff --git a/src/sage/combinat/rigged_configurations/kr_tableaux.py b/src/sage/combinat/rigged_configurations/kr_tableaux.py index 6b3f8f5d849..d17a30d98ef 100644 --- a/src/sage/combinat/rigged_configurations/kr_tableaux.py +++ b/src/sage/combinat/rigged_configurations/kr_tableaux.py @@ -51,7 +51,7 @@ from sage.structure.parent import Parent from sage.structure.element_wrapper import ElementWrapper -from sage.categories.affine_derived_crystals import KirillovReshetikhinCrystals +from sage.categories.loop_crystals import KirillovReshetikhinCrystals from sage.combinat.crystals.letters import CrystalOfLetters, EmptyLetter from sage.combinat.root_system.cartan_type import CartanType diff --git a/src/sage/combinat/rigged_configurations/rigged_configurations.py b/src/sage/combinat/rigged_configurations/rigged_configurations.py index 01ff05f2712..61dd6842f56 100644 --- a/src/sage/combinat/rigged_configurations/rigged_configurations.py +++ b/src/sage/combinat/rigged_configurations/rigged_configurations.py @@ -31,7 +31,7 @@ from sage.combinat.misc import IterableFunctionCall import sage.combinat.tableau as tableau from sage.rings.all import QQ -from sage.categories.affine_derived_crystals import KirillovReshetikhinCrystals +from sage.categories.loop_crystals import KirillovReshetikhinCrystals from sage.combinat.root_system.cartan_type import CartanType from sage.combinat.rigged_configurations.kleber_tree import KleberTree, VirtualKleberTree from sage.combinat.rigged_configurations.rigged_configuration_element import ( From 12dc47d5c9f58264e9c3f02dcc108bf7758e0dd8 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 4 May 2017 21:49:44 -0500 Subject: [PATCH 234/452] Allow graphviz_string to take edges that are lists. --- src/sage/graphs/generic_graph.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 47740a7c5a4..9d7f62906fe 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -19494,6 +19494,13 @@ def graphviz_string(self, **options): node_4 -- node_5; } + Check that :trac:`22950` is fixed:: + + sage: D = DiGraph({1: [2]}) + sage: D.graphviz_string(edge_colors={'blue': [[1,2]]}) + 'digraph {\n node_0 [label="1"];\n node_1 [label="2"];\n\n + node_0 -> node_1 [color = "blue"];\n}' + REFERENCES: .. [dotspec] http://www.graphviz.org/doc/info/lang.html @@ -19528,7 +19535,7 @@ def graphviz_string(self, **options): color_by_edge = {} for color in options['edge_colors'].keys(): for edge in options['edge_colors'][color]: - assert isinstance(edge, tuple) and len(edge) >= 2 and len(edge) <= 3,\ + assert isinstance(edge, (list, tuple)) and len(edge) >= 2 and len(edge) <= 3,\ "%s is not a valid format for edge"%(edge) u = edge[0] v = edge[1] From 647ff396cc17c8acb59043dad905ab882834017b Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Fri, 5 May 2017 10:44:33 +0200 Subject: [PATCH 235/452] 17505: unevaluated symbolic product --- src/sage/calculus/calculus.py | 5 ++++- src/sage/functions/other.py | 30 ++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/sage/calculus/calculus.py b/src/sage/calculus/calculus.py index e0ae5df1739..216c41ba70a 100644 --- a/src/sage/calculus/calculus.py +++ b/src/sage/calculus/calculus.py @@ -2024,7 +2024,10 @@ def symbolic_expression_from_maxima_string(x, equals_sub=False, maxima=maxima): formal_functions = maxima_tick.findall(s) if len(formal_functions) > 0: for X in formal_functions: - syms[X[1:]] = function_factory(X[1:]) + try: + syms[X[1:]] = _syms[X[1:]] + except KeyError: + syms[X[1:]] = function_factory(X[1:]) # You might think there is a potential very subtle bug if 'foo # is in a string literal -- but string literals should *never* # ever be part of a symbolic expression. diff --git a/src/sage/functions/other.py b/src/sage/functions/other.py index 29b2753fde6..1cc42560f6f 100644 --- a/src/sage/functions/other.py +++ b/src/sage/functions/other.py @@ -2608,3 +2608,33 @@ def __init__(self): conversions=dict(maxima='sum')) symbolic_sum = Function_sum() + + +class Function_prod(BuiltinFunction): + """ + Placeholder symbolic product function that is only accessible internally. + + EXAMPLES:: + + sage: from sage.functions.other import symbolic_product as sprod + sage: sprod(x, x, 1, 10) + product(x, x, 1, 10) + """ + def __init__(self): + """ + EXAMPLES:: + + sage: from sage.functions.other import symbolic_product as sprod + sage: _ = var('n') + sage: r = maxima(sprod(sin(x), x, 1, n)).sage(); r + product(sin(x), x, 1, n) + sage: isinstance(r.operator(), sage.functions.other.Function_prod) + True + sage: maxima(sprod(x, x, 1, 5)) + 120 + """ + BuiltinFunction.__init__(self, "product", nargs=4, + conversions=dict(maxima='product', + sympy='Product')) + +symbolic_product = Function_prod() From df53e2fe24baf5733739e9ccd6c3de44f992442d Mon Sep 17 00:00:00 2001 From: "Erik M. Bray" Date: Fri, 5 May 2017 11:36:52 +0200 Subject: [PATCH 236/452] This should be passing the --all flag to sage-rebase.sh --- src/bin/sage-rebaseall.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/sage-rebaseall.sh b/src/bin/sage-rebaseall.sh index b4de6dbcdb0..aa0ab9df20f 100755 --- a/src/bin/sage-rebaseall.sh +++ b/src/bin/sage-rebaseall.sh @@ -17,4 +17,4 @@ # (which usually means admin rights). DIR=$(dirname "$(readlink -f "$0")") -exec "$DIR"/sage-rebase.sh" $@ +exec "$DIR"/sage-rebase.sh" --all $@ From 87d58c25308c9e6e4610569b44241d8ee20e591a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jori=20M=C3=A4ntysalo?= Date: Fri, 5 May 2017 13:04:03 +0300 Subject: [PATCH 237/452] Add a test. --- src/sage/combinat/posets/lattices.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/sage/combinat/posets/lattices.py b/src/sage/combinat/posets/lattices.py index d34a1950831..607155c3536 100644 --- a/src/sage/combinat/posets/lattices.py +++ b/src/sage/combinat/posets/lattices.py @@ -3751,6 +3751,16 @@ def is_constructible_by_doublings(self, type): sage: LatticePoset().is_constructible_by_doublings('interval') True + The congruence lattice of this lattice has maximal chains satisfying the needed + property, but also maximal chains not satisfying that; this shows that the code + can't be optimized to test just some maximal chain:: + + sage: L = LatticePoset(DiGraph('QSO?I?_?_GBG??_??a???@?K??A??B???C??s??G??I??@??A??@???')) + sage: L.is_constructible_by_doublings('convex') + False + sage: L.is_constructible_by_doublings('any') + True + ALGORITHM: According to [HOLM2016]_ a lattice `L` is lower bounded if and only if From 42aeeaeef9f4986dc0de93d630c81c651666f2f1 Mon Sep 17 00:00:00 2001 From: "Erik M. Bray" Date: Fri, 8 Jul 2016 14:31:04 +0200 Subject: [PATCH 238/452] Include ECL .fas binaries (which are DLLs) when calling rebase(all) Not sure if the -s options to rebaseall are strictly needed, but it can't hurt to include. --- src/bin/sage-rebase.sh | 2 +- src/bin/sage-rebaseall.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bin/sage-rebase.sh b/src/bin/sage-rebase.sh index 68f425cd1d6..e4f4caf37ed 100755 --- a/src/bin/sage-rebase.sh +++ b/src/bin/sage-rebase.sh @@ -11,6 +11,6 @@ # Invoke this script from a shell after going to the SAGE_ROOT directory. echo "Getting list of dlls. This may take a while..." -/bin/find local -name "*.dll" -o -name "*.so" > /tmp/sage-dlls.lst +/bin/find local -name "*.dll" -o -name "*.so" -o -name "*.fas" > /tmp/sage-dlls.lst echo "Now rebasing..." /bin/rebase -O -T /tmp/sage-dlls.lst diff --git a/src/bin/sage-rebaseall.sh b/src/bin/sage-rebaseall.sh index 09398ca8fbf..3b922812cc5 100755 --- a/src/bin/sage-rebaseall.sh +++ b/src/bin/sage-rebaseall.sh @@ -17,6 +17,6 @@ # (which usually means admin rights). echo "Getting list of dlls. This may take a while..." -/bin/find local -name "*.dll" -o -name "*.so" > /tmp/sage-dlls.lst +/bin/find local -name "*.dll" -o -name "*.so" -o -name "*.fas" > /tmp/sage-dlls.lst echo "Now rebasing..." -/bin/rebaseall -T /tmp/sage-dlls.lst +/bin/rebaseall -s dll -s exe -s so -s fas -T /tmp/sage-dlls.lst From b60823b727f76951f313445ef9f821bfeaf54556 Mon Sep 17 00:00:00 2001 From: "Erik M. Bray" Date: Fri, 8 Jul 2016 14:41:26 +0200 Subject: [PATCH 239/452] These scripts don't necessarily need to know where SAGE_ROOT is, just SAGE_LOCAL (SAGE_LOCAL may not even be *in* SAGE_ROOT) --- src/bin/sage-rebase.bat | 10 +++++----- src/bin/sage-rebase.sh | 6 +++--- src/bin/sage-rebaseall.bat | 10 +++++----- src/bin/sage-rebaseall.sh | 6 +++--- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/bin/sage-rebase.bat b/src/bin/sage-rebase.bat index 68777b06dfe..f0e45f87d3a 100755 --- a/src/bin/sage-rebase.bat +++ b/src/bin/sage-rebase.bat @@ -2,23 +2,23 @@ rem Author: rem * Jean-Pierre Flori rem -rem Rebase all dlls in the SAGE_ROOT directory (and its subdirectories), +rem Rebase all dlls in the SAGE_LOCAL directory (and its subdirectories), rem but do not touch the ones already stored in the system database, rem and do not update it. rem Note that subsequent calls to 'rebaseall' will not update the Sage dlls. rem rem Invoke this script from a Windows command prompt, -rem after adjusting SAGE_ROOT to the Windows location of the Sage directory, +rem after adjusting SAGE_LOCAL to the Windows location of the Sage directory, rem and, if Cygwin is installed in a non-standard location, rem adjusting CYGWIN_ROOT. set CYGWIN_ROOT=C:\cygwin\ -set SAGE_ROOT=C:\cygwin\usr\local\sage\ +set SAGE_LOCAL=C:\cygwin\usr\local\sage\ rem Make sure bash can be called from MSDOS prompt: path %CYGWIN_ROOT%\bin;%path% rem Suppress warning about MSDOS-style path: set CYGWIN=%CYGWIN% nodosfilewarning rem Call the bash script to do the real work: -cd %SAGE_ROOT% -bash .\local\bin\sage-rebase.sh +cd %SAGE_LOCAL% +bash bin\sage-rebase.sh diff --git a/src/bin/sage-rebase.sh b/src/bin/sage-rebase.sh index e4f4caf37ed..46f0affb987 100755 --- a/src/bin/sage-rebase.sh +++ b/src/bin/sage-rebase.sh @@ -3,14 +3,14 @@ # Author: # * Jean-Pierre Flori # -# Rebase all dlls in the SAGE_ROOT directory (and its subdirectories), +# Rebase all dlls in the SAGE_LOCAL directory (and its subdirectories), # but do not touch the ones already stored in the system database, # and do not update it. # Note that subsequent calls to 'rebaseall' will not update the Sage dlls. # -# Invoke this script from a shell after going to the SAGE_ROOT directory. +# Invoke this script from a shell after going to the SAGE_LOCAL directory. echo "Getting list of dlls. This may take a while..." -/bin/find local -name "*.dll" -o -name "*.so" -o -name "*.fas" > /tmp/sage-dlls.lst +/bin/find . -name "*.dll" -o -name "*.so" -o -name "*.fas" > /tmp/sage-dlls.lst echo "Now rebasing..." /bin/rebase -O -T /tmp/sage-dlls.lst diff --git a/src/bin/sage-rebaseall.bat b/src/bin/sage-rebaseall.bat index 75122e335a3..4078a37bd20 100755 --- a/src/bin/sage-rebaseall.bat +++ b/src/bin/sage-rebaseall.bat @@ -3,14 +3,14 @@ rem Authors: rem * Dmitrii Pasechnik rem * Jean-Pierre Flori rem -rem Rebase all dlls in the SAGE_ROOT directory (and its subdirectories), +rem Rebase all dlls in the SAGE_LOCAL directory (and its subdirectories), rem as well as the ones already stored in the system database, rem and update the database. rem This system-wide database is located in '/etc/rebase.db.i386' and rem includes the Cygwin system dlls. rem rem Invoke this script from a Windows command prompt, -rem after adjusting SAGE_ROOT to the Windows location of the Sage directory, +rem after adjusting SAGE_LOCAL to the Windows location of the Sage directory, rem and, if Cygwin is installed in a non-standard location, rem adjusting CYGWIN_ROOT. rem Ensure that no other Cygwin processes are currently running. @@ -18,12 +18,12 @@ rem Note that you need write access to the system-wide rebase database rem (which usually means admin rights). set CYGWIN_ROOT=C:\cygwin\ -set SAGE_ROOT=C:\cygwin\usr\local\sage\ +set SAGE_LOCAL=C:\cygwin\usr\local\sage\ rem Make sure dash can be called from MSDOS prompt: path %CYGWIN_ROOT%\bin;%path% rem Suppress warning about MSDOS-style path: set CYGWIN=%CYGWIN% nodosfilewarning rem Call the dash script to do the real work: -cd %SAGE_ROOT% -dash .\local\bin\sage-rebaseall.sh +cd %SAGE_LOCAL% +dash bin\sage-rebaseall.sh diff --git a/src/bin/sage-rebaseall.sh b/src/bin/sage-rebaseall.sh index 3b922812cc5..f43d73f39e5 100755 --- a/src/bin/sage-rebaseall.sh +++ b/src/bin/sage-rebaseall.sh @@ -5,18 +5,18 @@ # * Dmitrii Pasechnik # * Jean-Pierre Flori # -# Rebase all dlls in the SAGE_ROOT directory (and its subdirectories) +# Rebase all dlls in the SAGE_LOCAL directory (and its subdirectories) # as well as the ones already stored in the system database, # and update the database. # This system-wide database is located in '/etc/rebase.db.i386' and # includes the Cygwin system dlls. # -# Invoke this script from a dash shell after going to the SAGE_ROOT directory. +# Invoke this script from a dash shell after going to the SAGE_LOCAL directory. # Ensure that no other Cygwin processes are currently running. # Note that you need write access to the system-wide rebase database # (which usually means admin rights). echo "Getting list of dlls. This may take a while..." -/bin/find local -name "*.dll" -o -name "*.so" -o -name "*.fas" > /tmp/sage-dlls.lst +/bin/find . -name "*.dll" -o -name "*.so" -o -name "*.fas" > /tmp/sage-dlls.lst echo "Now rebasing..." /bin/rebaseall -s dll -s exe -s so -s fas -T /tmp/sage-dlls.lst From e2905b1c16a508027c66f6c118000b090d346f55 Mon Sep 17 00:00:00 2001 From: "Erik M. Bray" Date: Fri, 8 Jul 2016 15:16:34 +0200 Subject: [PATCH 240/452] Update these batch scripts so that it's not necessary to manually specify the paths of SAGE_LOCAL or CYGWIN_ROOT --- src/bin/sage-rebase.bat | 36 ++++++++++++++++++++++++++++++++---- src/bin/sage-rebaseall.bat | 35 +++++++++++++++++++++++++++++++---- 2 files changed, 63 insertions(+), 8 deletions(-) diff --git a/src/bin/sage-rebase.bat b/src/bin/sage-rebase.bat index f0e45f87d3a..de481343786 100755 --- a/src/bin/sage-rebase.bat +++ b/src/bin/sage-rebase.bat @@ -1,19 +1,32 @@ @echo off rem Author: rem * Jean-Pierre Flori +rem * Erik M. Bray rem rem Rebase all dlls in the SAGE_LOCAL directory (and its subdirectories), rem but do not touch the ones already stored in the system database, rem and do not update it. rem Note that subsequent calls to 'rebaseall' will not update the Sage dlls. rem -rem Invoke this script from a Windows command prompt, -rem after adjusting SAGE_LOCAL to the Windows location of the Sage directory, +rem Invoke this script from a Windows command prompt rem and, if Cygwin is installed in a non-standard location, rem adjusting CYGWIN_ROOT. -set CYGWIN_ROOT=C:\cygwin\ -set SAGE_LOCAL=C:\cygwin\usr\local\sage\ +setlocal ENABLEEXTENSIONS + +set THIS_BIN=%~dp0 + +rem SAGE_LOCAL should be one level up from the bin/ this script is in +rem This is about the most elegant way to do this I can find thanks +rem http://stackoverflow.com/a/33404867/982257 +call :NORMALIZEPATH "%THIS_BIN%.." +set SAGE_LOCAL=%RETVAL% + +rem Cygwin saves its installation root here +rem If there is more than one Cygwin installation on the system this +rem will just pick up the first one +call :READREGISTRY HKEY_LOCAL_MACHINE\SOFTWARE\Cygwin\setup rootdir +set CYGWIN_ROOT=%RETVAL% rem Make sure bash can be called from MSDOS prompt: path %CYGWIN_ROOT%\bin;%path% @@ -22,3 +35,18 @@ set CYGWIN=%CYGWIN% nodosfilewarning rem Call the bash script to do the real work: cd %SAGE_LOCAL% bash bin\sage-rebase.sh + + +:: ========== FUNCTIONS ========== +exit /B + +:READREGISTRY + for /F "usebackq skip=2 tokens=3" %%V in (`reg query %1 /v %2 2^>nul`) do ( + set RETVAL=%%V + break + ) + exit /B + +:NORMALIZEPATH + set RETVAL=%~dpfn1 + exit /B diff --git a/src/bin/sage-rebaseall.bat b/src/bin/sage-rebaseall.bat index 4078a37bd20..0ae927f5e64 100755 --- a/src/bin/sage-rebaseall.bat +++ b/src/bin/sage-rebaseall.bat @@ -2,6 +2,7 @@ rem Authors: rem * Dmitrii Pasechnik rem * Jean-Pierre Flori +rem * Erik M. Bray rem rem Rebase all dlls in the SAGE_LOCAL directory (and its subdirectories), rem as well as the ones already stored in the system database, @@ -9,16 +10,27 @@ rem and update the database. rem This system-wide database is located in '/etc/rebase.db.i386' and rem includes the Cygwin system dlls. rem -rem Invoke this script from a Windows command prompt, -rem after adjusting SAGE_LOCAL to the Windows location of the Sage directory, +rem Invoke this script from a Windows command prompt rem and, if Cygwin is installed in a non-standard location, rem adjusting CYGWIN_ROOT. +rem rem Ensure that no other Cygwin processes are currently running. rem Note that you need write access to the system-wide rebase database rem (which usually means admin rights). -set CYGWIN_ROOT=C:\cygwin\ -set SAGE_LOCAL=C:\cygwin\usr\local\sage\ +set THIS_BIN=%~dp0 + +rem SAGE_LOCAL should be one level up from the bin/ this script is in +rem This is about the most elegant way to do this I can find thanks +rem http://stackoverflow.com/a/33404867/982257 +call :NORMALIZEPATH "%THIS_BIN%.." +set SAGE_LOCAL=%RETVAL% + +rem Cygwin saves its installation root here +rem If there is more than one Cygwin installation on the system this +rem will just pick up the first one +call :READREGISTRY HKEY_LOCAL_MACHINE\SOFTWARE\Cygwin\setup rootdir +set CYGWIN_ROOT=%RETVAL% rem Make sure dash can be called from MSDOS prompt: path %CYGWIN_ROOT%\bin;%path% @@ -27,3 +39,18 @@ set CYGWIN=%CYGWIN% nodosfilewarning rem Call the dash script to do the real work: cd %SAGE_LOCAL% dash bin\sage-rebaseall.sh + + +:: ========== FUNCTIONS ========== +exit /B + +:READREGISTRY + for /F "usebackq skip=2 tokens=3" %%V in (`reg query %1 /v %2 2^>nul`) do ( + set RETVAL=%%V + break + ) + exit /B + +:NORMALIZEPATH + set RETVAL=%~dpfn1 + exit /B From 5d8910c65f8c193ddb265a4a0ca10a436206c033 Mon Sep 17 00:00:00 2001 From: "Erik M. Bray" Date: Fri, 21 Apr 2017 16:46:45 +0200 Subject: [PATCH 241/452] Accept the path to SAGE_LOCAL as an argument (this is useful for running outside the Sage shell). Exclude /var/tmp from the list of DLLs to rebase. --- src/bin/sage-rebase.sh | 11 ++++++++++- src/bin/sage-rebaseall.sh | 12 +++++++++++- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/bin/sage-rebase.sh b/src/bin/sage-rebase.sh index 46f0affb987..ba17749b964 100755 --- a/src/bin/sage-rebase.sh +++ b/src/bin/sage-rebase.sh @@ -9,8 +9,17 @@ # Note that subsequent calls to 'rebaseall' will not update the Sage dlls. # # Invoke this script from a shell after going to the SAGE_LOCAL directory. +SAGE_LOCAL=${1%/} + +if [ -z "$SAGE_LOCAL" ]; then + # Assume we are in $SAGE_LOCAL by default (the old behavior of this script) + SAGE_LOCAL=. +fi + +FINDFLAGS="-type f ( -name *.dll -o -name *.so -o -name *.fas ) -print" +FINDFLAGS="$FINDFLAGS -o -path "$SAGE_LOCAL"/var/tmp -prune" echo "Getting list of dlls. This may take a while..." -/bin/find . -name "*.dll" -o -name "*.so" -o -name "*.fas" > /tmp/sage-dlls.lst +/bin/find "$SAGE_LOCAL" $FINDFLAGS > /tmp/sage-dlls.lst echo "Now rebasing..." /bin/rebase -O -T /tmp/sage-dlls.lst diff --git a/src/bin/sage-rebaseall.sh b/src/bin/sage-rebaseall.sh index f43d73f39e5..6db661c00d4 100755 --- a/src/bin/sage-rebaseall.sh +++ b/src/bin/sage-rebaseall.sh @@ -16,7 +16,17 @@ # Note that you need write access to the system-wide rebase database # (which usually means admin rights). +SAGE_LOCAL=${1%/} + +if [ -z "$SAGE_LOCAL" ]; then + # Assume we are in $SAGE_LOCAL by default (the old behavior of this script) + SAGE_LOCAL=. +fi + +FINDFLAGS="-type f ( -name *.dll -o -name *.so -o -name *.fas ) -print" +FINDFLAGS="$FINDFLAGS -o -path "$SAGE_LOCAL"/var/tmp -prune" + echo "Getting list of dlls. This may take a while..." -/bin/find . -name "*.dll" -o -name "*.so" -o -name "*.fas" > /tmp/sage-dlls.lst +/bin/find "$SAGE_LOCAL" $FINDFLAGS > /tmp/sage-dlls.lst echo "Now rebasing..." /bin/rebaseall -s dll -s exe -s so -s fas -T /tmp/sage-dlls.lst From 43eb7bfc8757b82c88b01f5e4350271dc3776c67 Mon Sep 17 00:00:00 2001 From: "Erik M. Bray" Date: Tue, 25 Apr 2017 09:50:17 +0200 Subject: [PATCH 242/452] Enhance sage-rebase.sh to be able to pass additional arguments to rebase, and to wrap the call to rebaseall sage-rebaseall.sh is now just a wrapper around sage-rebase.sh so there doesn't have to be so much duplication between them. --- src/bin/sage-rebase.sh | 54 +++++++++++++++++++++++++++++++++++++-- src/bin/sage-rebaseall.sh | 16 ++---------- 2 files changed, 54 insertions(+), 16 deletions(-) diff --git a/src/bin/sage-rebase.sh b/src/bin/sage-rebase.sh index ba17749b964..79b0b4bdc1c 100755 --- a/src/bin/sage-rebase.sh +++ b/src/bin/sage-rebase.sh @@ -2,14 +2,59 @@ # Author: # * Jean-Pierre Flori +# * Gary Zablackis +# * Dmitrii Pasechnik +# * Erik M. Bray # # Rebase all dlls in the SAGE_LOCAL directory (and its subdirectories), # but do not touch the ones already stored in the system database, # and do not update it. # Note that subsequent calls to 'rebaseall' will not update the Sage dlls. # +# Usage: +# +# sage-rebase.sh [--all] [sage_local] [-- additional_flags] +# +# Positional arguments: +# +# sage_local optionally, provide the path to the $SAGE_LOCAL directory to +# search for DLLs to rebase; otherwise the current working +# directory is assumed to be $SAGE_LOCAL unless $SAGE_LOCAL +# is already set in the environment +# +# Optional arguments: +# +# --all run rebaseall instead of rebase (originally the call to +# rebaseall was in the sage-rebaseall.sh script, but now that is +# just a wrapper around this script) +# +# -- additional arguments passed in after -- are passed to the +# rebase/rebaseall call in addition to the default arguments +# passed in by this script +# # Invoke this script from a shell after going to the SAGE_LOCAL directory. -SAGE_LOCAL=${1%/} +ALL=0 +REBASEFLAGS="" + +while [ $# -gt 0 ]; do + case "$1" in + --all) + ALL=1 + ;; + --) + shift + REBASEFLAGS="$REBASEFLAGS $1" + ;; + *) + if [ -z "$REBASEFLAGS" ]; then + SAGE_LOCAL="${1%/}" + else + REBASEFLAGS="$REBASEFLAGS $1" + fi + ;; + esac + shift +done if [ -z "$SAGE_LOCAL" ]; then # Assume we are in $SAGE_LOCAL by default (the old behavior of this script) @@ -22,4 +67,9 @@ FINDFLAGS="$FINDFLAGS -o -path "$SAGE_LOCAL"/var/tmp -prune" echo "Getting list of dlls. This may take a while..." /bin/find "$SAGE_LOCAL" $FINDFLAGS > /tmp/sage-dlls.lst echo "Now rebasing..." -/bin/rebase -O -T /tmp/sage-dlls.lst + +if [ $ALL -eq 0 ]; then + /bin/rebase -O -T /tmp/sage-dlls.lst $REBASEFLAGS +else + /bin/rebaseall -s dll -s exe -s so -s fas -T /tmp/sage-dlls.lst $REBASEFLAGS +fi diff --git a/src/bin/sage-rebaseall.sh b/src/bin/sage-rebaseall.sh index 6db661c00d4..b4de6dbcdb0 100755 --- a/src/bin/sage-rebaseall.sh +++ b/src/bin/sage-rebaseall.sh @@ -16,17 +16,5 @@ # Note that you need write access to the system-wide rebase database # (which usually means admin rights). -SAGE_LOCAL=${1%/} - -if [ -z "$SAGE_LOCAL" ]; then - # Assume we are in $SAGE_LOCAL by default (the old behavior of this script) - SAGE_LOCAL=. -fi - -FINDFLAGS="-type f ( -name *.dll -o -name *.so -o -name *.fas ) -print" -FINDFLAGS="$FINDFLAGS -o -path "$SAGE_LOCAL"/var/tmp -prune" - -echo "Getting list of dlls. This may take a while..." -/bin/find "$SAGE_LOCAL" $FINDFLAGS > /tmp/sage-dlls.lst -echo "Now rebasing..." -/bin/rebaseall -s dll -s exe -s so -s fas -T /tmp/sage-dlls.lst +DIR=$(dirname "$(readlink -f "$0")") +exec "$DIR"/sage-rebase.sh" $@ From 784c0e2098ecd2ccbc3fc774604d0ab85c150f77 Mon Sep 17 00:00:00 2001 From: "Erik M. Bray" Date: Fri, 5 May 2017 11:36:52 +0200 Subject: [PATCH 243/452] This should be passing the --all flag to sage-rebase.sh --- src/bin/sage-rebaseall.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin/sage-rebaseall.sh b/src/bin/sage-rebaseall.sh index b4de6dbcdb0..aa0ab9df20f 100755 --- a/src/bin/sage-rebaseall.sh +++ b/src/bin/sage-rebaseall.sh @@ -17,4 +17,4 @@ # (which usually means admin rights). DIR=$(dirname "$(readlink -f "$0")") -exec "$DIR"/sage-rebase.sh" $@ +exec "$DIR"/sage-rebase.sh" --all $@ From 747e201d99e0b527419fe3c396f81264aae49bca Mon Sep 17 00:00:00 2001 From: "Erik M. Bray" Date: Fri, 3 Feb 2017 16:43:45 +0100 Subject: [PATCH 244/452] Run sage-rebase between each spkg install on Cygwin --- build/bin/sage-spkg | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/build/bin/sage-spkg b/build/bin/sage-spkg index 5086e5e1fa4..2f249585c9a 100755 --- a/build/bin/sage-spkg +++ b/build/bin/sage-spkg @@ -749,6 +749,13 @@ else fi fi +if [ "$UNAME" = "CYGWIN" ]; then + # Rebase after installing each package--in case any packages load this + # package at build time we need to ensure during the build that no binaries + # have conflicting address spaces + sage-rebase.sh "$SAGE_LOCAL" +fi + echo "Successfully installed $PKG_NAME" if [ "$SAGE_CHECK" = "yes" ]; then From 6579d0afeda1a5998ddb54a4686345f1b631c483 Mon Sep 17 00:00:00 2001 From: "Erik M. Bray" Date: Fri, 5 May 2017 11:03:51 +0200 Subject: [PATCH 245/452] Also rebase after building sagelib itself --- build/make/deps | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build/make/deps b/build/make/deps index d966369ca44..76d553a9ded 100644 --- a/build/make/deps +++ b/build/make/deps @@ -163,7 +163,10 @@ sagelib: \ $(EXTCODE) $(AM_V_at)if [ -z "$$SAGE_INSTALL_FETCH_ONLY" ]; then \ cd $(SAGE_SRC) && source bin/sage-env && \ - sage-logger -p 'time $(MAKE) sage' '$(SAGE_LOGS)/sagelib-$(SAGE_VERSION).log'; \ + sage-logger -p 'time $(MAKE) sage' '$(SAGE_LOGS)/sagelib-$(SAGE_VERSION).log' && \ + if [ "$$UNAME" = "CYGWIN" ]; then \ + sage-rebase.sh "$$SAGE_LOCAL"; \ + fi \ fi From 8c2d48e8c2cbf0e3423a284a471d6b7957223097 Mon Sep 17 00:00:00 2001 From: "Erik M. Bray" Date: Fri, 5 May 2017 14:15:18 +0200 Subject: [PATCH 246/452] Make the rebase call after each package quiet. Originally tried to pass the --quiet option to rebase, but it turns out that doesn't really work as advertised, as it's actually still quite noisy about non-critical issues (specifically rebased DLLs that are already in its database). So the only way to really make it shut up is to divert stderr to /dev/null, which is a shame since it could mask real errors. --- build/bin/sage-spkg | 2 +- build/make/deps | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build/bin/sage-spkg b/build/bin/sage-spkg index 2f249585c9a..c7e29d04fd5 100755 --- a/build/bin/sage-spkg +++ b/build/bin/sage-spkg @@ -753,7 +753,7 @@ if [ "$UNAME" = "CYGWIN" ]; then # Rebase after installing each package--in case any packages load this # package at build time we need to ensure during the build that no binaries # have conflicting address spaces - sage-rebase.sh "$SAGE_LOCAL" + sage-rebase.sh "$SAGE_LOCAL" 2>/dev/null fi echo "Successfully installed $PKG_NAME" diff --git a/build/make/deps b/build/make/deps index 76d553a9ded..5b939d4abe1 100644 --- a/build/make/deps +++ b/build/make/deps @@ -165,7 +165,7 @@ sagelib: \ cd $(SAGE_SRC) && source bin/sage-env && \ sage-logger -p 'time $(MAKE) sage' '$(SAGE_LOGS)/sagelib-$(SAGE_VERSION).log' && \ if [ "$$UNAME" = "CYGWIN" ]; then \ - sage-rebase.sh "$$SAGE_LOCAL"; \ + sage-rebase.sh "$$SAGE_LOCAL" 2>/dev/null \ fi \ fi From ff8e807cc09c483cc84527bb06dc4464892c1a1e Mon Sep 17 00:00:00 2001 From: "Erik M. Bray" Date: Fri, 5 May 2017 16:15:37 +0200 Subject: [PATCH 247/452] Move the sage-rebase.sh after sagelib installation to the Makefile for sagelib itself, rather than build/make/deps This ensures that rebase is run in other contexts, such as running ./sage -b. If setup.py is run manually then rebase needs to be run manually too. --- build/make/deps | 5 +---- src/Makefile.in | 5 ++++- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build/make/deps b/build/make/deps index 5b939d4abe1..d966369ca44 100644 --- a/build/make/deps +++ b/build/make/deps @@ -163,10 +163,7 @@ sagelib: \ $(EXTCODE) $(AM_V_at)if [ -z "$$SAGE_INSTALL_FETCH_ONLY" ]; then \ cd $(SAGE_SRC) && source bin/sage-env && \ - sage-logger -p 'time $(MAKE) sage' '$(SAGE_LOGS)/sagelib-$(SAGE_VERSION).log' && \ - if [ "$$UNAME" = "CYGWIN" ]; then \ - sage-rebase.sh "$$SAGE_LOCAL" 2>/dev/null \ - fi \ + sage-logger -p 'time $(MAKE) sage' '$(SAGE_LOGS)/sagelib-$(SAGE_VERSION).log'; \ fi diff --git a/src/Makefile.in b/src/Makefile.in index bf04a2c52e6..49e18df2135 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -39,7 +39,10 @@ sage: SAGE_BUILD_DIR=/doesnotexist \ SAGE_PKGS=$(abs_top_srcdir)/build/pkgs \ SAGE_CYTHONIZED=$(abs_builddir)/build/cythonized \ - && sage-python23 -u setup.py --no-user-cfg build install) + && sage-python23 -u setup.py --no-user-cfg build install \ + && if [ "$$UNAME" = "CYGWIN" ]; then \ + sage-rebase.sh "$$SAGE_LOCAL" 2>/dev/null; \ + fi) clean: @echo "Deleting Sage library build artifacts..." From 394de758ff2e20e31028e0496d920b0e282441d8 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Fri, 5 May 2017 10:30:43 -0500 Subject: [PATCH 248/452] A few last little doc tweaks. --- .../lie_algebras/affine_lie_algebra.py | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/sage/algebras/lie_algebras/affine_lie_algebra.py b/src/sage/algebras/lie_algebras/affine_lie_algebra.py index ba8cb4a345c..df44fe3fc84 100644 --- a/src/sage/algebras/lie_algebras/affine_lie_algebra.py +++ b/src/sage/algebras/lie_algebras/affine_lie_algebra.py @@ -40,8 +40,8 @@ class AffineLieAlgebra(FinitelyGeneratedLieAlgebra): .. MATH:: - \widehat{\mathfrak{g}}^{\prime} = \left( \mathfrak{g} \otimes - R[t, t^{-1}] \right) \oplus R c, + \widehat{\mathfrak{g}}' = \bigl( \mathfrak{g} \otimes + R[t, t^{-1}] \bigr) \oplus R c, where `c` is the canonical central element and `R[t, t^{-1}]` is the Laurent polynomial ring over `R`. We define the Lie bracket as @@ -53,8 +53,8 @@ class AffineLieAlgebra(FinitelyGeneratedLieAlgebra): where `( a | b )` is the Killing form on `\mathfrak{g}`. - There is a canonical derivative on `\widehat{\mathfrak{g}}^{\prime}` - which is known as the *Lie derivative* and is denoted by `\delta`. + There is a canonical derivative on `\widehat{\mathfrak{g}}'` + known as the *Lie derivative* and is denoted by `\delta`. The Lie derivative is defined as .. MATH:: @@ -64,9 +64,9 @@ class AffineLieAlgebra(FinitelyGeneratedLieAlgebra): or equivalently by `\delta = t \frac{d}{dt}`. We can form the affine Kac-Moody algebra `\widehat{\mathfrak{g}}` - by adding the additional generator `d` such that `[d, x] = \delta(x)` - where `\delta` is the Lie derivative. We note that the derived subalgebra - of the Kac-Moody algebra is the affine Lie algebra. + by adding the additional generator `d` such that `[d, x] = \delta(x)`, + where `\delta` is the Lie derivative. We note that the derived + subalgebra of the Kac-Moody algebra is the affine Lie algebra. .. NOTE:: @@ -191,7 +191,7 @@ def __init__(self, g, kac_moody): FinitelyGeneratedLieAlgebra.__init__(self, R, names, names, category=cat) def _repr_(self): - """ + r""" Return a string representation of ``self``. EXAMPLES:: @@ -213,7 +213,7 @@ def _repr_(self): @cached_method def basis(self): - """ + r""" Return the basis of ``self``. EXAMPLES:: @@ -243,7 +243,7 @@ def basis(self): return Family(keys, self.monomial) def _element_constructor_(self, x): - """ + r""" Construct an element of ``self`` from ``x``. EXAMPLES:: @@ -356,7 +356,7 @@ def cartan_type(self): return self._cartan_type def classical(self): - """ + r""" Return the classical Lie algebra of ``self``. EXAMPLES:: @@ -374,7 +374,7 @@ def classical(self): @cached_method def zero(self): - """ + r""" Return the element `0`. EXAMPLES:: @@ -405,7 +405,7 @@ def delta(self): r""" Return the Lie derivative element `\delta` or ``self``. - If ``self`` is the affine Lie algebra, then this returns 0. + If ``self`` is the affine Lie algebra, then this returns `0`. EXAMPLES:: @@ -423,7 +423,7 @@ def delta(self): @cached_method def lie_algebra_generators(self): - """ + r""" Return the Lie algebra generators of ``self``. EXAMPLES:: @@ -459,7 +459,7 @@ def lie_algebra_generators(self): return Family(self.variable_names(), d.__getitem__) def monomial(self, m): - """ + r""" Construct the monomial indexed by ``m``. EXAMPLES:: From 3821151a0f02808ac9a6edd28544cac0a27c241f Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Fri, 5 May 2017 08:56:13 -0700 Subject: [PATCH 249/452] trac 22942: update python3 patches --- .../python3/patches/2.6.5-FD_SETSIZE.patch | 14 ++++++----- build/pkgs/python3/patches/2.7.3-dylib.patch | 14 ++++++----- .../patches/3.2.6-getpath-exe-extension.patch | 2 +- .../patches/3.2.6-no-enable-new-dtags.patch | 2 +- .../python3/patches/3.2.6-no-native-tls.patch | 8 +++---- .../python3/patches/3.4.5-issue13756.patch | 6 ++--- .../3.5.2-struct_siginfo_si_band.patch | 16 ++++++------- .../pkgs/python3/patches/cygwin-ctypes.patch | 10 ++++---- .../python3/patches/cygwin-readline.patch | 4 ++-- .../patches/no_strict_proto-issue_5755.patch | 4 ++-- build/pkgs/python3/patches/permissions.patch | 2 +- .../python3/patches/pyport-apple-c++.patch | 23 ------------------- build/pkgs/python3/patches/sdist.patch | 4 ++-- 13 files changed, 45 insertions(+), 64 deletions(-) delete mode 100644 build/pkgs/python3/patches/pyport-apple-c++.patch diff --git a/build/pkgs/python3/patches/2.6.5-FD_SETSIZE.patch b/build/pkgs/python3/patches/2.6.5-FD_SETSIZE.patch index 1059ca4ad45..d1e0aa7352e 100644 --- a/build/pkgs/python3/patches/2.6.5-FD_SETSIZE.patch +++ b/build/pkgs/python3/patches/2.6.5-FD_SETSIZE.patch @@ -2,11 +2,13 @@ This patch has never been submitted upstream for some reason, but it simply increases the default number of file descriptors the Python process can have on Cygwin, which mitigates some issues; see https://cygwin.com/ml/cygwin/2011-03/msg00651.html ---- a/Modules/selectmodule.c 2012-02-02 22:35:21.835125000 -0500 -+++ b/Modules/selectmodule.c 2012-02-02 22:41:41.210125000 -0500 -@@ -6,6 +6,21 @@ - >= 0. - */ +diff --git a/Python-3.6.1/Modules/selectmodule.c.orig b/Python-3.6.1/Modules/selectmodule.c +index 47da493..ae60234 100644 +--- a/Modules/selectmodule.c ++++ b/Modules/selectmodule.c +@@ -8,6 +8,21 @@ + #define _GNU_SOURCE + #endif +/* Windows #defines FD_SETSIZE to 64 if FD_SETSIZE isn't already defined. + 64 is too small (too many people have bumped into that limit). @@ -26,7 +28,7 @@ https://cygwin.com/ml/cygwin/2011-03/msg00651.html #include "Python.h" #include -@@ -16,16 +31,6 @@ +@@ -26,16 +41,6 @@ #undef HAVE_BROKEN_POLL #endif diff --git a/build/pkgs/python3/patches/2.7.3-dylib.patch b/build/pkgs/python3/patches/2.7.3-dylib.patch index c45fc26f698..be0de05d388 100644 --- a/build/pkgs/python3/patches/2.7.3-dylib.patch +++ b/build/pkgs/python3/patches/2.7.3-dylib.patch @@ -1,13 +1,15 @@ This patch provides a workaround to one long-standing problem with building extension modules on Cygwin; see https://bugs.python.org/issue2445 for more background. ---- a/Lib/distutils/unixccompiler.py 2012-11-27 07:44:15.409993500 -0500 -+++ b/Lib/distutils/unixccompiler.py 2012-11-27 08:09:57.801770900 -0500 -@@ -141,6 +141,7 @@ - static_lib_format = shared_lib_format = dylib_lib_format = "lib%s%s" +diff --git a/Lib/distutils/unixccompiler.py.orig b/Lib/distutils/unixccompiler.py +index 3f321c2..fb5a8fc 100644 +--- a/Lib/distutils/unixccompiler.py ++++ b/Lib/distutils/unixccompiler.py +@@ -81,6 +81,7 @@ class UnixCCompiler(CCompiler): + xcode_stub_lib_format = dylib_lib_format if sys.platform == "cygwin": exe_extension = ".exe" + dylib_lib_extension = ".dll.a" - def preprocess(self, source, - output_file=None, macros=None, include_dirs=None, + def preprocess(self, source, output_file=None, macros=None, + include_dirs=None, extra_preargs=None, extra_postargs=None): diff --git a/build/pkgs/python3/patches/3.2.6-getpath-exe-extension.patch b/build/pkgs/python3/patches/3.2.6-getpath-exe-extension.patch index ce4e403a2e6..bded83b383b 100644 --- a/build/pkgs/python3/patches/3.2.6-getpath-exe-extension.patch +++ b/build/pkgs/python3/patches/3.2.6-getpath-exe-extension.patch @@ -2,7 +2,7 @@ Fixes a known issue with sys.executable ambiguity on Cygwin. This is a simpler version of the patch found at http://bugs.python.org/issue28441 --- a/Modules/getpath.c +++ b/Modules/getpath.c -@@ -491,6 +491,28 @@ calculate_path(void) +@@ -551,6 +551,28 @@ calculate_path(void) if (isxfile(progpath)) break; diff --git a/build/pkgs/python3/patches/3.2.6-no-enable-new-dtags.patch b/build/pkgs/python3/patches/3.2.6-no-enable-new-dtags.patch index 7b642805925..ea9b7cecd03 100644 --- a/build/pkgs/python3/patches/3.2.6-no-enable-new-dtags.patch +++ b/build/pkgs/python3/patches/3.2.6-no-enable-new-dtags.patch @@ -4,7 +4,7 @@ diff --git a/Lib/distutils/unixccompiler.py b/Lib/distutils/unixccompiler.py index 69045f8..7ed0a5f 100644 --- a/Lib/distutils/unixccompiler.py +++ b/Lib/distutils/unixccompiler.py -@@ -239,9 +239,13 @@ class UnixCCompiler(CCompiler): +@@ -243,9 +243,13 @@ class UnixCCompiler(CCompiler): # -Wl whenever gcc was used in the past it is probably # safest to keep doing so. if sysconfig.get_config_var("GNULD") == "yes": diff --git a/build/pkgs/python3/patches/3.2.6-no-native-tls.patch b/build/pkgs/python3/patches/3.2.6-no-native-tls.patch index 8675880c2b5..9e1acab59b7 100644 --- a/build/pkgs/python3/patches/3.2.6-no-native-tls.patch +++ b/build/pkgs/python3/patches/3.2.6-no-native-tls.patch @@ -21,7 +21,7 @@ index de42f1a..a4eab78 100644 #define Py_HAVE_NATIVE_TLS int -@@ -643,3 +649,5 @@ PyThread_get_key_value(int key) +@@ -648,3 +654,5 @@ PyThread_get_key_value(int key) void PyThread_ReInitTLS(void) {} @@ -31,7 +31,7 @@ diff --git a/configure.ac b/configure.ac index 0ab4430..89e422a 100644 --- a/configure.ac +++ b/configure.ac -@@ -1610,6 +1610,19 @@ if test "$have_pthread_t" = yes ; then +@@ -2258,6 +2258,19 @@ if test "$have_pthread_t" = yes ; then #endif ]) fi @@ -55,7 +55,7 @@ diff --git a/configure b/configure index b107bf2..59f80cb 100755 --- a/configure +++ b/configure -@@ -7564,6 +7564,35 @@ _ACEOF +@@ -8981,6 +8981,35 @@ _ACEOF fi @@ -95,7 +95,7 @@ diff --git a/pyconfig.h.in b/pyconfig.h.in index cf0ea1f..0bd8387 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in -@@ -973,6 +973,9 @@ +@@ -1238,6 +1238,9 @@ /* Define if POSIX semaphores aren't enabled on your system */ #undef POSIX_SEMAPHORES_NOT_ENABLED diff --git a/build/pkgs/python3/patches/3.4.5-issue13756.patch b/build/pkgs/python3/patches/3.4.5-issue13756.patch index 7ac330d7aa0..6d35b4eebec 100644 --- a/build/pkgs/python3/patches/3.4.5-issue13756.patch +++ b/build/pkgs/python3/patches/3.4.5-issue13756.patch @@ -4,7 +4,7 @@ diff --git a/Lib/distutils/command/build_ext.py b/Lib/distutils/command/build_ex index acbe648..6bedbb2 100644 --- a/Lib/distutils/command/build_ext.py +++ b/Lib/distutils/command/build_ext.py -@@ -695,10 +695,6 @@ class build_ext(Command): +@@ -715,10 +715,6 @@ class build_ext(Command): return ext.libraries + [pythonlib] else: return ext.libraries @@ -19,7 +19,7 @@ diff --git a/Makefile.pre.in b/Makefile.pre.in index e19fc00..87b6dad 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in -@@ -636,9 +636,9 @@ $(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK): \ +@@ -672,9 +672,9 @@ $(PYTHONFRAMEWORKDIR)/Versions/$(VERSION)/$(PYTHONFRAMEWORK): \ $(LN) -fsn Versions/Current/$(PYTHONFRAMEWORK) $(PYTHONFRAMEWORKDIR)/$(PYTHONFRAMEWORK) $(LN) -fsn Versions/Current/Resources $(PYTHONFRAMEWORKDIR)/Resources @@ -35,7 +35,7 @@ diff --git a/Modules/makesetup b/Modules/makesetup index 8b5cc28..abc7eee 100755 --- a/Modules/makesetup +++ b/Modules/makesetup -@@ -91,7 +91,7 @@ CYGWIN*) if test $libdir = . +@@ -92,7 +92,7 @@ CYGWIN*) if test $libdir = . else ExtraLibDir='$(LIBPL)' fi diff --git a/build/pkgs/python3/patches/3.5.2-struct_siginfo_si_band.patch b/build/pkgs/python3/patches/3.5.2-struct_siginfo_si_band.patch index c2ee6104051..e0c76403d52 100644 --- a/build/pkgs/python3/patches/3.5.2-struct_siginfo_si_band.patch +++ b/build/pkgs/python3/patches/3.5.2-struct_siginfo_si_band.patch @@ -5,7 +5,7 @@ diff --git a/Modules/signalmodule.c b/Modules/signalmodule.c index 753d987..c69c0ce 100644 --- a/Modules/signalmodule.c +++ b/Modules/signalmodule.c -@@ -962,7 +962,11 @@ fill_siginfo(siginfo_t *si) +@@ -957,7 +957,11 @@ fill_siginfo(siginfo_t *si) PyStructSequence_SET_ITEM(result, 4, _PyLong_FromUid(si->si_uid)); PyStructSequence_SET_ITEM(result, 5, PyLong_FromLong((long)(si->si_status))); @@ -39,15 +39,13 @@ index 2fbe259..8281f95 100755 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for time.h that defines altzone" >&5 $as_echo_n "checking for time.h that defines altzone... " >&6; } diff --git a/configure.ac b/configure.ac -index 8ef1760..6bfee80 100644 +index 9eacf52..b4da665 100644 --- a/configure.ac +++ b/configure.ac -@@ -3692,7 +3692,9 @@ - AC_CHECK_MEMBERS([struct stat.st_flags]) - AC_CHECK_MEMBERS([struct stat.st_gen]) - AC_CHECK_MEMBERS([struct stat.st_birthtime]) --AC_STRUCT_ST_BLOCKS -+AC_CHECK_MEMBERS([struct stat.st_blocks]) +@@ -3943,6 +3943,8 @@ AC_CHECK_MEMBERS([struct passwd.pw_gecos, struct passwd.pw_passwd], [], [], [[ + #include + #include + ]]) +# Issue #21085: In Cygwin, siginfo_t does not have si_band field. +AC_CHECK_MEMBERS([siginfo_t.si_band], [], [], [[#include ]]) @@ -57,7 +55,7 @@ diff --git a/pyconfig.h.in b/pyconfig.h.in index 6304a8e..eda0cf9 100644 --- a/pyconfig.h.in +++ b/pyconfig.h.in -@@ -837,6 +837,9 @@ +@@ -856,6 +856,9 @@ /* Define to 1 if you have the `sigaltstack' function. */ #undef HAVE_SIGALTSTACK diff --git a/build/pkgs/python3/patches/cygwin-ctypes.patch b/build/pkgs/python3/patches/cygwin-ctypes.patch index 7b2f0717733..d3a0cc9053e 100644 --- a/build/pkgs/python3/patches/cygwin-ctypes.patch +++ b/build/pkgs/python3/patches/cygwin-ctypes.patch @@ -1,9 +1,11 @@ This patch is needed for the ctypes library to get the correct name of the libpython DLL, and is related to https://bugs.python.org/issue13756 ---- a/Lib/ctypes/__init__.py 2017-03-21 15:16:01.564958900 +0100 -+++ b/Lib/ctypes/__init__.py 2017-03-21 15:18:10.476792300 +0100 -@@ -430,7 +430,8 @@ - if _os.name in ("nt", "ce"): +diff --git a/Lib/ctypes/__init__.py.orig b/Lib/ctypes/__init__.py +index f870968..8c87b7c 100644 +--- a/Lib/ctypes/__init__.py ++++ b/Lib/ctypes/__init__.py +@@ -431,7 +431,8 @@ pydll = LibraryLoader(PyDLL) + if _os.name == "nt": pythonapi = PyDLL("python dll", None, _sys.dllhandle) elif _sys.platform == "cygwin": - pythonapi = PyDLL("libpython%d.%d.dll" % _sys.version_info[:2]) diff --git a/build/pkgs/python3/patches/cygwin-readline.patch b/build/pkgs/python3/patches/cygwin-readline.patch index 220f1664744..5702428ff50 100644 --- a/build/pkgs/python3/patches/cygwin-readline.patch +++ b/build/pkgs/python3/patches/cygwin-readline.patch @@ -6,7 +6,7 @@ the appropriate alternative). Also adds the correct link flags for curses on Cygwin. --- a/setup.py 2017-03-20 17:39:35.351935000 +0100 +++ b/setup.py 2017-03-20 18:16:33.670791400 +0100 -@@ -686,7 +686,8 @@ +@@ -719,7 +719,8 @@ if not os.path.exists(self.build_temp): os.makedirs(self.build_temp) # Determine if readline is already linked against curses or tinfo. @@ -16,7 +16,7 @@ Also adds the correct link flags for curses on Cygwin. if cross_compiling: ret = os.system("%s -d %s | grep '(NEEDED)' > %s" \ % (sysconfig.get_config_var('READELF'), -@@ -1322,6 +1323,9 @@ +@@ -1371,6 +1371,9 @@ if curses_library.startswith('ncurses'): curses_libs = [curses_library] diff --git a/build/pkgs/python3/patches/no_strict_proto-issue_5755.patch b/build/pkgs/python3/patches/no_strict_proto-issue_5755.patch index 153972fc3f4..e511dbdb9e9 100644 --- a/build/pkgs/python3/patches/no_strict_proto-issue_5755.patch +++ b/build/pkgs/python3/patches/no_strict_proto-issue_5755.patch @@ -1,7 +1,7 @@ diff -ru src/configure.ac b/configure.ac --- src/configure.ac 2013-04-06 16:02:41.000000000 +0200 +++ b/configure.ac 2013-04-11 18:11:17.947929754 +0200 -@@ -1047,9 +1047,6 @@ +@@ -1451,9 +1451,6 @@ then case $GCC in yes) @@ -14,7 +14,7 @@ diff -ru src/configure.ac b/configure.ac diff -ru src/configure b/configure --- src/configure 2013-04-06 16:02:41.000000000 +0200 +++ b/configure 2013-04-11 18:11:25.737930322 +0200 -@@ -5914,9 +5914,6 @@ +@@ -6843,9 +6843,6 @@ then case $GCC in yes) diff --git a/build/pkgs/python3/patches/permissions.patch b/build/pkgs/python3/patches/permissions.patch index d982758d9e1..553f879ddf3 100644 --- a/build/pkgs/python3/patches/permissions.patch +++ b/build/pkgs/python3/patches/permissions.patch @@ -1,6 +1,6 @@ --- src.orig/Makefile.pre.in 2013-04-06 15:02:34.000000000 +0100 +++ src/Makefile.pre.in 2013-04-07 12:59:46.675111329 +0100 -@@ -59,7 +59,7 @@ +@@ -70,7 +70,7 @@ # Shared libraries must be installed with executable mode on some systems; # rather than figuring out exactly which, we always give them executable mode. # Also, making them read-only seems to be a good idea... diff --git a/build/pkgs/python3/patches/pyport-apple-c++.patch b/build/pkgs/python3/patches/pyport-apple-c++.patch deleted file mode 100644 index 61aea6e2cef..00000000000 --- a/build/pkgs/python3/patches/pyport-apple-c++.patch +++ /dev/null @@ -1,23 +0,0 @@ ---- a/Include/pyport.h 2017-04-07 13:26:39.000000000 -0700 -+++ b/Include/pyport.h 2017-04-07 13:27:54.000000000 -0700 -@@ -688,6 +688,12 @@ - #endif - - #ifdef _PY_PORT_CTYPE_UTF8_ISSUE -+#ifndef __cplusplus -+ /* The workaround below is unsafe in C++ because -+ * the defines these symbols as real functions, -+ * with a slightly different signature. -+ * See issue #10910 -+ */ - #include - #include - #undef isalnum -@@ -705,6 +711,7 @@ - #undef toupper - #define toupper(c) towupper(btowc(c)) - #endif -+#endif - - - /* Declarations for symbol visibility. diff --git a/build/pkgs/python3/patches/sdist.patch b/build/pkgs/python3/patches/sdist.patch index c6b36df6046..552d265474f 100644 --- a/build/pkgs/python3/patches/sdist.patch +++ b/build/pkgs/python3/patches/sdist.patch @@ -1,6 +1,6 @@ --- src/Lib/distutils/command/sdist.py.orig 2011-05-20 15:24:44.936515549 +1200 +++ src/Lib/distutils/command/sdist.py 2011-05-20 15:25:54.920519189 +1200 -@@ -336,7 +336,7 @@ +@@ -317,7 +317,7 @@ * the build tree (typically "build") * the release tree itself (only an issue if we ran "sdist" previously with --keep-temp, or it aborted) @@ -9,7 +9,7 @@ """ build = self.get_finalized_command('build') base_dir = self.distribution.get_fullname() -@@ -351,7 +351,7 @@ +@@ -330,7 +330,7 @@ else: seps = '/' From 253502169a1efb5b7e2b30ba5ebace8432920fb3 Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Fri, 5 May 2017 13:06:12 -0700 Subject: [PATCH 250/452] trac 22953: implement "sage --python3" --- src/bin/sage | 13 ++++++++++++- src/doc/en/reference/repl/options.rst | 3 ++- src/sage/tests/cmdline.py | 9 +++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/bin/sage b/src/bin/sage index 42d3ab38271..2091144bd04 100755 --- a/src/bin/sage +++ b/src/bin/sage @@ -27,7 +27,8 @@ usage() { echo " 'default', 'sagenb', 'jupyter', and 'export')" echo " -n, --notebook -- shortcut for --notebook=default" echo " -optional -- list all optional packages that can be installed" - echo " -python [...] -- run the Python interpreter" + echo " -python [...] -- run the Python 2 interpreter" + echo " -python3 [...] -- run the Python 3 interpreter" echo " -R [...] -- run Sage's R with given arguments" echo " -singular [...] -- run Sage's singular with given arguments" echo " -sqlite3 [...] -- run Sage's sqlite3 with given arguments" @@ -572,6 +573,16 @@ if [ "$1" = '-python' -o "$1" = '--python' ]; then exec python "$@" fi +if [ "$1" = '-python2' -o "$1" = '--python2' ]; then + shift + exec python2 "$@" +fi + +if [ "$1" = '-python3' -o "$1" = '--python3' ]; then + shift + exec python3 "$@" +fi + if [ "$1" = '-R' -o "$1" = '--R' ]; then shift exec R "$@" diff --git a/src/doc/en/reference/repl/options.rst b/src/doc/en/reference/repl/options.rst index a714b73e0b3..e87c58ad1df 100644 --- a/src/doc/en/reference/repl/options.rst +++ b/src/doc/en/reference/repl/options.rst @@ -71,7 +71,8 @@ Command-line options for Sage - ``--M2 [...]`` -- run Sage's Macaulay2 with the given arguments - ``--maxima [...]`` -- run Sage's Maxima with the given arguments - ``--mwrank [...]`` -- run Sage's mwrank with the given arguments -- ``--python [...]`` -- run the Python interpreter +- ``--python [...]``, ``--python2 [...]`` -- run the Python 2 interpreter +- ``--python3 [...]`` -- run the Python 3 interpreter - ``-R [...]`` -- run Sage's R with the given arguments - ``--scons [...]`` -- run Sage's scons - ``--singular [...]`` -- run Sage's singular with the given arguments diff --git a/src/sage/tests/cmdline.py b/src/sage/tests/cmdline.py index b81d1daa0d4..e63b20fa7ce 100644 --- a/src/sage/tests/cmdline.py +++ b/src/sage/tests/cmdline.py @@ -32,6 +32,7 @@ --optional --preparse --python +--python3 -q --R --root @@ -489,6 +490,14 @@ def test_executable(args, input="", timeout=100.0, **kwds): sage: ret 0 + sage: (out, err, ret) = test_executable(["sage", "--python3"], "print(3^33)\n") + sage: out + '34\n' + sage: err + '' + sage: ret + 0 + sage: (out, err, ret) = test_executable(["sage", "--cython"]) sage: print(err) Cython (http://cython.org) is a compiler for code written in the From 6aa556593554e71bba7c0ae84f077f95d9e6820d Mon Sep 17 00:00:00 2001 From: Ben Salisbury Date: Fri, 5 May 2017 20:18:08 -0400 Subject: [PATCH 251/452] added loop_crystals to rst --- src/doc/en/reference/categories/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/en/reference/categories/index.rst b/src/doc/en/reference/categories/index.rst index 1d4ed57a230..9e51d5b15b6 100644 --- a/src/doc/en/reference/categories/index.rst +++ b/src/doc/en/reference/categories/index.rst @@ -125,6 +125,7 @@ Individual Categories sage/categories/lie_algebras sage/categories/lie_algebras_with_basis sage/categories/lie_groups + sage/categories/loop_crystals sage/categories/l_trivial_semigroups sage/categories/magmas sage/categories/magmas_and_additive_magmas From be222550e83c6bd02b5da56673f84f14f8988c2e Mon Sep 17 00:00:00 2001 From: Ben Salisbury Date: Fri, 5 May 2017 20:19:08 -0400 Subject: [PATCH 252/452] removed typo from monomial_crystals.py --- src/sage/combinat/crystals/monomial_crystals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/crystals/monomial_crystals.py b/src/sage/combinat/crystals/monomial_crystals.py index 621e18f68c1..55dd94a9bc4 100644 --- a/src/sage/combinat/crystals/monomial_crystals.py +++ b/src/sage/combinat/crystals/monomial_crystals.py @@ -972,7 +972,7 @@ def c(self): def cardinality(self): r""" - Return the cardinality of ``self``, which is always `\infty`.i + Return the cardinality of ``self``, which is always `\infty`. EXAMPLES:: From 50494fa742511c12e693ccba9bb54c22b9effb9d Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Fri, 5 May 2017 23:36:19 -0500 Subject: [PATCH 253/452] Fixing the docbuild and some other small tweaks. --- src/sage/categories/loop_crystals.py | 12 ++++++------ src/sage/combinat/crystals/affinization.py | 19 ------------------- .../combinat/crystals/kirillov_reshetikhin.py | 3 ++- 3 files changed, 8 insertions(+), 26 deletions(-) diff --git a/src/sage/categories/loop_crystals.py b/src/sage/categories/loop_crystals.py index 02a32370a8d..40f70f2e85f 100644 --- a/src/sage/categories/loop_crystals.py +++ b/src/sage/categories/loop_crystals.py @@ -66,7 +66,7 @@ def super_categories(self): def example(self, n = 3): """ - Returns an example of Kirillov-Reshetikhin crystals, as per + Return an example of Kirillov-Reshetikhin crystals, as per :meth:`Category.example`. EXAMPLES:: @@ -440,18 +440,18 @@ def is_perfect(self, ell=None): A crystal `\mathcal{B}` is perfect of level `\ell` if: #. `\mathcal{B}` is isomorphic to the crystal graph of a - finite-dimensional `U_q^{'}(\mathfrak{g})`-module. - #. `\mathcal{B}\otimes \mathcal{B}` is connected. + finite-dimensional `U_q'(\mathfrak{g})`-module. + #. `\mathcal{B} \otimes \mathcal{B}` is connected. #. There exists a `\lambda\in X`, such that `\mathrm{wt}(\mathcal{B}) \subset \lambda + \sum_{i\in I} - \ZZ_{\le 0} \alpha_i` and there is a unique element in + \ZZ_{\le 0} \alpha_i` and there is a unique element in `\mathcal{B}` of classical weight `\lambda`. #. For all `b \in \mathcal{B}`, `\mathrm{level}(\varepsilon (b)) \geq \ell`. #. For all `\Lambda` dominant weights of level `\ell`, there exist unique elements `b_{\Lambda}, b^{\Lambda} \in - \mathcal{B}`, such that `\varepsilon ( b_{\Lambda}) = - \Lambda = \varphi( b^{\Lambda})`. + \mathcal{B}`, such that `\varepsilon(b_{\Lambda}) = + \Lambda = \varphi(b^{\Lambda})`. Points (1)-(3) are known to hold. This method checks points (4) and (5). diff --git a/src/sage/combinat/crystals/affinization.py b/src/sage/combinat/crystals/affinization.py index 84008708ee2..91ccc0488ef 100644 --- a/src/sage/combinat/crystals/affinization.py +++ b/src/sage/combinat/crystals/affinization.py @@ -106,25 +106,6 @@ def _repr_(self): """ return "Affinization of {}".format(self._B) - # TODO: This should become unnecessary once we have a proper category for KR crystals - def digraph(self, subset=None, index_set=None): - """ - Return the DiGraph associated with ``self``. See - :meth:`~sage.categories.crystals.ParentMethods.digraph()` for more - information. - - EXAMPLES:: - - sage: A = crystals.KirillovReshetikhin(['A',2,1], 2, 2).affinization() - sage: S = A.subcrystal(max_depth=3) - sage: G = A.digraph(subset=S) - """ - G = super(AffinizationOfCrystal, self).digraph(subset, index_set) - from sage.graphs.dot2tex_utils import have_dot2tex - if have_dot2tex(): - G.set_latex_options(edge_options=lambda u_v_label: ({})) - return G - class Element(Element): """ An element in an affinization crystal. diff --git a/src/sage/combinat/crystals/kirillov_reshetikhin.py b/src/sage/combinat/crystals/kirillov_reshetikhin.py index 73e3446d7dc..a94863ccccb 100644 --- a/src/sage/combinat/crystals/kirillov_reshetikhin.py +++ b/src/sage/combinat/crystals/kirillov_reshetikhin.py @@ -1134,7 +1134,8 @@ def affine_weight(self, b): Return the affine level zero weight corresponding to the element ``b`` of the classical crystal underlying ``self``. - For the coefficients to calculate the level, see Kac pg. 48. + For the coefficients to calculate the level, see Table Aff 1 + in [Ka1990]_. EXAMPLES:: From f5c35ff65d77df6f3193dd1fe709f0f7c2451bbc Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Sat, 6 May 2017 07:59:48 +0200 Subject: [PATCH 254/452] 22877: fix reality check --- src/sage/libs/pynac/pynac.pyx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/sage/libs/pynac/pynac.pyx b/src/sage/libs/pynac/pynac.pyx index bbb98813190..733dc6c2bfe 100644 --- a/src/sage/libs/pynac/pynac.pyx +++ b/src/sage/libs/pynac/pynac.pyx @@ -1800,11 +1800,15 @@ cdef py_atan2(x, y): [0.55357435889705 +/- 5.75e-15] + [0.40235947810852 +/- 6.01e-15]*I """ from sage.symbolic.constants import pi, NaN + from sage.rings.real_arb import RealBallField + from sage.rings.real_mpfr import RealField_class P = coercion_model.common_parent(x, y) is_real = False if P is ZZ: P = RR - if P in (float, RR, RBF): + if (P is float + or parent(P) is RealField_class + or isinstance(P, RealBallField)): is_real = True if y != 0: try: From 2dd1ca5ad23b4bf1760554f3397cc5422abf129f Mon Sep 17 00:00:00 2001 From: Thierry Monteil Date: Sat, 6 May 2017 17:23:26 +0200 Subject: [PATCH 255/452] 22684 : lower memory requirement of a normaliz doctest. --- src/sage/geometry/polyhedron/backend_normaliz.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/geometry/polyhedron/backend_normaliz.py b/src/sage/geometry/polyhedron/backend_normaliz.py index 6c29099d45f..208e6140de8 100644 --- a/src/sage/geometry/polyhedron/backend_normaliz.py +++ b/src/sage/geometry/polyhedron/backend_normaliz.py @@ -494,11 +494,11 @@ def integral_points(self, threshold=10000): be a very bad idea (note this is a rational (non-lattice) polytope, so the other backends use the bounding box method):: - sage: P = Polyhedron(vertices=((0, 0), (1789345,37121))) + 1/1000*polytopes.hypercube(2) + sage: P = Polyhedron(vertices=((0, 0), (178933,37121))) + 1/1000*polytopes.hypercube(2) sage: P = Polyhedron(vertices=P.vertices_list(), # optional - pynormaliz ....: backend='normaliz') sage: len(P.integral_points()) # optional - pynormaliz - 3654 + 434 Finally, the 3-d reflexive polytope number 4078:: From 7a04a519036f98db301ee20baff192f93cc3386f Mon Sep 17 00:00:00 2001 From: David Coudert Date: Sat, 6 May 2017 19:42:18 +0200 Subject: [PATCH 256/452] trac #22954: add generator of Windmill graphs --- src/sage/graphs/generators/families.py | 93 ++++++++++++++++++++++++++ src/sage/graphs/graph_generators.py | 4 +- 2 files changed, 96 insertions(+), 1 deletion(-) diff --git a/src/sage/graphs/generators/families.py b/src/sage/graphs/generators/families.py index 39213551145..e955f775078 100644 --- a/src/sage/graphs/generators/families.py +++ b/src/sage/graphs/generators/families.py @@ -2501,6 +2501,99 @@ def WheelGraph(n): G = networkx.wheel_graph(n) return Graph(G, pos=pos_dict, name="Wheel graph") +def WindmillGraph(k, n): + r""" + Return the Windmill graph `Wd(k, n)`. + + The windmill graph `Wd(k,n)` is an undirected graph constructed for `k \geq + 2` and `n \geq 2` by joining `n` copies of the complete graph `K_k` at a + shared vertex. It has `(k-1)n+1` vertices and `nk(k−1)/2` edges, girth 3 (if + `k > 2`), radius 1 and diameter 2. It has vertex connectivity 1 because its + central vertex is an articulation point; however, like the complete graphs + from which it is formed, it is `(k-1)`-edge-connected. It is trivially + perfect and a block graph. + + .. SEEALSO:: + + - :wikipedia:`Windmill_graph` + - :meth:`GraphGenerators.StarGraph` + - :meth:`GraphGenerators.FriendshipGraph` + + EXAMPLES: + + The Windmill graph `Wd(2, n)` is a star graph:: + + sage: n = 5 + sage: W = graphs.WindmillGraph(2, n) + sage: W.is_isomorphic( graphs.StarGraph(n) ) + True + + The Windmill graph `Wd(3, n)` is the Friendship graph `F_n`:: + + sage: n = 5 + sage: W = graphs.WindmillGraph(3, n) + sage: W.is_isomorphic( graphs.FriendshipGraph(n) ) + True + + The Windmill graph `Wd(3, 2)` is the Butterfly graph:: + + sage: W = graphs.WindmillGraph(3, 2) + sage: W.is_isomorphic( graphs.ButterflyGraph() ) + True + + The Windmill graph `Wd(k, n)` has chromatic number `k`:: + + sage: n,k = 5,6 + sage: W = graphs.WindmillGraph(k, n) + sage: W.chromatic_number() == k + True + + TESTS: + + Giving too small parameters:: + + sage: graphs.WindmillGraph(1, 2) + Traceback (most recent call last): + ... + ValueError: parameters k and n must be >= 2 + sage: graphs.WindmillGraph(2, 1) + Traceback (most recent call last): + ... + ValueError: parameters k and n must be >= 2 + """ + if k < 2 or n < 2: + raise ValueError('parameters k and n must be >= 2') + + if k == 2 or False: + from sage.graphs.generators.basic import StarGraph + G = StarGraph(n) + else: + sector = 2*pi/n + slide = 1/sin(sector/4) + + pos_dict = {} + for i in range(0,k): + x = float(cos(i*pi/(k-2))) + y = float(sin(i*pi/(k-2))) + slide + pos_dict[i] = (x,y) + + G = Graph() + pos = {0: [0, 0]} + for i in range(n): + V = list( range(i*(k-1)+1, (i+1)*(k-1)+1) ) + G.add_clique([0]+V) + for j,v in enumerate(V): + x,y = pos_dict[j] + xv = x*cos(i*sector) - y*sin(i*sector) + yv = x*sin(i*sector) + y*cos(i*sector) + pos[v] = [xv, yv] + + G.set_pos(pos) + + G.name("Windmill graph Wd({}, {})".format(k, n)) + return G + + def trees(vertices): r""" Returns a generator of the distinct trees on a fixed number of vertices. diff --git a/src/sage/graphs/graph_generators.py b/src/sage/graphs/graph_generators.py index 85ae7c71b93..368be589194 100644 --- a/src/sage/graphs/graph_generators.py +++ b/src/sage/graphs/graph_generators.py @@ -241,7 +241,8 @@ def __append_to_doc(methods): "trees", "triangulations", "TuranGraph", - "WheelGraph"]) + "WheelGraph", + "WindmillGraph"]) __doc__ += """ @@ -2027,6 +2028,7 @@ def quadrangulations(self, order, minimum_degree=None, minimum_connectivity=None trees = staticmethod(sage.graphs.generators.families.trees) TuranGraph = staticmethod(sage.graphs.generators.families.TuranGraph) WheelGraph = staticmethod(sage.graphs.generators.families.WheelGraph) + WindmillGraph = staticmethod(sage.graphs.generators.families.WindmillGraph) ########################################################################### # Graphs from classical geometries over `F_q` From 1ff3a5f9bcc1eff19867c9c041fc1db3c1814467 Mon Sep 17 00:00:00 2001 From: Ben Salisbury Date: Sat, 6 May 2017 13:55:06 -0400 Subject: [PATCH 257/452] fixed documentation errors in loop_crystals.py --- src/sage/categories/loop_crystals.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/categories/loop_crystals.py b/src/sage/categories/loop_crystals.py index 40f70f2e85f..b8ed01b422c 100644 --- a/src/sage/categories/loop_crystals.py +++ b/src/sage/categories/loop_crystals.py @@ -402,7 +402,7 @@ def b_sharp(self): Let `B` be a KR crystal. The element `b^{\sharp}` is the unique element such that `\varphi(b^{\sharp}) = \ell \Lambda_0` with - `\ell = \min \{ \langle c, \varphi(b) \mid b \in B \}`. + `\ell = \min \{ \langle c, \varphi(b) \rangle \mid b \in B \}`. EXAMPLES:: @@ -982,7 +982,7 @@ def e_string_to_ground_state(self): This method calculates a path from ``self`` to a ground state path using Demazure arrows as defined in Lemma 7.3 - in [SchillingTingley2011]_. + in [ST2011]_. OUTPUT: a tuple of integers `(i_1, \ldots, i_k)` From 909bedfb9e888ad569174f780697e2e694cfa004 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sat, 6 May 2017 14:06:23 -0500 Subject: [PATCH 258/452] Correcting hyperlink in R_matrix. --- src/sage/categories/loop_crystals.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/categories/loop_crystals.py b/src/sage/categories/loop_crystals.py index 40f70f2e85f..03ddcd5279b 100644 --- a/src/sage/categories/loop_crystals.py +++ b/src/sage/categories/loop_crystals.py @@ -314,7 +314,7 @@ def R_matrix(self, K): isomorphism `R : L \otimes K \to K \otimes L` which maps `u_{L} \otimes u_K` to `u_K \otimes u_{L}`, where `u_K` is the unique element in `K = B^{r,s}` of weight - `s\Lambda_r - s c \Lambda_0` (see :meth:`module_generator`). + `s\Lambda_r - s c \Lambda_0` (see :meth:`maximal_vector`). INPUT: From e2babc80e55902ccba884a345fd8c96e15b7c185 Mon Sep 17 00:00:00 2001 From: David Coudert Date: Sat, 6 May 2017 23:09:31 +0200 Subject: [PATCH 259/452] trac #22954: correct if condition --- src/sage/graphs/generators/families.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/graphs/generators/families.py b/src/sage/graphs/generators/families.py index e955f775078..1f39031c3a2 100644 --- a/src/sage/graphs/generators/families.py +++ b/src/sage/graphs/generators/families.py @@ -2564,7 +2564,7 @@ def WindmillGraph(k, n): if k < 2 or n < 2: raise ValueError('parameters k and n must be >= 2') - if k == 2 or False: + if k == 2: from sage.graphs.generators.basic import StarGraph G = StarGraph(n) else: From 773c43a725c0c46feb1be301269d37ea34fe6629 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 6 May 2017 21:03:29 -0700 Subject: [PATCH 260/452] #21993: Add doctest --- src/sage/geometry/integral_points.pyx | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/sage/geometry/integral_points.pyx b/src/sage/geometry/integral_points.pyx index 785f9f54ed3..62ff1462163 100644 --- a/src/sage/geometry/integral_points.pyx +++ b/src/sage/geometry/integral_points.pyx @@ -886,6 +886,16 @@ cdef class Inequality_int: Traceback (most recent call last): ... OverflowError: ... + + TESTS: + + Check that :trac:`21993` is fixed:: + + sage: Inequality_int([18560500, -89466500], 108027, [178933, 37121]) + Traceback (most recent call last): + ... + OverflowError: ... + """ cdef int A[INEQ_INT_MAX_DIM] cdef int b From 76cd1ea370076c04901fe331760839d6c0166cf4 Mon Sep 17 00:00:00 2001 From: Matthias Koeppe Date: Sat, 6 May 2017 21:10:20 -0700 Subject: [PATCH 261/452] #21993: Fix test for possible overflow during enumeration --- src/sage/geometry/integral_points.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/geometry/integral_points.pyx b/src/sage/geometry/integral_points.pyx index 62ff1462163..ed055ebf51d 100644 --- a/src/sage/geometry/integral_points.pyx +++ b/src/sage/geometry/integral_points.pyx @@ -938,8 +938,8 @@ cdef class Inequality_int: if self.dim > 0: self.coeff_next = self.A[1] # finally, make sure that there cannot be any overflow during the enumeration - self._to_int(ZZ(b) + sum( ZZ(A[i]) * ZZ(max_abs_coordinates[i]) - for i in range(self.dim) )) + self._to_int(abs(ZZ(b)) + sum( abs(ZZ(A[i])) * ZZ(max_abs_coordinates[i]) + for i in range(self.dim) )) def __repr__(self): """ From f64520f609260af0fbab6949bdb69f8a8fa3ccc8 Mon Sep 17 00:00:00 2001 From: Thierry Monteil Date: Sun, 7 May 2017 09:30:14 +0200 Subject: [PATCH 262/452] #22684 : update PyNormaliz checksums. --- build/pkgs/pynormaliz/checksums.ini | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/build/pkgs/pynormaliz/checksums.ini b/build/pkgs/pynormaliz/checksums.ini index c534d164a98..e4ca9b4c1aa 100644 --- a/build/pkgs/pynormaliz/checksums.ini +++ b/build/pkgs/pynormaliz/checksums.ini @@ -1,4 +1,4 @@ tarball=PyNormaliz-VERSION.tar.gz -sha1=6a584ab5e6fb6159a2c1b54f4f8e101b03fbeaa9 -md5=89d99966599db1c694fb1f229d44860f -cksum=322380391 +sha1=619d2b01d9ee20bfcf880cb25ea04b72cc2d2942 +md5=22eea4624caff219618640ed67003b9d +cksum=4251733870 From e3ee8828ba86c70eacc30cae7ae2895f34bc3990 Mon Sep 17 00:00:00 2001 From: Thierry Monteil Date: Sun, 7 May 2017 19:19:33 +0200 Subject: [PATCH 263/452] #22957 : faster implementation for has_perfect_matching. --- src/sage/graphs/graph.py | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index 0669fc30693..c81bb378050 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -7580,10 +7580,31 @@ def perfect_matchings(self, labels=False): yield [e] + mat @doc_index("Leftovers") - def has_perfect_matching(self): + def has_perfect_matching(self, algorithm="Edmonds", solver=None, verbose=0): r""" Return whether this graph has a perfect matching. + INPUT: + + - ``algorithm`` -- string (default: ``"Edmonds"``) + + - ``"Edmonds"`` selects Edmonds' algorithm as implemented in NetworkX + + - ``"LP"`` uses a Linear Program formulation of the matching problem + + - ``solver`` -- (default: ``None``) specify a Linear Program (LP) + solver to be used; if set to ``None``, the default one is used + + - ``verbose`` -- integer (default: ``0``); sets the level of + verbosity: set to 0 by default, which means quiet + (only useful when ``algorithm == "LP"``) + + For more information on LP solvers and which default solver is + used, see the method + :meth:`solve ` + of the class :class:`MixedIntegerLinearProgram + `. + OUTPUT: A boolean. @@ -7597,11 +7618,11 @@ def has_perfect_matching(self): sage: graphs.WheelGraph(5).has_perfect_matching() False """ - try: - next(self.perfect_matchings()) - except StopIteration: - return False - return True + return len(self) == 2*self.matching(value_only=True, + use_edge_labels=False, + algorithm=algorithm, + solver=solver, + verbose=verbose) # Aliases to functions defined in Cython modules From 841850bf34d64cf6721ce25a27f7c51aaa2864db Mon Sep 17 00:00:00 2001 From: Thierry Monteil Date: Sun, 7 May 2017 22:11:36 +0200 Subject: [PATCH 264/452] #22957 : ad-hoc faster LP formulation for has_perfect_matching. --- src/sage/graphs/graph.py | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index c81bb378050..b94f8ec02ae 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -7590,7 +7590,7 @@ def has_perfect_matching(self, algorithm="Edmonds", solver=None, verbose=0): - ``"Edmonds"`` selects Edmonds' algorithm as implemented in NetworkX - - ``"LP"`` uses a Linear Program formulation of the matching problem + - ``"LP"`` uses a Linear Program formulation of the perfect matching problem - ``solver`` -- (default: ``None``) specify a Linear Program (LP) solver to be used; if set to ``None``, the default one is used @@ -7617,12 +7617,30 @@ def has_perfect_matching(self, algorithm="Edmonds", solver=None, verbose=0): True sage: graphs.WheelGraph(5).has_perfect_matching() False + sage: graphs.PetersenGraph().has_perfect_matching(algorithm="LP") + True + sage: graphs.WheelGraph(6).has_perfect_matching(algorithm="LP") + True + sage: graphs.WheelGraph(5).has_perfect_matching(algorithm="LP") + False """ - return len(self) == 2*self.matching(value_only=True, - use_edge_labels=False, - algorithm=algorithm, - solver=solver, - verbose=verbose) + if algorithm == "Edmonds": + return len(self) == 2*self.matching(value_only=True, + use_edge_labels=False, + algorithm="Edmonds") + elif algorithm == "LP": + from sage.numerical.mip import MixedIntegerLinearProgram, MIPSolverException + p = MixedIntegerLinearProgram(solver=solver) + b = p.new_variable(binary = True) + for v in self: + p.add_constraint(sum([b[e] for e in self.edges_incident(v, labels=False)]) == 1) + try: + p.solve(log=verbose) + return True + except MIPSolverException: + return False + else: + raise ValueError('algorithm must be set to either "Edmonds" or "LP"') # Aliases to functions defined in Cython modules From 27f66e6b85f7cc5159be1524aa21064ef9fccddb Mon Sep 17 00:00:00 2001 From: Thierry Monteil Date: Sun, 7 May 2017 23:42:55 +0200 Subject: [PATCH 265/452] #22957 : allow both LP formulations for has_perfect_matching. --- src/sage/graphs/graph.py | 60 ++++++++++++++++++++++++++++++++-------- 1 file changed, 48 insertions(+), 12 deletions(-) diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index b94f8ec02ae..6d77976255b 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -7588,16 +7588,25 @@ def has_perfect_matching(self, algorithm="Edmonds", solver=None, verbose=0): - ``algorithm`` -- string (default: ``"Edmonds"``) - - ``"Edmonds"`` selects Edmonds' algorithm as implemented in NetworkX - - - ``"LP"`` uses a Linear Program formulation of the perfect matching problem - + - ``"Edmonds"`` uses Edmonds' algorithm as implemented in NetworkX to + find a matching of maximal cardinality, then check whether this + cardinality is half the number of vertices of the graph. + + - ``"LP_matching"`` uses uses a Linear Program to find a matching of + maximal cardinality, then check whether this cardinality is half the + number of vertices of the graph. + + - ``"LP"`` uses a Linear Program formulation of the perfect matching + problem: put a binary variable ``b[e]`` on each edge ``e``, and for + each vertex ``v``, require that the sum of the values of the edges + incident to ``v`` is 1. + - ``solver`` -- (default: ``None``) specify a Linear Program (LP) solver to be used; if set to ``None``, the default one is used - - ``verbose`` -- integer (default: ``0``); sets the level of - verbosity: set to 0 by default, which means quiet - (only useful when ``algorithm == "LP"``) + - ``verbose`` -- integer (default: ``0``); sets the level of verbosity: + set to 0 by default, which means quiet (only useful when + ``algorithm == "LP_matching"`` or ``algorithm == "LP"``) For more information on LP solvers and which default solver is used, see the method @@ -7617,30 +7626,57 @@ def has_perfect_matching(self, algorithm="Edmonds", solver=None, verbose=0): True sage: graphs.WheelGraph(5).has_perfect_matching() False - sage: graphs.PetersenGraph().has_perfect_matching(algorithm="LP") + sage: graphs.PetersenGraph().has_perfect_matching(algorithm="LP_matching") True - sage: graphs.WheelGraph(6).has_perfect_matching(algorithm="LP") + sage: graphs.WheelGraph(6).has_perfect_matching(algorithm="LP_matching") True - sage: graphs.WheelGraph(5).has_perfect_matching(algorithm="LP") + sage: graphs.WheelGraph(5).has_perfect_matching(algorithm="LP_matching") + False + sage: graphs.PetersenGraph().has_perfect_matching(algorithm="LP_matching") + True + sage: graphs.WheelGraph(6).has_perfect_matching(algorithm="LP_matching") + True + sage: graphs.WheelGraph(5).has_perfect_matching(algorithm="LP_matching") + False + + TESTS:: + + sage: G = graphs.EmptyGraph() + sage: all(G.has_perfect_matching(algorithm=algo) for algo in ['Edmonds', 'LP_matching', 'LP']) + + Be careful with isolated vertices:: + + sage: G = graphs.PetersenGraph() + sage: G.add_vertex(11) + sage: any(G.has_perfect_matching(algorithm=algo) for algo in ['Edmonds', 'LP_matching', 'LP']) False """ if algorithm == "Edmonds": return len(self) == 2*self.matching(value_only=True, use_edge_labels=False, algorithm="Edmonds") + elif algorithm == "LP_matching": + return len(self) == 2*self.matching(value_only=True, + use_edge_labels=False, + algorithm="LP", + solver=solver, + verbose=verbose) elif algorithm == "LP": from sage.numerical.mip import MixedIntegerLinearProgram, MIPSolverException p = MixedIntegerLinearProgram(solver=solver) b = p.new_variable(binary = True) for v in self: - p.add_constraint(sum([b[e] for e in self.edges_incident(v, labels=False)]) == 1) + edges = self.edges_incident(v, labels=False) + if not edges: + return False + p.add_constraint(sum([b[e] for e in edges]) == 1) try: p.solve(log=verbose) return True except MIPSolverException: return False else: - raise ValueError('algorithm must be set to either "Edmonds" or "LP"') + raise ValueError('algorithm must be set to "Edmonds", "LP_matching" or "LP"') # Aliases to functions defined in Cython modules From 7c6ae9895d1a54453de2f1035a7a82087da2f092 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jori=20M=C3=A4ntysalo?= Date: Mon, 8 May 2017 08:22:17 +0300 Subject: [PATCH 266/452] Correction as #22867 is now done. --- src/sage/categories/finite_lattice_posets.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/sage/categories/finite_lattice_posets.py b/src/sage/categories/finite_lattice_posets.py index 681cd0ab169..19330da28cc 100644 --- a/src/sage/categories/finite_lattice_posets.py +++ b/src/sage/categories/finite_lattice_posets.py @@ -128,10 +128,8 @@ def irreducibles_poset(self): has exactly one upper cover. This is the smallest poset with completion by cuts being - isomorphic to the lattice. (Due to implementation detail - in Sage, actually isomorphic to the dual of the lattice.) - As a special case this returns one-element poset from one-element - lattice. + isomorphic to the lattice. As a special case this returns + one-element poset from one-element lattice. .. SEEALSO:: @@ -145,7 +143,7 @@ def irreducibles_poset(self): sage: L_ = L.irreducibles_poset() sage: sorted(L_) [2, 3, 4, 7, 8, 9, 10, 11] - sage: L_.completion_by_cuts().is_isomorphic(L.dual()) + sage: L_.completion_by_cuts().is_isomorphic(L) True TESTS:: From a2d87defac6fc38fccd71953c02a08129c3d9b88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jori=20M=C3=A4ntysalo?= Date: Mon, 8 May 2017 09:36:02 +0300 Subject: [PATCH 267/452] Add 'a'. --- src/sage/combinat/posets/poset_examples.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/posets/poset_examples.py b/src/sage/combinat/posets/poset_examples.py index b41093a175f..abf59b5a822 100644 --- a/src/sage/combinat/posets/poset_examples.py +++ b/src/sage/combinat/posets/poset_examples.py @@ -1575,7 +1575,7 @@ def _random_distributive_lattice(n): def _random_stone_lattice(n): """ - Return a random Stone lattice of `n` elements. + Return a random Stone lattice on `n` elements. INPUT: @@ -1583,7 +1583,7 @@ def _random_stone_lattice(n): OUTPUT: - A random lattice (as DiGraph) of `n` elements. + A random lattice (as a digraph) of `n` elements. EXAMPLES:: From e4769b5524ae5629db4189d06684646b22781efb Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Mon, 8 May 2017 10:17:11 +0200 Subject: [PATCH 268/452] 17505: symbolic product --- src/sage/calculus/calculus.py | 83 +++++++++++++++++++++ src/sage/functions/other.py | 31 ++++++-- src/sage/interfaces/maxima_lib.py | 21 ++++++ src/sage/symbolic/expression_conversions.py | 6 +- 4 files changed, 132 insertions(+), 9 deletions(-) diff --git a/src/sage/calculus/calculus.py b/src/sage/calculus/calculus.py index 216c41ba70a..0e1e0ebc52f 100644 --- a/src/sage/calculus/calculus.py +++ b/src/sage/calculus/calculus.py @@ -809,6 +809,89 @@ def nintegral(ex, x, a, b, nintegrate = nintegral +def symbolic_prod(expression, v, a, b, algorithm='maxima', hold=False): + r""" + Return the symbolic product `\prod_{v = a}^b expression` with respect + to the variable `v` with endpoints `a` and `b`. + + INPUT: + + - ``expression`` - a symbolic expression + + - ``v`` - a variable or variable name + + - ``a`` - lower endpoint of the product + + - ``b`` - upper endpoint of the prduct + + - ``algorithm`` - (default: ``'maxima'``) one of + + - ``'maxima'`` - use Maxima (the default) + + - ``'giac'`` - (optional) use Giac + + - ``'sympy'`` - use SymPy + + - ``hold`` - (default: ``False``) if ``True`` don't evaluate + + EXAMPLES:: + + sage: k, n = var('k,n') + sage: from sage.calculus.calculus import symbolic_prod + sage: symbolic_prod(k, k, 1, n) + factorial(n) + sage: symbolic_prod(x + i*(i+1)/2, i, 1, 4) + x^4 + 20*x^3 + 127*x^2 + 288*x + 180 + sage: symbolic_prod(i^2, i, 1, 7) + 25401600 + sage: f = function('f') + sage: symbolic_prod(f(i), i, 1, 7) + f(7)*f(6)*f(5)*f(4)*f(3)*f(2)*f(1) + sage: symbolic_prod(f(i), i, 1, n) + product(f(i), i, 1, n) + sage: assume(k>0) + sage: symbolic_prod(integrate (x^k, x, 0, 1), k, 1, n) + 1/factorial(n + 1) + """ + if not is_SymbolicVariable(v): + if isinstance(v, str): + v = var(v) + else: + raise TypeError("need a multiplication variable") + + if v in SR(a).variables() or v in SR(b).variables(): + raise ValueError("product limits must not depend on the multiplication variable") + + if hold == True: + from sage.functions.other import symbolic_prod as sprod + return sprod(expression, v, a, b) + + if algorithm == 'maxima': + return maxima.sr_prod(expression,v,a,b) + + elif algorithm == 'giac': + sum = "product(%s, %s, %s, %s)" % tuple([repr(expr._giac_()) for expr in (expression, v, a, b)]) + from sage.interfaces.giac import giac + try: + result = giac(sum) + except TypeError: + raise ValueError("Giac cannot make sense of: %s" % sum) + return result.sage() + + elif algorithm == 'sympy': + expression,v,a,b = [expr._sympy_() for expr in (expression, v, a, b)] + from sympy import product as sproduct + result = sproduct(expression, (v, a, b)) + try: + return result._sage_() + except AttributeError: + raise AttributeError("Unable to convert SymPy result (={}) into" + " Sage".format(result)) + + else: + raise ValueError("unknown algorithm: %s" % algorithm) + + def minpoly(ex, var='x', algorithm=None, bits=None, degree=None, epsilon=0): r""" Return the minimal polynomial of self, if possible. diff --git a/src/sage/functions/other.py b/src/sage/functions/other.py index 1cc42560f6f..c2216c3fae3 100644 --- a/src/sage/functions/other.py +++ b/src/sage/functions/other.py @@ -2617,24 +2617,41 @@ class Function_prod(BuiltinFunction): EXAMPLES:: sage: from sage.functions.other import symbolic_product as sprod - sage: sprod(x, x, 1, 10) + sage: r = sprod(x, x, 1, 10); r product(x, x, 1, 10) + sage: r.unhold() + 3628800 """ def __init__(self): """ EXAMPLES:: sage: from sage.functions.other import symbolic_product as sprod - sage: _ = var('n') - sage: r = maxima(sprod(sin(x), x, 1, n)).sage(); r - product(sin(x), x, 1, n) + sage: _ = var('m n', domain='integer') + sage: r = maxima(sprod(sin(m), m, 1, n)).sage(); r + product(sin(m), m, 1, n) sage: isinstance(r.operator(), sage.functions.other.Function_prod) True - sage: maxima(sprod(x, x, 1, 5)) - 120 + sage: r = sympy(sprod(sin(m), m, 1, n)).sage(); r # known bug + product(sin(m), m, 1, n) + sage: isinstance(r.operator(), + ....: sage.functions.other.Function_prod) # known bug + True + sage: giac(sprod(m, m, 1, n)) + n! """ BuiltinFunction.__init__(self, "product", nargs=4, conversions=dict(maxima='product', - sympy='Product')) + sympy='Product', giac='product')) + + def _print_latex_(self, x, var, a, b): + r""" + EXAMPLES:: + + sage: from sage.functions.other import symbolic_product as sprod + sage: latex(sprod(x^2, x, 1, 10)) + \prod_{x=1}^{10} x^2 + """ + return r"\prod_{{{}={}}}^{{{}}} {}".format(var, a, b, x) symbolic_product = Function_prod() diff --git a/src/sage/interfaces/maxima_lib.py b/src/sage/interfaces/maxima_lib.py index 552c96a0b91..f056c8f8bbf 100644 --- a/src/sage/interfaces/maxima_lib.py +++ b/src/sage/interfaces/maxima_lib.py @@ -232,6 +232,8 @@ max_integrate=EclObject("$INTEGRATE") max_sum=EclObject("$SUM") max_simplify_sum=EclObject("$SIMPLIFY_SUM") +max_prod=EclObject("$PRODUCT") +max_simplify_prod=EclObject("$SIMPLIFY_PRODUCT") max_ratsimp=EclObject("$RATSIMP") max_limit=EclObject("$LIMIT") max_tlimit=EclObject("$TLIMIT") @@ -898,6 +900,25 @@ def sr_sum(self,*args): else: raise + def sr_prod(self,*args): + """ + Helper function to wrap calculus use of Maxima's summation. + """ + try: + return max_to_sr(maxima_eval([[max_ratsimp],[[max_simplify_prod],([max_prod],[sr_to_max(SR(a)) for a in args])]])); + except RuntimeError as error: + s = str(error) + if "divergent" in s: +# in pexpect interface, one looks for this; +# could not find an example where 'Pole encountered' occurred, though +# if "divergent" in s or 'Pole encountered' in s: + raise ValueError("Sum is divergent.") + elif "Is" in s: # Maxima asked for a condition + self._missing_assumption(s) + else: + raise + + def sr_limit(self, expr, v, a, dir=None): """ Helper function to wrap calculus use of Maxima's limits. diff --git a/src/sage/symbolic/expression_conversions.py b/src/sage/symbolic/expression_conversions.py index 1fb9aa14c8a..b5f7e299167 100644 --- a/src/sage/symbolic/expression_conversions.py +++ b/src/sage/symbolic/expression_conversions.py @@ -2008,12 +2008,14 @@ def composition(self, ex, operator): sage: h() 0 """ - from sage.functions.other import Function_sum - from sage.calculus.calculus import symbolic_sum + from sage.functions.other import Function_sum, Function_prod + from sage.calculus.calculus import symbolic_sum, symbolic_prod if not operator: return self if isinstance(operator, Function_sum): return symbolic_sum(*map(self, ex.operands())) + if isinstance(operator, Function_prod): + return symbolic_prod(*map(self, ex.operands())) if operator in self._exclude: return operator(*map(self, ex.operands()), hold=True) else: From ef8436ada5c1eab174718593c53595c8db6ded51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jori=20M=C3=A4ntysalo?= Date: Mon, 8 May 2017 18:28:12 +0300 Subject: [PATCH 269/452] Add is_join_pseudocomplemented(), some minor corrections. --- src/sage/combinat/posets/lattices.py | 80 ++++++++++++++++++++++++---- 1 file changed, 71 insertions(+), 9 deletions(-) diff --git a/src/sage/combinat/posets/lattices.py b/src/sage/combinat/posets/lattices.py index d83e9c38aff..19616525a9b 100644 --- a/src/sage/combinat/posets/lattices.py +++ b/src/sage/combinat/posets/lattices.py @@ -54,7 +54,8 @@ :meth:`~FiniteLatticePoset.is_sectionally_complemented` | Return ``True`` if every interval from the bottom is complemented. :meth:`~FiniteLatticePoset.is_cosectionally_complemented` | Return ``True`` if every interval to the top is complemented. :meth:`~FiniteLatticePoset.is_relatively_complemented` | Return ``True`` if every interval of the lattice is complemented. - :meth:`~FiniteLatticePoset.is_pseudocomplemented` | Return ``True`` if every element of the lattice has a pseudocomplement. + :meth:`~FiniteLatticePoset.is_pseudocomplemented` | Return ``True`` if every element of the lattice has a (meet-)pseudocomplement. + :meth:`~FiniteLatticePoset.is_join_pseudocomplemented` | Return ``True`` if every element of the lattice has a join-pseudocomplement. :meth:`~FiniteLatticePoset.is_orthocomplemented` | Return ``True`` if the lattice has an orthocomplementation. :meth:`~FiniteLatticePoset.is_supersolvable` | Return ``True`` if the lattice is supersolvable. :meth:`~FiniteLatticePoset.is_planar` | Return ``True`` if the lattice has an upward planar drawing. @@ -1140,7 +1141,8 @@ def is_distributive(self, certificate=False): - Weaker properties: :meth:`is_modular`, :meth:`is_semidistributive`, :meth:`is_join_distributive`, :meth:`is_meet_distributive`, - :meth:`is_subdirectly_reducible` + :meth:`is_subdirectly_reducible`, + :meth:`is_constructible_by_doublings` (by interval doubling) - Stronger properties: :meth:`is_stone` EXAMPLES:: @@ -1256,7 +1258,7 @@ def is_meet_semidistributive(self, certificate=False): - Dual property: :meth:`is_join_semidistributive` - Weaker properties: :meth:`is_pseudocomplemented` - - Stronger properties: :meth:`is_semidistributive`, :meth:`is_join_distributive` + - Stronger properties: :meth:`is_semidistributive`, :meth:`is_join_distributive`, :meth:`is_constructible_by_doublings` (by upper pseudo-intervals) EXAMPLES:: @@ -1344,7 +1346,7 @@ def is_join_semidistributive(self, certificate=False): .. SEEALSO:: - Dual property: :meth:`is_meet_semidistributive` - - Stronger properties: :meth:`is_semidistributive`, :meth:`is_meet_distributive` + - Stronger properties: :meth:`is_semidistributive`, :meth:`is_meet_distributive`, :meth:`is_constructible_by_doublings` (by lower pseudo-intervals) EXAMPLES:: @@ -1945,6 +1947,7 @@ def is_pseudocomplemented(self, certificate=False): .. SEEALSO:: + - Dual property: :meth:`is_join_pseudocomplemented` - Stronger properties: :meth:`is_meet_semidistributive` - Other: :meth:`~sage.combinat.posets.lattices.FiniteMeetSemilattice.pseudocomplement()`. @@ -1972,6 +1975,65 @@ def is_pseudocomplemented(self, certificate=False): return (True, None) return True + def is_join_pseudocomplemented(self, certificate=False): + """ + Return ``True`` if the lattice is join-pseudocomplemented, and + ``False`` otherwise. + + A lattice is join-pseudocomplemented if every element `e` has a + join-pseudocomplement `e'`, i.e. the greatest element such that + the join of `e` and `e'` is the top element. + + INPUT: + + - ``certificate`` -- (default: ``False``) whether to return + a certificate + + OUTPUT: + + - If ``certificate=True`` return either ``(True, None)`` or + ``(False, e)``, where ``e`` is an element without a + join-pseudocomplement. If ``certificate=False`` return ``True`` + or ``False``. + + EXAMPLES:: + + sage: L = LatticePoset({1: [2, 5], 2: [3, 6], 3: [4], 4: [7], + ....: 5: [6], 6: [7]}) + sage: L.is_join_pseudocomplemented() + True + + sage: L = LatticePoset({1: [2, 3], 2: [4, 5, 6], 3: [6], 4: [7], + ....: 5: [7], 6: [7]}) + sage: L.is_join_pseudocomplemented() + False + sage: L.is_join_pseudocomplemented(certificate=True) + (False, 4) + + .. SEEALSO:: + + - Dual property: :meth:`is_pseudocomplemented` + - Stronger properties: :meth:`is_join_semidistributive` + + TESTS:: + + sage: LatticePoset({}).is_pseudocomplemented() + True + """ + H = self._hasse_diagram + if H.order() == 0: + if certificate: + return (True, None) + return True + for e in H.neighbor_in_iterator(H.order()-1): + if H.kappa_dual(e) is None: + if certificate: + return (False, self._vertex_to_element(e)) + return False + if certificate: + return (True, None) + return True + def skeleton(self): """ Return the skeleton of the lattice. @@ -2211,7 +2273,7 @@ def is_geometric(self): .. SEEALSO:: - - Weaker properties: :meth:`is_modular`, :meth:`is_relatively_complemented` + - Weaker properties: :meth:`is_upper_semimodular`, :meth:`is_relatively_complemented` EXAMPLES: @@ -2485,7 +2547,7 @@ def is_upper_semimodular(self, certificate=False): - Dual property: :meth:`is_lower_semimodular` - Weaker properties: :meth:`~sage.combinat.posets.posets.FinitePoset.is_graded` - - Stronger properties: :meth:`is_modular`, :meth:`is_join_distributive` + - Stronger properties: :meth:`is_modular`, :meth:`is_join_distributive`, :meth:`is_geometric` See :wikipedia:`Semimodular_lattice` @@ -3756,7 +3818,7 @@ def is_isoform(self, certificate=False): """ Return ``True`` if the lattice is isoform and ``False`` otherwise. - A congruence is *isoform* if all blocks are isomorphic + A congruence is *isoform* (or *isotype*) if all blocks are isomorphic sublattices. A lattice is isoform if it has only isoform congruences. @@ -3910,9 +3972,9 @@ def is_regular(self, certificate=False): .. SEEALSO:: - - Weaker properties: :meth:`is_sectionally_complemented`, + - Stronger properties: :meth:`is_uniform`, + :meth:`is_sectionally_complemented`, :meth:`is_cosectionally_complemented` - - Stronger properties: :meth:`is_uniform` - Other: :meth:`congruence` EXAMPLES:: From c3bcef0564e154e930191471334b7c43e5637bea Mon Sep 17 00:00:00 2001 From: Emmanuel Charpentier Date: Tue, 9 May 2017 06:54:51 +0200 Subject: [PATCH 270/452] First implementation of distribute() : sums. --- src/sage/symbolic/expression.pyx | 72 ++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 4205550777a..0e09c2e08a2 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -10384,7 +10384,79 @@ cdef class Expression(CommutativeRingElement): log_expand = expand_log + def distribute(self, recursive=True): + """ + Distribute some indiced operators over similar operators in + order to allow further groupings or simplifications. + + Implemented cases (so far) : + + - Symbolic sum of a sum ==> sum of symbolic sums + + - Integral (definite or not) of a sum ==> sum of integrals. + + INPUT: + + - ``self`` - expression whose operator may be distributed. + + - ``recursive`` - the distribution proceeds along the subtrees + of the expression (default : True). + TESTS: + + sage: var("j,k,p,q", domain="integer") + (j, k, p, q) + sage: X,Y,Z,f,g=function("X,Y,Z,f,g") + sage: var("x,a,b") + (x, a, b) + sage: sum(X(j)+Y(j),j,1,p) + sum(X(j) + Y(j), j, 1, p) + sage: sum(X(j)+Y(j),j,1,p).distribute() + sum(X(j), j, 1, p) + sum(Y(j), j, 1, p) + sage: integrate(f(x)+g(x),x) + integrate(f(x) + g(x), x) + sage: integrate(f(x)+g(x),x).distribute() + integrate(f(x), x) + integrate(g(x), x) + sage: integrate(f(x)+g(x),x,a,b) + integrate(f(x) + g(x), x, a, b) + sage: integrate(f(x)+g(x),x,a,b).distribute() + integrate(f(x), x, a, b) + integrate(g(x), x, a, b) + sage: sum(X(j)+sum(Y(k)+Z(k),k,1,q),j,1,p) + sum(X(j) + sum(Y(k) + Z(k), k, 1, q), j, 1, p) + sage: sum(X(j)+sum(Y(k)+Z(k),k,1,q),j,1,p).distribute() + sum(sum(Y(k), k, 1, q) + sum(Z(k), k, 1, q), j, 1, p) + sum(X(j), j, 1, p) + sage: sum(X(j)+sum(Y(k)+Z(k),k,1,q),j,1,p).distribute(recursive=False) + sum(X(j), j, 1, p) + sum(sum(Y(k) + Z(k), k, 1, q), j, 1, p) + + AUTHORS: + + - Emmanuel Charpentier, Ralf Stephan (05-2017) + """ + from sage.functions.other import symbolic_sum as opsum + from sage.symbolic.integration.integral \ + import indefinite_integral as opii, definite_integral as opdi + from sage.symbolic.operators import add_vararg as opadd + def treat_term(op, term, args): + l=sage.all.copy(args) + l.insert(0, term) + return(apply(op, l)) + if self.parent() is not sage.all.SR: return self + op = self.operator() + if op in {opsum, opdi, opii}: + sa = self.operands()[0] + op1 = sa.operator() + if op1 is opadd: + la = self.operands()[1:] + aa = sa.operands() + if recursive: + return sum(map(lambda t:treat_term(op, + t.distribute(), + la), + aa)) + else: return sum(map(lambda t:treat_term(op, t, la), aa)) + else: return self + else: return self + def factor(self, dontfactor=[]): """ Factor the expression, containing any number of variables or functions, into From 8c544adf3334db569139be3a49f40810030771f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jori=20M=C3=A4ntysalo?= Date: Tue, 9 May 2017 08:00:43 +0300 Subject: [PATCH 271/452] Split some long lines. --- src/sage/combinat/posets/lattices.py | 41 ++++++++++++++++++---------- 1 file changed, 27 insertions(+), 14 deletions(-) diff --git a/src/sage/combinat/posets/lattices.py b/src/sage/combinat/posets/lattices.py index 19616525a9b..2cc5b2a44b7 100644 --- a/src/sage/combinat/posets/lattices.py +++ b/src/sage/combinat/posets/lattices.py @@ -875,7 +875,8 @@ def is_join_distributive(self, certificate=False): .. SEEALSO:: - Dual property: :meth:`is_meet_distributive` - - Weaker properties: :meth:`is_meet_semidistributive`, :meth:`is_upper_semimodular` + - Weaker properties: :meth:`is_meet_semidistributive`, + :meth:`is_upper_semimodular` - Stronger properties: :meth:`is_distributive` EXAMPLES:: @@ -964,7 +965,8 @@ def is_meet_distributive(self, certificate=False): .. SEEALSO:: - Dual property: :meth:`is_join_distributive` - - Weaker properties: :meth:`is_join_semidistributive`, :meth:`is_lower_semimodular` + - Weaker properties: :meth:`is_join_semidistributive`, + :meth:`is_lower_semimodular` - Stronger properties: :meth:`is_distributive` EXAMPLES:: @@ -1139,9 +1141,9 @@ def is_distributive(self, certificate=False): .. SEEALSO:: - - Weaker properties: :meth:`is_modular`, :meth:`is_semidistributive`, - :meth:`is_join_distributive`, :meth:`is_meet_distributive`, - :meth:`is_subdirectly_reducible`, + - Weaker properties: :meth:`is_modular`, + :meth:`is_semidistributive`, :meth:`is_join_distributive`, + :meth:`is_meet_distributive`, :meth:`is_subdirectly_reducible`, :meth:`is_constructible_by_doublings` (by interval doubling) - Stronger properties: :meth:`is_stone` @@ -1192,7 +1194,8 @@ def is_semidistributive(self): .. SEEALSO:: - - Weaker properties: :meth:`is_join_semidistributive`, :meth:`is_meet_semidistributive` + - Weaker properties: :meth:`is_join_semidistributive`, + :meth:`is_meet_semidistributive` - Stronger properties: :meth:`is_distributive` EXAMPLES: @@ -1258,7 +1261,9 @@ def is_meet_semidistributive(self, certificate=False): - Dual property: :meth:`is_join_semidistributive` - Weaker properties: :meth:`is_pseudocomplemented` - - Stronger properties: :meth:`is_semidistributive`, :meth:`is_join_distributive`, :meth:`is_constructible_by_doublings` (by upper pseudo-intervals) + - Stronger properties: :meth:`is_semidistributive`, + :meth:`is_join_distributive`, + :meth:`is_constructible_by_doublings` (by upper pseudo-intervals) EXAMPLES:: @@ -1346,7 +1351,9 @@ def is_join_semidistributive(self, certificate=False): .. SEEALSO:: - Dual property: :meth:`is_meet_semidistributive` - - Stronger properties: :meth:`is_semidistributive`, :meth:`is_meet_distributive`, :meth:`is_constructible_by_doublings` (by lower pseudo-intervals) + - Stronger properties: :meth:`is_semidistributive`, + :meth:`is_meet_distributive`, + :meth:`is_constructible_by_doublings` (by lower pseudo-intervals) EXAMPLES:: @@ -1432,7 +1439,8 @@ def is_complemented(self, certificate=False): .. SEEALSO:: - Stronger properties: :meth:`is_sectionally_complemented`, - :meth:`is_cosectionally_complemented`, :meth:`is_orthocomplemented` + :meth:`is_cosectionally_complemented`, + :meth:`is_orthocomplemented` - Other: :meth:`complements` EXAMPLES:: @@ -2424,7 +2432,8 @@ def is_modular(self, L=None, certificate=False): .. SEEALSO:: - - Weaker properties: :meth:`is_upper_semimodular`, :meth:`is_lower_semimodular` + - Weaker properties: :meth:`is_upper_semimodular`, + :meth:`is_lower_semimodular` - Stronger properties: :meth:`is_distributive` - Other: :meth:`is_modular_element` @@ -2547,7 +2556,8 @@ def is_upper_semimodular(self, certificate=False): - Dual property: :meth:`is_lower_semimodular` - Weaker properties: :meth:`~sage.combinat.posets.posets.FinitePoset.is_graded` - - Stronger properties: :meth:`is_modular`, :meth:`is_join_distributive`, :meth:`is_geometric` + - Stronger properties: :meth:`is_modular`, + :meth:`is_join_distributive`, :meth:`is_geometric` See :wikipedia:`Semimodular_lattice` @@ -2606,7 +2616,8 @@ def is_lower_semimodular(self, certificate=False): - Dual property: :meth:`is_upper_semimodular` - Weaker properties: :meth:`~sage.combinat.posets.posets.FinitePoset.is_graded` - - Stronger properties: :meth:`is_modular`, :meth:`is_meet_distributive` + - Stronger properties: :meth:`is_modular`, + :meth:`is_meet_distributive` See :wikipedia:`Semimodular_lattice` @@ -3566,7 +3577,8 @@ def is_subdirectly_reducible(self, certificate=False): .. SEEALSO:: - - Stronger properties: :meth:`is_distributive`, :meth:`is_vertically_decomposable` + - Stronger properties: :meth:`is_distributive`, + :meth:`is_vertically_decomposable` EXAMPLES:: @@ -3837,7 +3849,8 @@ def is_isoform(self, certificate=False): .. SEEALSO:: - Weaker properties: :meth:`is_uniform` - - Stronger properties: :meth:`is_simple`, :meth:`is_relatively_complemented` + - Stronger properties: :meth:`is_simple`, + :meth:`is_relatively_complemented` - Other: :meth:`congruence` EXAMPLES:: From 67d03ba32d42298153885197b6ea04ed4b392885 Mon Sep 17 00:00:00 2001 From: David Coudert Date: Tue, 9 May 2017 08:58:56 +0200 Subject: [PATCH 272/452] trac #22954: replace wrong symbol with a minus --- src/sage/graphs/generators/families.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/graphs/generators/families.py b/src/sage/graphs/generators/families.py index 1f39031c3a2..23f240f2c08 100644 --- a/src/sage/graphs/generators/families.py +++ b/src/sage/graphs/generators/families.py @@ -2505,9 +2505,9 @@ def WindmillGraph(k, n): r""" Return the Windmill graph `Wd(k, n)`. - The windmill graph `Wd(k,n)` is an undirected graph constructed for `k \geq + The windmill graph `Wd(k, n)` is an undirected graph constructed for `k \geq 2` and `n \geq 2` by joining `n` copies of the complete graph `K_k` at a - shared vertex. It has `(k-1)n+1` vertices and `nk(k−1)/2` edges, girth 3 (if + shared vertex. It has `(k-1)n+1` vertices and `nk(k-1)/2` edges, girth 3 (if `k > 2`), radius 1 and diameter 2. It has vertex connectivity 1 because its central vertex is an articulation point; however, like the complete graphs from which it is formed, it is `(k-1)`-edge-connected. It is trivially From 69a1ae8bee93bae886058f6df3abb056d876439a Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Tue, 9 May 2017 10:08:11 +0100 Subject: [PATCH 273/452] fixed the wrong bound, and made sure docstrings are correctly formatted --- src/sage/coding/code_bounds.py | 50 +++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 10 deletions(-) diff --git a/src/sage/coding/code_bounds.py b/src/sage/coding/code_bounds.py index 9fa04f3c52f..68e934ec4c4 100644 --- a/src/sage/coding/code_bounds.py +++ b/src/sage/coding/code_bounds.py @@ -180,7 +180,9 @@ @rename_keyword(deprecation=6094, method="algorithm") def codesize_upper_bound(n,d,q,algorithm=None): r""" - This computes the minimum value of the upper bound using the + Returns an upper bound on the code size. + + This function computes the minimum value of the upper bound using the methods of Singleton, Hamming, Plotkin, and Elias. If algorithm="gap" then this returns the best known upper @@ -213,6 +215,12 @@ def codesize_upper_bound(n,d,q,algorithm=None): sage: codes.bounds.codesize_upper_bound(11,3,4,algorithm="LP") 109226 + TESTS: + + Make sure :trac:`22961` is fixed:: + + sage: codes.bounds.codesize_upper_bound(19,10,2) + 20 """ if algorithm=="gap": gap.load_package('guava') @@ -221,7 +229,6 @@ def codesize_upper_bound(n,d,q,algorithm=None): return int(delsarte_bound_hamming_space(n,d,q)) else: eub = elias_upper_bound(n,q,d) - gub = griesmer_upper_bound(n,q,d) hub = hamming_upper_bound(n,q,d) pub = plotkin_upper_bound(n,q,d) sub = singleton_upper_bound(n,q,d) @@ -230,6 +237,8 @@ def codesize_upper_bound(n,d,q,algorithm=None): @rename_keyword(deprecation=6094, method="algorithm") def dimension_upper_bound(n,d,q,algorithm=None): r""" + Returns an upper bound for the dimension of a linear code. + Returns an upper bound `B(n,d) = B_q(n,d)` for the dimension of a linear code of length n, minimum distance d over a field of size q. @@ -255,6 +264,8 @@ def dimension_upper_bound(n,d,q,algorithm=None): def volume_hamming(n,q,r): r""" + Returns number of elements in a Hamming ball. + Returns number of elements in a Hamming ball of radius r in `\GF{q}^n`. Agrees with Guava's SphereContent(n,r,GF(q)). @@ -268,7 +279,9 @@ def volume_hamming(n,q,r): def gilbert_lower_bound(n,q,d): r""" - Returns lower bound for number of elements in the largest code of + Returns Gilbert–Varshamov lower bound. + + Returns Gilbert–Varshamov lower bound for number of elements in a largest code of minimum distance d in `\GF{q}^n`. EXAMPLES:: @@ -282,9 +295,10 @@ def gilbert_lower_bound(n,q,d): @rename_keyword(deprecation=6094, method="algorithm") def plotkin_upper_bound(n,q,d, algorithm=None): r""" + Returns Plotkin upper bound. + Returns Plotkin upper bound for number of elements in the largest code of minimum distance d in `\GF{q}^n`. - The algorithm="gap" option wraps Guava's UpperBoundPlotkin. EXAMPLES:: @@ -315,9 +329,11 @@ def plotkin_upper_bound(n,q,d, algorithm=None): @rename_keyword(deprecation=6094, method="algorithm") def griesmer_upper_bound(n,q,d,algorithm=None): r""" - Returns the Griesmer upper bound for number of elements in the - largest code of minimum distance d in `\GF{q}^n`. - Wraps GAP's UpperBoundGriesmer. + Returns the Griesmer upper bound. + + Returns the Griesmer upper bound for number of elements in a + largest linear code of minimum distance d in `\GF{q}^n`. + If the method is "GAP", it wraps GAP's UpperBoundGriesmer. EXAMPLES:: @@ -333,7 +349,7 @@ def griesmer_upper_bound(n,q,d,algorithm=None): else: den = 1 s = 0 - k = 0 + k = 1 add = 0 while s <= n: if not(add == 1): @@ -350,6 +366,8 @@ def griesmer_upper_bound(n,q,d,algorithm=None): @rename_keyword(deprecation=6094, method="algorithm") def elias_upper_bound(n,q,d,algorithm=None): r""" + Returns the Elias upper bound. + Returns the Elias upper bound for number of elements in the largest code of minimum distance d in `\GF{q}^n`. Wraps GAP's UpperBoundElias. @@ -382,6 +400,8 @@ def get_list(n,d,q): def hamming_upper_bound(n,q,d): r""" + Returns the Hamming upper bound. + Returns the Hamming upper bound for number of elements in the largest code of minimum distance d in `\GF{q}^n`. Wraps GAP's UpperBoundHamming. @@ -415,6 +435,8 @@ def hamming_upper_bound(n,q,d): def singleton_upper_bound(n,q,d): r""" + Returns the Singleton upper bound. + Returns the Singleton upper bound for number of elements in the largest code of minimum distance d in `\GF{q}^n`. Wraps GAP's UpperBoundSingleton. @@ -442,7 +464,9 @@ def singleton_upper_bound(n,q,d): def gv_info_rate(n,delta,q): """ - GV lower bound for information rate of a q-ary code of length n + Gilbert-Varshamov lower bound for information rate. + + Gilbert-Varshamov lower bound for information rate of a q-ary code of length n minimum distance delta\*n EXAMPLES:: @@ -550,7 +574,7 @@ def entropy_inverse(x, q=2): def gv_bound_asymp(delta,q): """ - Computes the asymptotic GV bound for the information rate, R. + Computes the asymptotic Gilbert-Varshamov bound for the information rate, R. EXAMPLES:: @@ -593,6 +617,8 @@ def singleton_bound_asymp(delta,q): def plotkin_bound_asymp(delta,q): """ + Computes the asymptotic Plotkin bound for the information rate. + Computes the asymptotic Plotkin bound for the information rate, provided `0 < \delta < 1-1/q`. @@ -606,6 +632,8 @@ def plotkin_bound_asymp(delta,q): def elias_bound_asymp(delta,q): """ + Computes the asymptotic Elias bound for the information rate. + Computes the asymptotic Elias bound for the information rate, provided `0 < \delta < 1-1/q`. @@ -619,6 +647,8 @@ def elias_bound_asymp(delta,q): def mrrw1_bound_asymp(delta,q): """ + Computes the first asymptotic McEliese-Rumsey-Rodemich-Welsh bound. + Computes the first asymptotic McEliese-Rumsey-Rodemich-Welsh bound for the information rate, provided `0 < \delta < 1-1/q`. From 3b80b3e310132ab06a1c71d1098a718ed198e284 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Tue, 9 May 2017 12:32:22 +0100 Subject: [PATCH 274/452] fixed non-ascii and other typos --- src/sage/coding/code_bounds.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sage/coding/code_bounds.py b/src/sage/coding/code_bounds.py index 68e934ec4c4..075c95891af 100644 --- a/src/sage/coding/code_bounds.py +++ b/src/sage/coding/code_bounds.py @@ -232,7 +232,7 @@ def codesize_upper_bound(n,d,q,algorithm=None): hub = hamming_upper_bound(n,q,d) pub = plotkin_upper_bound(n,q,d) sub = singleton_upper_bound(n,q,d) - return min([eub,gub,hub,pub,sub]) + return min([eub,hub,pub,sub]) @rename_keyword(deprecation=6094, method="algorithm") def dimension_upper_bound(n,d,q,algorithm=None): @@ -279,9 +279,9 @@ def volume_hamming(n,q,r): def gilbert_lower_bound(n,q,d): r""" - Returns Gilbert–Varshamov lower bound. + Returns Gilbert-Varshamov lower bound. - Returns Gilbert–Varshamov lower bound for number of elements in a largest code of + Returns Gilbert-Varshamov lower bound for number of elements in a largest code of minimum distance d in `\GF{q}^n`. EXAMPLES:: @@ -466,8 +466,8 @@ def gv_info_rate(n,delta,q): """ Gilbert-Varshamov lower bound for information rate. - Gilbert-Varshamov lower bound for information rate of a q-ary code of length n - minimum distance delta\*n + Gilbert-Varshamov lower bound for information rate of a `q`-ary code of length `n` + minimum distance `n\delta`. EXAMPLES:: From 7f9666a22d0d290f4b3504bc1d4b61a4dcf7c455 Mon Sep 17 00:00:00 2001 From: Emmanuel Charpentier Date: Tue, 9 May 2017 17:10:26 +0200 Subject: [PATCH 275/452] Fixed recursion when non-match at toplevel. --- 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 0e09c2e08a2..d59d4d95f0b 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -10442,8 +10442,9 @@ cdef class Expression(CommutativeRingElement): return(apply(op, l)) if self.parent() is not sage.all.SR: return self op = self.operator() + if op is None : return self if op in {opsum, opdi, opii}: - sa = self.operands()[0] + sa = self.operands()[0].expand() op1 = sa.operator() if op1 is opadd: la = self.operands()[1:] @@ -10453,10 +10454,13 @@ cdef class Expression(CommutativeRingElement): t.distribute(), la), aa)) - else: return sum(map(lambda t:treat_term(op, t, la), aa)) - else: return self - else: return self - + return sum(map(lambda t:treat_term(op, t, la), aa)) + return self + if recursive: + return apply(op, map(lambda t:t.distribute(), self.operands())) + return self + + def factor(self, dontfactor=[]): """ Factor the expression, containing any number of variables or functions, into From fcee19cbf6606f7676cbabcc44ee8d539b440b33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 9 May 2017 21:03:15 +0200 Subject: [PATCH 276/452] trac 22952 adding ellipses --- src/sage/tests/py3_syntax.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/tests/py3_syntax.py b/src/sage/tests/py3_syntax.py index e3dd733e0fa..e564860b485 100644 --- a/src/sage/tests/py3_syntax.py +++ b/src/sage/tests/py3_syntax.py @@ -77,7 +77,7 @@ def __iter__(self): sage: from sage.tests.py3_syntax import Python3SyntaxTest sage: test = Python3SyntaxTest('sage/tests/french_book') sage: next(iter(test)) - ('src/sage/tests/french_book', 'README', '') + ('...src/sage/tests/french_book', 'README', '') """ tree_walk = itertools.chain(*map(os.walk, self._directories)) for path, _, files in tree_walk: From a75ec910414f17772072ea13d57fb11117877c16 Mon Sep 17 00:00:00 2001 From: Vincent Delecroix <20100.delecroix@gmail.com> Date: Tue, 9 May 2017 21:35:38 +0200 Subject: [PATCH 277/452] 22924: better FIXME message --- src/sage/libs/linbox/linbox_flint_interface.pyx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/libs/linbox/linbox_flint_interface.pyx b/src/sage/libs/linbox/linbox_flint_interface.pyx index 7809d86eb65..f9d5b687eb0 100644 --- a/src/sage/libs/linbox/linbox_flint_interface.pyx +++ b/src/sage/libs/linbox/linbox_flint_interface.pyx @@ -192,8 +192,8 @@ cdef void linbox_fmpz_mat_charpoly(fmpz_poly_t cp, fmpz_mat_t A): cdef LinBoxIntegerDenseMatrix * LBA cdef LinBoxIntegerPolynomialRing.Element m_A - # FIXME: looks like a bug in LinBox - # see https://trac.sagemath.org/ticket/22924#comment:17 + # FIXME: bug in LinBox + # see https://github.com/linbox-team/linbox/issues/51 if fmpz_mat_nrows(A) == 0: fmpz_poly_one(cp) return @@ -212,8 +212,8 @@ cdef void linbox_fmpz_mat_minpoly(fmpz_poly_t mp, fmpz_mat_t A): cdef LinBoxIntegerDenseMatrix * LBA cdef LinBoxIntegerPolynomialRing.Element m_A - # FIXME: looks like a bug in LinBox - # see https://trac.sagemath.org/ticket/22924#comment:17 + # FIXME: bug in LinBox + # see https://github.com/linbox-team/linbox/issues/51 if fmpz_mat_nrows(A) == 0: fmpz_poly_one(mp) return From 5755b9536a33e162e621649368595fc417631567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Tue, 9 May 2017 22:21:16 +0200 Subject: [PATCH 278/452] trac 21668 add try except --- src/sage/stats/basic_stats.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/sage/stats/basic_stats.py b/src/sage/stats/basic_stats.py index e2479a73626..994b8d17ccf 100644 --- a/src/sage/stats/basic_stats.py +++ b/src/sage/stats/basic_stats.py @@ -84,6 +84,7 @@ def mean(v): return s/ZZ(len(v)) return s/len(v) + def mode(v): """ Return the mode of `v`. @@ -114,14 +115,17 @@ def mode(v): 3 sage: mode([]) [] + sage: mode([1,2,3,4,5]) [1, 2, 3, 4, 5] sage: mode([3,1,2,1,2,3]) [1, 2, 3] sage: mode([0, 2, 7, 7, 13, 20, 2, 13]) [2, 7, 13] - sage: mode(['sage', 4, I, 3/5, 'sage', pi]) + + sage: mode(['sage', 'four', 'I', 'three', 'sage', 'pi']) ['sage'] + sage: class MyClass: ....: def mode(self): ....: return [1] @@ -142,7 +146,10 @@ def mode(v): freq[i] = 1 n = max(freq.values()) - return sorted(u for u, f in freq.items() if f == n) + try: + return sorted(u for u, f in freq.items() if f == n) + except TypeError: + return [u for u, f in freq.items() if f == n] def std(v, bias=False): From 1652bef04e5bae631c97690ab64468871daf7810 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 10 May 2017 08:42:06 +0200 Subject: [PATCH 279/452] trac 21668 change in doc --- src/sage/stats/basic_stats.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/sage/stats/basic_stats.py b/src/sage/stats/basic_stats.py index 994b8d17ccf..3c532a62c75 100644 --- a/src/sage/stats/basic_stats.py +++ b/src/sage/stats/basic_stats.py @@ -89,14 +89,14 @@ def mode(v): """ Return the mode of `v`. - The mode is the sorted list of the most frequently occuring - elements in `v`. If `n` is the most times that any element occurs - in `v`, then the mode is the sorted list of elements of `v` that - occur `n` times. + The mode is the list of the most frequently occuring + elements in `v`. If `n` is the most times that any element occurs + in `v`, then the mode is the list of elements of `v` that + occur `n` times. The list is sorted if possible. .. NOTE:: - The elements of `v` must be hashable and comparable. + The elements of `v` must be hashable. INPUT: @@ -104,7 +104,7 @@ def mode(v): OUTPUT: - - a list + - a list (sorted if possible) EXAMPLES:: From 3aca1919e5526fbab6ab55ae52a884edb2326b71 Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Wed, 10 May 2017 09:00:11 +0200 Subject: [PATCH 280/452] 22969: pynac-0.7.7 version/chksum/delete old patch --- build/pkgs/pynac/checksums.ini | 6 +++--- build/pkgs/pynac/package-version.txt | 2 +- build/pkgs/pynac/patches/coeff-to-ex.patch | 22 ---------------------- 3 files changed, 4 insertions(+), 26 deletions(-) delete mode 100644 build/pkgs/pynac/patches/coeff-to-ex.patch diff --git a/build/pkgs/pynac/checksums.ini b/build/pkgs/pynac/checksums.ini index d5ada9ee7fe..22a7b185139 100644 --- a/build/pkgs/pynac/checksums.ini +++ b/build/pkgs/pynac/checksums.ini @@ -1,4 +1,4 @@ tarball=pynac-VERSION.tar.bz2 -sha1=6ff23c35da9f424751522267ab925b46d5aaeff1 -md5=0400e2c1333ee0b657c543cd788ee250 -cksum=4257838880 +sha1=13d73ad7b1bdac7726f5140dc5230ad93a987f40 +md5=78f29f401fa67d5bf7dc6ee2d5e3da81 +cksum=1873135840 diff --git a/build/pkgs/pynac/package-version.txt b/build/pkgs/pynac/package-version.txt index c006218557f..879be8a98fc 100644 --- a/build/pkgs/pynac/package-version.txt +++ b/build/pkgs/pynac/package-version.txt @@ -1 +1 @@ -0.7.6 +0.7.7 diff --git a/build/pkgs/pynac/patches/coeff-to-ex.patch b/build/pkgs/pynac/patches/coeff-to-ex.patch deleted file mode 100644 index cc11bb5a6de..00000000000 --- a/build/pkgs/pynac/patches/coeff-to-ex.patch +++ /dev/null @@ -1,22 +0,0 @@ -diff --git a/ginac/mpoly-singular.cpp b/ginac/mpoly-singular.cpp -index 4ddb961..74b8815 100644 ---- a/ginac/mpoly-singular.cpp -+++ b/ginac/mpoly-singular.cpp -@@ -255,7 +255,7 @@ static ex coeff_to_ex(const CanonicalForm& f, const exvector& revmap) - if (f.isImm()) - return numeric(f.intval()); - if (f.inZ()) -- throw std::runtime_error("can't happen in coeff_to_ex"); -+ return can2num(f); - if (f.inQ()) { - CanonicalForm num = f.num(); - CanonicalForm den = f.den(); -@@ -277,7 +277,7 @@ static ex canonical_to_ex(const CanonicalForm& f, const exvector& revmap) - if (f.isImm()) - return numeric(f.intval()); - if (f.inZ()) -- throw std::runtime_error("can't happen in canonical_to_ex #1"); -+ return can2num(f); - if (f.inQ()) { - CanonicalForm num = f.num(); - CanonicalForm den = f.den(); From 894c5f288f95ac22b7d468687c470ce046dbbc23 Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Wed, 10 May 2017 09:02:51 +0200 Subject: [PATCH 281/452] 22969: doctest fixes --- src/sage/functions/log.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/functions/log.py b/src/sage/functions/log.py index c08a2b5a09d..49cec23548a 100644 --- a/src/sage/functions/log.py +++ b/src/sage/functions/log.py @@ -432,9 +432,9 @@ def __init__(self): sage: polylog(2.0, 1) 1.64493406684823 sage: polylog(2, 1.0) - NaN + NaN*I + NaN sage: polylog(2.0, 1.0) - NaN + NaN*I + NaN """ GinacFunction.__init__(self, "polylog", nargs=2) From 179ac5e247e0eb8a090d0cf8cd22b203a8982f12 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Tue, 9 May 2017 22:47:10 +0100 Subject: [PATCH 282/452] cleanup of Griesmer bound, docs and examples --- src/sage/coding/code_bounds.py | 90 ++++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 30 deletions(-) diff --git a/src/sage/coding/code_bounds.py b/src/sage/coding/code_bounds.py index 075c95891af..0108802aad5 100644 --- a/src/sage/coding/code_bounds.py +++ b/src/sage/coding/code_bounds.py @@ -171,6 +171,7 @@ from sage.interfaces.all import gap from sage.rings.all import QQ, RR, ZZ, RDF +from sage.arith.misc import is_prime_power from sage.arith.all import factorial from sage.functions.all import log, sqrt from sage.misc.decorators import rename_keyword @@ -221,6 +222,8 @@ def codesize_upper_bound(n,d,q,algorithm=None): sage: codes.bounds.codesize_upper_bound(19,10,2) 20 + sage: codes.bounds.codesize_upper_bound(19,10,2,algorithm="gap") # optional - gap_packages (Guava package) + 20 """ if algorithm=="gap": gap.load_package('guava') @@ -255,11 +258,12 @@ def dimension_upper_bound(n,d,q,algorithm=None): """ q = ZZ(q) - if algorithm=="LP": - return delsarte_bound_additive_hamming_space(n,d,q) + if is_prime_power(q) and n>0 and d>0 and n in ZZ and d in ZZ: # sanity check + if algorithm=="LP": + return delsarte_bound_additive_hamming_space(n,d,q) - else: # algorithm==None or algorithm=="gap": - return int(log(codesize_upper_bound(n,d,q,algorithm=algorithm),q)) + else: # algorithm==None or algorithm=="gap": + return int(log(codesize_upper_bound(n,d,q,algorithm=algorithm),q)) def volume_hamming(n,q,r): @@ -282,7 +286,7 @@ def gilbert_lower_bound(n,q,d): Returns Gilbert-Varshamov lower bound. Returns Gilbert-Varshamov lower bound for number of elements in a largest code of - minimum distance d in `\GF{q}^n`. + minimum distance d in `\GF{q}^n`. See :wikipedia:`Gilbert-Varshamov_bound` EXAMPLES:: @@ -297,8 +301,10 @@ def plotkin_upper_bound(n,q,d, algorithm=None): r""" Returns Plotkin upper bound. - Returns Plotkin upper bound for number of elements in the largest + Returns Plotkin upper bound for number of elements in a largest code of minimum distance d in `\GF{q}^n`. + More precisely this is a generalization of Plotkin's result for q=2 + to bigger q due to Berlekamp. The algorithm="gap" option wraps Guava's UpperBoundPlotkin. EXAMPLES:: @@ -332,35 +338,59 @@ def griesmer_upper_bound(n,q,d,algorithm=None): Returns the Griesmer upper bound. Returns the Griesmer upper bound for number of elements in a - largest linear code of minimum distance d in `\GF{q}^n`. - If the method is "GAP", it wraps GAP's UpperBoundGriesmer. + largest linear code of minimum distance d in `\GF{q}^n`, cf. [HP2003]_. + If the method is "GAP", it wraps GAP's UpperBoundGriesmer. Namely, - EXAMPLES:: + .. MATH:: + + `n\geq \sum_{i=0}^{k-1} \lceil d/q^i \rceil.` + + To compute the bound, we keep summing up the terms on the RHS + until we start violating the inequality. + + + EXAMPLES: + + The bound is reached for the ternary Golay codes:: + + sage: codes.bounds.griesmer_upper_bound(12,3,6) + 729 + sage: codes.bounds.griesmer_upper_bound(11,3,5) + 729 + + :: sage: codes.bounds.griesmer_upper_bound(10,2,3) 128 sage: codes.bounds.griesmer_upper_bound(10,2,3,algorithm="gap") # optional - gap_packages (Guava package) 128 + + TESTS:: + + sage: codes.bounds.griesmer_upper_bound(10,6,5) + 0 + sage: codes.bounds.griesmer_upper_bound(11,3,6) + 243 + sage: codes.bounds.griesmer_upper_bound(11,3,6) + 243 """ - if algorithm=="gap": - gap.load_package("guava") - ans=gap.eval("UpperBoundGriesmer(%s,%s,%s)"%(n,d,q)) - return QQ(ans) + if is_prime_power(q) and n>0 and d>0 and n in ZZ and d in ZZ: # sanity check + if algorithm=="gap": + gap.load_package("guava") + ans=gap.eval("UpperBoundGriesmer(%s,%s,%s)"%(n,d,q)) + return QQ(ans) + else: + from sage.functions.other import ceil + den = 1 + s = 0 + k = 0 + while s <= n: + s += ceil(d/den) + den *= q + k = k + 1 + return q**(k-1) else: - den = 1 - s = 0 - k = 1 - add = 0 - while s <= n: - if not(add == 1): - if d%den==0: - add = int(d/den) - else: - add = int(d/den)+1 - s = s + add - den = den * q - k = k + 1 - return q**(k-1) + return 0 @rename_keyword(deprecation=6094, method="algorithm") @@ -369,7 +399,7 @@ def elias_upper_bound(n,q,d,algorithm=None): Returns the Elias upper bound. Returns the Elias upper bound for number of elements in the largest - code of minimum distance d in `\GF{q}^n`. Wraps + code of minimum distance d in `\GF{q}^n`, cf. [HP2003]_. Wraps GAP's UpperBoundElias. EXAMPLES:: @@ -424,7 +454,7 @@ def hamming_upper_bound(n,q,d): where M is the maximum number of codewords and `V(n,e)` is equal to the contents of a ball of radius e. This bound is useful for small values of d. Codes for which equality holds are called - perfect. + perfect. See e.g. [HP2003]_. EXAMPLES:: @@ -437,7 +467,7 @@ def singleton_upper_bound(n,q,d): r""" Returns the Singleton upper bound. - Returns the Singleton upper bound for number of elements in the + Returns the Singleton upper bound for number of elements in a largest code of minimum distance d in `\GF{q}^n`. Wraps GAP's UpperBoundSingleton. From 22af33afbb4ccca6f0ca71deba1efe8d4fe2e588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 10 May 2017 13:41:53 +0200 Subject: [PATCH 283/452] py3: more care for range (again) --- src/sage/coding/binary_code.pyx | 2 +- src/sage/coding/reed_muller_code.py | 3 +- src/sage/matrix/matrix0.pyx | 30 +++++++++---------- .../numerical/backends/generic_backend.pyx | 10 +++---- .../numerical/backends/gurobi_backend.pyx | 2 +- src/sage/parallel/multiprocessing_sage.py | 5 ++-- 6 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/sage/coding/binary_code.pyx b/src/sage/coding/binary_code.pyx index 9a204dfc726..cd35de932a7 100644 --- a/src/sage/coding/binary_code.pyx +++ b/src/sage/coding/binary_code.pyx @@ -3812,7 +3812,7 @@ cdef class BinaryCodeClassifier: sage: from sage.coding.binary_code import * sage: BC = BinaryCodeClassifier() sage: B = BinaryCode(codes.GolayCode(GF(2)).generator_matrix()) - sage: B.apply_permutation(range(24,-1,-1)) + sage: B.apply_permutation(list(range(24,-1,-1))) sage: B Binary [24,12] linear code, generator matrix [011000111010100000000000] diff --git a/src/sage/coding/reed_muller_code.py b/src/sage/coding/reed_muller_code.py index 8345c823af8..1f934109278 100644 --- a/src/sage/coding/reed_muller_code.py +++ b/src/sage/coding/reed_muller_code.py @@ -24,6 +24,7 @@ # (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** +from six.moves import range from operator import mul from sage.matrix.constructor import matrix @@ -657,7 +658,7 @@ def generator_matrix(self): matrix_list = [] max_individual_degree = min(order, (q - 1)) for degree in range(order + 1): - exponents = Subsets(range(num_of_var) * max_individual_degree, + exponents = Subsets(list(range(num_of_var)) * max_individual_degree, degree, submultiset=True) matrix_list += [[reduce(mul, [x[i] for i in exponent], 1) for x in points] for exponent in exponents] diff --git a/src/sage/matrix/matrix0.pyx b/src/sage/matrix/matrix0.pyx index 48d9980e1b5..b1af13d9713 100644 --- a/src/sage/matrix/matrix0.pyx +++ b/src/sage/matrix/matrix0.pyx @@ -639,20 +639,20 @@ cdef class Matrix(sage.structure.element.Matrix): More examples:: - sage: M[range(2),:] + sage: M[list(range(2)),:] [ 1 -2 -1 -1 9] [ 1 8 6 2 2] - sage: M[range(2),4] + sage: M[list(range(2)),4] [9] [2] - sage: M[range(3),range(5)] + sage: M[list(range(3)),list(range(5))] [ 1 -2 -1 -1 9] [ 1 8 6 2 2] [ 1 1 -1 1 4] :: - sage: M[3,range(5)] + sage: M[3,list(range(5))] [-1 2 -2 -1 4] sage: M[3,:] [-1 2 -2 -1 4] @@ -701,14 +701,14 @@ cdef class Matrix(sage.structure.element.Matrix): :: sage: A= matrix(3,4,[1, 0, -3, -1, 3, 0, -2, 1, -3, -5, -1, -5]) - sage: A[range(2,-1,-1),:] + sage: A[list(range(2,-1,-1)),:] [-3 -5 -1 -5] [ 3 0 -2 1] [ 1 0 -3 -1] :: - sage: A[range(2,-1,-1),range(3,-1,-1)] + sage: A[list(range(2,-1,-1)),list(range(3,-1,-1))] [-5 -1 -5 -3] [ 1 -2 0 3] [-1 -3 0 1] @@ -729,7 +729,7 @@ cdef class Matrix(sage.structure.element.Matrix): [] sage: M[2:3, 3:3] [] - sage: M[range(2,2), :3] + sage: M[list(range(2,2)), :3] [] sage: M[(1,2), 3] [ 7] @@ -1157,26 +1157,26 @@ cdef class Matrix(sage.structure.element.Matrix): More examples:: - sage: M[range(2),:]=[[1..5], [6..10]]; M + sage: M[list(range(2)),:]=[[1..5], [6..10]]; M [ 1 2 3 4 5] [ 6 7 8 9 10] [30 -1 2 -2 4] [30 2 -2 -1 4] - sage: M[range(2),4]=0; M + sage: M[list(range(2)),4]=0; M [ 1 2 3 4 0] [ 6 7 8 9 0] [30 -1 2 -2 4] [30 2 -2 -1 4] - sage: M[range(3),range(5)]=M[range(1,4), :]; M + sage: M[list(range(3)),list(range(5))]=M[list(range(1,4)), :]; M [ 6 7 8 9 0] [30 -1 2 -2 4] [30 2 -2 -1 4] [30 2 -2 -1 4] - sage: M[3,range(5)]=vector([-2,3,4,-5,4]); M + sage: M[3,list(range(5))]=vector([-2,3,4,-5,4]); M [ 6 7 8 9 0] [30 -1 2 -2 4] [30 2 -2 -1 4] @@ -1204,12 +1204,12 @@ cdef class Matrix(sage.structure.element.Matrix): [ 3 0 -2 1] [-3 -5 -1 -5] - sage: A[range(2,-1,-1),:]=A; A + sage: A[list(range(2,-1,-1)),:]=A; A [-3 -5 -1 -5] [ 3 0 -2 1] [ 1 0 -3 -1] - sage: A[range(2,-1,-1),range(3,-1,-1)]=A; A + sage: A[list(range(2,-1,-1)),list(range(3,-1,-1))]=A; A [-1 -3 0 1] [ 1 -2 0 3] [-5 -1 -5 -3] @@ -1232,7 +1232,7 @@ cdef class Matrix(sage.structure.element.Matrix): [ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11] - sage: M[range(2,2), :3]=20; M + sage: M[list(range(2,2)), :3]=20; M [ 0 1 2 3] [ 4 5 6 7] [ 8 9 10 11] @@ -3479,7 +3479,7 @@ cdef class Matrix(sage.structure.element.Matrix): else: L.extend( L_prime ) if return_diag: - return [ d[i] for i in xrange(self._nrows) ] + return [d[i] for i in xrange(self._nrows)] else: return True diff --git a/src/sage/numerical/backends/generic_backend.pyx b/src/sage/numerical/backends/generic_backend.pyx index 7944e8a6154..a4421c30341 100644 --- a/src/sage/numerical/backends/generic_backend.pyx +++ b/src/sage/numerical/backends/generic_backend.pyx @@ -570,7 +570,7 @@ cdef class GenericBackend: sage: p.nrows() # optional - Nonexistent_LP_solver 0 sage: p.add_linear_constraints(5, 0, None) # optional - Nonexistent_LP_solver - sage: p.add_col(range(5), range(5)) # optional - Nonexistent_LP_solver + sage: p.add_col(list(range(5)), list(range(5))) # optional - Nonexistent_LP_solver sage: p.nrows() # optional - Nonexistent_LP_solver 5 """ @@ -679,7 +679,7 @@ cdef class GenericBackend: sage: from sage.numerical.backends.generic_backend import get_solver sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver sage: p.add_linear_constraints(5, 0, None) # optional - Nonexistent_LP_solver - sage: p.add_col(range(5), range(5)) # optional - Nonexistent_LP_solver + sage: p.add_col(list(range(5)), list(range(5))) # optional - Nonexistent_LP_solver sage: p.solve() # optional - Nonexistent_LP_solver 0 sage: p.objective_coefficient(0,1) # optional - Nonexistent_LP_solver @@ -711,7 +711,7 @@ cdef class GenericBackend: tester = p._tester(**options) # From doctest of GenericBackend.solve: tester.assertIsNone(p.add_linear_constraints(5, 0, None)) - tester.assertIsNone(p.add_col(range(5), range(5))) + tester.assertIsNone(p.add_col(list(xrange(5)), list(xrange(5)))) tester.assertEqual(p.solve(), 0) tester.assertIsNone(p.objective_coefficient(0,1)) from sage.numerical.mip import MIPSolverException @@ -1063,7 +1063,7 @@ cdef class GenericBackend: sage: p = get_solver(solver = "Nonexistent_LP_solver") # optional - Nonexistent_LP_solver sage: p.add_variables(5) # optional - Nonexistent_LP_solver 4 - sage: p.add_linear_constraint(range(5), range(5), 2, 2) # optional - Nonexistent_LP_solver + sage: p.add_linear_constraint(list(range(5)), list(range(5)), 2, 2) # optional - Nonexistent_LP_solver sage: p.row(0) # optional - Nonexistent_LP_solver ([4, 3, 2, 1], [4.0, 3.0, 2.0, 1.0]) ## FIXME: Why backwards? sage: p.row_bounds(0) # optional - Nonexistent_LP_solver @@ -1275,7 +1275,7 @@ cdef class GenericBackend: p.add_linear_constraints(5, 0, None) try: # p.add_col(range(5), range(5)) -- bad test because COIN sparsifies the 0s away on copy - p.add_col(range(5), range(1, 6)) + p.add_col(list(xrange(5)), list(xrange(1, 6))) except NotImplementedError: # Gurobi does not implement add_col pass diff --git a/src/sage/numerical/backends/gurobi_backend.pyx b/src/sage/numerical/backends/gurobi_backend.pyx index a0c92bbbd76..b4e11c56a0e 100644 --- a/src/sage/numerical/backends/gurobi_backend.pyx +++ b/src/sage/numerical/backends/gurobi_backend.pyx @@ -221,7 +221,7 @@ cdef class GurobiBackend(GenericBackend): sage: p.nrows() 0 sage: p.add_linear_constraints(5, 0, None) - sage: p.add_col(range(5), range(5)) + sage: p.add_col(list(range(5)), list(range(5))) sage: p.nrows() 5 """ diff --git a/src/sage/parallel/multiprocessing_sage.py b/src/sage/parallel/multiprocessing_sage.py index cd271fd5499..10d7ac0c641 100644 --- a/src/sage/parallel/multiprocessing_sage.py +++ b/src/sage/parallel/multiprocessing_sage.py @@ -37,10 +37,11 @@ def pyprocessing(processes=0): sage: p_iter = pyprocessing(4) sage: P = parallel(p_iter=p_iter) sage: def f(x): return x+x - sage: v = list(P(f)(range(10))); v.sort(); v + sage: v = list(P(f)(list(range(10)))); v.sort(); v [(((0,), {}), 0), (((1,), {}), 2), (((2,), {}), 4), (((3,), {}), 6), (((4,), {}), 8), (((5,), {}), 10), (((6,), {}), 12), (((7,), {}), 14), (((8,), {}), 16), (((9,), {}), 18)] """ - if processes == 0: processes = ncpus.ncpus() + if processes == 0: + processes = ncpus.ncpus() return partial(parallel_iter, processes) def parallel_iter(processes, f, inputs): From 6ec9d736f20143323b5ff9a24339f618fa952a02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 10 May 2017 15:10:46 +0200 Subject: [PATCH 284/452] py3 some care for cmp in units and interfaces --- src/sage/interfaces/interface.py | 26 ++++++++++++++------------ src/sage/symbolic/units.py | 30 +++++++++++++++++++++++------- 2 files changed, 37 insertions(+), 19 deletions(-) diff --git a/src/sage/interfaces/interface.py b/src/sage/interfaces/interface.py index 3404d594585..e547eb332c6 100644 --- a/src/sage/interfaces/interface.py +++ b/src/sage/interfaces/interface.py @@ -587,13 +587,14 @@ def __getattr__(self, attrname): raise return self._function_class()(self, attrname) - def __cmp__(self, other): + def __eq__(self, other): """ - Compare two pseudo-tty interfaces. Two interfaces compare - equal if and only if they are identical objects (this is a - critical constraint so that caching of representations of - objects in interfaces works correctly). Otherwise they are - never equal. + Compare two pseudo-tty interfaces. + + Two interfaces compare equal if and only if they are identical + objects (this is a critical constraint so that caching of + representations of objects in interfaces works + correctly). Otherwise they are never equal. EXAMPLES:: @@ -602,12 +603,13 @@ def __cmp__(self, other): sage: maxima == maxima True """ - if self is other: - return 0 - c = cmp(type(self), type(other)) - if c: - return c - return -1 # sucky, but I can't think of anything better; it is important that different interfaces to the same system still compare differently; unfortunately there is nothing to distinguish them. + return self is other + + def __ne__(self, other): + """ + Test for unequality. + """ + return not (self == other) def console(self): raise NotImplementedError diff --git a/src/sage/symbolic/units.py b/src/sage/symbolic/units.py index f1d862023e7..f2939fa7ec7 100644 --- a/src/sage/symbolic/units.py +++ b/src/sage/symbolic/units.py @@ -1044,10 +1044,10 @@ class Units(ExtraTabCompletion): """ A collection of units of some type. - EXAMPLES:: + EXAMPLES:: - sage: units.power - Collection of units of power: cheval_vapeur horsepower watt + sage: units.power + Collection of units of power: cheval_vapeur horsepower watt """ def __init__(self, data, name=''): """ @@ -1092,9 +1092,10 @@ def __setstate__(self, state): self.__data = state[1] self.__units = {} - def __cmp__(self, other): + def __eq__(self, other): """ - Compare two collections of units, or a collection of units with some other object. + Compare two collections of units, or a collection of units + with some other object. EXAMPLES:: @@ -1106,9 +1107,24 @@ def __cmp__(self, other): False """ if not isinstance(other, Units): - return cmp(type(self), type(other)) - return cmp((self.__name, self.__data), (other.__name, other.__data)) + return False + return (self.__name, self.__data) == (other.__name, other.__data) + + def __ne__(self, other): + """ + Test for unequality. + + EXAMPLES:: + sage: units.length != 5 + True + sage: units.length != units.length + False + sage: units.length != units.mass + True + """ + return not (self == other) + def _tab_completion(self): """ Return tab completions. From 2aca10e42eab75fdab0dcd4e8aeecd8941a3f51e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 10 May 2017 15:58:44 +0200 Subject: [PATCH 285/452] py3: some absolute_import added in pyx files --- src/sage/groups/old.pyx | 2 +- src/sage/libs/singular/function.pyx | 5 +++-- src/sage/matrix/matrix0.pyx | 12 ++++++------ src/sage/matroids/unpickling.pyx | 6 ++++-- src/sage/modules/free_module_element.pyx | 15 ++++++++------- src/sage/modules/vector_double_dense.pyx | 5 +++-- src/sage/rings/finite_rings/element_ntl_gf2e.pyx | 3 ++- src/sage/rings/padics/pow_computer_flint.pyx | 8 +++++--- 8 files changed, 32 insertions(+), 24 deletions(-) diff --git a/src/sage/groups/old.pyx b/src/sage/groups/old.pyx index 31e77750763..07c524f3fbb 100644 --- a/src/sage/groups/old.pyx +++ b/src/sage/groups/old.pyx @@ -23,7 +23,7 @@ Base class for all groups import random -from sage.rings.infinity import infinity +from sage.rings.infinity import infinity import sage.rings.integer_ring cdef class Group(sage.structure.parent_gens.ParentWithGens): diff --git a/src/sage/libs/singular/function.pyx b/src/sage/libs/singular/function.pyx index 019f30887ae..d0c13b8d4cf 100644 --- a/src/sage/libs/singular/function.pyx +++ b/src/sage/libs/singular/function.pyx @@ -74,6 +74,7 @@ TESTS:: # (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** +from __future__ import absolute_import from libc.string cimport memcpy @@ -515,7 +516,7 @@ cdef class Converter(SageObject): if ring is not None: self._singular_ring = access_singular_ring(ring) - from sage.matrix.matrix_mpolynomial_dense import Matrix_mpolynomial_dense + from sage.matrix.matrix_mpolynomial_dense import Matrix_mpolynomial_dense from sage.matrix.matrix_integer_dense import Matrix_integer_dense from sage.matrix.matrix_generic_dense import Matrix_generic_dense for a in args: @@ -1397,7 +1398,7 @@ The Singular documentation for '%s' is given below. - ``args`` -- a list of Python objects - ``ring`` -- an optional ring to check """ - from sage.matrix.matrix_mpolynomial_dense import Matrix_mpolynomial_dense + from sage.matrix.matrix_mpolynomial_dense import Matrix_mpolynomial_dense from sage.matrix.matrix_integer_dense import Matrix_integer_dense ring2 = None for a in args: diff --git a/src/sage/matrix/matrix0.pyx b/src/sage/matrix/matrix0.pyx index 48d9980e1b5..a40a1a57d33 100644 --- a/src/sage/matrix/matrix0.pyx +++ b/src/sage/matrix/matrix0.pyx @@ -22,7 +22,7 @@ EXAMPLES:: # (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** -from __future__ import print_function +from __future__ import print_function, absolute_import from cpython cimport * @@ -30,13 +30,13 @@ import sage.modules.free_module import sage.misc.latex import sage.rings.integer -from sage.misc.misc import verbose, get_verbose -from sage.structure.sequence import Sequence +from sage.misc.misc import verbose, get_verbose +from sage.structure.sequence import Sequence cimport sage.structure.element -from sage.structure.element cimport ModuleElement, Element, RingElement, Vector -from sage.structure.mutability cimport Mutability -from sage.misc.misc_c cimport normalize_index +from sage.structure.element cimport ModuleElement, Element, RingElement, Vector +from sage.structure.mutability cimport Mutability +from sage.misc.misc_c cimport normalize_index from sage.rings.ring cimport CommutativeRing from sage.rings.ring import is_Ring diff --git a/src/sage/matroids/unpickling.pyx b/src/sage/matroids/unpickling.pyx index eca871caa96..70ab690629a 100644 --- a/src/sage/matroids/unpickling.pyx +++ b/src/sage/matroids/unpickling.pyx @@ -24,11 +24,13 @@ AUTHORS: # the License, or (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** +from __future__ import absolute_import + include 'sage/data_structures/bitset.pxi' import sage.matroids.matroid import sage.matroids.basis_exchange_matroid -from minor_matroid import MinorMatroid -from dual_matroid import DualMatroid +from .minor_matroid import MinorMatroid +from .dual_matroid import DualMatroid from .circuit_closures_matroid cimport CircuitClosuresMatroid from .basis_matroid cimport BasisMatroid from .linear_matroid cimport LinearMatroid, RegularMatroid, BinaryMatroid, TernaryMatroid, QuaternaryMatroid diff --git a/src/sage/modules/free_module_element.pyx b/src/sage/modules/free_module_element.pyx index 71e81cdb443..b4ca4e1f127 100644 --- a/src/sage/modules/free_module_element.pyx +++ b/src/sage/modules/free_module_element.pyx @@ -104,6 +104,7 @@ TESTS:: # (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** +from __future__ import absolute import cimport cython from cpython.slice cimport PySlice_GetIndicesEx @@ -429,7 +430,7 @@ def vector(arg0, arg1=None, arg2=None, sparse=None): # !! PLEASE DO NOT MOVE THIS CODE LOWER IN THIS FUNCTION !! if arg2 is None and is_Ring(arg0) and (isinstance(arg1, (int, long, Integer))): if sparse: - from free_module import FreeModule + from .free_module import FreeModule M = FreeModule(arg0, arg1, sparse=True) else: M = arg0 ** arg1 @@ -481,14 +482,14 @@ def vector(arg0, arg1=None, arg2=None, sparse=None): if isinstance(v, ndarray): if len(v.shape) != 1: raise TypeError("cannot convert %r-dimensional array to a vector" % len(v.shape)) - from free_module import VectorSpace + from .free_module import VectorSpace if (R is None or R is RDF) and v.dtype.kind == 'f': V = VectorSpace(RDF, v.shape[0]) - from vector_real_double_dense import Vector_real_double_dense + from .vector_real_double_dense import Vector_real_double_dense return Vector_real_double_dense(V, v) if (R is None or R is CDF) and v.dtype.kind == 'c': V = VectorSpace(CDF, v.shape[0]) - from vector_complex_double_dense import Vector_complex_double_dense + from .vector_complex_double_dense import Vector_complex_double_dense return Vector_complex_double_dense(V, v) # Use slower conversion via list v = list(v) @@ -506,7 +507,7 @@ def vector(arg0, arg1=None, arg2=None, sparse=None): v, R = prepare(v, R, degree) if sparse: - from free_module import FreeModule + from .free_module import FreeModule M = FreeModule(R, len(v), sparse=True) else: M = R ** len(v) @@ -1755,7 +1756,7 @@ cdef class FreeModuleElement(Vector): # abstract base class values = [] for n in range(slicelength): values.append(self.get_unsafe(start + n*step)) - from free_module import FreeModule + from .free_module import FreeModule M = FreeModule(self.coordinate_ring(), slicelength, sparse=self.is_sparse()) return M(values, coerce=False, copy=False) else: @@ -4820,7 +4821,7 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): if min <= n <= max and n % step == mod: k = (n - start) // step newentries[k] = x - from free_module import FreeModule + from .free_module import FreeModule M = FreeModule(self.coordinate_ring(), slicelength, sparse=True) return M(newentries, coerce=False, copy=False) diff --git a/src/sage/modules/vector_double_dense.pyx b/src/sage/modules/vector_double_dense.pyx index f6e3817c742..93470d4dc6b 100644 --- a/src/sage/modules/vector_double_dense.pyx +++ b/src/sage/modules/vector_double_dense.pyx @@ -40,6 +40,7 @@ AUTHORS: # (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** +from __future__ import absolute_import cimport numpy import numpy @@ -467,8 +468,8 @@ cdef class Vector_double_dense(FreeModuleElement): else: self._vector_numpy = scipy.fftpack.ifft(self._vector_numpy, overwrite_x = True) else: - V = CDF**self._degree - from vector_complex_double_dense import Vector_complex_double_dense + V = CDF ** self._degree + from .vector_complex_double_dense import Vector_complex_double_dense if direction == 'forward': return Vector_complex_double_dense(V, scipy.fft(self._vector_numpy)) else: diff --git a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx index c0d70049fb4..96ae0da979e 100644 --- a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx +++ b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx @@ -18,6 +18,7 @@ AUTHORS: # (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** +from __future__ import absolute_import include "cysignals/memory.pxi" include "cysignals/signals.pxi" @@ -1259,7 +1260,7 @@ cdef class FiniteField_ntl_gf2eElement(FinitePolyExtElement): AUTHOR: David Joyner and William Stein (2005-11) """ - from sage.groups.generic import discrete_log + from sage.groups.generic import discrete_log b = self.parent()(base) return discrete_log(self, b) diff --git a/src/sage/rings/padics/pow_computer_flint.pyx b/src/sage/rings/padics/pow_computer_flint.pyx index 6d3c5370ca1..c8ddd3f2826 100644 --- a/src/sage/rings/padics/pow_computer_flint.pyx +++ b/src/sage/rings/padics/pow_computer_flint.pyx @@ -1,3 +1,5 @@ +from __future__ import absolute_import + include "cysignals/signals.pxi" include "cysignals/memory.pxi" @@ -622,11 +624,11 @@ def PowComputer_flint_maker(prime, cache_limit, prec_cap, ram_prec_cap, in_field """ if prec_type == 'capped-rel': - from qadic_flint_CR import PowComputer_ + from .qadic_flint_CR import PowComputer_ elif prec_type == 'capped-abs': - from qadic_flint_CA import PowComputer_ + from .qadic_flint_CA import PowComputer_ elif prec_type == 'fixed-mod': - from qadic_flint_FM import PowComputer_ + from .qadic_flint_FM import PowComputer_ else: raise ValueError("unknown prec_type `%s`" % prec_type) return PowComputer_(prime, cache_limit, prec_cap, ram_prec_cap, in_field, poly) From 0a98b8d3cd54afbb9a6364be6d20d1de961ece5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 10 May 2017 18:40:03 +0200 Subject: [PATCH 286/452] trac 22973 add test for __ne__ --- src/sage/interfaces/interface.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/sage/interfaces/interface.py b/src/sage/interfaces/interface.py index e547eb332c6..86d0a2c6951 100644 --- a/src/sage/interfaces/interface.py +++ b/src/sage/interfaces/interface.py @@ -608,6 +608,13 @@ def __eq__(self, other): def __ne__(self, other): """ Test for unequality. + + EXAMPLES:: + + sage: Maxima() != maxima + True + sage: maxima != maxima + False """ return not (self == other) From 12584a04bed132d0b1934986892ff441ceb60683 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 10 May 2017 11:50:19 -0500 Subject: [PATCH 287/452] Use WithEqualityById for Interface. --- src/sage/interfaces/interface.py | 56 ++++++++++++++------------------ 1 file changed, 24 insertions(+), 32 deletions(-) diff --git a/src/sage/interfaces/interface.py b/src/sage/interfaces/interface.py index 86d0a2c6951..ba93d58bfa4 100644 --- a/src/sage/interfaces/interface.py +++ b/src/sage/interfaces/interface.py @@ -49,6 +49,7 @@ from sage.structure.element import Element, parent import sage.misc.sage_eval +from sage.misc.fast_methods import WithEqualityById from sage.docs.instancedoc import instancedoc @@ -57,11 +58,33 @@ def __repr__(self): return str(self) -class Interface(ParentWithBase): +class Interface(WithEqualityById, ParentWithBase): """ Interface interface object. + + .. NOTE:: + + Two interfaces compare equal if and only if they are identical + objects (this is a critical constraint so that caching of + representations of objects in interfaces works + correctly). Otherwise they are never equal. """ def __init__(self, name): + """ + Initialize ``self``. + + EXAMPLES:: + + sage: Maxima() == maxima + False + sage: maxima == maxima + True + + sage: Maxima() != maxima + True + sage: maxima != maxima + False + """ self.__name = name self.__coerce_name = '_' + name.lower() + '_' self.__seq = -1 @@ -587,37 +610,6 @@ def __getattr__(self, attrname): raise return self._function_class()(self, attrname) - def __eq__(self, other): - """ - Compare two pseudo-tty interfaces. - - Two interfaces compare equal if and only if they are identical - objects (this is a critical constraint so that caching of - representations of objects in interfaces works - correctly). Otherwise they are never equal. - - EXAMPLES:: - - sage: Maxima() == maxima - False - sage: maxima == maxima - True - """ - return self is other - - def __ne__(self, other): - """ - Test for unequality. - - EXAMPLES:: - - sage: Maxima() != maxima - True - sage: maxima != maxima - False - """ - return not (self == other) - def console(self): raise NotImplementedError From e264a75e2128e751cc3d1faef930f001188efdf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Wed, 10 May 2017 20:00:36 +0200 Subject: [PATCH 288/452] a nice big bunch of typos --- .../en/thematic_tutorials/coding_theory.rst | 6 ++--- .../lie_algebras/structure_coefficients.py | 2 +- .../examples/lie_algebras_with_basis.py | 2 +- src/sage/categories/left_modules.py | 2 +- src/sage/categories/right_modules.py | 2 +- .../combinat/binary_recurrence_sequences.py | 2 +- src/sage/combinat/crystals/letters.pyx | 2 +- src/sage/combinat/designs/bibd.py | 2 +- src/sage/combinat/designs/database.py | 2 +- src/sage/combinat/matrices/hadamard_matrix.py | 2 +- .../combinat/ncsf_qsym/generic_basis_code.py | 2 +- .../rigged_configurations/kr_tableaux.py | 3 ++- src/sage/combinat/similarity_class_type.py | 5 +++-- src/sage/combinat/words/morphism.py | 2 +- src/sage/functions/log.py | 5 +++-- src/sage/games/quantumino.py | 4 ++-- .../hyperplane_arrangement/arrangement.py | 2 +- .../hyperplane_arrangement/library.py | 2 +- src/sage/geometry/polyhedron/base.py | 2 +- src/sage/geometry/polyhedron/constructor.py | 2 +- src/sage/geometry/polyhedron/library.py | 2 +- src/sage/geometry/ribbon_graph.py | 6 ++--- .../triangulation/point_configuration.py | 2 +- src/sage/graphs/generic_graph.py | 2 +- src/sage/graphs/generic_graph_pyx.pyx | 2 +- src/sage/groups/matrix_gps/unitary.py | 4 ++-- .../partn_ref2/refinement_generic.pyx | 4 ++-- src/sage/libs/pari/__init__.py | 2 +- src/sage/libs/ppl.pyx | 4 ++-- src/sage/libs/sirocco.pyx | 4 ++-- src/sage/logic/propcalc.py | 2 +- src/sage/manifolds/utilities.py | 2 +- src/sage/matroids/basis_exchange_matroid.pyx | 2 +- src/sage/misc/sage_unittest.py | 2 +- .../modform_hecketriangle/constructor.py | 2 +- src/sage/plot/plot3d/plot3d.py | 2 +- src/sage/rings/rational_field.py | 2 +- src/sage/schemes/curves/zariski_vankampen.py | 2 +- src/sage/schemes/elliptic_curves/cm.py | 5 ++--- .../elliptic_curves/ell_finite_field.py | 4 ++-- .../schemes/elliptic_curves/ell_tate_curve.py | 4 ++-- src/sage/schemes/elliptic_curves/heegner.py | 22 ++++++++++--------- .../schemes/elliptic_curves/padic_lseries.py | 10 ++++----- .../hyperelliptic_finite_field.py | 2 +- src/sage/schemes/plane_conics/con_field.py | 2 +- 45 files changed, 77 insertions(+), 73 deletions(-) diff --git a/src/doc/en/thematic_tutorials/coding_theory.rst b/src/doc/en/thematic_tutorials/coding_theory.rst index 155fdbe435b..d7014393137 100644 --- a/src/doc/en/thematic_tutorials/coding_theory.rst +++ b/src/doc/en/thematic_tutorials/coding_theory.rst @@ -491,7 +491,7 @@ We can describe these boundaries in two ways: Static error rate channel creating between 1 and 14 errors, of input and output space Vector space of dimension 40 over Finite Field of size 59 We already know that a channel has a -:meth:`sage.coding.channel_constuctions.Channel.transmit` method which will +:meth:`sage.coding.channel_constructions.Channel.transmit` method which will perform transmission over the channel; in this case it will return the transmitted word with some errors in it. This method will always check if the provided word belongs to @@ -502,7 +502,7 @@ if one is simulating millions of transmissions. For this usage there is :meth:`sage.coding.channel_constructions.Channel.transmit_unsafe` which does the same as -:meth:`sage.coding.channel_constuctions.Channel.transmit` +:meth:`sage.coding.channel_constructions.Channel.transmit` but without checking the input, as illustrated thereafter:: sage: c = C.random_element() @@ -513,7 +513,7 @@ but without checking the input, as illustrated thereafter:: False Note there exists a useful shortcut for -:meth:`sage.coding.channel_constuctions.Channel.transmit` :: +:meth:`sage.coding.channel_constructions.Channel.transmit` :: sage: r = Chan(c) sage: r in C diff --git a/src/sage/algebras/lie_algebras/structure_coefficients.py b/src/sage/algebras/lie_algebras/structure_coefficients.py index 394e0070b2a..226010a206a 100644 --- a/src/sage/algebras/lie_algebras/structure_coefficients.py +++ b/src/sage/algebras/lie_algebras/structure_coefficients.py @@ -244,7 +244,7 @@ def to_vector(tuples): def structure_coefficients(self, include_zeros=False): """ - Return the dictonary of structure coefficients of ``self``. + Return the dictionary of structure coefficients of ``self``. EXAMPLES:: diff --git a/src/sage/categories/examples/lie_algebras_with_basis.py b/src/sage/categories/examples/lie_algebras_with_basis.py index 6c122daa56e..af51f57a25d 100644 --- a/src/sage/categories/examples/lie_algebras_with_basis.py +++ b/src/sage/categories/examples/lie_algebras_with_basis.py @@ -135,7 +135,7 @@ def __init__(self, R, indices, **kwds): def _repr_(self): """ - Return a string represenation of ``self``. + Return a string representation of ``self``. EXAMPLES:: diff --git a/src/sage/categories/left_modules.py b/src/sage/categories/left_modules.py index d2ef58880ab..c54d187e102 100644 --- a/src/sage/categories/left_modules.py +++ b/src/sage/categories/left_modules.py @@ -17,7 +17,7 @@ class LeftModules(Category_over_base_ring): """ The category of left modules left modules over an rng (ring not necessarily with unit), i.e. - an abelian group with left multiplation by elements of the rng + an abelian group with left multiplication by elements of the rng EXAMPLES:: diff --git a/src/sage/categories/right_modules.py b/src/sage/categories/right_modules.py index b5cdca0600f..bdc23bd92ff 100644 --- a/src/sage/categories/right_modules.py +++ b/src/sage/categories/right_modules.py @@ -17,7 +17,7 @@ class RightModules(Category_over_base_ring): """ The category of right modules right modules over an rng (ring not necessarily with unit), i.e. - an abelian group with right multiplation by elements of the rng + an abelian group with right multiplication by elements of the rng EXAMPLES:: diff --git a/src/sage/combinat/binary_recurrence_sequences.py b/src/sage/combinat/binary_recurrence_sequences.py index d8068c2dc27..af61233a761 100644 --- a/src/sage/combinat/binary_recurrence_sequences.py +++ b/src/sage/combinat/binary_recurrence_sequences.py @@ -451,7 +451,7 @@ def period(self, m): p1fac = list((p-1).factor()) #The order of any matrix in GL_2(F_p) either divides p(p-1) or (p-1)(p+1). - #The order divides p-1 if it is diagaonalizable. In any case, det(F^(p-1))=1, + #The order divides p-1 if it is diagonalizable. In any case, det(F^(p-1))=1, #so if tr(F^(p-1)) = 2, then it must be triangular of the form [[1,a],[0,1]]. #The order of the subgroup of matrices of this form is p, so the order must divide #p(p-1) -- in fact it must be a multiple of p. If this is not the case, then the diff --git a/src/sage/combinat/crystals/letters.pyx b/src/sage/combinat/crystals/letters.pyx index fccc8b05f4f..43b7bc17b29 100644 --- a/src/sage/combinat/crystals/letters.pyx +++ b/src/sage/combinat/crystals/letters.pyx @@ -2521,7 +2521,7 @@ class ClassicalCrystalOfLettersWrapped(ClassicalCrystalOfLetters): @lazy_attribute def _tuple_to_element_dict(self): """ - A dictonary from tuples to elements of ``self``. + A dictionary from tuples to elements of ``self``. EXAMPLES:: diff --git a/src/sage/combinat/designs/bibd.py b/src/sage/combinat/designs/bibd.py index 4d3e001ee1a..0bb534f25d5 100644 --- a/src/sage/combinat/designs/bibd.py +++ b/src/sage/combinat/designs/bibd.py @@ -938,7 +938,7 @@ def v_5_1_BIBD(v, check=True): r""" Return a `(v,5,1)`-BIBD. - This method follows the constuction from [ClaytonSmith]_. + This method follows the construction from [ClaytonSmith]_. INPUT: diff --git a/src/sage/combinat/designs/database.py b/src/sage/combinat/designs/database.py index 66fd7d01693..ed1d9d9586f 100644 --- a/src/sage/combinat/designs/database.py +++ b/src/sage/combinat/designs/database.py @@ -1703,7 +1703,7 @@ def OA_520_plus_x(x): r""" Return an `OA(10+x,520+x)`. - The consruction shared by Julian R. Abel works for :func:`OA(10,520) + The construction shared by Julian R. Abel works for :func:`OA(10,520) `, :func:`OA(12,522) `, and :func:`OA(14,524) `. diff --git a/src/sage/combinat/matrices/hadamard_matrix.py b/src/sage/combinat/matrices/hadamard_matrix.py index 64f8b1d1003..8906c53bdd3 100644 --- a/src/sage/combinat/matrices/hadamard_matrix.py +++ b/src/sage/combinat/matrices/hadamard_matrix.py @@ -1215,7 +1215,7 @@ def szekeres_difference_set_pair(m, check=True): whenever `b+1 \in G`. See also Theorem 2.6 in [SWW72]_ (there the formula for `B` is correct, as opposed to (4.2) in [Sz69]_, where the sign before `1` is wrong. - In modern terminilogy, for `m>1` the sets `A` and `B` form a + In modern terminology, for `m>1` the sets `A` and `B` form a :func:`difference family` with parameters `(2m+1,m,1)`. I.e. each non-identity `g \in G` can be expressed uniquely as `xy^{-1}` for `x,y \in A` or `x,y \in B`. Other, specific to this construction, properties of `A` and `B` are: for `a` in `A` one has diff --git a/src/sage/combinat/ncsf_qsym/generic_basis_code.py b/src/sage/combinat/ncsf_qsym/generic_basis_code.py index 64bd73c8780..ccc043afd13 100644 --- a/src/sage/combinat/ncsf_qsym/generic_basis_code.py +++ b/src/sage/combinat/ncsf_qsym/generic_basis_code.py @@ -1013,7 +1013,7 @@ def __init__(self, domain, on_generators, position = 0, codomain = None, categor EXAMPLES: - We construct explicitly an algbera morphism:: + We construct explicitly an algebra morphism:: sage: from sage.combinat.ncsf_qsym.generic_basis_code import AlgebraMorphism sage: NCSF = NonCommutativeSymmetricFunctions(QQ) diff --git a/src/sage/combinat/rigged_configurations/kr_tableaux.py b/src/sage/combinat/rigged_configurations/kr_tableaux.py index 7d9ec53d8fc..ccf649492df 100644 --- a/src/sage/combinat/rigged_configurations/kr_tableaux.py +++ b/src/sage/combinat/rigged_configurations/kr_tableaux.py @@ -1776,10 +1776,11 @@ def phi(self, i): return rc.phi(0) return TensorProductOfRegularCrystalsElement.phi(self, i) + class KRTableauxTypeFromRC(KirillovReshetikhinTableaux): r""" Kirillov-Reshetikhin tableaux `B^{r,s}` constructed from rigged - configurations under the bijecton `\Phi`. + configurations under the bijection `\Phi`. .. WARNING:: diff --git a/src/sage/combinat/similarity_class_type.py b/src/sage/combinat/similarity_class_type.py index 088a917c594..13939a26d33 100644 --- a/src/sage/combinat/similarity_class_type.py +++ b/src/sage/combinat/similarity_class_type.py @@ -691,7 +691,7 @@ class SimilarityClassType(CombinatorialElement): r""" A similarity class type. - A matrix type is a multiset of primary similairty class types. + A matrix type is a multiset of primary similarity class types. INPUT: @@ -1311,9 +1311,10 @@ def input_parsing(data): case = 'pri' output = data except(TypeError, ValueError): - raise ValueError("Expected a Partition, a SimiliarityClassType or a PrimarySimilarityClassType, got a %s"%(type(data))) + raise ValueError("Expected a Partition, a SimilarityClassType or a PrimarySimilarityClassType, got a %s" % type(data)) return case, data + def ext_orbits(input_data, q = None, selftranspose = False): r""" Return the number of orbits in `\mathrm{Ext}^1(M, M)` for the action of diff --git a/src/sage/combinat/words/morphism.py b/src/sage/combinat/words/morphism.py index 87b1afc7d16..adfab2a4daa 100644 --- a/src/sage/combinat/words/morphism.py +++ b/src/sage/combinat/words/morphism.py @@ -2309,7 +2309,7 @@ def dual_map(self, k=1): .. NOTE:: - It is acually implemented only for `k=1`. + It is actually implemented only for `k=1`. INPUT: diff --git a/src/sage/functions/log.py b/src/sage/functions/log.py index c08a2b5a09d..f8d4a9acf01 100644 --- a/src/sage/functions/log.py +++ b/src/sage/functions/log.py @@ -676,8 +676,9 @@ def _eval_(self, n, z): TESTS: - When automatic simplication occurs, the parent of the output value should be - either the same as the parent of the input, or a Sage type:: + When automatic simplification occurs, the parent of the output + value should be either the same as the parent of the input, or + a Sage type:: sage: parent(lambert_w(int(0))) <... 'int'> diff --git a/src/sage/games/quantumino.py b/src/sage/games/quantumino.py index 01d79ada28c..9d6dd90a929 100644 --- a/src/sage/games/quantumino.py +++ b/src/sage/games/quantumino.py @@ -7,7 +7,7 @@ made by Family Games America (see also `this video `_ on Youtube). This puzzle was left at the dinner room of the Laboratoire de Combinatoire Informatique -Mathematique in Montreal by Franco Saliola during winter 2011. +Mathématique in Montreal by Franco Saliola during winter 2011. The solution uses the dancing links code which is in Sage and is based on the more general code available in the module :mod:`sage.combinat.tiling`. @@ -27,7 +27,7 @@ AUTHOR: - - Sebastien Labbe, April 28th, 2011 +- Sébastien Labbé, April 28th, 2011 DESCRIPTION (from [1]): diff --git a/src/sage/geometry/hyperplane_arrangement/arrangement.py b/src/sage/geometry/hyperplane_arrangement/arrangement.py index ebbefb1be32..77d3fb6e030 100644 --- a/src/sage/geometry/hyperplane_arrangement/arrangement.py +++ b/src/sage/geometry/hyperplane_arrangement/arrangement.py @@ -3029,7 +3029,7 @@ def _element_constructor_(self, *args, **kwds): if h.A() == 0: raise ValueError('linear expression must be non-constant to define a hyperplane') if not_char2 and -h in hyperplane_set: - raise ValueError('arrangement cannot simultaneouly have h and -h as hyperplane') + raise ValueError('arrangement cannot simultaneously have h and -h as hyperplane') return self.element_class(self, hyperplanes) @cached_method diff --git a/src/sage/geometry/hyperplane_arrangement/library.py b/src/sage/geometry/hyperplane_arrangement/library.py index 354b8e26416..433a3243d61 100644 --- a/src/sage/geometry/hyperplane_arrangement/library.py +++ b/src/sage/geometry/hyperplane_arrangement/library.py @@ -34,7 +34,7 @@ def make_parent(base_ring, dimension, names=None): - ``base_ring`` -- a ring - - ``dimenison`` -- integer + - ``dimension`` -- integer - ``names`` -- ``None`` (default) or a list/tuple/iterable of strings diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index bb1a9fc755a..97ba7c77461 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -5155,7 +5155,7 @@ def combinatorial_automorphism_group(self, vertex_graph_only=False): NOTE: Depending on ``vertex_graph_only``, this method returns groups - that are not neccessarily isomorphic, see the examples below. + that are not necessarily isomorphic, see the examples below. .. SEEALSO:: diff --git a/src/sage/geometry/polyhedron/constructor.py b/src/sage/geometry/polyhedron/constructor.py index fbb8aa5c47c..9d2a4444000 100644 --- a/src/sage/geometry/polyhedron/constructor.py +++ b/src/sage/geometry/polyhedron/constructor.py @@ -487,7 +487,7 @@ def Polyhedron(vertices=None, rays=None, lines=None, base_ring = common_ring convert = True - # Add the origin if necesarry + # Add the origin if necessary if got_Vrep and len(vertices)==0: vertices = [ [0]*ambient_dim ] diff --git a/src/sage/geometry/polyhedron/library.py b/src/sage/geometry/polyhedron/library.py index a0714f32ee2..64d902ce5f3 100644 --- a/src/sage/geometry/polyhedron/library.py +++ b/src/sage/geometry/polyhedron/library.py @@ -483,7 +483,7 @@ def great_rhombicuboctahedron(self, exact=True, base_ring=None): """ Return the great rhombicuboctahedron. - The great rohombicuboctahedron (or truncated cuboctahedron) is an + The great rhombicuboctahedron (or truncated cuboctahedron) is an Archimedean solid with 48 vertices and 26 faces. For more information see the :wikipedia:`Truncated_cuboctahedron`. diff --git a/src/sage/geometry/ribbon_graph.py b/src/sage/geometry/ribbon_graph.py index 59b52933b3f..b2902917aa7 100644 --- a/src/sage/geometry/ribbon_graph.py +++ b/src/sage/geometry/ribbon_graph.py @@ -3,7 +3,7 @@ This file implements objects called *ribbon graphs*. These are graphs together with a cyclic ordering of the darts adjacent to each -vertex. This data allows us to unambiguosly "thicken" the ribbon +vertex. This data allows us to unambiguously "thicken" the ribbon graph to an orientable surface with boundary. Also, every orientable surface with non-empty boundary is the thickening of a ribbon graph. @@ -1140,14 +1140,14 @@ def make_ribbon(g, r): #We first generate the surface of genus g and 1 boundary component. #This is done by considering the usual planar representation of - #a surface as a poligon of 4*g+2 edges with identifications. (see + #a surface as a polygon of 4*g+2 edges with identifications. (see #any topology book on the classification of surfaces) for i in range(2*g): repr_sigma[0].append(i+2) repr_sigma[1].append(i+(2*g+2)+1) repr_rho += [[i+2,i+(2*g+2)+1]] - #finally we add an edge for each aditional boundary component. + #finally we add an edge for each additional boundary component. max_dart = 4*g+2 for j in range(r-1): repr_sigma[0].insert(0, max_dart+2*(j+1)-1) diff --git a/src/sage/geometry/triangulation/point_configuration.py b/src/sage/geometry/triangulation/point_configuration.py index bdafadbeade..8078b89ebd6 100644 --- a/src/sage/geometry/triangulation/point_configuration.py +++ b/src/sage/geometry/triangulation/point_configuration.py @@ -1846,7 +1846,7 @@ def contained_simplex(self, large=True, initial_point=None): A tuple of points that span a simplex of dimension :meth:`dim`. If ``large==True``, the simplex is constructed by sucessively picking the farthest point. This will ensure that - the simplex is not unneccessarily small, but will in general + the simplex is not unnecessarily small, but will in general not return a maximal simplex. EXAMPLES:: diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 1553f5884fa..16abe5ece4c 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -12510,7 +12510,7 @@ def is_chordal(self, certificate = False, algorithm = "B"): if not hole is None: # There was a bug there once, so it's better to check the - # answer is valid, especally when it is so cheap ;-) + # answer is valid, especially when it is so cheap ;-) if hole.order() <= 3 or not hole.is_regular(k=2): raise RuntimeError("the graph is not chordal, and something went wrong in the computation of the certificate. Please report this bug, providing the graph if possible!") diff --git a/src/sage/graphs/generic_graph_pyx.pyx b/src/sage/graphs/generic_graph_pyx.pyx index af69556c94b..6847af92c46 100644 --- a/src/sage/graphs/generic_graph_pyx.pyx +++ b/src/sage/graphs/generic_graph_pyx.pyx @@ -1249,7 +1249,7 @@ cpdef tuple find_hamiltonian(G, long max_iter=100000, long reset_bound=30000, member[u] = True member[v] = True - #Initialize all the variables neccesary to start iterating + #Initialize all the variables necessary to start iterating cdef bint done = False cdef long counter = 0 cdef long bigcount = 0 diff --git a/src/sage/groups/matrix_gps/unitary.py b/src/sage/groups/matrix_gps/unitary.py index 7a8a0bebc85..3b795a95a8b 100644 --- a/src/sage/groups/matrix_gps/unitary.py +++ b/src/sage/groups/matrix_gps/unitary.py @@ -69,8 +69,8 @@ def finite_field_sqrt(ring): if not is_FiniteField(ring): raise ValueError('not a finite field') q, rem = ring.cardinality().sqrtrem() - if rem != 0: - raise ValueError('cardinatity not a square') + if rem: + raise ValueError('cardinality not a square') return q diff --git a/src/sage/groups/perm_gps/partn_ref2/refinement_generic.pyx b/src/sage/groups/perm_gps/partn_ref2/refinement_generic.pyx index 01202b31b82..9d78b5def80 100644 --- a/src/sage/groups/perm_gps/partn_ref2/refinement_generic.pyx +++ b/src/sage/groups/perm_gps/partn_ref2/refinement_generic.pyx @@ -796,7 +796,7 @@ cdef class PartitionRefinement_generic: - if the inner group has changed -> sets ``inner_group_changed`` to True - if the partition has changed -> sets ``changed_partition`` to True - The string ``refine_name`` is only neccessary for printing within the + The string ``refine_name`` is only necessary for printing within the latex output (if activated). """ cdef tuple res = PS_refinement(self._part, self._refine_vals_scratch, best, begin, end, @@ -826,7 +826,7 @@ cdef class PartitionRefinement_generic: cdef void _leaf_computations(self): r""" - All neccessary computations which have to be performed in a leaf. + All necessary computations which have to be performed in a leaf. There are to possibilities depending on the flag ``self._is_candidate_initialized``: diff --git a/src/sage/libs/pari/__init__.py b/src/sage/libs/pari/__init__.py index 59f05365bdd..5f7f18333cb 100644 --- a/src/sage/libs/pari/__init__.py +++ b/src/sage/libs/pari/__init__.py @@ -130,7 +130,7 @@ In these examples, we convert to Sage to ensure that PARI's real precision is not used when printing the numbers. As explained before, -this artificically increases the precision to a multiple of the +this artificially increases the precision to a multiple of the wordsize. :: sage: s = pari(1).sin(precision=180).sage(); print(s); print(parent(s)) diff --git a/src/sage/libs/ppl.pyx b/src/sage/libs/ppl.pyx index 749826f760b..6550429601c 100644 --- a/src/sage/libs/ppl.pyx +++ b/src/sage/libs/ppl.pyx @@ -82,7 +82,7 @@ documentation, in particular: 5 * PPL supports (topologically) closed polyhedra - (:class:`C_Polyhedron`) as well as not neccesarily closed polyhedra + (:class:`C_Polyhedron`) as well as not necessarily closed polyhedra (:class:`NNC_Polyhedron`). Only the latter allows closure points (=points of the closure but not of the actual polyhedron) and strict inequalities (``>`` and ``<``) @@ -2703,7 +2703,7 @@ cdef class Polyhedron(_mutable_or_immutable): .. NOTE:: - The modified polyhedron is not neccessarily a lattice + The modified polyhedron is not necessarily a lattice polyhedron; Some vertices will, in general, still be rational. Lattice points interior to the polyhedron may be lost in the process. diff --git a/src/sage/libs/sirocco.pyx b/src/sage/libs/sirocco.pyx index 77e0484ed99..40b499b02c7 100644 --- a/src/sage/libs/sirocco.pyx +++ b/src/sage/libs/sirocco.pyx @@ -29,9 +29,9 @@ cpdef list[list] contpath_mp(int deg, list values, RealNumber y0r, RealNumber y0 """ Mimics :func:`contpath`, but with the following differences: - - The floating point numbers can be arbitrary precission RealNumbers. + - The floating point numbers can be arbitrary precision RealNumbers. - - A extra argument is needed, indicating the bits of precission used + - A extra argument is needed, indicating the bits of precision used in the computations. """ cdef mpfr_t* cvalues = sage_malloc(sizeof(mpfr_t)*len(values)) diff --git a/src/sage/logic/propcalc.py b/src/sage/logic/propcalc.py index 6d17a5330b7..fafc7bfea5d 100644 --- a/src/sage/logic/propcalc.py +++ b/src/sage/logic/propcalc.py @@ -307,7 +307,7 @@ def consistent(*formulas): for formula in formulas[1:]: conjunction = conjunction & formula - # if conjnction is a contradiction, the formulas are inconsistent + # if conjunction is a contradiction, the formulas are inconsistent return not conjunction.is_contradiction() def valid_consequence(consequence, *formulas): diff --git a/src/sage/manifolds/utilities.py b/src/sage/manifolds/utilities.py index 43ec9eca893..5728fd31250 100644 --- a/src/sage/manifolds/utilities.py +++ b/src/sage/manifolds/utilities.py @@ -93,7 +93,7 @@ def simplify_sqrt_real(expr): # by Pynac symbols of the type D[0] or diff(...) # Lists to store the positions of all the top-level sqrt's in sexpr: pos_sqrts = [] # position of first character, i.e. 's' of 'sqrt(...)' - pos_after = [] # position of character immediatelty after 'sqrt(...)' + pos_after = [] # position of character immediately after 'sqrt(...)' the_sqrts = [] # the sqrt sub-expressions in sexpr, i.e. 'sqrt(...)' pos_max = len(sexpr) - 6 pos = 0 diff --git a/src/sage/matroids/basis_exchange_matroid.pyx b/src/sage/matroids/basis_exchange_matroid.pyx index f7c8f8ab801..5c695086ccf 100644 --- a/src/sage/matroids/basis_exchange_matroid.pyx +++ b/src/sage/matroids/basis_exchange_matroid.pyx @@ -61,7 +61,7 @@ cdef class BasisExchangeMatroid(Matroid): adjacent in the graph if their symmetric difference has 2 members. This base exchange graph is not stored as such, but should be provided - implicity by the child class in the form of two methods + implicitly by the child class in the form of two methods ``__is_exchange_pair(x, y)`` and ``__exchange(x, y)``, as well as an initial basis. At any moment, BasisExchangeMatroid keeps a current basis `B`. The method ``__is_exchange_pair(x, y)`` should return a boolean diff --git a/src/sage/misc/sage_unittest.py b/src/sage/misc/sage_unittest.py index 111dfeae0d7..c3269872770 100644 --- a/src/sage/misc/sage_unittest.py +++ b/src/sage/misc/sage_unittest.py @@ -269,7 +269,7 @@ def _test_b(self, tester): tester.fail() ... AssertionError: None - In conjonction with ``%pdb on``, this allows for the debbuger + In conjunction with ``%pdb on``, this allows for the debbuger to jump directly to the first failure location. """ if isinstance(skip, str): diff --git a/src/sage/modular/modform_hecketriangle/constructor.py b/src/sage/modular/modform_hecketriangle/constructor.py index 5c2c915f5d2..db0974fd125 100644 --- a/src/sage/modular/modform_hecketriangle/constructor.py +++ b/src/sage/modular/modform_hecketriangle/constructor.py @@ -171,7 +171,7 @@ def rational_type(f, n=ZZ(3), base_ring=ZZ): weight = None ep = None - # Note that we intentially leave out the d-factor! + # Note that we intentionally leave out the d-factor! if (n == infinity): finf_pol = (x-y**2) else: diff --git a/src/sage/plot/plot3d/plot3d.py b/src/sage/plot/plot3d/plot3d.py index 3b1e7aaa541..097551ea9c7 100644 --- a/src/sage/plot/plot3d/plot3d.py +++ b/src/sage/plot/plot3d/plot3d.py @@ -756,7 +756,7 @@ def plot3d(f, urange, vrange, adaptive=False, transformation=None, **kwds): - ``adaptive`` - (default: False) whether to use adaptive refinement to draw the plot (slower, but may look better). - This option does NOT work in conjuction with a transformation + This option does NOT work in conjunction with a transformation (see below). - ``mesh`` - bool (default: False) whether to display diff --git a/src/sage/rings/rational_field.py b/src/sage/rings/rational_field.py index 4c4c2750616..6fdc8b83453 100644 --- a/src/sage/rings/rational_field.py +++ b/src/sage/rings/rational_field.py @@ -974,7 +974,7 @@ def random_element(self, num_bound=None, den_bound=None, *args, **kwds): Return an random element of `\QQ`. Elements are constructed by randomly choosing integers - for the numerator and denominator, not neccessarily coprime. + for the numerator and denominator, not necessarily coprime. INPUT: diff --git a/src/sage/schemes/curves/zariski_vankampen.py b/src/sage/schemes/curves/zariski_vankampen.py index d75a58c1ed5..09efd68e204 100644 --- a/src/sage/schemes/curves/zariski_vankampen.py +++ b/src/sage/schemes/curves/zariski_vankampen.py @@ -238,7 +238,7 @@ def followstrand(f, x0, x1, y0a, prec=53): - ``x0`` -- a complex value, where the homotopy starts - ``x1`` -- a complex value, where the homotopy ends - ``y0a`` -- an approximate solution of the polynomial `F(y) = f(x_0, y)` - - ``prec`` -- the precission to use + - ``prec`` -- the precision to use OUTPUT: diff --git a/src/sage/schemes/elliptic_curves/cm.py b/src/sage/schemes/elliptic_curves/cm.py index dfbbaaf80e0..5606801aa05 100644 --- a/src/sage/schemes/elliptic_curves/cm.py +++ b/src/sage/schemes/elliptic_curves/cm.py @@ -545,7 +545,7 @@ def lb(f): @cached_function def is_cm_j_invariant(j): """ - Returns whether or not this is a CM `j`-invariant. + Return whether or not this is a CM `j`-invariant. INPUT: @@ -555,7 +555,7 @@ def is_cm_j_invariant(j): A pair (bool, (d,f)) which is either (False, None) if `j` is not a CM j-invariant or (True, (d,f)) if `j` is the `j`-invariant of the - immaginary quadratic order of discriminant `D=df^2` where `d` is + imaginary quadratic order of discriminant `D=df^2` where `d` is the associated fundamental discriminant and `f` the index. .. note:: @@ -568,7 +568,6 @@ def is_cm_j_invariant(j): primes dividing the discriminant of the minimal polynomial of `j`. - EXAMPLES:: sage: from sage.schemes.elliptic_curves.cm import is_cm_j_invariant diff --git a/src/sage/schemes/elliptic_curves/ell_finite_field.py b/src/sage/schemes/elliptic_curves/ell_finite_field.py index ea2fea8a411..615bc1b938f 100644 --- a/src/sage/schemes/elliptic_curves/ell_finite_field.py +++ b/src/sage/schemes/elliptic_curves/ell_finite_field.py @@ -1717,7 +1717,7 @@ def is_supersingular(self, proof=True): - ``proof`` (boolean, default True) -- If True, returns a proved result. If False, then a return value of False is certain but a return value of True may be based on a - probabilistic test. See the documentaion of the function + probabilistic test. See the documentation of the function :meth:`is_j_supersingular` for more details. EXAMPLES:: @@ -1752,7 +1752,7 @@ def is_ordinary(self, proof=True): - ``proof`` (boolean, default True) -- If True, returns a proved result. If False, then a return value of True is certain but a return value of False may be based on a - probabilistic test. See the documentaion of the function + probabilistic test. See the documentation of the function :meth:`is_j_supersingular` for more details. EXAMPLES:: diff --git a/src/sage/schemes/elliptic_curves/ell_tate_curve.py b/src/sage/schemes/elliptic_curves/ell_tate_curve.py index 5e93556d066..c0b8d134c4f 100644 --- a/src/sage/schemes/elliptic_curves/ell_tate_curve.py +++ b/src/sage/schemes/elliptic_curves/ell_tate_curve.py @@ -631,14 +631,14 @@ def padic_regulator(self, prec=20): INPUT: - - ``prec`` - the `p`-adic precision, default is 20. + - ``prec`` -- the `p`-adic precision, default is 20. REFERENCES: [MTT]_ .. [Wer] Annette Werner, Local heights on abelian varieties and - rigid analytic unifomization, Doc. Math. 3 (1998), 301-319. + rigid analytic uniformization, Doc. Math. 3 (1998), 301-319. [SW]_ diff --git a/src/sage/schemes/elliptic_curves/heegner.py b/src/sage/schemes/elliptic_curves/heegner.py index 19ea18fe000..cc919cf49dd 100644 --- a/src/sage/schemes/elliptic_curves/heegner.py +++ b/src/sage/schemes/elliptic_curves/heegner.py @@ -2759,9 +2759,11 @@ def reduced_quadratic_form(self): @cached_method def tau(self): """ - Return an element tau in the upper half plane that corresponds - to this particular Heegner point (actually, tau is in the - quadratic imagqinary field K associated to this Heegner point). + Return an element ``tau`` in the upper half plane that corresponds + to this particular Heegner point. + + Actually, ``tau`` is in the quadratic imaginary field K associated + to this Heegner point. EXAMPLES:: @@ -2773,10 +2775,9 @@ def tau(self): 37*x^2 + 11*x*y + 2*y^2 """ K = self.quadratic_field() - c = self.conductor() - d = K.gen()*c - A,B,_ = self.__f - return (-B + d)/(2*A) + d = K.gen() * self.conductor() + A, B, _ = self.__f + return (-B + d) / (2 * A) def map_to_curve(self, E): """ @@ -2862,6 +2863,7 @@ def plot(self, **kwds): from sage.plot.all import point return point(CDF(self.tau()), **kwds) + class HeegnerPointOnEllipticCurve(HeegnerPoint): """ A Heegner point on a curve associated to an order in a quadratic @@ -4678,11 +4680,11 @@ def optimal_embeddings(self, D, c, R): """ INPUT: - - `D` -- negative fundamental disriminant + - `D` -- negative fundamental discriminant - - `c` -- integer coprime + - `c` -- integer coprime - - `R` -- Eichler order + - `R` -- Eichler order EXAMPLES:: diff --git a/src/sage/schemes/elliptic_curves/padic_lseries.py b/src/sage/schemes/elliptic_curves/padic_lseries.py index 1c69e619209..56b585ec4f7 100644 --- a/src/sage/schemes/elliptic_curves/padic_lseries.py +++ b/src/sage/schemes/elliptic_curves/padic_lseries.py @@ -544,8 +544,8 @@ def order_of_vanishing(self): Swinnerton-Dyer, Inventiones mathematicae 84, (1986), 1-48. - [Ka] Kayuza Kato, `p`-adic Hodge theory and values of zeta functions of modular - forms, Cohomologies `p`-adiques et applications arithmetiques III, - Asterisque vol 295, SMF, Paris, 2004. + forms, Cohomologies `p`-adiques et applications arithmétiques III, + Astérisque vol 295, SMF, Paris, 2004. EXAMPLES:: @@ -1399,19 +1399,19 @@ def Dp_valued_series(self, n=3, quadratic_twist = +1, prec=5): @rename_keyword(deprecation=6094, method="algorithm") def frobenius(self, prec=20, algorithm = "mw"): r""" - This returns a geometric Frobenius `\varphi` on the Diedonne module `D_p(E)` + Return a geometric Frobenius `\varphi` on the Dieudonné module `D_p(E)` with respect to the basis `\omega`, the invariant differential, and `\eta=x\omega`. + It satisfies `\varphi^2 - a_p/p\, \varphi + 1/p = 0`. INPUT: - ``prec`` - (default: 20) a positive integer - - ``algorithm`` - either 'mw' (default) for Monsky-Washintzer + - ``algorithm`` - either 'mw' (default) for Monsky-Washnitzer or 'approx' for the algorithm described by Bernardi and Perrin-Riou (much slower and not fully tested) - EXAMPLES:: sage: E = EllipticCurve('14a') diff --git a/src/sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py b/src/sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py index 858277e95be..0ae864851da 100644 --- a/src/sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +++ b/src/sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py @@ -406,7 +406,7 @@ def frobenius_polynomial_matrix(self, M=None, algorithm='hypellfrob'): q = K.cardinality() g = self.genus() N = self._frobenius_coefficient_bound_charpoly() - # compute chapoly over ZZ and then reduce back + # compute charpoly over ZZ and then reduce back # (because charpoly of p-adic matrices sometimes loses precision) M = self.frobenius_matrix(N=N, algorithm=algorithm).change_ring(ZZ) diff --git a/src/sage/schemes/plane_conics/con_field.py b/src/sage/schemes/plane_conics/con_field.py index 642752e1d2c..6ad8f200f54 100644 --- a/src/sage/schemes/plane_conics/con_field.py +++ b/src/sage/schemes/plane_conics/con_field.py @@ -498,7 +498,7 @@ def has_rational_point(self, point = False, pass # The second attempt tries to split Magma elements into - # numerators and denominators first. This is neccessary + # numerators and denominators first. This is necessary # for the field of rational functions, because (at the moment of # writing) fraction field elements are not converted automatically # from Magma to Sage. From 239745581d474c0a92d4de530726b9ea143f59b9 Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Wed, 10 May 2017 15:46:37 -0400 Subject: [PATCH 289/452] Sort the partitions as well --- src/sage/combinat/set_partition.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index f50e818b795..6dc49619e8f 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -522,9 +522,9 @@ def _latex_(self): \node[label=-54:a] (2) at (-54:1cm) {}; \node[label=-126:b] (3) at (-126:1cm) {}; \node[label=-198:c] (4) at (-198:1cm) {}; + \draw[-,thick,color=blue,fill=blue,fill opacity=0.1] (2.center) -- (4.center) -- cycle; \draw[-,thick,color=blue,fill=blue,fill opacity=0.1] (0.center) -- (3.center) -- cycle; \draw[-,thick,color=blue,fill=blue,fill opacity=0.1] (1.center) -- cycle; - \draw[-,thick,color=blue,fill=blue,fill opacity=0.1] (2.center) -- (4.center) -- cycle; \fill[color=black] (0) circle (1.5pt); \fill[color=black] (1) circle (1.5pt); \fill[color=black] (2) circle (1.5pt); @@ -566,7 +566,7 @@ def _latex_(self): res += " ({}) at ({}:{}) {{}};\n".format(k, location, radius) # Setup partitions - for partition in self: + for partition in sorted(self, key=sort_key): res += "\\draw[-,thick,color="+color if latex_options['fill'] is not False: if isinstance(latex_options['fill'], str): From 43c3421fdf5135b2ca4905a129abac42b43a5501 Mon Sep 17 00:00:00 2001 From: Aram Dermenjian Date: Wed, 10 May 2017 15:50:06 -0400 Subject: [PATCH 290/452] Adding sort for linear as well --- src/sage/combinat/set_partition.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index 6dc49619e8f..4db1d8307b6 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -566,7 +566,7 @@ def _latex_(self): res += " ({}) at ({}:{}) {{}};\n".format(k, location, radius) # Setup partitions - for partition in sorted(self, key=sort_key): + for partition in sorted(self, key=str): res += "\\draw[-,thick,color="+color if latex_options['fill'] is not False: if isinstance(latex_options['fill'], str): @@ -593,7 +593,7 @@ def _latex_(self): res += "({k}) at ({k},0) {{}};\n".format(k=k) # setup arcs - for partition in self: + for partition in sorted(self, key=str): p = sorted(partition, key=str) if len(p) <= 1: continue From 6b5dbb3fa26d51fbd4808bda1f90ae8b4e9829db Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 10 May 2017 15:50:53 -0500 Subject: [PATCH 291/452] Last tweak and adding a linear plot example. --- src/sage/combinat/set_partition.py | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/sage/combinat/set_partition.py b/src/sage/combinat/set_partition.py index 4db1d8307b6..02609ac2dfb 100644 --- a/src/sage/combinat/set_partition.py +++ b/src/sage/combinat/set_partition.py @@ -512,8 +512,27 @@ def _latex_(self): sage: x = SetPartition([[1,2], [3,5,4]]) sage: latex(x) \{\{1, 2\}, \{3, 4, 5\}\} - sage: p=SetPartition([['a','c'],['b',1],[20]]) - sage: p.set_latex_options(plot='cyclic', color='blue', angle=45, fill=True, tikz_scale=2) + + sage: x.set_latex_options(plot='linear', angle=25, color='red') + sage: latex(x) + \begin{tikzpicture}[scale=1] + \node[below=.05cm] at (0,0) {$1$}; + \node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black] (0) at (0,0) {}; + \node[below=.05cm] at (1,0) {$2$}; + \node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black] (1) at (1,0) {}; + \node[below=.05cm] at (2,0) {$3$}; + \node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black] (2) at (2,0) {}; + \node[below=.05cm] at (3,0) {$4$}; + \node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black] (3) at (3,0) {}; + \node[below=.05cm] at (4,0) {$5$}; + \node[draw,circle, inner sep=0pt, minimum width=4pt, fill=black] (4) at (4,0) {}; + \draw[color=red] (1) to [out=115,in=65] (0); + \draw[color=red] (3) to [out=115,in=65] (2); + \draw[color=red] (4) to [out=115,in=65] (3); + \end{tikzpicture} + + sage: p = SetPartition([['a','c'],['b',1],[20]]) + sage: p.set_latex_options(plot='cyclic', color='blue', fill=True, tikz_scale=2) sage: latex(p) \begin{tikzpicture}[scale=2] \draw (0,0) circle [radius=1cm]; @@ -594,7 +613,7 @@ def _latex_(self): # setup arcs for partition in sorted(self, key=str): - p = sorted(partition, key=str) + p = sorted(partition, key=sort_key) if len(p) <= 1: continue for k in range(1, len(p)): From a7f6613942c2bcfc9c7a6590f7f44d15a5706afb Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Wed, 10 May 2017 13:51:27 -0700 Subject: [PATCH 292/452] trac 22941: Do not import sagenb.misc.support! It changes the display manager. --- src/sage/graphs/graph_editor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/graphs/graph_editor.py b/src/sage/graphs/graph_editor.py index 2109406bb5e..b53178ade94 100644 --- a/src/sage/graphs/graph_editor.py +++ b/src/sage/graphs/graph_editor.py @@ -22,7 +22,7 @@ from sage.misc.html import html import sagenb.notebook.interact -from sagenb.misc.support import EMBEDDED_MODE +from sage.server.support import EMBEDDED_MODE def graph_to_js(g): From 45e44a0d5d00ae08e04644de04d7adf03884946d Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Wed, 10 May 2017 14:27:20 -0700 Subject: [PATCH 293/452] trac 22942: do not build enum34 with Python 3.4 or later --- build/pkgs/enum34/spkg-install | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/build/pkgs/enum34/spkg-install b/build/pkgs/enum34/spkg-install index c1a2289ade0..cd57e98526f 100755 --- a/build/pkgs/enum34/spkg-install +++ b/build/pkgs/enum34/spkg-install @@ -1,3 +1,8 @@ #!/usr/bin/env bash +if [ "$SAGE_PYTHON3" = "yes" ]; then + echo "Not installing enum34: it is only needed for Python version 3.3 or older." + exit 0 +fi + cd src && $PIP_INSTALL . From 16de140f16af5e9e764b25d1b8c47da38784809b Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Wed, 10 May 2017 15:54:33 -0700 Subject: [PATCH 294/452] trac 22941: add a doctest. --- src/sage/graphs/all.py | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/sage/graphs/all.py b/src/sage/graphs/all.py index c31a1aead8c..050339ebe14 100644 --- a/src/sage/graphs/all.py +++ b/src/sage/graphs/all.py @@ -19,3 +19,13 @@ lazy_import("sage.graphs.graph_editor", "graph_editor") from sage.graphs.isgci import graph_classes + +""" +TESTS: + +Test that sagenb.misc.support is not imported (see :trac:`22941`):: + + sage: import sage.graphs.graph_editor + sage: 'sagenb.misc.support' in sys.modules + False +""" From dde736b3c5382de6617fadd7597e4f48131af4cb Mon Sep 17 00:00:00 2001 From: Antonio Rojas Date: Thu, 11 May 2017 10:43:51 +1200 Subject: [PATCH 295/452] Add interface patch for emc 7 from the Arch linux port. The Arch commit is credited to Antonio Rojas (arojas@archlinux.org) --- src/sage/interfaces/ecm.py | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/src/sage/interfaces/ecm.py b/src/sage/interfaces/ecm.py index ea8fe4cda6e..52e34b7a2de 100644 --- a/src/sage/interfaces/ecm.py +++ b/src/sage/interfaces/ecm.py @@ -141,9 +141,6 @@ def __init__(self, B1=10, B2=None, **kwds): - ``ve`` -- integer `n`. Verbosely show short (`< n` character) expressions on each loop - - ``cofdec`` -- boolean. Force cofactor output in decimal - (even if expressions are used ) - - ``B2scale`` -- integer. Multiplies the default B2 value - ``go`` -- integer. Preload with group order val, which can @@ -396,15 +393,15 @@ def _parse_output(self, n, out): if m is not None: factor = m.group('factor') primality = m.group('primality') - assert primality in ['probable prime', 'composite'] - result += [(ZZ(factor), primality == 'probable prime')] + assert primality in ['prime', 'composite'] + result += [(ZZ(factor), primality == 'prime')] continue # cofactor on the next line m = self._found_cofactor_re.match(line) if m is not None: cofactor = m.group('cofactor') primality = m.group('primality') - assert primality in ['Probable prime', 'Composite'] - result += [(ZZ(cofactor), primality == 'Probable prime')] + assert primality in ['Prime', 'Composite'] + result += [(ZZ(cofactor), primality == 'Prime')] # assert len(result) == 2 return result raise ValueError('failed to parse ECM output') @@ -501,7 +498,6 @@ def _find_factor(self, n, factor_digits, B1, **kwds): if factor_digits is not None: B1 = self.recommended_B1(factor_digits) kwds['one'] = True - kwds['cofdec'] = True cmd = self._make_cmd(B1, None, kwds) out = self._run_ecm(cmd, n) return self._parse_output(n, out) @@ -833,8 +829,8 @@ def _validate(self, n): Step 1 took 12ms Step 2 took 17ms ********** Factor found in step 2: 79792266297612017 -Found probable prime factor of 17 digits: 79792266297612017 -Probable prime cofactor 6366805760909027985741435139224233 has 34 digits +Found prime factor of 17 digits: 79792266297612017 +Prime cofactor 6366805760909027985741435139224233 has 34 digits """ TEST_ECM_OUTPUT_2 = """ @@ -844,8 +840,8 @@ def _validate(self, n): Step 1 took 2ms Step 2 took 3ms ********** Factor found in step 2: 179424673 -Found probable prime factor of 9 digits: 179424673 -Probable prime cofactor 179424673 has 9 digits +Found prime factor of 9 digits: 179424673 +Prime cofactor 179424673 has 9 digits """ TEST_ECM_OUTPUT_3 = """ @@ -863,7 +859,7 @@ def _validate(self, n): Step 1 took 5ms Step 2 took 4ms ********** Factor found in step 2: 197002597249 -Found probable prime factor of 12 digits: 197002597249 +Found prime factor of 12 digits: 197002597249 Composite cofactor 339872432034468861533158743041639097889948066859 has 48 digits """ @@ -875,5 +871,5 @@ def _validate(self, n): Step 2 took 2ms ********** Factor found in step 2: 265748496095531068869578877937 Found composite factor of 30 digits: 265748496095531068869578877937 -Probable prime cofactor 251951573867253012259144010843 has 30 digits +Prime cofactor 251951573867253012259144010843 has 30 digits """ From 0b082c2d7aac83d91253a450cd81e7accf13d76b Mon Sep 17 00:00:00 2001 From: Vincent Delecroix <20100.delecroix@gmail.com> Date: Thu, 11 May 2017 08:32:15 +0200 Subject: [PATCH 296/452] 22924: typos --- src/sage/libs/linbox/linbox_flint_interface.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/libs/linbox/linbox_flint_interface.pyx b/src/sage/libs/linbox/linbox_flint_interface.pyx index f9d5b687eb0..02a6151fcf0 100644 --- a/src/sage/libs/linbox/linbox_flint_interface.pyx +++ b/src/sage/libs/linbox/linbox_flint_interface.pyx @@ -7,7 +7,7 @@ Interface between flint matrices and linbox This module only contains C++ code (and the interface is fully C compatible). It basically contains what used to be in the LinBox -source code under interfaces/sage/linbox-Sage.C written by M. Albrecht +source code under interfaces/sage/linbox-sage.C written by M. Albrecht and C. Pernet. The functions available are: - ``void linbox_fmpz_mat_mul(fmpz_mat_t C, fmpz_mat_t A, fmpz_mat_t B)``: set @@ -125,7 +125,7 @@ cdef extern from "linbox/solutions/det.h": ############################################################################### -# set the entries of A from m (no allocation preformed) +# set the entries of A from m (no allocation performed) # NOTE: this function is not part of the interface (ie the .pxd file) to keep the # module C-compatible cdef void fmpz_mat_get_linbox(LinBoxIntegerDenseMatrix& A, fmpz_mat_t m): From 58119b0df21bcfbb89fc58e108493fde90ac733f Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Thu, 11 May 2017 08:57:15 +0200 Subject: [PATCH 297/452] 17505: fix doctests --- src/sage/calculus/calculus.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/calculus/calculus.py b/src/sage/calculus/calculus.py index 0e1e0ebc52f..41eb3fa0ba6 100644 --- a/src/sage/calculus/calculus.py +++ b/src/sage/calculus/calculus.py @@ -836,7 +836,7 @@ def symbolic_prod(expression, v, a, b, algorithm='maxima', hold=False): EXAMPLES:: - sage: k, n = var('k,n') + sage: i, k, n = var('i,k,n') sage: from sage.calculus.calculus import symbolic_prod sage: symbolic_prod(k, k, 1, n) factorial(n) From 7a56004ca73a73e04b0b6a7bdbe6b528c0358bb3 Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Thu, 11 May 2017 10:15:19 +0200 Subject: [PATCH 298/452] 17505: address reviewer's suggestions --- src/sage/calculus/calculus.py | 34 +++++++++++++++------ src/sage/functions/other.py | 14 ++++++++- src/sage/symbolic/expression_conversions.py | 4 +-- 3 files changed, 39 insertions(+), 13 deletions(-) diff --git a/src/sage/calculus/calculus.py b/src/sage/calculus/calculus.py index 41eb3fa0ba6..38a2ef71518 100644 --- a/src/sage/calculus/calculus.py +++ b/src/sage/calculus/calculus.py @@ -809,7 +809,7 @@ def nintegral(ex, x, a, b, nintegrate = nintegral -def symbolic_prod(expression, v, a, b, algorithm='maxima', hold=False): +def symbolic_product(expression, v, a, b, algorithm='maxima', hold=False): r""" Return the symbolic product `\prod_{v = a}^b expression` with respect to the variable `v` with endpoints `a` and `b`. @@ -837,21 +837,23 @@ def symbolic_prod(expression, v, a, b, algorithm='maxima', hold=False): EXAMPLES:: sage: i, k, n = var('i,k,n') - sage: from sage.calculus.calculus import symbolic_prod - sage: symbolic_prod(k, k, 1, n) + sage: from sage.calculus.calculus import symbolic_product + sage: symbolic_product(k, k, 1, n) factorial(n) - sage: symbolic_prod(x + i*(i+1)/2, i, 1, 4) + sage: symbolic_product(x + i*(i+1)/2, i, 1, 4) x^4 + 20*x^3 + 127*x^2 + 288*x + 180 - sage: symbolic_prod(i^2, i, 1, 7) + sage: symbolic_product(i^2, i, 1, 7) 25401600 sage: f = function('f') - sage: symbolic_prod(f(i), i, 1, 7) + sage: symbolic_product(f(i), i, 1, 7) f(7)*f(6)*f(5)*f(4)*f(3)*f(2)*f(1) - sage: symbolic_prod(f(i), i, 1, n) + sage: symbolic_product(f(i), i, 1, n) product(f(i), i, 1, n) sage: assume(k>0) - sage: symbolic_prod(integrate (x^k, x, 0, 1), k, 1, n) + sage: symbolic_product(integrate (x^k, x, 0, 1), k, 1, n) 1/factorial(n + 1) + sage: symbolic_product(f(i), i, 1, n).log().log_expand() + sum(log(f(i)), i, 1, n) """ if not is_SymbolicVariable(v): if isinstance(v, str): @@ -869,11 +871,23 @@ def symbolic_prod(expression, v, a, b, algorithm='maxima', hold=False): if algorithm == 'maxima': return maxima.sr_prod(expression,v,a,b) + elif algorithm == 'mathematica': + try: + prod = "Product[%s, {%s, %s, %s}]" % tuple([repr(expr._mathematica_()) for expr in (expression, v, a, b)]) + except TypeError: + raise ValueError("Mathematica cannot make sense of input") + from sage.interfaces.mathematica import mathematica + try: + result = mathematica(prod) + except TypeError: + raise ValueError("Mathematica cannot make sense of: %s" % sum) + return result.sage() + elif algorithm == 'giac': - sum = "product(%s, %s, %s, %s)" % tuple([repr(expr._giac_()) for expr in (expression, v, a, b)]) + prod = "product(%s, %s, %s, %s)" % tuple([repr(expr._giac_()) for expr in (expression, v, a, b)]) from sage.interfaces.giac import giac try: - result = giac(sum) + result = giac(prod) except TypeError: raise ValueError("Giac cannot make sense of: %s" % sum) return result.sage() diff --git a/src/sage/functions/other.py b/src/sage/functions/other.py index c2216c3fae3..dc13c3953e7 100644 --- a/src/sage/functions/other.py +++ b/src/sage/functions/other.py @@ -2593,8 +2593,10 @@ class Function_sum(BuiltinFunction): EXAMPLES:: sage: from sage.functions.other import symbolic_sum as ssum - sage: ssum(x, x, 1, 10) + sage: r = ssum(x, x, 1, 10); r sum(x, x, 1, 10) + sage: r.unhold() + 55 """ def __init__(self): """ @@ -2607,6 +2609,16 @@ def __init__(self): BuiltinFunction.__init__(self, "sum", nargs=4, conversions=dict(maxima='sum')) + def _print_latex_(self, x, var, a, b): + r""" + EXAMPLES:: + + sage: from sage.functions.other import symbolic_sum as ssum + sage: latex(ssum(x^2, x, 1, 10)) + \sum_{x=1}^{10} x^2 + """ + return r"\sum_{{{}={}}}^{{{}}} {}".format(var, a, b, x) + symbolic_sum = Function_sum() diff --git a/src/sage/symbolic/expression_conversions.py b/src/sage/symbolic/expression_conversions.py index b5f7e299167..16f7f3ebdf3 100644 --- a/src/sage/symbolic/expression_conversions.py +++ b/src/sage/symbolic/expression_conversions.py @@ -2009,13 +2009,13 @@ def composition(self, ex, operator): 0 """ from sage.functions.other import Function_sum, Function_prod - from sage.calculus.calculus import symbolic_sum, symbolic_prod + from sage.calculus.calculus import symbolic_sum, symbolic_product if not operator: return self if isinstance(operator, Function_sum): return symbolic_sum(*map(self, ex.operands())) if isinstance(operator, Function_prod): - return symbolic_prod(*map(self, ex.operands())) + return symbolic_product(*map(self, ex.operands())) if operator in self._exclude: return operator(*map(self, ex.operands()), hold=True) else: From 89528153136a1286ac4ab1f6738d2409aaebe2d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 11 May 2017 12:05:58 +0200 Subject: [PATCH 299/452] py3 : get rid of cmp in coerce.pyx --- src/sage/structure/coerce.pyx | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/sage/structure/coerce.pyx b/src/sage/structure/coerce.pyx index 2e88998f2f9..3cf0012efb8 100644 --- a/src/sage/structure/coerce.pyx +++ b/src/sage/structure/coerce.pyx @@ -1881,9 +1881,13 @@ cdef class CoercionModel_cache_maps(CoercionModel): return res # If types are not equal: compare types - cdef int c = cmp(type(x), type(y)) - if c: - return rich_to_bool(op, c) + # avoiding call to cmp() for compatibility with python3 + cdef type tx = type(x) + cdef type ty = type(y) + if tx < ty: + return rich_to_bool(op, -1) + elif tx > ty: + return rich_to_bool(op, 1) # Final attempt: compare by id() if (x) >= (y): From 224b1be1b5480867849c6bb44f3e52394df1a94e Mon Sep 17 00:00:00 2001 From: Johan Rosenkilde Date: Thu, 11 May 2017 14:05:59 +0200 Subject: [PATCH 300/452] Remove rename_keyword deprecation warning (6 years old) --- src/sage/coding/code_bounds.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/sage/coding/code_bounds.py b/src/sage/coding/code_bounds.py index 0108802aad5..346da171460 100644 --- a/src/sage/coding/code_bounds.py +++ b/src/sage/coding/code_bounds.py @@ -174,11 +174,9 @@ from sage.arith.misc import is_prime_power from sage.arith.all import factorial from sage.functions.all import log, sqrt -from sage.misc.decorators import rename_keyword from .delsarte_bounds import delsarte_bound_hamming_space, \ delsarte_bound_additive_hamming_space -@rename_keyword(deprecation=6094, method="algorithm") def codesize_upper_bound(n,d,q,algorithm=None): r""" Returns an upper bound on the code size. @@ -237,7 +235,6 @@ def codesize_upper_bound(n,d,q,algorithm=None): sub = singleton_upper_bound(n,q,d) return min([eub,hub,pub,sub]) -@rename_keyword(deprecation=6094, method="algorithm") def dimension_upper_bound(n,d,q,algorithm=None): r""" Returns an upper bound for the dimension of a linear code. @@ -296,7 +293,6 @@ def gilbert_lower_bound(n,q,d): ans=q**n/volume_hamming(n,q,d-1) return ans -@rename_keyword(deprecation=6094, method="algorithm") def plotkin_upper_bound(n,q,d, algorithm=None): r""" Returns Plotkin upper bound. @@ -332,7 +328,6 @@ def plotkin_upper_bound(n,q,d, algorithm=None): fact = int(fact) + 1 return int(d/( d - t * fact)) * q**(n - fact) -@rename_keyword(deprecation=6094, method="algorithm") def griesmer_upper_bound(n,q,d,algorithm=None): r""" Returns the Griesmer upper bound. @@ -393,7 +388,6 @@ def griesmer_upper_bound(n,q,d,algorithm=None): return 0 -@rename_keyword(deprecation=6094, method="algorithm") def elias_upper_bound(n,q,d,algorithm=None): r""" Returns the Elias upper bound. From 1ee9d38a5fc003d6cad6c9faf54cbf936f6954a8 Mon Sep 17 00:00:00 2001 From: Johan Rosenkilde Date: Thu, 11 May 2017 14:38:25 +0200 Subject: [PATCH 301/452] Basic parameter sanity check on more bounds --- src/sage/coding/code_bounds.py | 116 +++++++++++++++++++++++++++++---- 1 file changed, 105 insertions(+), 11 deletions(-) diff --git a/src/sage/coding/code_bounds.py b/src/sage/coding/code_bounds.py index 346da171460..ca89f2d14ad 100644 --- a/src/sage/coding/code_bounds.py +++ b/src/sage/coding/code_bounds.py @@ -177,12 +177,36 @@ from .delsarte_bounds import delsarte_bound_hamming_space, \ delsarte_bound_additive_hamming_space +def _check_n_q_d(n, q, d): + r""" + Check that the length `n`, alphabet size `q` and minimum distance `d` type + check and make sense for a code over a field. + + More precisely, checks that the parameters are positive integers, that `q` + is a prime power, and that `n >= d`. Raises a ``ValueError`` otherwise. + + EXAMPLES:: + + sage: from sage.coding.code_bounds import _check_n_q_d + sage: _check_n_q_d(20, 16, 5) + True + sage: _check_n_q_d(20, 16, 21) + Traceback (most recent call last): + ... + ValueError: The length, alphabet size and minimum distance does not make sense for a code over a field + """ + if not( is_prime_power(q) and d > 0 and n >= d and n in ZZ and d in ZZ ): + raise ValueError("The length, alphabet size and minimum distance does not make sense for a code over a field") + return True + + def codesize_upper_bound(n,d,q,algorithm=None): r""" - Returns an upper bound on the code size. + Returns an upper bound on the number of codewords in a (possibly non-linear) + code. - This function computes the minimum value of the upper bound using the - methods of Singleton, Hamming, Plotkin, and Elias. + This function computes the minimum value of the upper bounds of Singleton, + Hamming, Plotkin, and Elias. If algorithm="gap" then this returns the best known upper bound `A(n,d)=A_q(n,d)` for the size of a code of length n, @@ -222,7 +246,14 @@ def codesize_upper_bound(n,d,q,algorithm=None): 20 sage: codes.bounds.codesize_upper_bound(19,10,2,algorithm="gap") # optional - gap_packages (Guava package) 20 + + Meaningless parameters are rejected:: + sage: codes.bounds.codesize_upper_bound(10, 20, 16) + Traceback (most recent call last): + ... + ValueError: The length, alphabet size and minimum distance does not make sense for a code over a field """ + _check_n_q_d(n, q, d) if algorithm=="gap": gap.load_package('guava') return int(gap.eval("UpperBound(%s,%s,%s)"%( n, d, q ))) @@ -253,14 +284,22 @@ def dimension_upper_bound(n,d,q,algorithm=None): sage: codes.bounds.dimension_upper_bound(30,15,4,algorithm="LP") 12 + TESTS: + + Meaningless code parameters are rejected:: + + sage: codes.bounds.dimension_upper_bound(-3,3,2) + Traceback (most recent call last): + ... + ValueError: The length, alphabet size and minimum distance does not make sense for a code over a field + """ + _check_n_q_d(n, q, d) q = ZZ(q) - if is_prime_power(q) and n>0 and d>0 and n in ZZ and d in ZZ: # sanity check - if algorithm=="LP": - return delsarte_bound_additive_hamming_space(n,d,q) - - else: # algorithm==None or algorithm=="gap": - return int(log(codesize_upper_bound(n,d,q,algorithm=algorithm),q)) + if algorithm=="LP": + return delsarte_bound_additive_hamming_space(n,d,q) + else: # algorithm==None or algorithm=="gap": + return int(log(codesize_upper_bound(n,d,q,algorithm=algorithm),q)) def volume_hamming(n,q,r): @@ -289,7 +328,17 @@ def gilbert_lower_bound(n,q,d): sage: codes.bounds.gilbert_lower_bound(10,2,3) 128/7 + + TESTS: + + Meaningless parameters are rejected:: + + sage: codes.bounds.gilbert_lower_bound(10, 6, 3) + Traceback (most recent call last): + ... + ValueError: The length, alphabet size and minimum distance does not make sense for a code over a field """ + _check_n_q_d(n, q, d) ans=q**n/volume_hamming(n,q,d-1) return ans @@ -309,7 +358,17 @@ def plotkin_upper_bound(n,q,d, algorithm=None): 192 sage: codes.bounds.plotkin_upper_bound(10,2,3,algorithm="gap") # optional - gap_packages (Guava package) 192 + + TESTS: + + Meaningless parameters are rejected:: + + sage: codes.bounds.plotkin_upper_bound(10, 16, 20) + Traceback (most recent call last): + ... + ValueError: The length, alphabet size and minimum distance does not make sense for a code over a field """ + _check_n_q_d(n, q, d) if algorithm=="gap": gap.load_package("guava") ans=gap.eval("UpperBoundPlotkin(%s,%s,%s)"%(n,d,q)) @@ -362,13 +421,19 @@ def griesmer_upper_bound(n,q,d,algorithm=None): TESTS:: - sage: codes.bounds.griesmer_upper_bound(10,6,5) - 0 sage: codes.bounds.griesmer_upper_bound(11,3,6) 243 sage: codes.bounds.griesmer_upper_bound(11,3,6) 243 + + Meaningless parameters are rejected:: + + sage: codes.bounds.griesmer_upper_bound(10, 16, 20) + Traceback (most recent call last): + ... + ValueError: The length, alphabet size and minimum distance does not make sense for a code over a field """ + _check_n_q_d(n, q, d) if is_prime_power(q) and n>0 and d>0 and n in ZZ and d in ZZ: # sanity check if algorithm=="gap": gap.load_package("guava") @@ -403,7 +468,16 @@ def elias_upper_bound(n,q,d,algorithm=None): sage: codes.bounds.elias_upper_bound(10,2,3,algorithm="gap") # optional - gap_packages (Guava package) 232 + TESTS: + + Meaningless parameters are rejected:: + + sage: codes.bounds.elias_upper_bound(10, 16, 20) + Traceback (most recent call last): + ... + ValueError: The length, alphabet size and minimum distance does not make sense for a code over a field """ + _check_n_q_d(n, q, d) r = 1-1/q if algorithm=="gap": gap.load_package("guava") @@ -454,7 +528,17 @@ def hamming_upper_bound(n,q,d): sage: codes.bounds.hamming_upper_bound(10,2,3) 93 + + TESTS: + + Meaningless parameters are rejected:: + + sage: codes.bounds.hamming_upper_bound(10, 16, 20) + Traceback (most recent call last): + ... + ValueError: The length, alphabet size and minimum distance does not make sense for a code over a field """ + _check_n_q_d(n, q, d) return int((q**n)/(volume_hamming(n, q, int((d-1)/2)))) def singleton_upper_bound(n,q,d): @@ -483,7 +567,17 @@ def singleton_upper_bound(n,q,d): sage: codes.bounds.singleton_upper_bound(10,2,3) 256 + + TESTS: + + Meaningless parameters are rejected:: + + sage: codes.bounds.singleton_upper_bound(10, 16, 20) + Traceback (most recent call last): + ... + ValueError: The length, alphabet size and minimum distance does not make sense for a code over a field """ + _check_n_q_d(n, q, d) return q**(n - d + 1) def gv_info_rate(n,delta,q): From 4b0a57e3495b937e78c4cf60df1271c6dc024d0c Mon Sep 17 00:00:00 2001 From: Johan Rosenkilde Date: Thu, 11 May 2017 14:46:55 +0200 Subject: [PATCH 302/452] More doc-string fixes --- src/sage/coding/code_bounds.py | 111 +++++++++++++++------------------ 1 file changed, 52 insertions(+), 59 deletions(-) diff --git a/src/sage/coding/code_bounds.py b/src/sage/coding/code_bounds.py index ca89f2d14ad..e6a4f7fe5eb 100644 --- a/src/sage/coding/code_bounds.py +++ b/src/sage/coding/code_bounds.py @@ -304,10 +304,10 @@ def dimension_upper_bound(n,d,q,algorithm=None): def volume_hamming(n,q,r): r""" - Returns number of elements in a Hamming ball. + Returns the number of elements in a Hamming ball. - Returns number of elements in a Hamming ball of radius r in `\GF{q}^n`. - Agrees with Guava's SphereContent(n,r,GF(q)). + Returns the number of elements in a Hamming ball of radius `r` in + `\GF{q}^n`. EXAMPLES:: @@ -319,9 +319,9 @@ def volume_hamming(n,q,r): def gilbert_lower_bound(n,q,d): r""" - Returns Gilbert-Varshamov lower bound. + Returns the Gilbert-Varshamov lower bound. - Returns Gilbert-Varshamov lower bound for number of elements in a largest code of + Returns the Gilbert-Varshamov lower bound for number of elements in a largest code of minimum distance d in `\GF{q}^n`. See :wikipedia:`Gilbert-Varshamov_bound` EXAMPLES:: @@ -344,13 +344,14 @@ def gilbert_lower_bound(n,q,d): def plotkin_upper_bound(n,q,d, algorithm=None): r""" - Returns Plotkin upper bound. + Returns the Plotkin upper bound. - Returns Plotkin upper bound for number of elements in a largest - code of minimum distance d in `\GF{q}^n`. - More precisely this is a generalization of Plotkin's result for q=2 - to bigger q due to Berlekamp. - The algorithm="gap" option wraps Guava's UpperBoundPlotkin. + Returns the Plotkin upper bound for the number of elements in a largest + code of minimum distance `d` in `\GF{q}^n`. + More precisely this is a generalization of Plotkin's result for `q=2` + to bigger `q` due to Berlekamp. + + The ``algorithm="gap"`` option wraps Guava's ``UpperBoundPlotkin``. EXAMPLES:: @@ -391,17 +392,16 @@ def griesmer_upper_bound(n,q,d,algorithm=None): r""" Returns the Griesmer upper bound. - Returns the Griesmer upper bound for number of elements in a - largest linear code of minimum distance d in `\GF{q}^n`, cf. [HP2003]_. - If the method is "GAP", it wraps GAP's UpperBoundGriesmer. Namely, + Returns the Griesmer upper bound for the number of elements in a + largest linear code of minimum distance `d` in `\GF{q}^n`, cf. [HP2003]_. + If the method is "gap", it wraps GAP's ``UpperBoundGriesmer``. + + The bound states: .. MATH:: `n\geq \sum_{i=0}^{k-1} \lceil d/q^i \rceil.` - To compute the bound, we keep summing up the terms on the RHS - until we start violating the inequality. - EXAMPLES: @@ -434,23 +434,22 @@ def griesmer_upper_bound(n,q,d,algorithm=None): ValueError: The length, alphabet size and minimum distance does not make sense for a code over a field """ _check_n_q_d(n, q, d) - if is_prime_power(q) and n>0 and d>0 and n in ZZ and d in ZZ: # sanity check - if algorithm=="gap": - gap.load_package("guava") - ans=gap.eval("UpperBoundGriesmer(%s,%s,%s)"%(n,d,q)) - return QQ(ans) - else: - from sage.functions.other import ceil - den = 1 - s = 0 - k = 0 - while s <= n: - s += ceil(d/den) - den *= q - k = k + 1 - return q**(k-1) + if algorithm=="gap": + gap.load_package("guava") + ans=gap.eval("UpperBoundGriesmer(%s,%s,%s)"%(n,d,q)) + return QQ(ans) else: - return 0 + #To compute the bound, we keep summing up the terms on the RHS + #until we start violating the inequality. + from sage.functions.other import ceil + den = 1 + s = 0 + k = 0 + while s <= n: + s += ceil(d/den) + den *= q + k = k + 1 + return q**(k-1) def elias_upper_bound(n,q,d,algorithm=None): @@ -458,8 +457,8 @@ def elias_upper_bound(n,q,d,algorithm=None): Returns the Elias upper bound. Returns the Elias upper bound for number of elements in the largest - code of minimum distance d in `\GF{q}^n`, cf. [HP2003]_. Wraps - GAP's UpperBoundElias. + code of minimum distance `d` in `\GF{q}^n`, cf. [HP2003]_. + If the method is "gap", it wraps GAP's ``UpperBoundElias``. EXAMPLES:: @@ -502,14 +501,13 @@ def hamming_upper_bound(n,q,d): Returns the Hamming upper bound for number of elements in the largest code of minimum distance d in `\GF{q}^n`. - Wraps GAP's UpperBoundHamming. The Hamming bound (also known as the sphere packing bound) returns - an upper bound on the size of a code of length n, minimum distance - d, over a field of size q. The Hamming bound is obtained by + an upper bound on the size of a code of length `n`, minimum distance + `d`, over a field of size `q`. The Hamming bound is obtained by dividing the contents of the entire space `\GF{q}^n` by the contents of a ball with radius - floor((d-1)/2). As all these balls are disjoint, they can never + `floor((d-1)/2)`. As all these balls are disjoint, they can never contain more than the whole vector space. @@ -519,9 +517,9 @@ def hamming_upper_bound(n,q,d): - where M is the maximum number of codewords and `V(n,e)` is + where `M` is the maximum number of codewords and `V(n,e)` is equal to the contents of a ball of radius e. This bound is useful - for small values of d. Codes for which equality holds are called + for small values of `d`. Codes for which equality holds are called perfect. See e.g. [HP2003]_. EXAMPLES:: @@ -547,10 +545,9 @@ def singleton_upper_bound(n,q,d): Returns the Singleton upper bound for number of elements in a largest code of minimum distance d in `\GF{q}^n`. - Wraps GAP's UpperBoundSingleton. This bound is based on the shortening of codes. By shortening an - `(n, M, d)` code d-1 times, an `(n-d+1,M,1)` code + `(n, M, d)` code `d-1` times, an `(n-d+1,M,1)` code results, with `M \leq q^n-d+1`. Thus @@ -559,7 +556,6 @@ def singleton_upper_bound(n,q,d): M \leq q^{n-d+1}. - Codes that meet this bound are called maximum distance separable (MDS). @@ -582,10 +578,10 @@ def singleton_upper_bound(n,q,d): def gv_info_rate(n,delta,q): """ - Gilbert-Varshamov lower bound for information rate. + The Gilbert-Varshamov lower bound for information rate. - Gilbert-Varshamov lower bound for information rate of a `q`-ary code of length `n` - minimum distance `n\delta`. + The Gilbert-Varshamov lower bound for information rate of a `q`-ary code of + length `n` and minimum distance `n\delta`. EXAMPLES:: @@ -692,7 +688,7 @@ def entropy_inverse(x, q=2): def gv_bound_asymp(delta,q): """ - Computes the asymptotic Gilbert-Varshamov bound for the information rate, R. + The asymptotic Gilbert-Varshamov bound for the information rate, R. EXAMPLES:: @@ -707,7 +703,7 @@ def gv_bound_asymp(delta,q): def hamming_bound_asymp(delta,q): """ - Computes the asymptotic Hamming bound for the information rate. + The asymptotic Hamming bound for the information rate. EXAMPLES:: @@ -721,7 +717,7 @@ def hamming_bound_asymp(delta,q): def singleton_bound_asymp(delta,q): """ - Computes the asymptotic Singleton bound for the information rate. + The asymptotic Singleton bound for the information rate. EXAMPLES:: @@ -735,10 +731,9 @@ def singleton_bound_asymp(delta,q): def plotkin_bound_asymp(delta,q): """ - Computes the asymptotic Plotkin bound for the information rate. + The asymptotic Plotkin bound for the information rate. - Computes the asymptotic Plotkin bound for the information rate, - provided `0 < \delta < 1-1/q`. + This only makes sense when `0 < \delta < 1-1/q`. EXAMPLES:: @@ -750,10 +745,9 @@ def plotkin_bound_asymp(delta,q): def elias_bound_asymp(delta,q): """ - Computes the asymptotic Elias bound for the information rate. + The asymptotic Elias bound for the information rate. - Computes the asymptotic Elias bound for the information rate, - provided `0 < \delta < 1-1/q`. + This only makes sense when `0 < \delta < 1-1/q`. EXAMPLES:: @@ -765,10 +759,9 @@ def elias_bound_asymp(delta,q): def mrrw1_bound_asymp(delta,q): """ - Computes the first asymptotic McEliese-Rumsey-Rodemich-Welsh bound. + The first asymptotic McEliese-Rumsey-Rodemich-Welsh bound. - Computes the first asymptotic McEliese-Rumsey-Rodemich-Welsh bound - for the information rate, provided `0 < \delta < 1-1/q`. + This only makes sense when `0 < \delta < 1-1/q`. EXAMPLES:: From 55a30b7a36b30b3f588865a5d0e7e5980a1e9ab5 Mon Sep 17 00:00:00 2001 From: Daniel Krenn Date: Thu, 11 May 2017 16:14:19 +0200 Subject: [PATCH 303/452] Trac #22944: doctest fixup --- src/sage/rings/big_oh.py | 2 -- src/sage/symbolic/ring.pyx | 4 ---- 2 files changed, 6 deletions(-) diff --git a/src/sage/rings/big_oh.py b/src/sage/rings/big_oh.py index 9801d7aff2c..c96afa6b285 100644 --- a/src/sage/rings/big_oh.py +++ b/src/sage/rings/big_oh.py @@ -83,8 +83,6 @@ def O(*x, **kwds): We can also work with `asymptotic expansions`_:: sage: A. = AsymptoticRing(growth_group='QQ^n * n^QQ * log(n)^QQ', coefficient_ring=QQ); A - doctest:...: FutureWarning: - This class/method/function is marked as experimental. ... Asymptotic Ring over Rational Field sage: O(n) O(n) diff --git a/src/sage/symbolic/ring.pyx b/src/sage/symbolic/ring.pyx index 6a60ee4c480..03efab62918 100644 --- a/src/sage/symbolic/ring.pyx +++ b/src/sage/symbolic/ring.pyx @@ -286,10 +286,6 @@ cdef class SymbolicRing(CommutativeRing): Asymptotic expansions:: sage: A. = AsymptoticRing(growth_group='x^ZZ * y^QQ * log(y)^ZZ', coefficient_ring=ZZ) - doctest:...: FutureWarning: This class/method/function is - marked as experimental. - ... - See http://trac.sagemath.org/17601 for details. sage: s = SR(3*x^5 * log(y) + 4*y^(3/7) + O(x*log(y))); s 3*x^5*log(y) + 4*y^(3/7) + Order(x*log(y)) sage: s.operator(), s.operands() From c67f95735d1f816c0255dad81985a8c98aa49757 Mon Sep 17 00:00:00 2001 From: Emmanuel Charpentier Date: Thu, 11 May 2017 16:19:12 +0200 Subject: [PATCH 304/452] Implement distribute() in the multiplicative case. --- src/sage/symbolic/expression.pyx | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index d59d4d95f0b..99528b36d48 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -10395,6 +10395,8 @@ cdef class Expression(CommutativeRingElement): - Integral (definite or not) of a sum ==> sum of integrals. + _ Symbolic product of a product ==> product of symbolic products. + INPUT: - ``self`` - expression whose operator may be distributed. @@ -10427,15 +10429,22 @@ cdef class Expression(CommutativeRingElement): sum(sum(Y(k), k, 1, q) + sum(Z(k), k, 1, q), j, 1, p) + sum(X(j), j, 1, p) sage: sum(X(j)+sum(Y(k)+Z(k),k,1,q),j,1,p).distribute(recursive=False) sum(X(j), j, 1, p) + sum(sum(Y(k) + Z(k), k, 1, q), j, 1, p) + sage: maxima("product(X(j)*Y(j),j,1,p)").sage() + product(X(j)*Y(j), j, 1, p) + sage: maxima("product(X(j)*Y(j),j,1,p)").sage().distribute() + product(X(j), j, 1, p)*product(Y(j), j, 1, p) + AUTHORS: - Emmanuel Charpentier, Ralf Stephan (05-2017) """ - from sage.functions.other import symbolic_sum as opsum + from sage.functions.other import symbolic_sum as opsum, \ + symbolic_product as opprod from sage.symbolic.integration.integral \ import indefinite_integral as opii, definite_integral as opdi - from sage.symbolic.operators import add_vararg as opadd + from sage.symbolic.operators import add_vararg as opadd, \ + mul_vararg as opmul def treat_term(op, term, args): l=sage.all.copy(args) l.insert(0, term) @@ -10456,6 +10465,19 @@ cdef class Expression(CommutativeRingElement): aa)) return sum(map(lambda t:treat_term(op, t, la), aa)) return self + if op is opprod: + sa = self.operands()[0].expand() + op1 = sa.operator() + if op1 is opmul: + la = self.operands()[1:] + aa = sa.operands() + if recursive: + return sage.all.prod(map(lambda t:treat_term(op, + t.distribute(), + la), + aa)) + return sage.all.prod(map(lambda t:treat_term(op, t, la), aa)) + return self if recursive: return apply(op, map(lambda t:t.distribute(), self.operands())) return self From 687cc8ea8b0a225d81309bcfffcb3aa948afd31b Mon Sep 17 00:00:00 2001 From: Emmanuel Charpentier Date: Thu, 11 May 2017 18:10:12 +0200 Subject: [PATCH 305/452] Distribute : implement Travis Scrimshaw's suggestion for iterations. --- src/sage/symbolic/expression.pyx | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 99528b36d48..d096fcd391d 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -10437,7 +10437,7 @@ cdef class Expression(CommutativeRingElement): AUTHORS: - - Emmanuel Charpentier, Ralf Stephan (05-2017) + - Emmanuel Charpentier, Ralf Stephan, Travis Scrimshaw (05-2017) """ from sage.functions.other import symbolic_sum as opsum, \ symbolic_product as opprod @@ -10445,6 +10445,7 @@ cdef class Expression(CommutativeRingElement): import indefinite_integral as opii, definite_integral as opdi from sage.symbolic.operators import add_vararg as opadd, \ mul_vararg as opmul + from sage.all import prod def treat_term(op, term, args): l=sage.all.copy(args) l.insert(0, term) @@ -10459,11 +10460,8 @@ cdef class Expression(CommutativeRingElement): la = self.operands()[1:] aa = sa.operands() if recursive: - return sum(map(lambda t:treat_term(op, - t.distribute(), - la), - aa)) - return sum(map(lambda t:treat_term(op, t, la), aa)) + return sum(treat_term(op, t.distribute(), la) for t in aa) + return sum(treat_term(op, t, la) for t in aa) return self if op is opprod: sa = self.operands()[0].expand() @@ -10472,11 +10470,8 @@ cdef class Expression(CommutativeRingElement): la = self.operands()[1:] aa = sa.operands() if recursive: - return sage.all.prod(map(lambda t:treat_term(op, - t.distribute(), - la), - aa)) - return sage.all.prod(map(lambda t:treat_term(op, t, la), aa)) + return prod(treat_term(op, t.distribute(), la) for t in aa) + return prod(treat_term(op, t, la) for t in aa) return self if recursive: return apply(op, map(lambda t:t.distribute(), self.operands())) From 89b27622e668b1bd03b12a7aadb59327ef4cec30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 11 May 2017 20:27:54 +0200 Subject: [PATCH 306/452] trac 22981 another try: replace cmp() by raise --- src/sage/structure/element.pyx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sage/structure/element.pyx b/src/sage/structure/element.pyx index 9355df10e45..81d06d2428c 100644 --- a/src/sage/structure/element.pyx +++ b/src/sage/structure/element.pyx @@ -1054,7 +1054,9 @@ cdef class Element(SageObject): if not isinstance(left, Element): assert type(left) is type(right) - return cmp(left, right) + raise NotImplementedError("old-style comparisons are not " + "supported anymore (see " + "https://trac.sagemath.org/ticket/22981)") # Now we have two Sage Elements with the same parent try: From 61cb00ccf1648775300d83c7896ae058a51b0ebb Mon Sep 17 00:00:00 2001 From: Xavier Caruso Date: Thu, 11 May 2017 22:28:09 +0200 Subject: [PATCH 307/452] Newton polygon and slope factorization fixed --- .../polynomial/polynomial_element_generic.py | 48 ++++++++++++++----- 1 file changed, 37 insertions(+), 11 deletions(-) diff --git a/src/sage/rings/polynomial/polynomial_element_generic.py b/src/sage/rings/polynomial/polynomial_element_generic.py index 8370a4ca2ac..961af3b6de9 100644 --- a/src/sage/rings/polynomial/polynomial_element_generic.py +++ b/src/sage/rings/polynomial/polynomial_element_generic.py @@ -41,7 +41,7 @@ from sage.libs.pari.all import pari_gen from sage.structure.element import coerce_binop -from sage.rings.infinity import infinity +from sage.rings.infinity import infinity, Infinity from sage.rings.integer_ring import ZZ from sage.rings.integer import Integer from sage.structure.factorization import Factorization @@ -1117,6 +1117,16 @@ def newton_polygon(self): ... PrecisionError: The coefficient of t^4 has not enough precision + TESTS: + + Check that :trac:`22936` is fixed:: + + sage: S. = PowerSeriesRing(GF(5)) + sage: R. = S[] + sage: p = x^2+y+x*y^2 + sage: p.newton_polygon() + Finite Newton polygon with 3 vertices: (0, 2), (1, 0), (2, 1) + AUTHOR: - Xavier Caruso (2013-03-20) @@ -1127,14 +1137,15 @@ def newton_polygon(self): polygon_prec = NewtonPolygon([ (x, self[x].precision_absolute()) for x in range(d+1) ]) vertices = polygon.vertices(copy=False) vertices_prec = polygon_prec.vertices(copy=False) - if vertices[0][0] > vertices_prec[0][0]: - raise PrecisionError("first term with non-infinite valuation must have determined valuation") - elif vertices[-1][0] < vertices_prec[-1][0]: - raise PrecisionError("last term with non-infinite valuation must have determined valuation") - else: - for (x, y) in vertices: - if polygon_prec(x) <= y: - raise PrecisionError("The coefficient of %s^%s has not enough precision" % (self.parent().variable_name(), x)) + if len(vertices_prec) > 0: + if vertices[0][0] > vertices_prec[0][0]: + raise PrecisionError("first term with non-infinite valuation must have determined valuation") + elif vertices[-1][0] < vertices_prec[-1][0]: + raise PrecisionError("last term with non-infinite valuation must have determined valuation") + else: + for (x, y) in vertices: + if polygon_prec(x) <= y: + raise PrecisionError("The coefficient of %s^%s has not enough precision" % (self.parent().variable_name(), x)) return polygon def hensel_lift(self, a): @@ -1211,6 +1222,14 @@ def _factor_of_degree(self, deg): ... KeyboardInterrupt: + TESTS: + + sage: S. = PowerSeriesRing(GF(5)) + sage: R. = S[] + sage: p = x^2+y+x*y^2 + sage: p._factor_of_degree(1) + (1 + O(x^20))*y + x^2 + x^5 + 2*x^8 + 4*x^14 + 2*x^17 + 2*x^20 + O(x^22) + AUTHOR: - Xavier Caruso (2013-03-20) @@ -1220,8 +1239,15 @@ def _factor_of_degree(self, deg): Precision is not optimal, and can be improved. """ coeffs = self.list() - a = self.truncate(deg + 1) - b = v = self.parent()(1) + a = coeffs[:deg+1] + # The leading coefficient need to be known at finite precision + # in order to ensure that the while loop below terminates + if a[deg].precision_absolute() is Infinity: + a[deg] = a[deg].add_bigoh(self.base_ring().default_prec()) + + parent = self.parent() + a = parent(a) + b = v = parent(1) x = self % a while(not x.is_zero()): a += (v * x) % a From da7cb4d06fb82ce0bf3e7bb75e148299e7b36901 Mon Sep 17 00:00:00 2001 From: Kwankyu Lee Date: Thu, 11 May 2017 22:29:39 +0200 Subject: [PATCH 308/452] Improve _test_derivative test --- .../rings/function_field/function_field.py | 18 +++++------------- 1 file changed, 5 insertions(+), 13 deletions(-) diff --git a/src/sage/rings/function_field/function_field.py b/src/sage/rings/function_field/function_field.py index 11d247f6dba..6190ed360d6 100644 --- a/src/sage/rings/function_field/function_field.py +++ b/src/sage/rings/function_field/function_field.py @@ -67,16 +67,11 @@ sage: TestSuite(K).run() sage: TestSuite(L).run() # long time (8s on sage.math, 2012) sage: TestSuite(M).run() # long time (52s on sage.math, 2012) - sage: TestSuite(N).run() # long time - sage: TestSuite(O).run() # long time + sage: TestSuite(N).run(skip = '_test_derivation') # long time + sage: TestSuite(O).run(skip = '_test_derivation') # long time -The following two test suites do not pass ``_test_elements`` yet since -``R.an_element()`` has a ``_test_category`` method which it should not have. -It is not the fault of the function field code so this will -be fixed in another ticket:: - - sage: TestSuite(R).run(skip = '_test_elements') - sage: TestSuite(S).run(skip = '_test_elements') + sage: TestSuite(R).run() + sage: TestSuite(S).run() """ from __future__ import absolute_import #***************************************************************************** @@ -369,10 +364,7 @@ def _test_derivation(self, **options): tester = self._tester(**options) S = tester.some_elements() K = self.constant_base_field().some_elements() - try: - d = self.derivation() - except NotImplementedError: - return # some function fields no not implement derivation() yet + d = self.derivation() from itertools import product # Leibniz's law for x,y in tester.some_elements(product(S, S)): From ac0d97598c09c76e7a7b8ccf56e4bad9d6a1ce5a Mon Sep 17 00:00:00 2001 From: Xavier Caruso Date: Thu, 11 May 2017 22:48:34 +0200 Subject: [PATCH 309/452] Replace TESTS: by TESTS:: --- .../rings/polynomial/polynomial_element_generic.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/sage/rings/polynomial/polynomial_element_generic.py b/src/sage/rings/polynomial/polynomial_element_generic.py index 961af3b6de9..56c38443510 100644 --- a/src/sage/rings/polynomial/polynomial_element_generic.py +++ b/src/sage/rings/polynomial/polynomial_element_generic.py @@ -8,7 +8,7 @@ - David Harvey: split off polynomial_integer_dense_ntl.pyx (2007-09) - Robert Bradshaw: split off polynomial_modn_dense_ntl.pyx (2007-09) -TESTS: +TESTS:: We test coercion in a particularly complicated situation:: @@ -259,7 +259,7 @@ def integral(self, var=None): sage: (1 + 3*x^10 - 2*x^100).integral() -2/101*x^101 + 3/11*x^11 + x - TESTS: + TESTS:: Check that :trac:`18600` is fixed:: @@ -711,7 +711,7 @@ def shift(self, n): sage: p.shift(2) x^100002 + 2*x^3 + 4*x^2 - TESTS: + TESTS:: Check that :trac:`18600` is fixed:: @@ -865,7 +865,7 @@ def gcd(self,other,algorithm=None): ... ValueError: Unknown algorithm 'foobar' - TESTS: + TESTS:: Check that :trac:`19676` is fixed:: @@ -1117,7 +1117,7 @@ def newton_polygon(self): ... PrecisionError: The coefficient of t^4 has not enough precision - TESTS: + TESTS:: Check that :trac:`22936` is fixed:: @@ -1222,7 +1222,7 @@ def _factor_of_degree(self, deg): ... KeyboardInterrupt: - TESTS: + TESTS:: sage: S. = PowerSeriesRing(GF(5)) sage: R. = S[] From d420ec4ab00a322f97bd05326741ec7de3e3d65a Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Fri, 12 May 2017 09:18:41 +0200 Subject: [PATCH 310/452] 17505: fix latex, cosmetics --- src/sage/functions/other.py | 4 ++-- src/sage/interfaces/maxima_lib.py | 7 ++----- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/sage/functions/other.py b/src/sage/functions/other.py index dc13c3953e7..ff22f0898a7 100644 --- a/src/sage/functions/other.py +++ b/src/sage/functions/other.py @@ -2617,7 +2617,7 @@ def _print_latex_(self, x, var, a, b): sage: latex(ssum(x^2, x, 1, 10)) \sum_{x=1}^{10} x^2 """ - return r"\sum_{{{}={}}}^{{{}}} {}".format(var, a, b, x) + return r"{{\sum_{{{}={}}}^{{{}}} {}}}".format(var, a, b, x) symbolic_sum = Function_sum() @@ -2664,6 +2664,6 @@ def _print_latex_(self, x, var, a, b): sage: latex(sprod(x^2, x, 1, 10)) \prod_{x=1}^{10} x^2 """ - return r"\prod_{{{}={}}}^{{{}}} {}".format(var, a, b, x) + return r"{{\prod_{{{}={}}}^{{{}}} {}}}".format(var, a, b, x) symbolic_product = Function_prod() diff --git a/src/sage/interfaces/maxima_lib.py b/src/sage/interfaces/maxima_lib.py index f056c8f8bbf..9b6e8faedc3 100644 --- a/src/sage/interfaces/maxima_lib.py +++ b/src/sage/interfaces/maxima_lib.py @@ -902,17 +902,14 @@ def sr_sum(self,*args): def sr_prod(self,*args): """ - Helper function to wrap calculus use of Maxima's summation. + Helper function to wrap calculus use of Maxima's product. """ try: return max_to_sr(maxima_eval([[max_ratsimp],[[max_simplify_prod],([max_prod],[sr_to_max(SR(a)) for a in args])]])); except RuntimeError as error: s = str(error) if "divergent" in s: -# in pexpect interface, one looks for this; -# could not find an example where 'Pole encountered' occurred, though -# if "divergent" in s or 'Pole encountered' in s: - raise ValueError("Sum is divergent.") + raise ValueError("Product is divergent.") elif "Is" in s: # Maxima asked for a condition self._missing_assumption(s) else: From e793a923f9dc7deaf85f325eb6f3e9c90b82011f Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Fri, 12 May 2017 11:46:29 +0100 Subject: [PATCH 311/452] added field_based and used it whenever needed --- src/sage/coding/code_bounds.py | 113 ++++++++++++--------------------- 1 file changed, 39 insertions(+), 74 deletions(-) diff --git a/src/sage/coding/code_bounds.py b/src/sage/coding/code_bounds.py index e6a4f7fe5eb..d39b59ee75f 100644 --- a/src/sage/coding/code_bounds.py +++ b/src/sage/coding/code_bounds.py @@ -177,26 +177,42 @@ from .delsarte_bounds import delsarte_bound_hamming_space, \ delsarte_bound_additive_hamming_space -def _check_n_q_d(n, q, d): +def _check_n_q_d(n, q, d, field_based=True): r""" Check that the length `n`, alphabet size `q` and minimum distance `d` type check and make sense for a code over a field. More precisely, checks that the parameters are positive integers, that `q` - is a prime power, and that `n >= d`. Raises a ``ValueError`` otherwise. + is a prime power for codes over a field, or, more generally, that + `q` is of size at least 2, and that `n >= d`. Raises a ``ValueError`` + otherwise. - EXAMPLES:: + TESTS:: sage: from sage.coding.code_bounds import _check_n_q_d sage: _check_n_q_d(20, 16, 5) True - sage: _check_n_q_d(20, 16, 21) + sage: _check_n_q_d(20, 16, 6, field_based=False) + True + sage: _check_n_q_d(20, 21, 16) + Traceback (most recent call last): + ... + ValueError: The alphabet size does not make sense for a code over a field + sage: _check_n_q_d(20, -21, 16) + Traceback (most recent call last): + ... + ValueError: The alphabet size must be an integer >1 + sage: _check_n_q_d(20, 2, 26) Traceback (most recent call last): ... - ValueError: The length, alphabet size and minimum distance does not make sense for a code over a field + ValueError: The length or minimum distance does not make sense """ - if not( is_prime_power(q) and d > 0 and n >= d and n in ZZ and d in ZZ ): - raise ValueError("The length, alphabet size and minimum distance does not make sense for a code over a field") + if (q not in ZZ) or (q<2): + raise ValueError("The alphabet size must be an integer >1") + if field_based==True and (not is_prime_power(q)): + raise ValueError("The alphabet size does not make sense for a code over a field") + if not( d > 0 and n >= d and n in ZZ and d in ZZ ): + raise ValueError("The length or minimum distance does not make sense") return True @@ -248,12 +264,13 @@ def codesize_upper_bound(n,d,q,algorithm=None): 20 Meaningless parameters are rejected:: - sage: codes.bounds.codesize_upper_bound(10, 20, 16) + + sage: codes.bounds.codesize_upper_bound(10, -20, 6) Traceback (most recent call last): ... - ValueError: The length, alphabet size and minimum distance does not make sense for a code over a field + ValueError: The length or minimum distance does not make sense """ - _check_n_q_d(n, q, d) + _check_n_q_d(n, q, d, field_based=False) if algorithm=="gap": gap.load_package('guava') return int(gap.eval("UpperBound(%s,%s,%s)"%( n, d, q ))) @@ -288,11 +305,10 @@ def dimension_upper_bound(n,d,q,algorithm=None): Meaningless code parameters are rejected:: - sage: codes.bounds.dimension_upper_bound(-3,3,2) + sage: codes.bounds.dimension_upper_bound(13,3,6) Traceback (most recent call last): ... - ValueError: The length, alphabet size and minimum distance does not make sense for a code over a field - + ValueError: The alphabet size does not make sense for a code over a field """ _check_n_q_d(n, q, d) q = ZZ(q) @@ -328,17 +344,8 @@ def gilbert_lower_bound(n,q,d): sage: codes.bounds.gilbert_lower_bound(10,2,3) 128/7 - - TESTS: - - Meaningless parameters are rejected:: - - sage: codes.bounds.gilbert_lower_bound(10, 6, 3) - Traceback (most recent call last): - ... - ValueError: The length, alphabet size and minimum distance does not make sense for a code over a field """ - _check_n_q_d(n, q, d) + _check_n_q_d(n, q, d, field_based=False) ans=q**n/volume_hamming(n,q,d-1) return ans @@ -359,17 +366,8 @@ def plotkin_upper_bound(n,q,d, algorithm=None): 192 sage: codes.bounds.plotkin_upper_bound(10,2,3,algorithm="gap") # optional - gap_packages (Guava package) 192 - - TESTS: - - Meaningless parameters are rejected:: - - sage: codes.bounds.plotkin_upper_bound(10, 16, 20) - Traceback (most recent call last): - ... - ValueError: The length, alphabet size and minimum distance does not make sense for a code over a field """ - _check_n_q_d(n, q, d) + _check_n_q_d(n, q, d, field_based=False) if algorithm=="gap": gap.load_package("guava") ans=gap.eval("UpperBoundPlotkin(%s,%s,%s)"%(n,d,q)) @@ -425,13 +423,6 @@ def griesmer_upper_bound(n,q,d,algorithm=None): 243 sage: codes.bounds.griesmer_upper_bound(11,3,6) 243 - - Meaningless parameters are rejected:: - - sage: codes.bounds.griesmer_upper_bound(10, 16, 20) - Traceback (most recent call last): - ... - ValueError: The length, alphabet size and minimum distance does not make sense for a code over a field """ _check_n_q_d(n, q, d) if algorithm=="gap": @@ -466,17 +457,8 @@ def elias_upper_bound(n,q,d,algorithm=None): 232 sage: codes.bounds.elias_upper_bound(10,2,3,algorithm="gap") # optional - gap_packages (Guava package) 232 - - TESTS: - - Meaningless parameters are rejected:: - - sage: codes.bounds.elias_upper_bound(10, 16, 20) - Traceback (most recent call last): - ... - ValueError: The length, alphabet size and minimum distance does not make sense for a code over a field """ - _check_n_q_d(n, q, d) + _check_n_q_d(n, q, d, field_based=False) r = 1-1/q if algorithm=="gap": gap.load_package("guava") @@ -500,13 +482,14 @@ def hamming_upper_bound(n,q,d): Returns the Hamming upper bound. Returns the Hamming upper bound for number of elements in the - largest code of minimum distance d in `\GF{q}^n`. + largest code of length n and minimum distance d over alphabet + of size q. The Hamming bound (also known as the sphere packing bound) returns an upper bound on the size of a code of length `n`, minimum distance - `d`, over a field of size `q`. The Hamming bound is obtained by - dividing the contents of the entire space - `\GF{q}^n` by the contents of a ball with radius + `d`, over an alphabet of size `q`. The Hamming bound is obtained by + dividing the contents of the entire Hamming space + `q^n` by the contents of a ball with radius `floor((d-1)/2)`. As all these balls are disjoint, they can never contain more than the whole vector space. @@ -526,17 +509,8 @@ def hamming_upper_bound(n,q,d): sage: codes.bounds.hamming_upper_bound(10,2,3) 93 - - TESTS: - - Meaningless parameters are rejected:: - - sage: codes.bounds.hamming_upper_bound(10, 16, 20) - Traceback (most recent call last): - ... - ValueError: The length, alphabet size and minimum distance does not make sense for a code over a field """ - _check_n_q_d(n, q, d) + _check_n_q_d(n, q, d, field_based=False) return int((q**n)/(volume_hamming(n, q, int((d-1)/2)))) def singleton_upper_bound(n,q,d): @@ -563,17 +537,8 @@ def singleton_upper_bound(n,q,d): sage: codes.bounds.singleton_upper_bound(10,2,3) 256 - - TESTS: - - Meaningless parameters are rejected:: - - sage: codes.bounds.singleton_upper_bound(10, 16, 20) - Traceback (most recent call last): - ... - ValueError: The length, alphabet size and minimum distance does not make sense for a code over a field """ - _check_n_q_d(n, q, d) + _check_n_q_d(n, q, d, field_based=False) return q**(n - d + 1) def gv_info_rate(n,delta,q): From 00e03d4e7591c167f148b6db4c8e59b076890c72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 12 May 2017 13:50:59 +0200 Subject: [PATCH 312/452] trac 22987 fixing cardinality of 0 vector space --- src/sage/modules/free_module.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/sage/modules/free_module.py b/src/sage/modules/free_module.py index 19b2192c243..83a7a081772 100644 --- a/src/sage/modules/free_module.py +++ b/src/sage/modules/free_module.py @@ -1170,8 +1170,17 @@ def cardinality(self): 144 sage: (QQ^3).cardinality() +Infinity + + TESTS: + + Check that :trac:`22987` is fixed:: + + sage: VectorSpace(QQ, 0).cardinality() + 1 """ - return (self.base_ring().cardinality())**self.rank() + if not self.rank(): + return ZZ.one() + return self.base_ring().cardinality() ** self.rank() __len__ = cardinality # for backward compatibility From f4b45dc8654be7d0d194448a17dc6689ac7cc730 Mon Sep 17 00:00:00 2001 From: David Coudert Date: Fri, 12 May 2017 14:26:36 +0200 Subject: [PATCH 313/452] trac #22985: fix bug --- src/sage/graphs/graph_input.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/sage/graphs/graph_input.py b/src/sage/graphs/graph_input.py index bf29d0f04aa..9202096441e 100644 --- a/src/sage/graphs/graph_input.py +++ b/src/sage/graphs/graph_input.py @@ -369,6 +369,15 @@ def from_oriented_incidence_matrix(G, M, loops=False, multiedges=False, weighted sage: from_oriented_incidence_matrix(g, digraphs.Circuit(10).incidence_matrix()) sage: g.is_isomorphic(digraphs.Circuit(10)) True + + TESTS: + + Fix bug reported in :trac:`22985`:: + + sage: DiGraph(matrix ([[1,0,0,1],[0,0,1,1],[0,0,1,1]]).transpose()) + Traceback (most recent call last): + ... + ValueError: each column represents an edge: -1 goes to 1 """ from sage.matrix.matrix import is_Matrix assert is_Matrix(M) @@ -380,8 +389,7 @@ def from_oriented_incidence_matrix(G, M, loops=False, multiedges=False, weighted raise ValueError("There must be two nonzero entries (-1 & 1) per column.") L = sorted(set(c.list())) if L != [-1,0,1]: - msg += "Each column represents an edge: -1 goes to 1." - raise ValueError(msg) + raise ValueError("each column represents an edge: -1 goes to 1") if c[NZ[0]] == -1: positions.append(tuple(NZ)) else: From 5779423aac340d1d7dc415da287b9af5e0e1f381 Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Fri, 12 May 2017 14:55:19 +0200 Subject: [PATCH 314/452] 17505: fix doctests --- src/sage/functions/other.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/functions/other.py b/src/sage/functions/other.py index ff22f0898a7..aaee96cf87e 100644 --- a/src/sage/functions/other.py +++ b/src/sage/functions/other.py @@ -2615,7 +2615,7 @@ def _print_latex_(self, x, var, a, b): sage: from sage.functions.other import symbolic_sum as ssum sage: latex(ssum(x^2, x, 1, 10)) - \sum_{x=1}^{10} x^2 + {\sum_{x=1}^{10} x^2} """ return r"{{\sum_{{{}={}}}^{{{}}} {}}}".format(var, a, b, x) @@ -2662,7 +2662,7 @@ def _print_latex_(self, x, var, a, b): sage: from sage.functions.other import symbolic_product as sprod sage: latex(sprod(x^2, x, 1, 10)) - \prod_{x=1}^{10} x^2 + {\prod_{x=1}^{10} x^2} """ return r"{{\prod_{{{}={}}}^{{{}}} {}}}".format(var, a, b, x) From 2412f7a387cf0dec3a764a52a8e644d545cef5f8 Mon Sep 17 00:00:00 2001 From: Emmanuel Charpentier Date: Fri, 12 May 2017 16:38:20 +0200 Subject: [PATCH 315/452] Distribute : cosmetics on documentation. --- src/sage/symbolic/expression.pyx | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index d096fcd391d..2a336a12907 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -10395,14 +10395,12 @@ cdef class Expression(CommutativeRingElement): - Integral (definite or not) of a sum ==> sum of integrals. - _ Symbolic product of a product ==> product of symbolic products. + - Symbolic product of a product ==> product of symbolic products. INPUT: - - ``self`` - expression whose operator may be distributed. - - - ``recursive`` - the distribution proceeds along the subtrees - of the expression (default : True). + - ``recursive`` -- (default : True) the distribution proceeds + along the subtrees of the expression. TESTS: @@ -12516,4 +12514,3 @@ cdef operators compatible_relation(operators lop, operators rop) except Date: Fri, 12 May 2017 16:57:18 +0200 Subject: [PATCH 316/452] Distribute : at his request, Travis Crimshaw removed from Author's list. --- 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 2a336a12907..54d2c686d04 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -10435,7 +10435,7 @@ cdef class Expression(CommutativeRingElement): AUTHORS: - - Emmanuel Charpentier, Ralf Stephan, Travis Scrimshaw (05-2017) + - Emmanuel Charpentier, Ralf Stephan (05-2017) """ from sage.functions.other import symbolic_sum as opsum, \ symbolic_product as opprod From 7aee739cceff13c596c12e93130250f1ea1fae3f Mon Sep 17 00:00:00 2001 From: Emmanuel Charpentier Date: Fri, 12 May 2017 17:03:31 +0200 Subject: [PATCH 317/452] Distribute : one last typo (I hope...). --- 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 54d2c686d04..e6c6d8384eb 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -10386,7 +10386,7 @@ cdef class Expression(CommutativeRingElement): def distribute(self, recursive=True): """ - Distribute some indiced operators over similar operators in + Distribute some indexed operators over similar operators in order to allow further groupings or simplifications. Implemented cases (so far) : From f5fbc720f82b11787301b36efe8359c7e1dc653b Mon Sep 17 00:00:00 2001 From: Xavier Caruso Date: Fri, 12 May 2017 17:50:44 +0200 Subject: [PATCH 318/452] Better writing for TESTS::? --- .../polynomial/polynomial_element_generic.py | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/sage/rings/polynomial/polynomial_element_generic.py b/src/sage/rings/polynomial/polynomial_element_generic.py index 44a5aa1802f..4ceafa52336 100644 --- a/src/sage/rings/polynomial/polynomial_element_generic.py +++ b/src/sage/rings/polynomial/polynomial_element_generic.py @@ -8,7 +8,7 @@ - David Harvey: split off polynomial_integer_dense_ntl.pyx (2007-09) - Robert Bradshaw: split off polynomial_modn_dense_ntl.pyx (2007-09) -TESTS:: +TESTS: We test coercion in a particularly complicated situation:: @@ -259,7 +259,7 @@ def integral(self, var=None): sage: (1 + 3*x^10 - 2*x^100).integral() -2/101*x^101 + 3/11*x^11 + x - TESTS:: + TESTS: Check that :trac:`18600` is fixed:: @@ -704,7 +704,7 @@ def shift(self, n): sage: p.shift(2) x^100002 + 2*x^3 + 4*x^2 - TESTS:: + TESTS: Check that :trac:`18600` is fixed:: @@ -858,7 +858,7 @@ def gcd(self,other,algorithm=None): ... ValueError: Unknown algorithm 'foobar' - TESTS:: + TESTS: Check that :trac:`19676` is fixed:: @@ -1110,7 +1110,7 @@ def newton_polygon(self): ... PrecisionError: The coefficient of t^4 has not enough precision - TESTS:: + TESTS: Check that :trac:`22936` is fixed:: @@ -1351,6 +1351,14 @@ def slope_factorization(self): [0, 0, 0] [1] + TESTS:: + + sage: S. = PowerSeriesRing(GF(5)) + sage: R. = S[] + sage: p = x^2+y+x*y^2 + sage: p.slope_factorization() + (x) * ((x + O(x^22))*y + 1 + 4*x^3 + 4*x^6 + 3*x^9 + x^15 + 3*x^18 + O(x^21)) * ((x^-1 + O(x^20))*y + x + x^4 + 2*x^7 + 4*x^13 + 2*x^16 + 2*x^19 + O(x^22)) + AUTHOR: - Xavier Caruso (2013-03-20) From e6b73d37e09fabae7f885ab700431704b51b5ec8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 12 May 2017 22:00:52 +0200 Subject: [PATCH 319/452] trac 11759 adding enclosed keyword to octahedron etc --- src/sage/plot/plot3d/platonic.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sage/plot/plot3d/platonic.py b/src/sage/plot/plot3d/platonic.py index e4da07ffd5c..4744ee3abe2 100644 --- a/src/sage/plot/plot3d/platonic.py +++ b/src/sage/plot/plot3d/platonic.py @@ -435,6 +435,7 @@ def octahedron(center=(0, 0, 0), size=1, **kwds): sphinx_plot(G) """ + kwds['enclosed'] = True if 'aspect_ratio' not in kwds: kwds['aspect_ratio'] = [1, 1, 1] return prep(Box(1,1,1).dual(**kwds), center, size, kwds) @@ -592,6 +593,7 @@ def icosahedron(center=(0, 0, 0), size=1, **kwds): sphinx_plot(p) """ + kwds['enclosed'] = True if 'aspect_ratio' not in kwds: kwds['aspect_ratio'] = [1, 1, 1] return prep(dodecahedron().dual(**kwds), center, size, kwds) From df03447ef0deccce7b598fc70b141da2c8bef568 Mon Sep 17 00:00:00 2001 From: Volker Braun Date: Sat, 13 May 2017 00:51:58 +0200 Subject: [PATCH 320/452] Updated SageMath version to 8.0.beta6 --- VERSION.txt | 2 +- build/pkgs/configure/checksums.ini | 6 +++--- build/pkgs/configure/package-version.txt | 2 +- src/bin/sage-banner | 2 +- src/bin/sage-version.sh | 4 ++-- src/sage/version.py | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/VERSION.txt b/VERSION.txt index 962601e185e..8518a1669ae 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -SageMath version 8.0.beta5, Release Date: 2017-05-04 +SageMath version 8.0.beta6, Release Date: 2017-05-12 diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index 6816671ce21..e7d57ea79f9 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,4 +1,4 @@ tarball=configure-VERSION.tar.gz -sha1=339f2474b789d33051dde8f69d047ae723a36379 -md5=9bb01c255b39648bb19f62a3fa24a80d -cksum=2072910001 +sha1=6a2d4b05426a912b1589d9213760a6438105a502 +md5=4175d83db6c8a9a2a229bdbb383a923d +cksum=2310778507 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index 037ba971962..3d4c7bfe8ef 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -219 +220 diff --git a/src/bin/sage-banner b/src/bin/sage-banner index 4ee00d5aff2..0b69cae5c39 100644 --- a/src/bin/sage-banner +++ b/src/bin/sage-banner @@ -1,5 +1,5 @@ ┌────────────────────────────────────────────────────────────────────┐ -│ SageMath version 8.0.beta5, Release Date: 2017-05-04 │ +│ SageMath version 8.0.beta6, Release Date: 2017-05-12 │ │ Type "notebook()" for the browser-based notebook interface. │ │ Type "help()" for help. │ └────────────────────────────────────────────────────────────────────┘ diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index 3dd582b0ed1..caac449efca 100644 --- a/src/bin/sage-version.sh +++ b/src/bin/sage-version.sh @@ -1,4 +1,4 @@ # Sage version information for shell scripts # This file is auto-generated by the sage-update-version script, do not edit! -SAGE_VERSION='8.0.beta5' -SAGE_RELEASE_DATE='2017-05-04' +SAGE_VERSION='8.0.beta6' +SAGE_RELEASE_DATE='2017-05-12' diff --git a/src/sage/version.py b/src/sage/version.py index bc64af91cba..7ce1258f0fd 100644 --- a/src/sage/version.py +++ b/src/sage/version.py @@ -1,4 +1,4 @@ # Sage version information for Python scripts # This file is auto-generated by the sage-update-version script, do not edit! -version = '8.0.beta5' -date = '2017-05-04' +version = '8.0.beta6' +date = '2017-05-12' From 228451d2512401669b68961aa0995c17b573ca52 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Sat, 13 May 2017 00:29:27 +0100 Subject: [PATCH 321/452] adjusted the top docs to talk about codes not only over fields --- src/sage/coding/code_bounds.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/sage/coding/code_bounds.py b/src/sage/coding/code_bounds.py index d39b59ee75f..5d81f6e5057 100644 --- a/src/sage/coding/code_bounds.py +++ b/src/sage/coding/code_bounds.py @@ -18,8 +18,10 @@ - Dima Pasechnik (2012-10): added LP bounds. -Let `F` be a finite field (we denote the finite field with `q` elements by -`\GF{q}`). A subset `C` of `V=F^n` is called a code of length `n`. A subspace +Let `F` be a finite set of size `q`. +A subset `C` of `V=F^n` is called a code of length `n`. +Often one considers the case where `F` is a finite field, +denoted by `\GF{q}`. Then `V` is an `F`-vector space. A subspace of `V` (with the standard basis) is called a linear code of length `n`. If its dimension is denoted `k` then we typically store a basis of `C` as a `k\times n` matrix (the rows are the basis vectors). If `F=\GF{2}` then `C` is called a @@ -33,7 +35,7 @@ where `\vert C\vert` denotes the number of elements of `C`. If `{\bf -v}=(v_1,v_2,...,v_n)`, `{\bf w}=(w_1,w_2,...,w_n)` are vectors in `V=F^n` then +v}=(v_1,v_2,...,v_n)`, `{\bf w}=(w_1,w_2,...,w_n)` are elements of `V=F^n` then we define @@ -43,8 +45,11 @@ to be the Hamming distance between `{\bf v}` and `{\bf w}`. The function -`d:V\times V\rightarrow \Bold{N}` is called the Hamming metric. The weight of a -vector (in the Hamming metric) is `d({\bf v},{\bf 0})`. The minimum distance of +`d:V\times V\rightarrow \Bold{N}` is called the Hamming metric. The weight of +an element (in the Hamming metric) is `d({\bf v},{\bf 0})`, +where `0` is a distinguished element of `F`; +in particular it is `0` of the field if `F` is a field. +The minimum distance of a linear code is the smallest non-zero weight of a codeword in `C`. The relatively minimum distance is denoted @@ -59,8 +64,8 @@ distance `d` is called an `(n,M,d)_q`-code (using parentheses instead of square brackets). Of course, `k=\log_q(M)` for linear codes. -What is the "best" code of a given length? Let `F` be a finite field with `q` -elements. Let `A_q(n,d)` denote the largest `M` such that there exists a +What is the "best" code of a given length? +Let `A_q(n,d)` denote the largest `M` such that there exists a `(n,M,d)` code in `F^n`. Let `B_q(n,d)` (also denoted `A^{lin}_q(n,d)`) denote the largest `k` such that there exists a `[n,k,d]` code in `F^n`. (Of course, `A_q(n,d)\geq B_q(n,d)`.) Determining `A_q(n,d)` and `B_q(n,d)` is one of the From 946c5808691c5437cb6b2148fe0a5b7a200ce140 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Bissey?= Date: Sat, 13 May 2017 11:38:22 +1200 Subject: [PATCH 322/452] making the longcheck tests run serially --- build/pkgs/ecm/spkg-check | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/build/pkgs/ecm/spkg-check b/build/pkgs/ecm/spkg-check index 1f42390bff7..9c121b1ec4e 100755 --- a/build/pkgs/ecm/spkg-check +++ b/build/pkgs/ecm/spkg-check @@ -14,7 +14,10 @@ cd src echo echo "Now running GMP-ECM's test suite..." -$MAKE check longcheck +$MAKE check +# There are potential race conditions in the long check, +# running it serially. +$MAKE -j1 longcheck if [ $? -ne 0 ]; then echo >&2 "Error: GMP-ECM's test suite failed." From e2d74c645b48c3288802f9080d6651aaccf658fb Mon Sep 17 00:00:00 2001 From: Marcelo Forets Date: Sat, 13 May 2017 08:56:48 +0200 Subject: [PATCH 323/452] parse unevaluated expression in EN and FR --- src/sage/calculus/calculus.py | 16 +++++++++------- src/sage/symbolic/integration/integral.py | 6 ++++-- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/sage/calculus/calculus.py b/src/sage/calculus/calculus.py index e0ae5df1739..6c8bf2be8ff 100644 --- a/src/sage/calculus/calculus.py +++ b/src/sage/calculus/calculus.py @@ -1390,7 +1390,7 @@ def laplace(ex, t, s, algorithm='maxima'): sage: laplace(heaviside(t-1), t, s, algorithm='sympy') (e^(-s)/s, 0, True) - TESTS:: + TESTS: Testing Giac:: @@ -1399,15 +1399,14 @@ def laplace(ex, t, s, algorithm='maxima'): sage: laplace(5*cos(3*t-2)*heaviside(t-2), t, s, algorithm='giac') 5*(s*cos(4)*e^(-2*s) - 3*e^(-2*s)*sin(4))/(s^2 + 9) - Testing unevaluated expression from Giac:: + Check unevaluated expression from Giac (it is locale-dependent, see + :trac:`22833`):: sage: var('n') n sage: laplace(t^n, t, s, algorithm='giac') - Traceback (most recent call last): - ... - NotImplementedError: Unable to parse Giac output: integrate(t^n*exp(-s*t),t,0,+infinity) - + laplace(t^n, t, s) + Testing SymPy:: sage: laplace(t^n, t, s, algorithm='sympy') @@ -1454,7 +1453,10 @@ def laplace(ex, t, s, algorithm='maxima'): result = giac.laplace(ex, t, s) except TypeError: raise ValueError("Giac cannot make sense of: %s" % ex_gi) - return result.sage() + if 'integrate' in format(result) or 'integration' in format(result): + return dummy_laplace(ex, t, s) + else: + return result.sage() else: raise ValueError("Unknown algorithm: %s" % algorithm) diff --git a/src/sage/symbolic/integration/integral.py b/src/sage/symbolic/integration/integral.py index 9d169797711..956a80fc09f 100644 --- a/src/sage/symbolic/integration/integral.py +++ b/src/sage/symbolic/integration/integral.py @@ -62,7 +62,8 @@ def __init__(self): # creating a subclasses which define a different set of integrators self.integrators = [external.maxima_integrator] - BuiltinFunction.__init__(self, "integrate", nargs=2, conversions={'sympy': 'Integral'}) + BuiltinFunction.__init__(self, "integrate", nargs=2, conversions={'sympy': 'Integral', + 'giac': 'integrate'}) def _eval_(self, f, x): """ @@ -150,7 +151,8 @@ def __init__(self): # creating a subclasses which define a different set of integrators self.integrators = [external.maxima_integrator] - BuiltinFunction.__init__(self, "integrate", nargs=4, conversions={'sympy': 'Integral'}) + BuiltinFunction.__init__(self, "integrate", nargs=4, conversions={'sympy': 'Integral', + 'giac': 'integrate'}) def _eval_(self, f, x, a, b): """ From 5bd034d5d2e25d35cc3896a7e51e0d0e6ab47a9a Mon Sep 17 00:00:00 2001 From: Thierry Monteil Date: Sat, 13 May 2017 11:26:00 +0200 Subject: [PATCH 324/452] #22957 : apply suggestions of comment 11. --- src/sage/graphs/graph.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index 6d77976255b..a5656ef36db 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -7643,6 +7643,7 @@ def has_perfect_matching(self, algorithm="Edmonds", solver=None, verbose=0): sage: G = graphs.EmptyGraph() sage: all(G.has_perfect_matching(algorithm=algo) for algo in ['Edmonds', 'LP_matching', 'LP']) + True Be careful with isolated vertices:: @@ -7651,6 +7652,8 @@ def has_perfect_matching(self, algorithm="Edmonds", solver=None, verbose=0): sage: any(G.has_perfect_matching(algorithm=algo) for algo in ['Edmonds', 'LP_matching', 'LP']) False """ + if self.order() % 2: + return False if algorithm == "Edmonds": return len(self) == 2*self.matching(value_only=True, use_edge_labels=False, @@ -7669,7 +7672,7 @@ def has_perfect_matching(self, algorithm="Edmonds", solver=None, verbose=0): edges = self.edges_incident(v, labels=False) if not edges: return False - p.add_constraint(sum([b[e] for e in edges]) == 1) + p.add_constraint(sum(b[e] for e in edges) == 1) try: p.solve(log=verbose) return True From cdb94bbf5722c7a2c95ab3be48ffd6cf53b7df79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 13 May 2017 11:29:07 +0200 Subject: [PATCH 325/452] trac 22975 oops, typo --- 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 b4ca4e1f127..2e2cb443aa1 100644 --- a/src/sage/modules/free_module_element.pyx +++ b/src/sage/modules/free_module_element.pyx @@ -104,7 +104,7 @@ TESTS:: # (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** -from __future__ import absolute import +from __future__ import absolute_import cimport cython from cpython.slice cimport PySlice_GetIndicesEx From 0fc10392efa9bcf1213cf1da6078c930e930a675 Mon Sep 17 00:00:00 2001 From: Thierry Monteil Date: Sat, 13 May 2017 11:43:47 +0200 Subject: [PATCH 326/452] #22957 : use p.sum which is faster than sum. --- src/sage/graphs/graph.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index a5656ef36db..81c9e4dcbeb 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -7672,7 +7672,7 @@ def has_perfect_matching(self, algorithm="Edmonds", solver=None, verbose=0): edges = self.edges_incident(v, labels=False) if not edges: return False - p.add_constraint(sum(b[e] for e in edges) == 1) + p.add_constraint(p.sum(b[e] for e in edges) == 1) try: p.solve(log=verbose) return True From e009a0d7cff1951eae61680c62a467133f1503ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 13 May 2017 13:01:54 +0200 Subject: [PATCH 327/452] trac 22916 fix detail --- src/sage/typeset/character_art_factory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/typeset/character_art_factory.py b/src/sage/typeset/character_art_factory.py index bff5bbb65ab..9a1c3d53fa2 100644 --- a/src/sage/typeset/character_art_factory.py +++ b/src/sage/typeset/character_art_factory.py @@ -61,7 +61,7 @@ def __init__(self, """ self.art_type = art_type - assert string_type in string_types + assert isinstance(string_type('a'), string_types) self.string_type = string_type assert magic_method_name in ['_ascii_art_', '_unicode_art_'] self.magic_method_name = magic_method_name From 133eeda37707460172c67f1ab8d40c616b6e152b Mon Sep 17 00:00:00 2001 From: Jeroen Demeyer Date: Sat, 13 May 2017 12:03:43 +0300 Subject: [PATCH 328/452] PY_NEW should be a cimport (not a Python import) --- src/sage/libs/mpmath/ext_impl.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/libs/mpmath/ext_impl.pyx b/src/sage/libs/mpmath/ext_impl.pyx index 952b20b7998..6a5a3469e37 100644 --- a/src/sage/libs/mpmath/ext_impl.pyx +++ b/src/sage/libs/mpmath/ext_impl.pyx @@ -38,7 +38,7 @@ from libc.math cimport frexp from cysignals.signals cimport sig_check -from sage.ext.stdsage import PY_NEW +from sage.ext.stdsage cimport PY_NEW from sage.libs.gmp.all cimport * from sage.libs.mpfr cimport * from sage.rings.integer cimport Integer From c71c40d949413333d4eeba28f7acbd2d75c396ce Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Mon, 20 Mar 2017 15:38:29 -0500 Subject: [PATCH 329/452] Using faster Weyl group implementation for energy in LS paths. --- src/sage/categories/weyl_groups.py | 3 ++- src/sage/combinat/crystals/littelmann_path.py | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/sage/categories/weyl_groups.py b/src/sage/categories/weyl_groups.py index 677f81e4f82..bb6c1f5f9e4 100644 --- a/src/sage/categories/weyl_groups.py +++ b/src/sage/categories/weyl_groups.py @@ -221,7 +221,8 @@ def length(x): from sage.graphs.digraph import DiGraph return DiGraph(visited, name="Parabolic Quantum Bruhat Graph of %s for nodes %s"%(self, index_set), - format="dict_of_dicts") + format="dict_of_dicts", + data_structure="static_sparse") class ElementMethods: diff --git a/src/sage/combinat/crystals/littelmann_path.py b/src/sage/combinat/crystals/littelmann_path.py index 81082335e48..100b85c2c5d 100644 --- a/src/sage/combinat/crystals/littelmann_path.py +++ b/src/sage/combinat/crystals/littelmann_path.py @@ -967,11 +967,11 @@ def weyl_group_representation(self): sage: b = LS.module_generators[0] sage: c = b.f(1).f(3).f(2) sage: c.weyl_group_representation() - [s2*s3*s1, s3*s1] + [s2*s1*s3, s1*s3] """ cartan = self.parent().weight.parent().cartan_type().classical() I = cartan.index_set() - W = WeylGroup(cartan,prefix='s') + W = WeylGroup(cartan, prefix='s', implementation="permutation") return [W.from_reduced_word(x.to_dominant_chamber(index_set=I, reduced_word=True)[1]) for x in self.value] @cached_in_parent_method @@ -1131,7 +1131,7 @@ def energy_function(self): ct = P.cartan_type() cartan = ct.classical() Qv = RootSystem(cartan).coroot_lattice() - W = WeylGroup(cartan,prefix='s') + W = WeylGroup(cartan, prefix='s', implementation="permutation") J = tuple(weight.weyl_stabilizer()) L = self.weyl_group_representation() if ct.is_untwisted_affine() or ct.type() == 'BC': @@ -1140,7 +1140,7 @@ def energy_function(self): else: untwisted = False cartan_dual = cartan.dual() - Wd = WeylGroup(cartan_dual, prefix='s') + Wd = WeylGroup(cartan_dual, prefix='s', implementation="permutation") G = Wd.quantum_bruhat_graph(J) Qd = RootSystem(cartan_dual).root_lattice() dualize = lambda x: Qv.from_vector(x.to_vector()) From ce4d0b52d7ad3e1679f664a21279ec6b194a2f21 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sat, 13 May 2017 14:30:19 -0500 Subject: [PATCH 330/452] Making the crystal of rigged configurations not use the virtual crystal structure. --- src/doc/en/reference/references/index.rst | 14 ++++ .../rigged_configurations/rc_crystal.py | 68 ++++++++++++----- .../rigged_configurations/rc_infinity.py | 75 +++++++++++++------ .../rigged_configuration_element.py | 68 +++++++++-------- .../rigged_configurations.py | 1 + 5 files changed, 155 insertions(+), 71 deletions(-) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index dc95b571607..88f3606f856 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -1520,6 +1520,20 @@ REFERENCES: manifolds and complexes into a cubic lattice", *Uspekhi Mat. Nauk* 47 (1992), 219-220. + +.. [SS2015] Anne Schilling and Travis Scrimshaw. + *Crystal structure on rigged configurations and the filling map*. + Electon. J. Combin., **22**(1) (2015) #P1.73. :arxiv:`1409.2920`. + +.. [SS2015II] Ben Salisbury and Travis Scrimshaw. + *A rigged configuration model for* `B(\infty)`. + J. Combin. Theory Ser. A, ***133** (2015) pp. 29-75. + :arxiv:`1404.6539`. + +.. [SS2017] Ben Salisbury and Travis Scrimshaw. + *Rigged configurations for all symmetrizable types*. + Electon. J. Combin., **24**(1) (2017) #P1.30. :arxiv:`1509.07833`. + .. [ST2011] \A. Schilling, P. Tingley. *Demazure crystals, Kirillov-Reshetikhin crystals, and the energy function*. Electronic Journal of Combinatorics. **19(2)**. 2012. diff --git a/src/sage/combinat/rigged_configurations/rc_crystal.py b/src/sage/combinat/rigged_configurations/rc_crystal.py index b7d3d932fa8..a97b7bb935f 100644 --- a/src/sage/combinat/rigged_configurations/rc_crystal.py +++ b/src/sage/combinat/rigged_configurations/rc_crystal.py @@ -45,12 +45,14 @@ class CrystalOfRiggedConfigurations(UniqueRepresentation, Parent): The crystal structure for finite simply-laced types is given in [CrysStructSchilling06]_. These were then shown to be the crystal - operators in all finite types in [SchScr]_ and all simply-laced and - a large class of foldings of simply-laced types in [SalScr]_. + operators in all finite types in [SS2015]_, all simply-laced and + a large class of foldings of simply-laced types in [SS2015II]_, + and all symmetrizable types (uniformly) in [SS2017]_. INPUT: - - ``cartan_type`` -- (optional) a Cartan type + - ``cartan_type`` -- (optional) a Cartan type or a Cartan type + given as a folding - ``wt`` -- the highest weight vector in the weight lattice @@ -78,18 +80,38 @@ class CrystalOfRiggedConfigurations(UniqueRepresentation, Parent): sage: RC.digraph().is_isomorphic(T.digraph(), edge_labels=True) True + We construct a non-simply-laced affine type:: + + sage: La = RootSystem(['C', 3]).weight_lattice().fundamental_weights() + sage: RC = crystals.RiggedConfigurations(La[2]) + sage: mg = RC.highest_weight_vector() + sage: mg.f_string([2,3]) + (/) 1[ ]1 -1[ ]-1 + sage: T = crystals.Tableaux(['C', 3], shape=[1,1]) + sage: RC.digraph().is_isomorphic(T.digraph(), edge_labels=True) + True + + We can construct rigged configurations using a diagram folding of + a simply-laced type. This yields an equivalent but distinct crystal:: + + sage: vct = CartanType(['C', 3]).as_folding() + sage: RC = crystals.RiggedConfigurations(vct, La[2]) + sage: mg = RC.highest_weight_vector() + sage: mg.f_string([2,3]) + (/) 0[ ]0 -1[ ]-1 + sage: T = crystals.Tableaux(['C', 3], shape=[1,1]) + sage: RC.digraph().is_isomorphic(T.digraph(), edge_labels=True) + True + We reset the global options:: sage: RiggedConfigurations.options._reset() REFERENCES: - .. [SchScr] Anne Schilling and Travis Scrimshaw. - *Crystal structure on rigged configurations and the filling map*. - :arxiv:`1409.2920`. - - .. [SalScr] Ben Salisbury and Travis Scrimshaw. - *A rigged configuration model for* `B(\infty)`. :arxiv:`1404.6539`. + - [SS2015]_ + - [SS2015II]_ + - [SS2017]_ """ @staticmethod def __classcall_private__(cls, cartan_type, wt=None, WLR=None): @@ -112,20 +134,22 @@ def __classcall_private__(cls, cartan_type, wt=None, WLR=None): sage: RC is RCE False """ + from sage.combinat.root_system.type_folded import CartanTypeFolded + if wt is None: wt = cartan_type cartan_type = wt.parent().cartan_type() else: - cartan_type = CartanType(cartan_type) + if not isinstance(cartan_type, CartanTypeFolded): + cartan_type = CartanType(cartan_type) if WLR is None: WLR = wt.parent() else: wt = WLR(wt) - if not cartan_type.is_simply_laced(): - vct = cartan_type.as_folding() - return CrystalOfNonSimplyLacedRC(vct, wt, WLR) + if isinstance(cartan_type, CartanTypeFolded): + return CrystalOfNonSimplyLacedRC(cartan_type, wt, WLR) return super(CrystalOfRiggedConfigurations, cls).__classcall__(cls, wt, WLR=WLR) @@ -146,6 +170,7 @@ def __init__(self, wt, WLR): self._cartan_type = WLR.cartan_type() self._wt = wt self._rc_index = self._cartan_type.index_set() + self._rc_index_inverse = {i: ii for ii,i in enumerate(self._rc_index)} # We store the cartan matrix for the vacancy number calculations for speed self._cartan_matrix = self._cartan_type.cartan_matrix() if self._cartan_type.is_finite(): @@ -247,7 +272,9 @@ def _calc_vacancy_number(self, partitions, a, i, **options): vac_num = self._wt[self.index_set()[a]] for b in range(self._cartan_matrix.ncols()): - vac_num -= self._cartan_matrix[a,b] * partitions[b].get_num_cells_to_column(i) + val = self._cartan_matrix[a,b] + if val: + vac_num -= val * partitions[b].get_num_cells_to_column(i) return vac_num @@ -292,7 +319,8 @@ def virtual(self): EXAMPLES:: sage: La = RootSystem(['C', 2, 1]).weight_lattice().fundamental_weights() - sage: RC = crystals.RiggedConfigurations(La[0]) + sage: vct = CartanType(['C', 2, 1]).as_folding() + sage: RC = crystals.RiggedConfigurations(vct, La[0]) sage: RC Crystal of rigged configurations of type ['C', 2, 1] and weight Lambda[0] sage: RC.virtual @@ -319,7 +347,8 @@ def _calc_vacancy_number(self, partitions, a, i, **options): TESTS:: sage: La = RootSystem(['C', 3]).weight_lattice().fundamental_weights() - sage: RC = crystals.RiggedConfigurations(La[2]) + sage: vct = CartanType(['C', 3]).as_folding() + sage: RC = crystals.RiggedConfigurations(vct, La[2]) sage: elt = RC(partition_list=[[], [1], [1]]) sage: RC._calc_vacancy_number(elt.nu(), 1, 1) 0 @@ -350,7 +379,8 @@ def to_virtual(self, rc): EXAMPLES:: sage: La = RootSystem(['C', 3]).weight_lattice().fundamental_weights() - sage: RC = crystals.RiggedConfigurations(La[2]) + sage: vct = CartanType(['C', 3]).as_folding() + sage: RC = crystals.RiggedConfigurations(vct, La[2]) sage: elt = RC(partition_list=[[], [1], [1]]); elt (/) @@ -398,7 +428,8 @@ def from_virtual(self, vrc): EXAMPLES:: sage: La = RootSystem(['C', 3]).weight_lattice().fundamental_weights() - sage: RC = crystals.RiggedConfigurations(La[2]) + sage: vct = CartanType(['C', 3]).as_folding() + sage: RC = crystals.RiggedConfigurations(vct, La[2]) sage: elt = RC(partition_list=[[0], [1], [1]]) sage: elt == RC.from_virtual(RC.to_virtual(elt)) True @@ -421,3 +452,4 @@ def from_virtual(self, vrc): # deprecations from trac:18555 from sage.misc.superseded import deprecated_function_alias CrystalOfRiggedConfigurations.global_options = deprecated_function_alias(18555, CrystalOfRiggedConfigurations.options) + diff --git a/src/sage/combinat/rigged_configurations/rc_infinity.py b/src/sage/combinat/rigged_configurations/rc_infinity.py index 60b5efacd9e..066723f6758 100644 --- a/src/sage/combinat/rigged_configurations/rc_infinity.py +++ b/src/sage/combinat/rigged_configurations/rc_infinity.py @@ -80,11 +80,29 @@ class InfinityCrystalOfRiggedConfigurations(UniqueRepresentation, Parent): sage: RC = crystals.infinity.RiggedConfigurations(['C', 3]) sage: mg = RC.highest_weight_vector() sage: mg.f_string([2,1,3,2]) + 0[ ]0 -1[ ]0 0[ ]0 + -1[ ]-1 + sage: mg.f_string([2,3,2,1,3,2]) + 0[ ]-1 -1[ ][ ]-1 -1[ ][ ]0 + -1[ ]0 + + We can construct rigged configurations using a diagram folding of + a simply-laced type. This yields an equivalent but distinct crystal:: + + sage: vct = CartanType(['C', 3]).as_folding() + sage: VRC = crystals.infinity.RiggedConfigurations(vct) + sage: mg = VRC.highest_weight_vector() + sage: mg.f_string([2,1,3,2]) 0[ ]0 -2[ ]-1 0[ ]0 -2[ ]-1 sage: mg.f_string([2,3,2,1,3,2]) -1[ ]-1 -2[ ][ ][ ]-1 -1[ ][ ]0 + sage: G = RC.subcrystal(max_depth=5).digraph() + sage: VG = VRC.subcrystal(max_depth=5).digraph() + sage: G.is_isomorphic(VG, edge_labels=True) + True + We can also construct `B(\infty)` using rigged configurations in affine types:: @@ -97,14 +115,14 @@ class InfinityCrystalOfRiggedConfigurations(UniqueRepresentation, Parent): sage: RC = crystals.infinity.RiggedConfigurations(['C', 3, 1]) sage: mg = RC.highest_weight_vector() sage: mg.f_string([1,2,3,0,1,2,3,3,0]) - -2[ ][ ]-1 -1[ ]0 -1[ ]-1 -4[ ][ ][ ]-2 - -1[ ]0 -1[ ]-1 + -2[ ][ ]-1 0[ ]1 0[ ]0 -4[ ][ ][ ]-2 + 0[ ]0 0[ ]-1 sage: RC = crystals.infinity.RiggedConfigurations(['A', 6, 2]) sage: mg = RC.highest_weight_vector() sage: mg.f_string([1,2,3,0,1,2,3,3,0]) - 0[ ]-1 0[ ]1 -1[ ]-1 -4[ ][ ][ ]-2 - 0[ ]-1 0[ ]1 -1[ ]-1 + 0[ ]-1 0[ ]1 0[ ]0 -4[ ][ ][ ]-2 + 0[ ]-1 0[ ]1 0[ ]-1 We reset the global options:: @@ -122,11 +140,11 @@ def __classcall_private__(cls, cartan_type): sage: RC2 is RC1 True """ - cartan_type = CartanType(cartan_type) - if not cartan_type.is_simply_laced(): - vct = cartan_type.as_folding() - return InfinityCrystalOfNonSimplyLacedRC(vct) + from sage.combinat.root_system.type_folded import CartanTypeFolded + if isinstance(cartan_type, CartanTypeFolded): + return InfinityCrystalOfNonSimplyLacedRC(cartan_type) + cartan_type = CartanType(cartan_type) return super(InfinityCrystalOfRiggedConfigurations, cls).__classcall__(cls, cartan_type) def __init__(self, cartan_type): @@ -139,10 +157,15 @@ def __init__(self, cartan_type): sage: TestSuite(RC).run() sage: RC = crystals.infinity.RiggedConfigurations(['A', 2, 1]) sage: TestSuite(RC).run() # long time + sage: RC = crystals.infinity.RiggedConfigurations(['C', 2]) + sage: TestSuite(RC).run() # long time + sage: RC = crystals.infinity.RiggedConfigurations(['C', 2, 1]) + sage: TestSuite(RC).run() # long time """ self._cartan_type = cartan_type Parent.__init__(self, category=HighestWeightCrystals().Infinite()) self._rc_index = self._cartan_type.index_set() + self._rc_index_inverse = {i: ii for ii,i in enumerate(self._rc_index)} # We store the cartan matrix for the vacancy number calculations for speed self._cartan_matrix = self._cartan_type.cartan_matrix() self.module_generators = (self.element_class(self, rigging_list=[[]]*cartan_type.rank()),) @@ -172,9 +195,9 @@ def _element_constructor_(self, lst=None, **options): 0[ ]1 0[ ]0 0[ ]0 0[ ]-1 sage: RC = crystals.infinity.RiggedConfigurations(['C', 3]) - sage: ascii_art(RC(partition_list=[[1],[1,1],[1]], rigging_list=[[0],[-1,-1],[0]])) - 0[ ]0 -2[ ]-1 0[ ]0 - -2[ ]-1 + sage: ascii_art(RC(partition_list=[[1],[1,1],[1]], rigging_list=[[0],[0,-1],[0]])) + 0[ ]0 -1[ ]0 0[ ]0 + -1[ ]-1 TESTS: @@ -299,9 +322,11 @@ def __init__(self, vct): EXAMPLES:: - sage: RC = crystals.infinity.RiggedConfigurations(['C', 2]) + sage: vct = CartanType(['C', 2]).as_folding() + sage: RC = crystals.infinity.RiggedConfigurations(vct) sage: TestSuite(RC).run() # long time - sage: RC = crystals.infinity.RiggedConfigurations(['C', 2, 1]) + sage: vct = CartanType(['C', 2, 1]).as_folding() + sage: RC = crystals.infinity.RiggedConfigurations(vct) sage: TestSuite(RC).run() # long time """ self._folded_ct = vct @@ -321,8 +346,9 @@ def _calc_vacancy_number(self, partitions, a, i): TESTS:: - sage: La = RootSystem(['C',2]).weight_lattice().fundamental_weights() - sage: RC = crystals.RiggedConfigurations(La[1]) + sage: La = RootSystem(['C', 2]).weight_lattice().fundamental_weights() + sage: vct = CartanType(['C', 2]).as_folding() + sage: RC = crystals.RiggedConfigurations(vct, La[1]) sage: elt = RC(partition_list=[[1], [1]]) sage: RC._calc_vacancy_number(elt.nu(), 0, 1) 0 @@ -349,7 +375,8 @@ def virtual(self): EXAMPLES:: - sage: RC = crystals.infinity.RiggedConfigurations(['C', 3]) + sage: vct = CartanType(['C', 3]).as_folding() + sage: RC = crystals.infinity.RiggedConfigurations(vct) sage: RC The infinity crystal of rigged configurations of type ['C', 3] sage: RC.virtual @@ -367,7 +394,8 @@ def to_virtual(self, rc): EXAMPLES:: - sage: RC = crystals.infinity.RiggedConfigurations(['C', 2]) + sage: vct = CartanType(['C', 2]).as_folding() + sage: RC = crystals.infinity.RiggedConfigurations(vct) sage: mg = RC.highest_weight_vector() sage: elt = mg.f_string([1,2,2,1,1]); elt @@ -411,7 +439,8 @@ def from_virtual(self, vrc): EXAMPLES:: - sage: RC = crystals.infinity.RiggedConfigurations(['C', 2]) + sage: vct = CartanType(['C', 2]).as_folding() + sage: RC = crystals.infinity.RiggedConfigurations(vct) sage: elt = RC(partition_list=[[3],[2]], rigging_list=[[-2],[0]]) sage: vrc_elt = RC.to_virtual(elt) sage: ret = RC.from_virtual(vrc_elt); ret @@ -444,7 +473,8 @@ class Element(RCNonSimplyLacedElement): TESTS:: - sage: RC = crystals.infinity.RiggedConfigurations(['C', 3]) + sage: vct = CartanType(['C', 3]).as_folding() + sage: RC = crystals.infinity.RiggedConfigurations(vct) sage: elt = RC(partition_list=[[1],[1,1],[1]]) sage: TestSuite(elt).run() """ @@ -454,12 +484,14 @@ def weight(self): EXAMPLES:: - sage: RC = crystals.infinity.RiggedConfigurations(['C', 3]) + sage: vct = CartanType(['C', 3]).as_folding() + sage: RC = crystals.infinity.RiggedConfigurations(vct) sage: elt = RC(partition_list=[[1],[1,1],[1]], rigging_list=[[0],[-1,-1],[0]]) sage: elt.weight() (-1, -1, 0) - sage: RC = crystals.infinity.RiggedConfigurations(['F', 4, 1]) + sage: vct = CartanType(['F', 4, 1]).as_folding() + sage: RC = crystals.infinity.RiggedConfigurations(vct) sage: mg = RC.highest_weight_vector() sage: elt = mg.f_string([1,0,3,4,2,2]); ascii_art(elt) -1[ ]-1 0[ ]1 -2[ ][ ]-2 0[ ]1 -1[ ]-1 @@ -476,3 +508,4 @@ def weight(self): # deprecations from trac:18555 from sage.misc.superseded import deprecated_function_alias InfinityCrystalOfRiggedConfigurations.global_options = deprecated_function_alias(18555, InfinityCrystalOfRiggedConfigurations.options) + diff --git a/src/sage/combinat/rigged_configurations/rigged_configuration_element.py b/src/sage/combinat/rigged_configurations/rigged_configuration_element.py index 2e4101a357b..56e936faae7 100644 --- a/src/sage/combinat/rigged_configurations/rigged_configuration_element.py +++ b/src/sage/combinat/rigged_configurations/rigged_configuration_element.py @@ -224,9 +224,6 @@ def __init__(self, parent, rigged_partitions=[], **options): # Parent's __call__ always passes at least 1 argument to the element constructor if options.get('use_vacancy_numbers', False): - # Special display case - if parent.cartan_type().type() == 'B': - rigged_partitions[-1] = RiggedPartitionTypeB(rigged_partitions[-1]) ClonableArray.__init__(self, parent, rigged_partitions) return nu = rigged_partitions @@ -260,10 +257,6 @@ def __init__(self, parent, rigged_partitions=[], **options): if partition.rigging[i] is None: partition.rigging[i] = partition.vacancy_numbers[i] - # Special display case - if parent.cartan_type().type() == 'B': - nu[-1] = RiggedPartitionTypeB(nu[-1]) - ClonableArray.__init__(self, parent, nu) def check(self): @@ -524,9 +517,9 @@ def e(self, a): -1[ ]-1 """ - if a not in self.parent()._rc_index: + if a not in self.parent()._rc_index_inverse: raise ValueError("{} is not in the index set".format(a)) - a = self.parent()._rc_index.index(a) + a = self.parent()._rc_index_inverse[a] new_list = self[a][:] new_vac_nums = self[a].vacancy_numbers[:] @@ -594,7 +587,7 @@ def e(self, a): # Update that row's vacancy number ret_RC[a].vacancy_numbers[rigging_index] = \ self.parent()._calc_vacancy_number(nu, a, nu[a][rigging_index]) - return(ret_RC) + return ret_RC def _generate_partition_e(self, a, b, k): r""" @@ -623,12 +616,12 @@ def _generate_partition_e(self, a, b, k): if not self.parent()._cartan_matrix[a,b]: return self[b] - new_list = self[b][:] + new_list = self[b]._list new_vac_nums = self[b].vacancy_numbers[:] new_rigging = self[b].rigging[:] # Update the vacancy numbers and the rigging - value = self.parent()._cartan_matrix[a,b] + value = self.parent()._cartan_matrix[b,a] for i in range(len(new_vac_nums)): if new_list[i] < k: break @@ -672,9 +665,9 @@ def f(self, a): (/) """ - if a not in self.parent()._rc_index: + if a not in self.parent()._rc_index_inverse: raise ValueError("{} is not in the index set".format(a)) - a = self.parent()._rc_index.index(a) + a = self.parent()._rc_index_inverse[a] new_list = self[a][:] new_vac_nums = self[a].vacancy_numbers[:] @@ -766,12 +759,12 @@ def _generate_partition_f(self, a, b, k): if not self.parent()._cartan_matrix[a,b]: return self[b] - new_list = self[b][:] + new_list = self[b]._list new_vac_nums = self[b].vacancy_numbers[:] new_rigging = self[b].rigging[:] # Update the vacancy numbers and the rigging - value = self.parent()._cartan_matrix[a,b] + value = self.parent()._cartan_matrix[b,a] for i in range(len(new_vac_nums)): if new_list[i] <= k: break @@ -800,7 +793,7 @@ def epsilon(self, a): [0 1] [0 2] """ - a = self.parent()._rc_index.index(a) + a = self.parent()._rc_index_inverse[a] if not self[a]: return ZZ.zero() return Integer(-min(0, min(self[a].rigging))) @@ -824,7 +817,7 @@ def phi(self, a): [0 2] [1 1] """ - a = self.parent()._rc_index.index(a) + a = self.parent()._rc_index_inverse[a] p_inf = self.parent()._calc_vacancy_number(self, a, float("inf")) if not self[a]: return Integer(p_inf) @@ -859,8 +852,8 @@ def vacancy_number(self, a, i): sage: x.vacancy_number(2,2) 1 """ - a = self.cartan_type().classical().index_set().index(a) - return self.parent()._calc_vacancy_number(self.nu(), a, i) + a = self.parent()._rc_index_inverse[a] + return self.parent()._calc_vacancy_number(self, a, i) def partition_rigging_lists(self): """ @@ -894,7 +887,8 @@ class RCNonSimplyLacedElement(RiggedConfigurationElement): TESTS:: - sage: RC = crystals.infinity.RiggedConfigurations(['C',2,1]) + sage: vct = CartanType(['C',2,1]).as_folding() + sage: RC = crystals.infinity.RiggedConfigurations(vct) sage: elt = RC.module_generators[0].f_string([1,0,2,2,0,1]); elt -2[ ][ ]-1 @@ -942,7 +936,8 @@ def e(self, a): EXAMPLES:: - sage: RC = crystals.infinity.RiggedConfigurations(['C',2,1]) + sage: vct = CartanType(['C',2,1]).as_folding() + sage: RC = crystals.infinity.RiggedConfigurations(vct) sage: elt = RC(partition_list=[[2],[1,1],[2]], rigging_list=[[-1],[-1,-1],[-1]]) sage: ascii_art(elt.e(0)) 0[ ]0 -2[ ]-1 -2[ ][ ]-1 @@ -977,7 +972,8 @@ def f(self, a): EXAMPLES:: - sage: RC = crystals.infinity.RiggedConfigurations(['C',2,1]) + sage: vct = CartanType(['C',2,1]).as_folding() + sage: RC = crystals.infinity.RiggedConfigurations(vct) sage: elt = RC(partition_list=[[2],[1,1],[2]], rigging_list=[[-1],[-1,-1],[-1]]) sage: ascii_art(elt.f(0)) -4[ ][ ][ ]-2 -2[ ]-1 -2[ ][ ]-1 @@ -1034,7 +1030,7 @@ def check(self): sage: elt = RC(partition_list=[[1,1],[1],[2]]) sage: elt.check() """ - for partition in self: + for a, partition in enumerate(self): for i, vac_num in enumerate(partition.vacancy_numbers): if vac_num < partition.rigging[i]: raise ValueError("rigging can be at most the vacancy number") @@ -1114,7 +1110,8 @@ class RCHWNonSimplyLacedElement(RCNonSimplyLacedElement): TESTS:: sage: La = RootSystem(['C',2,1]).weight_lattice(extended=True).fundamental_weights() - sage: RC = crystals.RiggedConfigurations(['C',2,1], La[0]) + sage: vct = CartanType(['C',2,1]).as_folding() + sage: RC = crystals.RiggedConfigurations(vct, La[0]) sage: elt = RC(partition_list=[[1,1],[2],[2]]); ascii_art(elt) -1[ ]-1 2[ ][ ]2 -2[ ][ ]-2 -1[ ]-1 @@ -1128,7 +1125,8 @@ def check(self): TESTS:: sage: La = RootSystem(['C',2,1]).weight_lattice(extended=True).fundamental_weights() - sage: RC = crystals.RiggedConfigurations(['C',2,1], La[0]) + sage: vct = CartanType(['C',2,1]).as_folding() + sage: RC = crystals.RiggedConfigurations(vct, La[0]) sage: elt = RC(partition_list=[[1,1],[2],[2]]) sage: elt.check() """ @@ -1152,7 +1150,8 @@ def f(self, a): EXAMPLES:: sage: La = RootSystem(['C',2,1]).weight_lattice(extended=True).fundamental_weights() - sage: RC = crystals.RiggedConfigurations(['C',2,1], La[0]) + sage: vct = CartanType(['C',2,1]).as_folding() + sage: RC = crystals.RiggedConfigurations(vct, La[0]) sage: elt = RC(partition_list=[[1,1],[2],[2]]) sage: elt.f(0) sage: ascii_art(elt.f(1)) @@ -1172,7 +1171,8 @@ def weight(self): EXAMPLES:: sage: La = RootSystem(['C',2,1]).weight_lattice(extended=True).fundamental_weights() - sage: B = crystals.RiggedConfigurations(['C',2,1], La[0]) + sage: vct = CartanType(['C',2,1]).as_folding() + sage: B = crystals.RiggedConfigurations(vct, La[0]) sage: mg = B.module_generators[0] sage: mg.f_string([0,1,2]).weight() 2*Lambda[1] - Lambda[2] - delta @@ -1267,6 +1267,11 @@ def __init__(self, parent, rigged_partitions=[], **options): ClonableArray.__init__(self, parent, nu) return RiggedConfigurationElement.__init__(self, parent, rigged_partitions, n=n, **options) + # Special display case + if parent.cartan_type().type() == 'B': + self._set_mutable() + self[-1] = RiggedPartitionTypeB(self[-1]) + self.set_immutable() def check(self): """ @@ -1503,8 +1508,7 @@ def classical_weight(self): alpha = WLR.simple_roots() rc_index = self.parent()._rc_index for a, nu in enumerate(self): - a = rc_index[a] - wt -= sum(nu) * alpha[a] + wt -= sum(nu) * alpha[rc_index[a]] return wt @@ -2272,7 +2276,7 @@ def epsilon(self, a): if a == self.parent()._cartan_type.special_node(): return self.to_tensor_product_of_kirillov_reshetikhin_tableaux().epsilon(a) - a = self.parent()._rc_index.index(a) + a = self.parent()._rc_index_inverse[a] if not self[a]: epsilon = 0 else: @@ -2305,7 +2309,7 @@ def phi(self, a): if a == self.parent()._cartan_type.special_node(): return self.to_tensor_product_of_kirillov_reshetikhin_tableaux().phi(a) - a = self.parent()._rc_index.index(a) + a = self.parent()._rc_index_inverse[a] p_inf = self.parent()._calc_vacancy_number(self, a, float("inf")) if not self[a]: phi = p_inf diff --git a/src/sage/combinat/rigged_configurations/rigged_configurations.py b/src/sage/combinat/rigged_configurations/rigged_configurations.py index 61dd6842f56..ef0f8778b61 100644 --- a/src/sage/combinat/rigged_configurations/rigged_configurations.py +++ b/src/sage/combinat/rigged_configurations/rigged_configurations.py @@ -381,6 +381,7 @@ def __init__(self, cartan_type, B): self.dims = B cl = cartan_type.classical() self._rc_index = cl.index_set() + self._rc_index_inverse = {i: ii for ii,i in enumerate(self._rc_index)} # We store the Cartan matrix for the vacancy number calculations for speed self._cartan_matrix = cl.cartan_matrix() Parent.__init__(self, category=KirillovReshetikhinCrystals().TensorProducts()) From 5f538803344feb1d8cac9d4332a83eca5dd88bc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 13 May 2017 22:18:09 +0200 Subject: [PATCH 331/452] some care for SEEALSO (various typos) --- src/sage/combinat/sf/monomial.py | 4 +++- src/sage/databases/findstat.py | 15 +++++++------ src/sage/functions/log.py | 2 +- src/sage/matrix/matrix1.pyx | 22 +++++++++++-------- src/sage/matrix/matrix_integer_sparse.pyx | 4 +++- src/sage/matrix/matrix_space.py | 2 +- src/sage/matroids/matroid.pyx | 2 +- src/sage/rings/integer.pyx | 8 +++---- .../multi_polynomial_libsingular.pyx | 9 +++++--- 9 files changed, 40 insertions(+), 28 deletions(-) diff --git a/src/sage/combinat/sf/monomial.py b/src/sage/combinat/sf/monomial.py index 02c6f39e462..e42fb4afdeb 100644 --- a/src/sage/combinat/sf/monomial.py +++ b/src/sage/combinat/sf/monomial.py @@ -219,7 +219,9 @@ def from_polynomial_exp(self, p): sage: m.from_polynomial_exp(f) 3*m[4] + 2*m[5, 5, 5, 3, 1, 1] - ..SEEALSO:: :func:`Partition`, :meth:`Partition.to_exp` + .. SEEALSO:: + + :func:`Partition`, :meth:`Partition.to_exp` """ assert self.base_ring() == p.parent().base_ring() return self.sum_of_terms((Partition(exp=monomial), coeff) diff --git a/src/sage/databases/findstat.py b/src/sage/databases/findstat.py index aec5a624702..e82426939a8 100644 --- a/src/sage/databases/findstat.py +++ b/src/sage/databases/findstat.py @@ -844,7 +844,8 @@ def __repr__(self): raise ValueError("FindStatStatistic._query should be either 'ID' or 'data', but is %s. This should not happen. Please send an email to the developers." %self._query) def __eq__(self, other): - """Return ``True`` if ``self`` is equal to ``other`` and ``False`` + """ + Return ``True`` if ``self`` is equal to ``other`` and ``False`` otherwise. INPUT: @@ -897,7 +898,8 @@ def __eq__(self, other): return False def __ne__(self, other): - """Determine whether ``other`` is a different query. + """ + Determine whether ``other`` is a different query. INPUT: @@ -908,9 +910,9 @@ def __ne__(self, other): A boolean. - SEEALSO: + .. SEEALSO:: - :meth:`__eq__` + :meth:`__eq__` EXAMPLES:: @@ -1853,10 +1855,9 @@ class FindStatCollection(Element): sage: FindStatCollection(DyckWords(2)) # optional -- internet Cc0005: Dyck paths - SEEALSO: - - :class:`FindStatCollections` + .. SEEALSO:: + :class:`FindStatCollections` """ @staticmethod def __classcall_private__(cls, entry): diff --git a/src/sage/functions/log.py b/src/sage/functions/log.py index c08a2b5a09d..acbb768c1ce 100644 --- a/src/sage/functions/log.py +++ b/src/sage/functions/log.py @@ -877,7 +877,7 @@ def __init__(self): sage: integrate(1/sqrt(1+x^3),x,algorithm='sympy') 1/3*x*hypergeometric((1/3, 1/2), (4/3,), -x^3)*gamma(1/3)/gamma(4/3) - SEEALSO: + .. SEEALSO:: `Examples in Sympy documentation `_, `Sympy source code of exp_polar `_ diff --git a/src/sage/matrix/matrix1.pyx b/src/sage/matrix/matrix1.pyx index 31ad8b27ee5..b9c35be1aed 100644 --- a/src/sage/matrix/matrix1.pyx +++ b/src/sage/matrix/matrix1.pyx @@ -1724,8 +1724,10 @@ cdef class Matrix(matrix0.Matrix): * ``dcols`` - list of indices of columns to be deleted from self. * ``check`` - checks whether any index in ``dcols`` is out of range. Defaults to ``True``. - SEE ALSO: - The methods :meth:`delete_rows` and :meth:`matrix_from_columns` are related. + .. SEEALSO:: + + The methods :meth:`delete_rows` and :meth:`matrix_from_columns` + are related. EXAMPLES:: @@ -1824,8 +1826,10 @@ cdef class Matrix(matrix0.Matrix): * ``drows`` - list of indices of rows to be deleted from self. * ``check`` - checks whether any index in ``drows`` is out of range. Defaults to ``True``. - SEE ALSO: - The methods :meth:`delete_columns` and :meth:`matrix_from_rows` are related. + .. SEEALSO:: + + The methods :meth:`delete_columns` and :meth:`matrix_from_rows` + are related. EXAMPLES:: @@ -1968,12 +1972,12 @@ cdef class Matrix(matrix0.Matrix): take. If not provided, take all rows below and all columns to the right of the starting entry. - SEE ALSO: + .. SEEALSO:: - The functions :func:`matrix_from_rows`, - :func:`matrix_from_columns`, and - :func:`matrix_from_rows_and_columns` allow one to select - arbitrary subsets of rows and/or columns. + The functions :func:`matrix_from_rows`, + :func:`matrix_from_columns`, and + :func:`matrix_from_rows_and_columns` allow one to select + arbitrary subsets of rows and/or columns. EXAMPLES: diff --git a/src/sage/matrix/matrix_integer_sparse.pyx b/src/sage/matrix/matrix_integer_sparse.pyx index dba6f9ac643..bd4e0a00b5c 100644 --- a/src/sage/matrix/matrix_integer_sparse.pyx +++ b/src/sage/matrix/matrix_integer_sparse.pyx @@ -537,7 +537,9 @@ cdef class Matrix_integer_sparse(Matrix_sparse): sage: M.elementary_divisors() [1, 1, 6] - ..SEEALSO:: :meth:`smith_form` + .. SEEALSO:: + + :meth:`smith_form` """ return self.dense_matrix().elementary_divisors(algorithm=algorithm) diff --git a/src/sage/matrix/matrix_space.py b/src/sage/matrix/matrix_space.py index 9fc0f8faf33..8b40094892b 100644 --- a/src/sage/matrix/matrix_space.py +++ b/src/sage/matrix/matrix_space.py @@ -985,7 +985,7 @@ def __getitem__(self, x): should eventually be implemented in the corresponding category rather than here.) - ..SEEALSO:: + .. SEEALSO:: :meth:`sage.categories.rings.Rings.ParentMethod.__getitem__`, :meth:`sage.structure.parent.Parent.__getitem__` diff --git a/src/sage/matroids/matroid.pyx b/src/sage/matroids/matroid.pyx index 225af7d523b..ae2b4c14a5a 100644 --- a/src/sage/matroids/matroid.pyx +++ b/src/sage/matroids/matroid.pyx @@ -3334,7 +3334,7 @@ cdef class Matroid(SageObject): Boolean. - ..SEEALSO:: + .. SEEALSO:: :meth:`M.is_isomorphism() ` diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index 63fc39a1662..9178028c319 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -1235,11 +1235,11 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): This method just calls :func:`digits` with ``base=2``. - SEE ALSO: + .. SEEALSO:: - :func:`nbits` (number of bits; a faster way to compute - ``len(x.bits())``; and :func:`binary`, which returns a string in - more-familiar notation. + :func:`nbits` (number of bits; a faster way to compute + ``len(x.bits())``; and :func:`binary`, which returns a string in + more-familiar notation. EXAMPLES:: diff --git a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx index 656acc95ce1..cf5596875aa 100644 --- a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx +++ b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx @@ -2859,10 +2859,13 @@ cdef class MPolynomial_libsingular(sage.rings.polynomial.multi_polynomial.MPolyn - ``mon`` - a monomial OUTPUT: - coefficient in base ring - SEE ALSO: - For coefficients in a base ring of fewer variables, look at ``coefficient``. + coefficient in base ring + + .. SEEALSO:: + + For coefficients in a base ring of fewer variables, + look at ``coefficient``. EXAMPLES:: From 90cda5ec752c76051b77536dc53560fd0645700e Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sat, 13 May 2017 17:04:23 -0500 Subject: [PATCH 332/452] Iterate over the weight's orbit as we may not need the full list. --- src/sage/combinat/crystals/littelmann_path.py | 10 +++--- .../root_system/root_lattice_realizations.py | 31 ++++++++++++++----- 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/sage/combinat/crystals/littelmann_path.py b/src/sage/combinat/crystals/littelmann_path.py index 100b85c2c5d..27556e808da 100644 --- a/src/sage/combinat/crystals/littelmann_path.py +++ b/src/sage/combinat/crystals/littelmann_path.py @@ -934,11 +934,13 @@ def scalar_factors(self): s = 0 for c in self.value: supp = c.support() - if len(supp) > 0: - for w in weight.orbit(): - i = supp[0] + if supp: + i = supp[0] + for w in weight._orbit_iter(): # Check whether the vectors c and w are positive scalar multiples of each other - if i in w.support() and c[i]*w[i] > 0 and c[i]*w == w[i]*c: + # If i is not in the support of w, then the first + # product is 0 + if c[i] * w[i] > 0 and c[i] * w == w[i] * c: s += c[i] / w[i] l += [s] break diff --git a/src/sage/combinat/root_system/root_lattice_realizations.py b/src/sage/combinat/root_system/root_lattice_realizations.py index b4b1429e127..2886af214e2 100644 --- a/src/sage/combinat/root_system/root_lattice_realizations.py +++ b/src/sage/combinat/root_system/root_lattice_realizations.py @@ -3424,18 +3424,37 @@ def simple_reflections(self): """ return [s(self) for s in self.parent().simple_reflections()] + def _orbit_iter(self): + """ + Iterate the orbit of ``self`` under the action of the Weyl group. + + Call this method when the orbit just needs to be iterated over. + + EXAMPLES:: + + sage: L = RootSystem(["A", 2]).ambient_lattice() + sage: sorted(L.rho()._orbit_iter()) # the output order is not specified + [(1, 2, 0), (1, 0, 2), (2, 1, 0), + (2, 0, 1), (0, 1, 2), (0, 2, 1)] + """ + R = RecursivelyEnumeratedSet([self], attrcall('simple_reflections'), + structure=None, enumeration='breadth') + return iter(R) + def orbit(self): r""" - The orbit of self under the action of the Weyl group + The orbit of ``self`` under the action of the Weyl group. EXAMPLES: - `\rho` is a regular element whose orbit is in bijection with the Weyl group. - In particular, it as 6 elements for the symmetric group `S_3`:: + `\rho` is a regular element whose orbit is in bijection + with the Weyl group. In particular, it as 6 elements for + the symmetric group `S_3`:: sage: L = RootSystem(["A", 2]).ambient_lattice() sage: sorted(L.rho().orbit()) # the output order is not specified - [(1, 2, 0), (1, 0, 2), (2, 1, 0), (2, 0, 1), (0, 1, 2), (0, 2, 1)] + [(1, 2, 0), (1, 0, 2), (2, 1, 0), + (2, 0, 1), (0, 1, 2), (0, 2, 1)] sage: L = RootSystem(["A", 3]).weight_lattice() sage: len(L.rho().orbit()) @@ -3445,9 +3464,7 @@ def orbit(self): sage: len(L.fundamental_weights()[2].orbit()) 6 """ - R = RecursivelyEnumeratedSet([self], attrcall('simple_reflections'), - structure=None, enumeration='breadth') - return list(R) + return list(self._orbit_iter) ########################################################################## # From 7e797993358f880fbbbf48bad045cd7dd3590548 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 14 May 2017 08:34:16 +0200 Subject: [PATCH 333/452] trac 22987 oops, missing import --- src/sage/modules/free_module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/modules/free_module.py b/src/sage/modules/free_module.py index 83a7a081772..638b306f958 100644 --- a/src/sage/modules/free_module.py +++ b/src/sage/modules/free_module.py @@ -1179,7 +1179,7 @@ def cardinality(self): 1 """ if not self.rank(): - return ZZ.one() + return sage.rings.integer.Integer(1) return self.base_ring().cardinality() ** self.rank() __len__ = cardinality # for backward compatibility From eb162f5edfe9ee833713ea9b0177736febe5c37b Mon Sep 17 00:00:00 2001 From: Marcelo Forets Date: Sun, 14 May 2017 08:57:20 +0200 Subject: [PATCH 334/452] standarization of SEEALSO blocks --- src/sage/calculus/calculus.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/sage/calculus/calculus.py b/src/sage/calculus/calculus.py index 6c8bf2be8ff..62c424afbc0 100644 --- a/src/sage/calculus/calculus.py +++ b/src/sage/calculus/calculus.py @@ -1299,8 +1299,9 @@ def laplace(ex, t, s, algorithm='maxima'): are auxiliary convergence conditions. .. SEEALSO:: + :func:`inverse_laplace` - + EXAMPLES: We compute a few Laplace transforms:: @@ -1498,8 +1499,9 @@ def inverse_laplace(ex, s, t, algorithm='maxima'): - ``'giac'`` - use Giac .. SEEALSO:: - :func:`laplace` - + + :func:`laplace + EXAMPLES:: sage: var('w, m') From 88aced297016a6e63c7f696ddf490f86cbb1bf47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 14 May 2017 09:10:17 +0200 Subject: [PATCH 335/452] change catalan_number behaviour at n=-1 --- src/sage/combinat/combinat.py | 41 +++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/sage/combinat/combinat.py b/src/sage/combinat/combinat.py index 75f73dda864..3c355692d00 100644 --- a/src/sage/combinat/combinat.py +++ b/src/sage/combinat/combinat.py @@ -410,11 +410,12 @@ def bell_number(n, algorithm='flint', **options): raise ValueError("unknown algorithm %r" % algorithm) + def catalan_number(n): r""" Return the `n`-th Catalan number. - Catalan numbers: The `n`-th Catalan number is given + The `n`-th Catalan number is given directly in terms of binomial coefficients by .. MATH:: @@ -422,26 +423,23 @@ def catalan_number(n): C_n = \frac{1}{n+1}\binom{2n}{n} = \frac{(2n)!}{(n+1)!\,n!} \qquad\mbox{ for }\quad n\ge 0. - - Consider the set `S = \{ 1, ..., n \}`. A noncrossing partition of `S` is a partition in which no two blocks "cross" each other, i.e., if `a` and `b` belong to one block and `x` and `y` to another, they are not arranged in the order `axby`. `C_n` is the number of noncrossing partitions of the set - `S`. There are many other interpretations (see - REFERENCES). + `S`. There are many other interpretations (see REFERENCES). - When `n=-1`, this function raises a ZeroDivisionError; for + When `n=-1`, this function returns the limit value `-1/2`. For other `n<0` it returns `0`. INPUT: - - ``n`` - integer - - OUTPUT: integer + - ``n`` -- integer + OUTPUT: + integer EXAMPLES:: @@ -449,23 +447,24 @@ def catalan_number(n): [1, 1, 2, 5, 14, 42, 132] sage: taylor((-1/2)*sqrt(1 - 4*x^2), x, 0, 15) 132*x^14 + 42*x^12 + 14*x^10 + 5*x^8 + 2*x^6 + x^4 + x^2 - 1/2 - sage: [catalan_number(i) for i in range(-7,7) if i != -1] - [0, 0, 0, 0, 0, 0, 1, 1, 2, 5, 14, 42, 132] - sage: catalan_number(-1) - Traceback (most recent call last): - ... - ZeroDivisionError + sage: [catalan_number(i) for i in range(-7,7)] + [0, 0, 0, 0, 0, 0, -1/2, 1, 1, 2, 5, 14, 42, 132] sage: [catalan_number(n).mod(2) for n in range(16)] [1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1] REFERENCES: - - http://en.wikipedia.org/wiki/Catalan_number + - :wikipedia:`Catalan_number` - http://www-history.mcs.st-andrews.ac.uk/~history/Miscellaneous/CatalanNumbers/catalan.html """ n = ZZ(n) - return binomial(2*n,n).divide_knowing_divisible_by(n+1) + if n < -1: + return ZZ.zero() + if n == -1: + return QQ((-1, 2)) + return binomial(2 * n, n).divide_knowing_divisible_by(n + 1) + def euler_number(n, algorithm='flint'): """ @@ -626,7 +625,9 @@ def lucas_number1(n, P, Q): Can you use Sage to find a counterexample to the conjecture? """ - n = ZZ(n); P = QQ(P); Q = QQ(Q) + n = ZZ(n) + P = QQ(P) + Q = QQ(Q) from sage.libs.gap.libgap import libgap return libgap.Lucas(P, Q, n)[0].sage() @@ -674,7 +675,9 @@ def lucas_number2(n, P, Q): sage: [lucas_number2(n,1,-1) for n in range(10)] [2, 1, 3, 4, 7, 11, 18, 29, 47, 76] """ - n = ZZ(n); P = QQ(P); Q = QQ(Q) + n = ZZ(n) + P = QQ(P) + Q = QQ(Q) from sage.libs.gap.libgap import libgap return libgap.Lucas(P, Q, n)[1].sage() From e7f82ed1ce530ac37aaec7b645bf8328fd31f066 Mon Sep 17 00:00:00 2001 From: Marcelo Forets Date: Sun, 14 May 2017 10:06:14 +0200 Subject: [PATCH 336/452] add dummy ilaplace --- src/sage/calculus/calculus.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/sage/calculus/calculus.py b/src/sage/calculus/calculus.py index 62c424afbc0..12f55673810 100644 --- a/src/sage/calculus/calculus.py +++ b/src/sage/calculus/calculus.py @@ -1570,10 +1570,8 @@ def inverse_laplace(ex, s, t, algorithm='maxima'): sage: n = var('n') sage: inverse_laplace(1/s^n, s, t, algorithm='giac') - Traceback (most recent call last): - ... - NotImplementedError: Unable to parse Giac output: ilaplace([s^(-n),s,t]) - + ilt(1/(s^n), t, s) + Try with Maxima:: sage: inverse_laplace(1/s^n, s, t, algorithm='maxima') @@ -1589,12 +1587,10 @@ def inverse_laplace(ex, s, t, algorithm='maxima'): sage: inverse_laplace(cos(s), s, t, algorithm='sympy') ilt(cos(s), t, s) - Testing unevaluated expression from Giac:: + Testing the same with Giac:: sage: inverse_laplace(cos(s), s, t, algorithm='giac') - Traceback (most recent call last): - ... - NotImplementedError: Unable to parse Giac output: ilaplace([cos(s),s,t]) + ilt(cos(s), t, s) """ if not isinstance(ex, Expression): ex = SR(ex) @@ -1621,7 +1617,10 @@ def inverse_laplace(ex, s, t, algorithm='maxima'): result = giac.invlaplace(ex, s, t) except TypeError: raise ValueError("Giac cannot make sense of: %s" % ex) - return result.sage() + if 'ilaplace' in format(result): + return dummy_inverse_laplace(ex, t, s) + else: + return result.sage() else: raise ValueError("Unknown algorithm: %s" % algorithm) From f3c9d15f97ebe44a4fa6fe83f3b56d62a34689ef Mon Sep 17 00:00:00 2001 From: Marcelo Forets Date: Sun, 14 May 2017 10:43:50 +0200 Subject: [PATCH 337/452] add one doctest --- src/sage/symbolic/integration/external.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/sage/symbolic/integration/external.py b/src/sage/symbolic/integration/external.py index 4ebd2dad19e..2b4a78bfcdf 100644 --- a/src/sage/symbolic/integration/external.py +++ b/src/sage/symbolic/integration/external.py @@ -142,6 +142,11 @@ def giac_integrator(expression, v, a=None, b=None): -cos(x) sage: giac_integrator(1/(x^2+6), x, -oo, oo) 1/6*sqrt(6)*pi + + TESTS:: + + sage: giac_integrator(e^(-x^2)*log(x), x) + integrate(e^(-x^2)*log(x), x) """ ex = expression._giac_() v = v._giac_() From 2bba41df3121f7c1b14f9bc072aae8893e8494c9 Mon Sep 17 00:00:00 2001 From: Marcelo Forets Date: Sun, 14 May 2017 11:46:56 +0200 Subject: [PATCH 338/452] parse result in giac_integrator --- src/sage/symbolic/integration/external.py | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/sage/symbolic/integration/external.py b/src/sage/symbolic/integration/external.py index 2b4a78bfcdf..0c2c5ba342c 100644 --- a/src/sage/symbolic/integration/external.py +++ b/src/sage/symbolic/integration/external.py @@ -149,9 +149,11 @@ def giac_integrator(expression, v, a=None, b=None): integrate(e^(-x^2)*log(x), x) """ ex = expression._giac_() - v = v._giac_() if a is None: - result = ex.integrate(v) + result = ex.integrate(v._giac_()) else: - result = ex.integrate(v, a._giac_(), b._giac_()) - return result._sage_() \ No newline at end of file + result = ex.integrate(v._giac_(), a._giac_(), b._giac_()) + if 'integrate' in format(result) or 'integration' in format(result): + return expression.integrate(v, a, b, hold=True) + else: + return result._sage_() From 7c393d7d7dc3eb62fb8061b9f4118e54a47228dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 14 May 2017 13:32:48 +0200 Subject: [PATCH 339/452] trac 22941 fixing syntax in calculus.py --- src/sage/calculus/calculus.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sage/calculus/calculus.py b/src/sage/calculus/calculus.py index 38a2ef71518..fadd5c437dc 100644 --- a/src/sage/calculus/calculus.py +++ b/src/sage/calculus/calculus.py @@ -2107,11 +2107,12 @@ def symbolic_expression_from_maxima_string(x, equals_sub=False, maxima=maxima): sage: sefms('%inf') +Infinity """ + global _syms syms = symbol_table.get('maxima', {}).copy() - if len(x) == 0: + if not len(x): raise RuntimeError("invalid symbolic expression -- ''") - maxima.set('_tmp_',x) + maxima.set('_tmp_', x) # This is inefficient since it so rarely is needed: #r = maxima._eval_line('listofvars(_tmp_);')[1:-1] @@ -2119,7 +2120,7 @@ def symbolic_expression_from_maxima_string(x, equals_sub=False, maxima=maxima): s = maxima._eval_line('_tmp_;') formal_functions = maxima_tick.findall(s) - if len(formal_functions) > 0: + if len(formal_functions): for X in formal_functions: try: syms[X[1:]] = _syms[X[1:]] @@ -2131,7 +2132,7 @@ def symbolic_expression_from_maxima_string(x, equals_sub=False, maxima=maxima): s = s.replace("'","") delayed_functions = maxima_qp.findall(s) - if len(delayed_functions) > 0: + if len(delayed_functions): for X in delayed_functions: if X == '?%at': # we will replace Maxima's "at" with symbolic evaluation, not an SFunction pass @@ -2202,7 +2203,6 @@ def symbolic_expression_from_maxima_string(x, equals_sub=False, maxima=maxima): # use a global flag so all expressions obtained via # evaluation of maxima code are assumed pre-simplified is_simplified = True - global _syms _syms = symbol_table['functions'].copy() try: global _augmented_syms From df4c1504395131fc1948fedf52934718d0e667fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 14 May 2017 13:41:15 +0200 Subject: [PATCH 340/452] trac 22890 better doc --- src/doc/en/thematic_tutorials/coercion_and_categories.rst | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/doc/en/thematic_tutorials/coercion_and_categories.rst b/src/doc/en/thematic_tutorials/coercion_and_categories.rst index 102f90c3fd6..8cbbe2ea643 100644 --- a/src/doc/en/thematic_tutorials/coercion_and_categories.rst +++ b/src/doc/en/thematic_tutorials/coercion_and_categories.rst @@ -308,9 +308,12 @@ considerations: etc. **We do not override the default double underscore __add__, __mul__**, since otherwise, we could not use Sage's coercion model. -- Comparisons can be implemented using ``_richcmp_`` (recommended) or +- Comparisons can be implemented using ``_richcmp_`` or ``_cmp_``. This automatically makes the relational operators like - ``==`` and ``<`` work. + ``==`` and ``<`` work. **Beware**: in these methods, calling the + Python2-only ``cmp`` function should be avoided for compatibility + with Python3. You can use instead the ``richcmp`` function provided + by sage. Note that either ``_cmp_`` or ``_richcmp_`` should be provided, since otherwise comparison does not work:: From 4c30fb1dafd693fdb259cf06cc7324d637347bfb Mon Sep 17 00:00:00 2001 From: Daniel Krenn Date: Sun, 14 May 2017 14:48:10 +0200 Subject: [PATCH 341/452] Trac #22957: blanks, lambda (PEP8) --- src/sage/graphs/graph.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index 81c9e4dcbeb..38801c9271a 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -4376,7 +4376,11 @@ def matching(self, value_only=False, algorithm="Edmonds", """ self._scream_if_not_simple(allow_loops=True) from sage.rings.real_mpfr import RR - weight = lambda x: x if x in RR else 1 + def weight(x): + if x in RR: + return x + else: + return 1 if algorithm == "Edmonds": import networkx @@ -4404,15 +4408,15 @@ def matching(self, value_only=False, algorithm="Edmonds", # returns the weight of an edge considering it may not be # weighted ... p = MixedIntegerLinearProgram(maximization=True, solver=solver) - b = p.new_variable(binary = True) + b = p.new_variable(binary=True) if use_edge_labels: p.set_objective( - p.sum(weight(w) * b[min(u, v),max(u, v)] for u, v, w in g.edge_iterator())) + p.sum(weight(w) * b[min(u, v), max(u, v)] else: p.set_objective( - p.sum(b[min(u, v),max(u, v)] for u, v in g.edge_iterator(labels=False))) + p.sum(b[min(u, v), max(u, v)] # for any vertex v, there is at most one edge incident to v in # the maximum matching for v in g.vertex_iterator(): From 3bde4310febdd6bd3bb0b1d65b9056e40d14a306 Mon Sep 17 00:00:00 2001 From: Daniel Krenn Date: Sun, 14 May 2017 14:48:22 +0200 Subject: [PATCH 342/452] Trac #22957: more blanks --- src/sage/graphs/graph.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index 38801c9271a..182660ccf3e 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -4411,18 +4411,18 @@ def weight(x): b = p.new_variable(binary=True) if use_edge_labels: p.set_objective( - for u, v, w in g.edge_iterator())) p.sum(weight(w) * b[min(u, v), max(u, v)] + for u, v, w in g.edge_iterator())) else: p.set_objective( - for u, v in g.edge_iterator(labels=False))) p.sum(b[min(u, v), max(u, v)] + for u, v in g.edge_iterator(labels=False))) # for any vertex v, there is at most one edge incident to v in # the maximum matching for v in g.vertex_iterator(): p.add_constraint( p.sum(b[min(u, v),max(u, v)] - for u in g.neighbors(v)), max=1) + for u in g.neighbors(v)), max=1) if value_only: if use_edge_labels: return p.solve(objective_only=True, log=verbose) From 624f0e3a8ba1887b33efa3db1273f84fb8dc5444 Mon Sep 17 00:00:00 2001 From: Marcelo Forets Date: Sun, 14 May 2017 17:01:19 +0200 Subject: [PATCH 343/452] error func mathematica conversion --- src/sage/functions/other.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sage/functions/other.py b/src/sage/functions/other.py index dc13c3953e7..1005b05db3f 100644 --- a/src/sage/functions/other.py +++ b/src/sage/functions/other.py @@ -163,7 +163,8 @@ def __init__(self): BuiltinFunction.__init__(self, "erf", latex_name=r"\text{erf}", conversions=dict(maxima='erf', sympy='erf', - fricas='erf')) + fricas='erf', + mathematica='Erf')) def _eval_(self, x): """ From 83c1dfc948b2b70bbba60b9db5e48bf9b633461e Mon Sep 17 00:00:00 2001 From: Marcelo Forets Date: Sun, 14 May 2017 17:10:10 +0200 Subject: [PATCH 344/452] use mathematica symbols table --- src/sage/symbolic/integration/external.py | 47 ++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/src/sage/symbolic/integration/external.py b/src/sage/symbolic/integration/external.py index 4ebd2dad19e..4841d78eef9 100644 --- a/src/sage/symbolic/integration/external.py +++ b/src/sage/symbolic/integration/external.py @@ -58,6 +58,11 @@ def mma_free_integrator(expression, v, a=None, b=None): sage: from sage.symbolic.integration.external import mma_free_integrator sage: mma_free_integrator(sin(x), x) # optional - internet -cos(x) + + TESTS:: + + sage: mma_free_integrator(exp(-x^2)*log(x), x) # optional - internet + 1/2*sqrt(pi)*erf(x)*log(x) - x*hypergeometric((1/2, 1/2), (3/2, 3/2), -x^2) """ import re # import compatible with py2 and py3 @@ -80,7 +85,47 @@ def mma_free_integrator(expression, v, a=None, b=None): page = re.sub("\s", "", page) mexpr = re.match(r".*Integrate.*==
(.*)

", page).groups()[0] try: - ans = SR(mexpr.lower().replace('[', '(').replace(']', ')')) + from sage.libs.pynac.pynac import symbol_table + from sage.interfaces.mathematica import _un_camel + from sage.symbolic.constants import constants_name_table as constants + from sage.calculus.calculus import symbolic_expression_from_string + from sage.calculus.calculus import _find_func as find_func + + expr = mexpr.replace('\n',' ').replace('\r', '') + expr = expr.replace('[', '(').replace(']', ')') + expr = expr.replace('{', '[').replace('}', ']') + lsymbols = symbol_table['mathematica'].copy() + autotrans = [str.lower, # Try it in lower case + _un_camel, # Convert `CamelCase` to `camel_case` + lambda x: x # Try the original name + ] + # Find the MMA funcs/vars/constants - they start with a letter. + # Exclude exponents (e.g. 'e8' from 4.e8) + p = re.compile('(? Date: Sun, 14 May 2017 18:45:30 +0100 Subject: [PATCH 345/452] remove obsolete test --- src/sage/combinat/designs/design_catalog.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/sage/combinat/designs/design_catalog.py b/src/sage/combinat/designs/design_catalog.py index 05b1cf26fac..3c838715308 100644 --- a/src/sage/combinat/designs/design_catalog.py +++ b/src/sage/combinat/designs/design_catalog.py @@ -71,11 +71,6 @@ .. [1] La Jolla Covering Repository, http://www.ccrwest.org/cover.html - -TESTS:: - - sage: 'absolute_import' in dir(designs) or 'deprecated_callable_import' in dir(designs) - False """ from __future__ import absolute_import from sage.combinat.designs.block_design import (BlockDesign, From f92d174b5e9890f57b14aeb9552cdb1399b268d4 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Sun, 14 May 2017 18:45:30 +0100 Subject: [PATCH 346/452] remove obsolete test --- src/sage/combinat/designs/design_catalog.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/sage/combinat/designs/design_catalog.py b/src/sage/combinat/designs/design_catalog.py index 05b1cf26fac..3c838715308 100644 --- a/src/sage/combinat/designs/design_catalog.py +++ b/src/sage/combinat/designs/design_catalog.py @@ -71,11 +71,6 @@ .. [1] La Jolla Covering Repository, http://www.ccrwest.org/cover.html - -TESTS:: - - sage: 'absolute_import' in dir(designs) or 'deprecated_callable_import' in dir(designs) - False """ from __future__ import absolute_import from sage.combinat.designs.block_design import (BlockDesign, From 017571be17eb4fe067314629c65a5f2b20989761 Mon Sep 17 00:00:00 2001 From: Marcelo Forets Date: Sun, 14 May 2017 21:10:12 +0200 Subject: [PATCH 347/452] add 2 mathematica conversions --- src/sage/functions/log.py | 3 ++- src/sage/functions/other.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/sage/functions/log.py b/src/sage/functions/log.py index c08a2b5a09d..ed6eb05fcf2 100644 --- a/src/sage/functions/log.py +++ b/src/sage/functions/log.py @@ -230,7 +230,8 @@ def __init__(self): polylog(1.414213562373095?, 3) """ GinacFunction.__init__(self, 'log', latex_name=r'\log', - conversions=dict(maxima='log', fricas='log')) + conversions=dict(maxima='log', fricas='log', + mathematica='Log')) def __call__(self, *args, **kwds): """ diff --git a/src/sage/functions/other.py b/src/sage/functions/other.py index 1005b05db3f..c1a29d6fb68 100644 --- a/src/sage/functions/other.py +++ b/src/sage/functions/other.py @@ -332,7 +332,8 @@ def __init__(self): (pi + e)*abs(x) """ GinacFunction.__init__(self, "abs", latex_name=r"\mathrm{abs}", - conversions=dict(sympy='Abs')) + conversions=dict(sympy='Abs', + mathematica='Abs')) abs = abs_symbolic = Function_abs() From ccc99a13ab67806d2d0f1fb7265bbf1cd1d76fff Mon Sep 17 00:00:00 2001 From: Marcelo Forets Date: Sun, 14 May 2017 21:14:08 +0200 Subject: [PATCH 348/452] tweak import as --- src/sage/symbolic/integration/external.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/symbolic/integration/external.py b/src/sage/symbolic/integration/external.py index 4841d78eef9..56a14589879 100644 --- a/src/sage/symbolic/integration/external.py +++ b/src/sage/symbolic/integration/external.py @@ -86,7 +86,7 @@ def mma_free_integrator(expression, v, a=None, b=None): mexpr = re.match(r".*Integrate.*==
(.*)

", page).groups()[0] try: from sage.libs.pynac.pynac import symbol_table - from sage.interfaces.mathematica import _un_camel + from sage.interfaces.mathematica import _un_camel as un_camel from sage.symbolic.constants import constants_name_table as constants from sage.calculus.calculus import symbolic_expression_from_string from sage.calculus.calculus import _find_func as find_func @@ -96,7 +96,7 @@ def mma_free_integrator(expression, v, a=None, b=None): expr = expr.replace('{', '[').replace('}', ']') lsymbols = symbol_table['mathematica'].copy() autotrans = [str.lower, # Try it in lower case - _un_camel, # Convert `CamelCase` to `camel_case` + un_camel, # Convert `CamelCase` to `camel_case` lambda x: x # Try the original name ] # Find the MMA funcs/vars/constants - they start with a letter. From 686f1cafe5918cad19db0afb6c9c8ae9a40ac4c8 Mon Sep 17 00:00:00 2001 From: Marcelo Forets Date: Sun, 14 May 2017 21:20:51 +0200 Subject: [PATCH 349/452] fix extra space in message --- src/sage/symbolic/integration/external.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sage/symbolic/integration/external.py b/src/sage/symbolic/integration/external.py index 56a14589879..1053b98e71f 100644 --- a/src/sage/symbolic/integration/external.py +++ b/src/sage/symbolic/integration/external.py @@ -117,8 +117,7 @@ def mma_free_integrator(expression, v, a=None, b=None): lsymbols[m.group()] = f break else: - raise NotImplementedError("Don't know a Sage equivalent \ - for Mathematica function '%s'." % m.group()) + raise NotImplementedError("Don't know a Sage equivalent for Mathematica function '%s'." % m.group()) # Check if Sage has an equivalent constant else: for t in autotrans: From a95ca7f209ee78d2e873210e939e16031dd47a62 Mon Sep 17 00:00:00 2001 From: Marcelo Forets Date: Mon, 15 May 2017 00:47:35 +0200 Subject: [PATCH 350/452] change decorator to typeerror exception --- src/sage/geometry/polyhedron/base.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index bb1a9fc755a..293f2852e58 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -2913,7 +2913,6 @@ def translation(self, displacement): new_ring = self.parent()._coerce_base_ring(displacement) return Polyhedron(vertices=new_vertices, rays=new_rays, lines=new_lines, base_ring=new_ring) - @coerce_binop def product(self, other): """ Return the Cartesian product. @@ -2946,7 +2945,20 @@ def product(self, other): A 1-dimensional polyhedron in ZZ^1 defined as the convex hull of 2 vertices sage: P1 * 2.0 A 1-dimensional polyhedron in RDF^1 defined as the convex hull of 2 vertices + + TESTS: + + Check that :trac:`15253` is fixed:: + + sage: polytopes.hypercube(1) * polytopes.hypercube(2) + A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 8 vertices """ + try: + new_ring = self.parent()._coerce_base_ring(other) + except TypeError: + raise TypeError("no common canonical parent for objects with parents: " + str(self.parent()) \ + + " and " + str(other.parent())) + new_vertices = [ list(x)+list(y) for x in self.vertex_generator() for y in other.vertex_generator()] new_rays = [] @@ -2961,7 +2973,7 @@ def product(self, other): for l in other.line_generator() ] ) return Polyhedron(vertices=new_vertices, rays=new_rays, lines=new_lines, - base_ring=self.parent()._coerce_base_ring(other)) + base_ring=new_ring) _mul_ = product From 1ba3103e52ff57ae321b3241a5bcbf9337b6df65 Mon Sep 17 00:00:00 2001 From: Daniel Krenn Date: Mon, 15 May 2017 10:35:22 +0200 Subject: [PATCH 351/452] Trac #19838: add doctest showing that issue was fixed --- src/sage/rings/real_arb.pyx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sage/rings/real_arb.pyx b/src/sage/rings/real_arb.pyx index 9a2fe328ed4..66979c78ce9 100644 --- a/src/sage/rings/real_arb.pyx +++ b/src/sage/rings/real_arb.pyx @@ -2957,6 +2957,8 @@ cdef class RealBall(RingElement): [1.098612288668110 +/- 6.63e-16] sage: RBF(3).log(2) [1.584962500721156 +/- 7.53e-16] + sage: log(RBF(5), 2) + [2.32192809488736 +/- 3.04e-15] sage: RBF(-1/3).log() nan From c0abf591cc677f0c3ab4f8bc24c1c143a2ad8543 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 15 May 2017 13:45:10 +0200 Subject: [PATCH 352/452] add a method to remove bounds of posets --- src/sage/combinat/posets/posets.py | 47 ++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index 48350ae59a9..31a81969e60 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -4850,6 +4850,53 @@ def with_bounds(self, labels=('bottom', 'top')): return constructor(D) + def without_bounds(self): + """ + Return the poset without its top and bottom elements. + + This is useful as an input for the method :meth:`order_complex`. + + If there is either no top or no bottom elements, this + raises a ``TypeError``. + + EXAMPLES:: + + sage: P = posets.PentagonPoset() + sage: Q = P.without_bounds(); Q + Finite poset containing 3 elements + sage: Q.cover_relations() + [[2, 3]] + + sage: P = posets.DiamondPoset(5) + sage: Q = P.without_bounds(); Q + Finite poset containing 3 elements + sage: Q.cover_relations() + [] + + TESTS:: + + sage: P = Poset({1:[2],3:[2,4]}) + sage: P.without_bounds() + Traceback (most recent call last): + ... + TypeError: the poset is missing either top or bottom + + sage: P = Poset({1:[]}) + sage: P.without_bounds() + Finite poset containing 0 elements + + sage: P = Poset({}) + sage: P.without_bounds() + Traceback (most recent call last): + ... + TypeError: the poset is missing either top or bottom + """ + if self.is_bounded(): + top = self.top() + bottom = self.bottom() + return self.subposet(u for u in self if not u in (top, bottom)) + raise TypeError('the poset is missing either top or bottom') + def relabel(self, relabeling=None): r""" Return a copy of this poset with its elements relabeled. From 6fc568145929ced10abd60ce0de67bc0c567b2eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 15 May 2017 13:54:48 +0200 Subject: [PATCH 353/452] trac 23003 adding crosslinks --- src/sage/combinat/posets/posets.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index 31a81969e60..588eb9fc36e 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -104,6 +104,7 @@ :meth:`~FinitePoset.ordinal_product` | Return the ordinal product of the poset with other poset. :meth:`~FinitePoset.star_product` | Return the star product of the poset with other poset. :meth:`~FinitePoset.with_bounds` | Return the poset with bottom and top element adjoined. + :meth:`~FinitePoset.without_bounds` | Return the poset with bottom and top element removed. :meth:`~FinitePoset.dual` | Return the dual of the poset. :meth:`~FinitePoset.completion_by_cuts` | Return the Dedekind-MacNeille completion of the poset. :meth:`~FinitePoset.intervals_poset` | Return the poset of intervals of the poset. @@ -4726,6 +4727,10 @@ def with_bounds(self, labels=('bottom', 'top')): ``'top'``. Either of them can be ``None``, and then a new bottom or top element will not be added. + .. SEEALSO:: + + :meth:`without_bounds` for the reverse operation + EXAMPLES:: sage: V = Poset({0: [1, 2]}) @@ -4859,6 +4864,10 @@ def without_bounds(self): If there is either no top or no bottom elements, this raises a ``TypeError``. + .. SEEALSO:: + + :meth:`with_bounds` for the reverse operation + EXAMPLES:: sage: P = posets.PentagonPoset() From 6bab78dce18165fa388bc5b24920281f8ce0dc95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 15 May 2017 13:56:46 +0200 Subject: [PATCH 354/452] trac 23003 a typo --- src/sage/combinat/posets/posets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index 588eb9fc36e..73324ff2356 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -4861,7 +4861,7 @@ def without_bounds(self): This is useful as an input for the method :meth:`order_complex`. - If there is either no top or no bottom elements, this + If there is either no top or no bottom element, this raises a ``TypeError``. .. SEEALSO:: From a6ac3d675022c7d78781bc357bb13dceb50d2021 Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Mon, 15 May 2017 17:16:41 +0200 Subject: [PATCH 355/452] 23001: is_NaN for elements of CC, CDF, CIF --- src/sage/rings/complex_double.pyx | 15 +++++++++++++++ src/sage/rings/complex_interval.pyx | 15 +++++++++++++++ src/sage/rings/complex_number.pyx | 15 +++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/src/sage/rings/complex_double.pyx b/src/sage/rings/complex_double.pyx index 51a0b20c295..2595e1515bb 100644 --- a/src/sage/rings/complex_double.pyx +++ b/src/sage/rings/complex_double.pyx @@ -1572,6 +1572,21 @@ cdef class ComplexDoubleElement(FieldElement): """ return self.real().is_infinity() or self.imag().is_infinity() + def is_NaN(self): + r""" + Check if ``self`` is not-a-number. + + EXAMPLES:: + + sage: CDF(1, 2).is_NaN() + False + sage: CDF(NaN).is_NaN() + True + sage: (1/CDF(0, 0)).is_NaN() + True + """ + return self.real().is_NaN() or self.imag().is_NaN() + def _pow_(self, ComplexDoubleElement a): """ The function returns the complex number `z` raised to the diff --git a/src/sage/rings/complex_interval.pyx b/src/sage/rings/complex_interval.pyx index ad1d47bf848..c0b40e11ff7 100644 --- a/src/sage/rings/complex_interval.pyx +++ b/src/sage/rings/complex_interval.pyx @@ -1839,6 +1839,21 @@ cdef class ComplexIntervalFieldElement(sage.structure.element.FieldElement): """ return True + def is_NaN(self): + r""" + Return ``True`` if this is not-a-number. + + EXAMPLES:: + + sage: CIF(2, 1).is_NaN() + False + sage: CIF(NaN).is_NaN() + True + sage: (1 / CIF(0, 0)).is_NaN() + True + """ + return mpfi_nan_p(self.__re) or mpfi_nan_p(self.__im) + def cos(self): r""" Compute the cosine of this complex interval. diff --git a/src/sage/rings/complex_number.pyx b/src/sage/rings/complex_number.pyx index 9b3270ffcbe..48ef6eda11e 100644 --- a/src/sage/rings/complex_number.pyx +++ b/src/sage/rings/complex_number.pyx @@ -2341,6 +2341,21 @@ cdef class ComplexNumber(sage.structure.element.FieldElement): """ return self.real().is_infinity() or self.imag().is_infinity() + def is_NaN(self): + r""" + Check if ``self`` is not-a-number. + + EXAMPLES:: + + sage: CC(1, 2).is_NaN() + False + sage: CC(NaN).is_NaN() + True + sage: CC(NaN,2).log().is_NaN() + True + """ + return mpfr_nan_p(self.__re) or mpfr_nan_p(self.__im) + def zeta(self): """ Return the Riemann zeta function evaluated at this complex number. From 0ac7893146826afa62ffe437868e8c5d6d313c17 Mon Sep 17 00:00:00 2001 From: Jeroen Demeyer Date: Mon, 15 May 2017 18:31:21 +0200 Subject: [PATCH 356/452] Remove absolute_import from catalog --- src/sage/combinat/designs/design_catalog.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/designs/design_catalog.py b/src/sage/combinat/designs/design_catalog.py index 3c838715308..ed6d81ee982 100644 --- a/src/sage/combinat/designs/design_catalog.py +++ b/src/sage/combinat/designs/design_catalog.py @@ -72,7 +72,7 @@ .. [1] La Jolla Covering Repository, http://www.ccrwest.org/cover.html """ -from __future__ import absolute_import + from sage.combinat.designs.block_design import (BlockDesign, ProjectiveGeometryDesign, DesarguesianProjectivePlaneDesign, From 57e4e0f518389e13420d18601a2e5ab0649dc3f2 Mon Sep 17 00:00:00 2001 From: Jeroen Demeyer Date: Mon, 15 May 2017 18:40:06 +0200 Subject: [PATCH 357/452] Add Cython patch for Cygwin --- build/pkgs/cython/package-version.txt | 2 +- .../patches/cdef_public_dll_linkage.patch | 32 +++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 build/pkgs/cython/patches/cdef_public_dll_linkage.patch diff --git a/build/pkgs/cython/package-version.txt b/build/pkgs/cython/package-version.txt index 34379825894..887ddb8eb13 100644 --- a/build/pkgs/cython/package-version.txt +++ b/build/pkgs/cython/package-version.txt @@ -1 +1 @@ -0.25.2.p1 +0.25.2.p2 diff --git a/build/pkgs/cython/patches/cdef_public_dll_linkage.patch b/build/pkgs/cython/patches/cdef_public_dll_linkage.patch new file mode 100644 index 00000000000..c4dc9016503 --- /dev/null +++ b/build/pkgs/cython/patches/cdef_public_dll_linkage.patch @@ -0,0 +1,32 @@ +Patch for https://github.com/cython/cython/pull/1687 +Only needed for Cygwin systems + +commit 632f18f2710eaf6ee2b3a3aaa0749c7886299e64 +Author: Jeroen Demeyer +Date: Thu Apr 27 17:13:39 2017 +0200 + + Do not use special dll linkage for "cdef public" functions + +diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py +index 6356e78..76fe4e5 100644 +--- a/Cython/Compiler/ModuleNode.py ++++ b/Cython/Compiler/ModuleNode.py +@@ -214,8 +214,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): + def generate_public_declaration(self, entry, h_code, i_code): + h_code.putln("%s %s;" % ( + Naming.extern_c_macro, +- entry.type.declaration_code( +- entry.cname, dll_linkage="DL_IMPORT"))) ++ entry.type.declaration_code(entry.cname))) + if i_code: + i_code.putln("cdef extern %s" % ( + entry.type.declaration_code(entry.cname, pyrex=1))) +@@ -2849,7 +2848,7 @@ def generate_cfunction_declaration(entry, env, code, definition): + dll_linkage = "DL_IMPORT" + elif entry.visibility == 'public': + storage_class = Naming.extern_c_macro +- dll_linkage = "DL_EXPORT" ++ dll_linkage = None + elif entry.visibility == 'private': + storage_class = "static" + dll_linkage = None From 13abce13aad6b3b7b570b5f030a210198520fb36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jori=20M=C3=A4ntysalo?= Date: Mon, 15 May 2017 21:46:06 +0300 Subject: [PATCH 358/452] From if-if to if-and. --- src/sage/combinat/posets/lattices.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/sage/combinat/posets/lattices.py b/src/sage/combinat/posets/lattices.py index 607155c3536..0b2bf99ceb2 100644 --- a/src/sage/combinat/posets/lattices.py +++ b/src/sage/combinat/posets/lattices.py @@ -3802,12 +3802,11 @@ def splitting_depth_2(a, b): while todo: e = todo.pop() for e_up in conL.upper_covers(e): - if e_up not in reachable: - if splitting_depth_2(e, e_up): - if len(e_up) == 1: # = the top of the cong. lattice - return True - reachable.append(e_up) - todo.append(e_up) + if e_up not in reachable and splitting_depth_2(e, e_up): + if len(e_up) == 1: # = the top of the cong. lattice + return True + reachable.append(e_up) + todo.append(e_up) return False def is_isoform(self, certificate=False): From 9689014c1b6dc94fa1af67bf047dc98ee32918ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 15 May 2017 21:13:56 +0200 Subject: [PATCH 359/452] py3: get rid of cmp in doctest framework --- src/sage/doctest/control.py | 22 +++++++++++++--- src/sage/doctest/parsing.py | 22 +++++++++++++--- src/sage/doctest/sources.py | 39 +++++++++++++++++++++------- src/sage/doctest/util.py | 52 +++++++++++++++++++++++++++++++------ 4 files changed, 109 insertions(+), 26 deletions(-) diff --git a/src/sage/doctest/control.py b/src/sage/doctest/control.py index 90db37a02bc..01ac77d2a58 100644 --- a/src/sage/doctest/control.py +++ b/src/sage/doctest/control.py @@ -123,7 +123,7 @@ def _repr_(self): s += ")" return s - def __cmp__(self, other): + def __eq__(self, other): """ Comparison by __dict__. @@ -135,9 +135,23 @@ def __cmp__(self, other): sage: DD1 == DD2 True """ - c = cmp(type(self), type(other)) - if c: return c - return cmp(self.__dict__,other.__dict__) + if not isinstance(other, DocTestDefaults): + return False + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """ + Test for unequality. + + EXAMPLES:: + + sage: from sage.doctest.control import DocTestDefaults + sage: DD1 = DocTestDefaults(long=True) + sage: DD2 = DocTestDefaults(long=True) + sage: DD1 != DD2 + False + """ + return not (self == other) def skipdir(dirname): diff --git a/src/sage/doctest/parsing.py b/src/sage/doctest/parsing.py index edc883ff791..b5eaa3e65f7 100644 --- a/src/sage/doctest/parsing.py +++ b/src/sage/doctest/parsing.py @@ -441,7 +441,7 @@ def __init__(self, long=False, optional_tags=()): else: self.optional_only = True - def __cmp__(self, other): + def __eq__(self, other): """ Comparison. @@ -453,9 +453,23 @@ def __cmp__(self, other): sage: DTP == DTP2 False """ - c = cmp(type(self), type(other)) - if c: return c - return cmp(self.__dict__, other.__dict__) + if not isinstance(other, SageDocTestParser): + return False + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """ + Test for unequality. + + EXAMPLES:: + + sage: from sage.doctest.parsing import SageDocTestParser + sage: DTP = SageDocTestParser(True, ('sage','magma','guava')) + sage: DTP2 = SageDocTestParser(False, ('sage','magma','guava')) + sage: DTP != DTP2 + True + """ + return not (self == other) def parse(self, string, *args): r""" diff --git a/src/sage/doctest/sources.py b/src/sage/doctest/sources.py index ecda271a11a..21c5fb12239 100644 --- a/src/sage/doctest/sources.py +++ b/src/sage/doctest/sources.py @@ -131,7 +131,7 @@ def __init__(self, options): """ self.options = options - def __cmp__(self, other): + def __eq__(self, other): """ Comparison is just by comparison of attributes. @@ -148,9 +148,28 @@ def __cmp__(self, other): sage: FDS == FDS2 True """ - c = cmp(type(self), type(other)) - if c: return c - return cmp(self.__dict__, other.__dict__) + if type(self) != type(other): + return False + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """ + Test for unequality. + + EXAMPLES:: + + sage: from sage.doctest.control import DocTestDefaults + sage: from sage.doctest.sources import FileDocTestSource + sage: from sage.env import SAGE_SRC + sage: import os + sage: filename = os.path.join(SAGE_SRC,'sage','doctest','sources.py') + sage: DD = DocTestDefaults() + sage: FDS = FileDocTestSource(filename,DD) + sage: FDS2 = FileDocTestSource(filename,DD) + sage: FDS != FDS2 + False + """ + return not (self == other) def _process_doc(self, doctests, doc, namespace, start): """ @@ -240,7 +259,7 @@ def _create_doctests(self, namespace, tab_okay=None): sage: FDS.qualified_name = NestedName('sage.doctest.sources') sage: doctests, extras = FDS._create_doctests({}) sage: len(doctests) - 40 + 41 sage: extras['tab'] False sage: extras['line_number'] @@ -633,16 +652,16 @@ def create_doctests(self, namespace): sage: FDS = FileDocTestSource(filename,DocTestDefaults()) sage: doctests, extras = FDS.create_doctests(globals()) sage: len(doctests) - 40 + 41 sage: extras['tab'] False We give a self referential example:: - sage: doctests[17].name + sage: doctests[18].name 'sage.doctest.sources.FileDocTestSource.create_doctests' - sage: doctests[17].examples[10].source - 'doctests[Integer(17)].examples[Integer(10)].source\n' + sage: doctests[18].examples[10].source + 'doctests[Integer(18)].examples[Integer(10)].source\n' TESTS: @@ -654,7 +673,7 @@ def create_doctests(self, namespace): sage: n = -920390823904823094890238490238484; hash(n) > 0 False # 32-bit True # 64-bit - sage: ex = doctests[17].examples[13] + sage: ex = doctests[18].examples[13] sage: (bitness == '64' and ex.want == 'True \n') or (bitness == '32' and ex.want == 'False \n') True diff --git a/src/sage/doctest/util.py b/src/sage/doctest/util.py index fd2cc1d934a..8cc394f5871 100644 --- a/src/sage/doctest/util.py +++ b/src/sage/doctest/util.py @@ -176,7 +176,7 @@ def __str__(self): """ return str(self.__dict__) - def __cmp__(self, other): + def __eq__(self, other): """ Comparison. @@ -189,9 +189,25 @@ def __cmp__(self, other): sage: loads(dumps(t)) == t True """ - c = cmp(type(self), type(other)) - if c: return c - return cmp(self.__dict__, other.__dict__) + if not isinstance(other, Timer): + return False + return self.__dict__ == other.__dict__ + + def __ne__(self, other): + """ + Test for unequality + + EXAMPLES:: + + sage: from sage.doctest.util import Timer + sage: Timer() == Timer() + True + sage: t = Timer().start() + sage: loads(dumps(t)) != t + False + """ + return not (self == other) + # Inheritance rather then delegation as globals() must be a dict class RecordingDict(dict): @@ -469,7 +485,7 @@ def __repr__(self): """ return '.'.join(a for a in self.all if a is not None) - def __cmp__(self, other): + def __eq__(self, other): """ Comparison is just comparison of the underlying lists. @@ -487,6 +503,26 @@ def __cmp__(self, other): sage: qname == qname2 False """ - c = cmp(type(self), type(other)) - if c: return c - return cmp(self.all, other.all) + if not isinstance(other, NestedName): + return False + return self.all == other.all + + def __ne__(self, other): + """ + Test for unequality. + + EXAMPLES:: + + sage: from sage.doctest.util import NestedName + sage: qname = NestedName('sage.categories.algebras') + sage: qname2 = NestedName('sage.categories.algebras') + sage: qname != qname2 + False + sage: qname[0] = 'Algebras' + sage: qname2[2] = 'Algebras' + sage: repr(qname) == repr(qname2) + True + sage: qname != qname2 + True + """ + return not (self == other) From c407a6c922091debe90c6222ccf10ea44491f418 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 15 May 2017 21:46:04 +0200 Subject: [PATCH 360/452] some cleanup of primes.py --- src/sage/sets/primes.py | 20 ++++++-------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/src/sage/sets/primes.py b/src/sage/sets/primes.py index 08039c8b343..8681c615e24 100644 --- a/src/sage/sets/primes.py +++ b/src/sage/sets/primes.py @@ -54,7 +54,6 @@ class Primes(Set_generic, UniqueRepresentation): ... NotImplementedError: infinite set """ - @staticmethod def __classcall__(cls, proof=True): """ @@ -92,26 +91,19 @@ def __init__(self, proof): sage: P = Primes() sage: R = Primes() - sage: cmp(P,R) - 0 sage: P == R True sage: P != R False - sage: Q=[1,2,3] + sage: Q = [1,2,3] sage: Q != P # indirect doctest True - sage: R.=ZZ[] - sage: P!=x^2+x - True - - Make sure changing order changes the comparison with something - of a different type:: - - sage: cmp('foo', Primes()) != cmp(Primes(), 'foo') + sage: R. = ZZ[] + sage: P != x^2+x True """ - super(Primes, self).__init__(facade = ZZ, category = InfiniteEnumeratedSets()) + super(Primes, self).__init__(facade=ZZ, + category=InfiniteEnumeratedSets()) self.__proof = proof def _repr_(self): @@ -142,7 +134,7 @@ def __contains__(self, x): False """ try: - if not x in ZZ: + if x not in ZZ: return False return ZZ(x).is_prime() except TypeError: From aaaa56d4537647b237abf19c038fc3a270184e48 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Mon, 15 May 2017 15:05:19 -0500 Subject: [PATCH 361/452] I need to actually call the function... --- src/sage/combinat/root_system/root_lattice_realizations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/root_system/root_lattice_realizations.py b/src/sage/combinat/root_system/root_lattice_realizations.py index 2886af214e2..a0e51363c69 100644 --- a/src/sage/combinat/root_system/root_lattice_realizations.py +++ b/src/sage/combinat/root_system/root_lattice_realizations.py @@ -3464,7 +3464,7 @@ def orbit(self): sage: len(L.fundamental_weights()[2].orbit()) 6 """ - return list(self._orbit_iter) + return list(self._orbit_iter()) ########################################################################## # From d800645cd9e7b1cc927205f0ca3f30f6ee445e3d Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Mon, 15 May 2017 15:07:33 -0500 Subject: [PATCH 362/452] Use the iterator in the other internal place orbit() is used. --- .../root_system/non_symmetric_macdonald_polynomials.py | 3 ++- src/sage/combinat/root_system/pieri_factors.py | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py b/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py index cb1faff3e21..cd89e7ece70 100644 --- a/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py +++ b/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py @@ -1814,7 +1814,7 @@ def symmetric_macdonald_polynomial(self, mu): # nonsymmetric Macdonald polynomial of the dominant weight mu # by searching the Weyl orbit of mu and remembering Torbit = {} - for c in mu.orbit(): + for c in mu._orbit_iter(): i = c.first_descent() if i is None: Torbit[c] = self[mu] # the nonsymmetric Macdonald polynomial of mu @@ -1822,3 +1822,4 @@ def symmetric_macdonald_polynomial(self, mu): Torbit[c] = v * self._T.Tw([i])(Torbit[c.simple_reflection(i)]) s = s + Torbit[c] return s + diff --git a/src/sage/combinat/root_system/pieri_factors.py b/src/sage/combinat/root_system/pieri_factors.py index ebe66cf847d..a439d468d6b 100644 --- a/src/sage/combinat/root_system/pieri_factors.py +++ b/src/sage/combinat/root_system/pieri_factors.py @@ -372,7 +372,8 @@ def maximal_elements(self): s = ct.translation_factors()[1] R = RootSystem(ct).weight_space() Lambda = R.fundamental_weights() - orbit = [ R.reduced_word_of_translation(x) for x in (s*(Lambda[1]-Lambda[1].level()*Lambda[0])).orbit() ] + orbit = [R.reduced_word_of_translation(x) + for x in (s*(Lambda[1]-Lambda[1].level()*Lambda[0]))._orbit_iter()] return [self.W.from_reduced_word(x) for x in orbit] From 398f16aa0182be5ac71c020b5da4f707680fce2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 15 May 2017 22:15:30 +0200 Subject: [PATCH 363/452] trac 21580 fixing coxeter3 check (update version) --- build/pkgs/coxeter3/patches/test.output.expected | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/coxeter3/patches/test.output.expected b/build/pkgs/coxeter3/patches/test.output.expected index 0a4fca16a11..d36e4b8c22d 100644 --- a/build/pkgs/coxeter3/patches/test.output.expected +++ b/build/pkgs/coxeter3/patches/test.output.expected @@ -1,4 +1,4 @@ -This is Coxeter version 3.0_beta2. +This is Coxeter version 3.1.sage. Enter help if you need assistance, carriage return to start the program. coxeter : From 95b9698ee687fc29b51ba1db7cb5d76a93e0a666 Mon Sep 17 00:00:00 2001 From: Jeroen Demeyer Date: Mon, 15 May 2017 23:27:40 +0200 Subject: [PATCH 364/452] Remove "public" from methods where it is not needed --- src/sage/libs/ntl/ntl_ZZ_p.pxd | 4 ++-- src/sage/libs/ntl/ntl_ZZ_pE.pxd | 4 ++-- src/sage/rings/fast_arith.pxd | 2 +- src/sage/rings/fast_arith.pyx | 22 ++++++++++------------ 4 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/sage/libs/ntl/ntl_ZZ_p.pxd b/src/sage/libs/ntl/ntl_ZZ_p.pxd index 51048ccb5f7..472587744db 100644 --- a/src/sage/libs/ntl/ntl_ZZ_p.pxd +++ b/src/sage/libs/ntl/ntl_ZZ_p.pxd @@ -4,6 +4,6 @@ from .ntl_ZZ_pContext cimport ntl_ZZ_pContext_class cdef class ntl_ZZ_p(object): cdef ZZ_p_c x cdef ntl_ZZ_pContext_class c - cdef public int get_as_int(ntl_ZZ_p self) - cdef public void set_from_int(ntl_ZZ_p self, int value) + cdef int get_as_int(ntl_ZZ_p self) + cdef void set_from_int(ntl_ZZ_p self, int value) cdef ntl_ZZ_p _new(self) diff --git a/src/sage/libs/ntl/ntl_ZZ_pE.pxd b/src/sage/libs/ntl/ntl_ZZ_pE.pxd index 321e7bcb1e3..d7d265b437d 100644 --- a/src/sage/libs/ntl/ntl_ZZ_pE.pxd +++ b/src/sage/libs/ntl/ntl_ZZ_pE.pxd @@ -5,6 +5,6 @@ from .ntl_ZZ_pX cimport ntl_ZZ_pX cdef class ntl_ZZ_pE(object): cdef ZZ_pE_c x cdef ntl_ZZ_pEContext_class c - cdef public ntl_ZZ_pX get_as_ZZ_pX(ntl_ZZ_pE self) - cdef public void set_from_ZZ_pX(ntl_ZZ_pE self, ntl_ZZ_pX value) + cdef ntl_ZZ_pX get_as_ZZ_pX(ntl_ZZ_pE self) + cdef void set_from_ZZ_pX(ntl_ZZ_pE self, ntl_ZZ_pX value) cdef ntl_ZZ_pE _new(self) diff --git a/src/sage/rings/fast_arith.pxd b/src/sage/rings/fast_arith.pxd index c84cf6d7d44..3fa30ce1c43 100644 --- a/src/sage/rings/fast_arith.pxd +++ b/src/sage/rings/fast_arith.pxd @@ -12,7 +12,7 @@ cdef class arith_llong: cdef long long abs_longlong(self, long long x) except -1 cdef long long sign_longlong(self, long long n) except -2 cdef long long c_gcd_longlong(self, long long a, long long b) except -1 - cdef public long long c_xgcd_longlong(self, long long a, long long b, + cdef long long c_xgcd_longlong(self, long long a, long long b, long long *ss, long long *tt) except -1 cdef long long c_inverse_mod_longlong(self, long long a, long long m) except -1 diff --git a/src/sage/rings/fast_arith.pyx b/src/sage/rings/fast_arith.pyx index 543c94d61c6..f062471976c 100644 --- a/src/sage/rings/fast_arith.pyx +++ b/src/sage/rings/fast_arith.pyx @@ -173,17 +173,17 @@ cpdef prime_range(start, stop=None, algorithm="pari_primes", bint py_ints=False) return res cdef class arith_int: - cdef public int abs_int(self, int x) except -1: + cdef int abs_int(self, int x) except -1: if x < 0: return -x return x - cdef public int sign_int(self, int n) except -2: + cdef int sign_int(self, int n) except -2: if n < 0: return -1 return 1 - cdef public int c_gcd_int(self, int a, int b) except -1: + cdef int c_gcd_int(self, int a, int b) except -1: cdef int c if a==0: return self.abs_int(b) @@ -202,7 +202,7 @@ cdef class arith_int: return self.c_gcd_int(a,b) - cdef public int c_xgcd_int(self, int a, int b, int* ss, int* tt) except -1: + cdef int c_xgcd_int(self, int a, int b, int* ss, int* tt) except -1: cdef int psign, qsign, p, q, r, s, c, quot, new_r, new_s if a == 0: @@ -239,7 +239,7 @@ cdef class arith_int: g = self.c_xgcd_int(a,b, &s, &t) return (g,s,t) - cdef public int c_inverse_mod_int(self, int a, int m) except -1: + cdef int c_inverse_mod_int(self, int a, int m) except -1: if a == 1 or m<=1: return a%m # common special case cdef int g, s, t g = self.c_xgcd_int(a,m, &s, &t) @@ -309,17 +309,17 @@ cdef class arith_int: # The long long versions are next. cdef class arith_llong: - cdef public long long abs_longlong(self, long long x) except -1: + cdef long long abs_longlong(self, long long x) except -1: if x < 0: return -x return x - cdef public long long sign_longlong(self, long long n) except -2: + cdef long long sign_longlong(self, long long n) except -2: if n < 0: return -1 return 1 - cdef public long long c_gcd_longlong(self, long long a, long long b) except -1: + cdef long long c_gcd_longlong(self, long long a, long long b) except -1: cdef long long c if a==0: return self.abs_longlong(b) @@ -333,12 +333,10 @@ cdef class arith_llong: b = c return a - def gcd_longlong(self, long long a, long long b): return self.c_gcd_longlong(a,b) - - cdef public long long c_xgcd_longlong(self, long long a, long long b, + cdef long long c_xgcd_longlong(self, long long a, long long b, long long *ss, long long *tt) except -1: cdef long long psign, qsign, p, q, r, s, c, quot, new_r, new_s @@ -374,7 +372,7 @@ cdef class arith_llong: return a - cdef public long long c_inverse_mod_longlong(self, long long a, long long m) except -1: + cdef long long c_inverse_mod_longlong(self, long long a, long long m) except -1: cdef long long g, s, t g = self.c_xgcd_longlong(a,m, &s, &t) if g != 1: From 70e23f4c5f769dd6ce8dc9502e8ecfdb5f5ff15e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=2E=20Thi=C3=A9ry?= Date: Mon, 15 May 2017 18:30:05 -0400 Subject: [PATCH 365/452] 23000: Fix inconsistency in Modules.FiniteDimensional.extra_super_categories --- src/sage/categories/modules.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/sage/categories/modules.py b/src/sage/categories/modules.py index c5235746eff..f51953b3b21 100644 --- a/src/sage/categories/modules.py +++ b/src/sage/categories/modules.py @@ -498,9 +498,18 @@ def extra_super_categories(self): True sage: Modules(ZZ).FiniteDimensional().is_subcategory(Sets().Finite()) False + + sage: Modules(Rings().Finite()).FiniteDimensional().is_subcategory(Sets().Finite()) + True + sage: Modules(Rings()).FiniteDimensional().is_subcategory(Sets().Finite()) + False """ - if self.base_ring() in Sets().Finite(): - return [Sets().Finite()] + base_ring = self.base_ring() + FiniteSets = Sets().Finite() + if (isinstance(base_ring, Category) and + base_ring.is_subcategory(FiniteSets)) or \ + base_ring in FiniteSets: + return [FiniteSets] else: return [] From fc766203eaecbbf86767571c68dc569a02b2582c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=2E=20Thi=C3=A9ry?= Date: Mon, 15 May 2017 21:54:39 -0400 Subject: [PATCH 366/452] 23000: trivial doctest update --- src/sage/modules/free_module.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/modules/free_module.py b/src/sage/modules/free_module.py index 19b2192c243..0e4b3afde45 100644 --- a/src/sage/modules/free_module.py +++ b/src/sage/modules/free_module.py @@ -688,13 +688,13 @@ def __init__(self, base_ring, rank, degree, sparse=False, Ambient free module of rank 3 over the integral domain Multivariate Polynomial Ring in x0, x1, x2 over Rational Field sage: FreeModule(GF(7),3).category() - Category of finite enumerated finite dimensional vector spaces with basis over + Category of enumerated finite dimensional vector spaces with basis over (finite enumerated fields and subquotients of monoids and quotients of semigroups) sage: V = QQ^4; V.category() Category of finite dimensional vector spaces with basis over (quotient fields and metric spaces) sage: V = GF(5)**20; V.category() - Category of finite enumerated finite dimensional vector spaces with basis over (finite enumerated fields and subquotients of monoids and quotients of semigroups) + Category of enumerated finite dimensional vector spaces with basis over (finite enumerated fields and subquotients of monoids and quotients of semigroups) sage: FreeModule(ZZ,3).category() Category of finite dimensional modules with basis over (euclidean domains and infinite enumerated sets From ca839eab442ac38fe07454a77a3ab1c19e3f5e8c Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Tue, 16 May 2017 08:34:14 +0200 Subject: [PATCH 367/452] 23001: is_NaN for ball fields --- src/sage/rings/complex_arb.pyx | 21 ++++++++++++++++++++- src/sage/rings/real_arb.pyx | 17 +++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/sage/rings/complex_arb.pyx b/src/sage/rings/complex_arb.pyx index ae1597a6eaa..873ec883724 100644 --- a/src/sage/rings/complex_arb.pyx +++ b/src/sage/rings/complex_arb.pyx @@ -148,7 +148,7 @@ from sage.libs.arb.arb cimport * from sage.libs.arb.acb cimport * from sage.libs.arb.acb_hypgeom cimport * from sage.libs.arb.acb_modular cimport * -from sage.libs.arb.arf cimport arf_init, arf_get_mpfr, arf_set_mpfr, arf_clear, arf_set_mag, arf_set +from sage.libs.arb.arf cimport arf_init, arf_get_mpfr, arf_set_mpfr, arf_clear, arf_set_mag, arf_set, arf_is_nan from sage.libs.arb.mag cimport mag_init, mag_clear, mag_add, mag_set_d, MAG_BITS, mag_is_inf, mag_is_finite, mag_zero from sage.libs.flint.fmpz cimport fmpz_t, fmpz_init, fmpz_get_mpz, fmpz_set_mpz, fmpz_clear, fmpz_abs from sage.libs.flint.fmpq cimport fmpq_t, fmpq_init, fmpq_set_mpq, fmpq_clear @@ -1357,6 +1357,25 @@ cdef class ComplexBall(RingElement): # Comparisons and predicates + def is_NaN(self): + """ + Return ``True`` iff either the real or the imaginary part + is not-a-number. + + EXAMPLES:: + + sage: CBF(NaN).is_NaN() + True + sage: CBF(-5).gamma().is_NaN() + True + sage: CBF(oo).is_NaN() + False + sage: CBF(42+I).is_NaN() + False + """ + return (arf_is_nan(arb_midref(acb_realref(self.value))) + or arf_is_nan(arb_midref(acb_imagref(self.value)))) + def is_zero(self): """ Return ``True`` iff the midpoint and radius of this ball are both zero. diff --git a/src/sage/rings/real_arb.pyx b/src/sage/rings/real_arb.pyx index 9a2fe328ed4..fcdc5c62b1e 100644 --- a/src/sage/rings/real_arb.pyx +++ b/src/sage/rings/real_arb.pyx @@ -2578,6 +2578,23 @@ cdef class RealBall(RingElement): """ return not self.is_finite() + def is_NaN(self): + """ + Return ``True`` if this ball is not-a-number. + + EXAMPLES:: + + sage: RBF(NaN).is_NaN() + True + sage: RBF(-5).gamma().is_NaN() + True + sage: RBF(infinity).is_NaN() + False + sage: RBF(42, rad=1.r).is_NaN() + False + """ + return arf_is_nan(arb_midref(self.value)) + # Arithmetic def __neg__(self): From 5f8b7030bb0bd7b17d87a1c957bdb1d290aae034 Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Tue, 16 May 2017 09:26:29 +0200 Subject: [PATCH 368/452] 23001: NaN back-conversion with interval fields --- src/sage/rings/real_interval_absolute.pyx | 2 ++ src/sage/rings/real_mpfr.pyx | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/sage/rings/real_interval_absolute.pyx b/src/sage/rings/real_interval_absolute.pyx index ec9f72afc39..15dea4b5ad3 100644 --- a/src/sage/rings/real_interval_absolute.pyx +++ b/src/sage/rings/real_interval_absolute.pyx @@ -266,6 +266,8 @@ cdef class RealIntervalAbsoluteElement(FieldElement): 6.? sage: R100(R((5,6))) 6.? + sage: RIF(CIF(NaN)) + [.. NaN ..] """ Element.__init__(self, parent) diff --git a/src/sage/rings/real_mpfr.pyx b/src/sage/rings/real_mpfr.pyx index 4fd2636d65e..aac05e8596e 100644 --- a/src/sage/rings/real_mpfr.pyx +++ b/src/sage/rings/real_mpfr.pyx @@ -629,6 +629,8 @@ cdef class RealField_class(sage.rings.ring.Field): Traceback (most recent call last): ... ValueError: can only convert signed infinity to RR + sage: R(CIF(NaN)) + NaN """ if hasattr(x, '_mpfr_'): return x._mpfr_(self) @@ -1451,7 +1453,7 @@ cdef class RealNumber(sage.structure.element.RingElement): raise ValueError('can only convert signed infinity to RR') elif mpfr_set_str(self.value, s, base, parent.rnd) == 0: pass - elif s == 'NaN' or s == '@NaN@': + elif s == 'NaN' or s == '@NaN@' or s == '[..NaN..]': mpfr_set_nan(self.value) elif s_lower == '+infinity': mpfr_set_inf(self.value, 1) From 9ad030eaeb854ba86569504a65f8486e0a6576bb Mon Sep 17 00:00:00 2001 From: Jeroen Demeyer Date: Tue, 16 May 2017 15:25:06 +0200 Subject: [PATCH 369/452] Various PEP8 formatting issues --- src/sage/rings/fast_arith.pxd | 4 ++-- src/sage/rings/fast_arith.pyx | 28 +++++++--------------------- 2 files changed, 9 insertions(+), 23 deletions(-) diff --git a/src/sage/rings/fast_arith.pxd b/src/sage/rings/fast_arith.pxd index 3fa30ce1c43..7a99e658b91 100644 --- a/src/sage/rings/fast_arith.pxd +++ b/src/sage/rings/fast_arith.pxd @@ -13,8 +13,8 @@ cdef class arith_llong: cdef long long sign_longlong(self, long long n) except -2 cdef long long c_gcd_longlong(self, long long a, long long b) except -1 cdef long long c_xgcd_longlong(self, long long a, long long b, - long long *ss, - long long *tt) except -1 + long long *ss, + long long *tt) except -1 cdef long long c_inverse_mod_longlong(self, long long a, long long m) except -1 cdef long long c_rational_recon_longlong(self, long long a, long long m, long long *n, long long *d) except -1 diff --git a/src/sage/rings/fast_arith.pyx b/src/sage/rings/fast_arith.pyx index f062471976c..545bd03cd69 100644 --- a/src/sage/rings/fast_arith.pyx +++ b/src/sage/rings/fast_arith.pyx @@ -5,19 +5,13 @@ Basic arithmetic with C integers #***************************************************************************** # Copyright (C) 2004 William Stein # -# 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: -# +# 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/ #***************************************************************************** - ################################################################### # We define the following functions in this file, both # for int (up to bound = 2**31 - 1) and longlong (up to 2**63 - 1). @@ -172,6 +166,7 @@ cpdef prime_range(start, stop=None, algorithm="pari_primes", bint py_ints=False) raise ValueError("algorithm argument must be either ``pari_primes`` or ``pari_isprime``") return res + cdef class arith_int: cdef int abs_int(self, int x) except -1: if x < 0: @@ -197,11 +192,9 @@ cdef class arith_int: b = c return a - def gcd_int(self, int a, int b): return self.c_gcd_int(a,b) - cdef int c_xgcd_int(self, int a, int b, int* ss, int* tt) except -1: cdef int psign, qsign, p, q, r, s, c, quot, new_r, new_s @@ -250,7 +243,6 @@ cdef class arith_int: s = s + m return s - def inverse_mod_int(self, int a, int m): return self.c_inverse_mod_int(a, m) @@ -337,11 +329,10 @@ cdef class arith_llong: return self.c_gcd_longlong(a,b) cdef long long c_xgcd_longlong(self, long long a, long long b, - long long *ss, - long long *tt) except -1: + long long *ss, + long long *tt) except -1: cdef long long psign, qsign, p, q, r, s, c, quot, new_r, new_s - if a == 0: ss[0] = 0 tt[0] = self.sign_longlong(b) @@ -369,7 +360,6 @@ cdef class arith_llong: ss[0] = p*psign tt[0] = q*qsign - return a cdef long long c_inverse_mod_longlong(self, long long a, long long m) except -1: @@ -436,7 +426,3 @@ cdef class arith_llong: cdef long long n, d self.c_rational_recon_longlong(a, m, &n, &d) return (n,d) - - - - From 920e5adcf6628c15f484e9f28bc970e3e2c96fe9 Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Tue, 16 May 2017 15:28:10 +0200 Subject: [PATCH 370/452] 23001: Back-convert complex NaN (NaN+NaN*I) to the resp. real field --- src/sage/rings/complex_number.pyx | 2 +- src/sage/rings/real_mpfr.pyx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/rings/complex_number.pyx b/src/sage/rings/complex_number.pyx index 48ef6eda11e..b4d34e4301c 100644 --- a/src/sage/rings/complex_number.pyx +++ b/src/sage/rings/complex_number.pyx @@ -1101,7 +1101,7 @@ cdef class ComplexNumber(sage.structure.element.FieldElement): sage: float(abs(ComplexNumber(1,1))) 1.4142135623730951 """ - if mpfr_zero_p(self.__im): + if mpfr_zero_p(self.__im) or mpfr_nan_p(self.__re): return mpfr_get_d(self.__re, rnd) else: raise TypeError("unable to convert {!r} to float; use abs() or real_part() as desired".format(self)) diff --git a/src/sage/rings/real_mpfr.pyx b/src/sage/rings/real_mpfr.pyx index aac05e8596e..e7fc8a28eeb 100644 --- a/src/sage/rings/real_mpfr.pyx +++ b/src/sage/rings/real_mpfr.pyx @@ -1453,7 +1453,7 @@ cdef class RealNumber(sage.structure.element.RingElement): raise ValueError('can only convert signed infinity to RR') elif mpfr_set_str(self.value, s, base, parent.rnd) == 0: pass - elif s == 'NaN' or s == '@NaN@' or s == '[..NaN..]': + elif s == 'NaN' or s == '@NaN@' or s == '[..NaN..]' or s == 'NaN+NaN*I': mpfr_set_nan(self.value) elif s_lower == '+infinity': mpfr_set_inf(self.value, 1) From 1eac4d808b9b56df1130afd3f6842d13cdea6ca4 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 16 May 2017 08:39:22 -0500 Subject: [PATCH 371/452] Some small tweaks to the doc. --- src/sage/functions/error.py | 64 +++++++++++++++++++++++------------ src/sage/functions/special.py | 3 +- 2 files changed, 45 insertions(+), 22 deletions(-) diff --git a/src/sage/functions/error.py b/src/sage/functions/error.py index 79924ac974a..a5bbe2a734a 100644 --- a/src/sage/functions/error.py +++ b/src/sage/functions/error.py @@ -28,15 +28,12 @@ """ #***************************************************************************** -# 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: +# Copyright (C) 2016 Ralf Stephan # +# 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/ #***************************************************************************** @@ -50,14 +47,17 @@ class Function_erf(BuiltinFunction): r""" - The error function, defined for real values as + The error function. + + The error function is defined for real values as - `\operatorname{erf}(x) = \frac{2}{\sqrt{\pi}} \int_0^x e^{-t^2} dt`. + .. MATH:: + + \operatorname{erf}(x) = \frac{2}{\sqrt{\pi}} \int_0^x e^{-t^2} dt. This function is also defined for complex values, via analytic continuation. - EXAMPLES: We can evaluate numerically:: @@ -86,7 +86,7 @@ class Function_erf(BuiltinFunction): REFERENCES: - - http://en.wikipedia.org/wiki/Error_function + - :wikipedia:`Error_function` - http://mpmath.googlecode.com/svn/trunk/doc/build/functions/expintegrals.html#error-functions TESTS: @@ -264,7 +264,7 @@ def _evalf_(self, x, parent=None, algorithm=None): def _derivative_(self, x, diff_param=None): """ - Derivative of erf function + Derivative of erf function. EXAMPLES:: @@ -287,10 +287,18 @@ def _derivative_(self, x, diff_param=None): erf = Function_erf() class Function_erfi(BuiltinFunction): + """ + The imaginary error function. + + The imaginary error function is defined by + + .. MATH:: + + \operatorname{erfi}(x) = -i \operatorname{erf}(ix). + """ def __init__(self): r""" - The imaginary error function - `\operatorname{erfi}(x)=-i\operatorname{erf}(ix)`. + Initialize ``self``. EXAMPLES:: @@ -357,8 +365,13 @@ def _derivative_(self, x, diff_param=None): class Function_erfc(BuiltinFunction): r""" - The complementary error function - `\frac{2}{\sqrt{\pi}}\int_t^\infty e^{-x^2} dx`. + The complementary error function. + + The complementary error function is defined by + + .. MATH:: + + \frac{2}{\sqrt{\pi}} \int_t^\infty e^{-x^2} dx. EXAMPLES:: @@ -445,10 +458,18 @@ def _derivative_(self, x, diff_param=None): class Function_erfinv(BuiltinFunction): + """ + The inverse error function. + + The inverse error function is defined by: + + .. MATH:: + + \operatorname{erfinv}(x) = \operatorname{erf}^{-1}(x). + """ def __init__(self): r""" - The inverse error function - `\operatorname{erfinv}(x)=\operatorname{erf}^{-1}(x)`. + Initialize ``self``. EXAMPLES:: @@ -460,7 +481,7 @@ def __init__(self): BuiltinFunction.__init__(self, "erfinv", latex_name=r"\operatorname{erfinv}", conversions=dict(sympy='erfinv', - maxima='inverse_erf')) + maxima='inverse_erf')) def _eval_(self, x): """ @@ -498,7 +519,7 @@ def _evalf_(self, x, parent=None, algorithm=None): def _derivative_(self, x, diff_param=None): """ - Derivative of inverse erf function + Derivative of inverse erf function. EXAMPLES:: @@ -511,3 +532,4 @@ def _derivative_(self, x, diff_param=None): from sage.structure.sage_object import register_unpickle_override register_unpickle_override('sage.functions.other', 'Function_erf', Function_erf) + diff --git a/src/sage/functions/special.py b/src/sage/functions/special.py index 2ca349605c3..7c42730f97f 100644 --- a/src/sage/functions/special.py +++ b/src/sage/functions/special.py @@ -1015,7 +1015,7 @@ def _print_latex_(self, n, z, m): def error_fcn(x): """ - Deprecated. Please use erfc(). + Deprecated in :trac:21819`. Please use ``erfc()``. EXAMPLES:: @@ -1030,3 +1030,4 @@ def error_fcn(x): from sage.misc.superseded import deprecation deprecation(21819, "error_fcn() is deprecated. Please use erfc()") return erfc(x) + From c1cff2dbe8921a381d2bc3148946f6907019462c Mon Sep 17 00:00:00 2001 From: Ralf Stephan Date: Tue, 16 May 2017 15:43:24 +0200 Subject: [PATCH 372/452] 22969: apply commits b65c3f7bd and ece8bd967 from future pynac --- build/pkgs/pynac/package-version.txt | 2 +- build/pkgs/pynac/patches/polylog-evalf.patch | 212 +++++++++++++++++++ 2 files changed, 213 insertions(+), 1 deletion(-) create mode 100644 build/pkgs/pynac/patches/polylog-evalf.patch diff --git a/build/pkgs/pynac/package-version.txt b/build/pkgs/pynac/package-version.txt index 879be8a98fc..9379314273e 100644 --- a/build/pkgs/pynac/package-version.txt +++ b/build/pkgs/pynac/package-version.txt @@ -1 +1 @@ -0.7.7 +0.7.7.p0 diff --git a/build/pkgs/pynac/patches/polylog-evalf.patch b/build/pkgs/pynac/patches/polylog-evalf.patch new file mode 100644 index 00000000000..636901c1b85 --- /dev/null +++ b/build/pkgs/pynac/patches/polylog-evalf.patch @@ -0,0 +1,212 @@ +diff --git a/ginac/numeric.cpp b/ginac/numeric.cpp +index eb247a5..07a6588 100644 +--- a/ginac/numeric.cpp ++++ b/ginac/numeric.cpp +@@ -166,84 +166,11 @@ inline void py_error(const char* errmsg) { + #if PY_MAJOR_VERSION < 3 + #define PyNumber_TrueDivide PyNumber_Divide + +-inline int Pynac_PyObj_Cmp(PyObject *optr1, PyObject *optr2, const char *errmsg) { +- int result; +- if (PyObject_Cmp(optr1, optr2, &result) == -1) +- py_error(errmsg); +- return result; +-} +- +-inline bool Pynac_PyObj_RichCmp(PyObject *optr1, PyObject *optr2, int opid, const char *errmsg) { +- PyObject *obj1(nullptr), *obj2(nullptr); +- if (PyComplex_CheckExact(optr1)) { +- if (PyComplex_ImagAsDouble(optr1) != 0.0) +- return false; +- obj1 = PyFloat_FromDouble(PyComplex_RealAsDouble(optr1)); +- optr1 = obj1; +- } +- if (PyComplex_CheckExact(optr2)) { +- if (PyComplex_ImagAsDouble(optr2) != 0.0) +- return false; +- obj2 = PyFloat_FromDouble(PyComplex_RealAsDouble(optr2)); +- optr2 = obj2; +- } +- int result; +- if (PyObject_Cmp(optr1, optr2, &result) == -1) +- py_error(errmsg); +- if (obj1 != nullptr) +- Py_DECREF(obj1); +- if (obj2 != nullptr) +- Py_DECREF(obj2); +- switch (result) { +- case -1: return opid == Py_LT || opid == Py_LE || opid == Py_NE; +- case 0: return opid == Py_LE || opid == Py_EQ || opid == Py_GE; +- case 1: return opid == Py_GT || opid == Py_GE || opid == Py_NE; +- default: return false; +- } +-} + #else + #define PyInt_Check PyLong_Check + #define PyInt_AsLong PyLong_AsLong + #define PyInt_FromLong PyLong_FromLong + #define PyString_FromString PyBytes_FromString +- +-inline int Pynac_PyObj_Cmp(PyObject *optr1, PyObject *optr2, const char *errmsg) { +- int result = PyObject_RichCompareBool(optr1, optr2, Py_LT); +- if (result == 1) +- return -1; +- else if (result == -1) +- py_error(errmsg); +- else { // result == 0 +- result = PyObject_RichCompareBool(optr1, optr2, Py_GT); +- if (result == -1) +- py_error(errmsg); +- } +- return result; +-} +- +-inline bool Pynac_PyObj_RichCmp(PyObject *optr1, PyObject *optr2, int opid, const char *errmsg) { +- PyObject *obj1(nullptr), *obj2(nullptr); +- if (PyComplex_CheckExact(optr1)) { +- if (PyComplex_ImagAsDouble(optr1) != 0.0) +- return false; +- obj1 = PyFloat_FromDouble(PyComplex_RealAsDouble(optr1)); +- optr1 = obj1; +- } +- if (PyComplex_CheckExact(optr2)) { +- if (PyComplex_ImagAsDouble(optr2) != 0.0) +- return false; +- obj2 = PyFloat_FromDouble(PyComplex_RealAsDouble(optr2)); +- optr2 = obj2; +- } +- int result = PyObject_RichCompareBool(optr1, optr2, opid); +- if (result == -1) +- py_error(errmsg); +- if (obj1 != nullptr) +- Py_DECREF(obj1); +- if (obj2 != nullptr) +- Py_DECREF(obj2); +- return result; +-} + #endif + + // The following variable gets changed to true once +@@ -609,7 +536,21 @@ int numeric::compare_same_type(const numeric& right) const { + ret = -1; + return ret; + case PYOBJECT: +- return Pynac_PyObj_Cmp(v._pyobject, right.v._pyobject, "compare_same_type"); ++ { ++ int result = PyObject_RichCompareBool(v._pyobject, ++ right.v._pyobject, Py_LT); ++ if (result == 1) ++ return -1; ++ else if (result == -1) ++ py_error("richcmp failed"); ++ else { // result == 0 ++ result = PyObject_RichCompareBool(v._pyobject, ++ right.v._pyobject, Py_GT); ++ if (result == -1) ++ py_error("richcmp failed"); ++ } ++ return result; ++ } + default: + stub("invalid type: compare_same_type type not handled"); + } +@@ -1601,15 +1542,17 @@ int numeric::csgn() const { + case PYOBJECT: + int result; + if (is_real()) { +- result = Pynac_PyObj_Cmp(v._pyobject, ZERO, "csgn"); ++ numeric z(ZERO); ++ Py_INCREF(ZERO); ++ return compare_same_type(z); + } else { +- PyObject *tmp = py_funcs.py_real(v._pyobject); +- result = Pynac_PyObj_Cmp(tmp, ZERO, "csgn"); +- Py_DECREF(tmp); ++ numeric re = real(); ++ numeric z(ZERO); ++ Py_INCREF(ZERO); ++ result = re.compare_same_type(z); + if (result == 0) { +- tmp = py_funcs.py_imag(v._pyobject); +- result = Pynac_PyObj_Cmp(tmp, ZERO, "csgn"); +- Py_DECREF(tmp); ++ numeric im = imag(); ++ result = im.compare_same_type(z); + } + } + return result; +@@ -1689,7 +1632,7 @@ bool numeric::is_positive() const { + case MPQ: + return mpq_cmp_si(v._bigrat, 0, 1) > 0; + case PYOBJECT: +- return is_real() and Pynac_PyObj_RichCmp(v._pyobject, ZERO, Py_GT, "is_positive"); ++ return is_real() and PyObject_RichCompareBool(v._pyobject, ZERO, Py_GT) == 1; + default: + stub("invalid type: is_positive() type not handled"); + } +@@ -1706,7 +1649,7 @@ bool numeric::is_negative() const { + case MPQ: + return mpq_cmp_si(v._bigrat, 0, 1) < 0; + case PYOBJECT: +- return is_real() and Pynac_PyObj_RichCmp(v._pyobject, ZERO, Py_LT, "is_negative"); ++ return is_real() and PyObject_RichCompareBool(v._pyobject, ZERO, Py_LT) == 1; + default: + stub("invalid type: is_negative() type not handled"); + } +@@ -1765,7 +1708,7 @@ bool numeric::is_nonneg_integer() const { + case MPQ: + return (is_integer() and (is_positive() or is_zero())); + case PYOBJECT: +- return is_integer() and Pynac_PyObj_RichCmp(v._pyobject, ZERO, Py_GE, "is_nonneg_integer"); ++ return is_integer() and PyObject_RichCompareBool(v._pyobject, ZERO, Py_GE) == 1; + default: + stub("invalid type: is_nonneg_integer() type not handled"); + } +@@ -2026,7 +1969,7 @@ bool numeric::operator<(const numeric &right) const { + case MPQ: + return mpq_cmp(v._bigrat, right.v._bigrat) < 0; + case PYOBJECT: +- return Pynac_PyObj_RichCmp(v._pyobject, right.v._pyobject, Py_LT, "<"); ++ return PyObject_RichCompareBool(v._pyobject, right.v._pyobject, Py_LT) == 1; + default: + stub("invalid type: operator< type not handled"); + } +@@ -2050,7 +1993,7 @@ bool numeric::operator<=(const numeric &right) const { + case MPQ: + return mpq_cmp(v._bigrat, right.v._bigrat) <= 0; + case PYOBJECT: +- return Pynac_PyObj_RichCmp(v._pyobject, right.v._pyobject, Py_LE, "<="); ++ return PyObject_RichCompareBool(v._pyobject, right.v._pyobject, Py_LE) == 1; + default: + stub("invalid type: operator<= type not handled"); + } +@@ -2074,7 +2017,7 @@ bool numeric::operator>(const numeric &right) const { + case MPQ: + return mpq_cmp(v._bigrat, right.v._bigrat) > 0; + case PYOBJECT: +- return Pynac_PyObj_RichCmp(v._pyobject, right.v._pyobject, Py_GT, ">"); ++ return PyObject_RichCompareBool(v._pyobject, right.v._pyobject, Py_GT) == 1; + default: + stub("invalid type: operator> type not handled"); + } +@@ -2098,7 +2041,7 @@ bool numeric::operator>=(const numeric &right) const { + case MPQ: + return mpq_cmp(v._bigrat, right.v._bigrat) >= 0; + case PYOBJECT: +- return Pynac_PyObj_RichCmp(v._pyobject, right.v._pyobject, Py_GE, ">="); ++ return PyObject_RichCompareBool(v._pyobject, right.v._pyobject, Py_GE) == 1; + default: + stub("invalid type: operator!= type not handled"); + } +@@ -2640,9 +2583,9 @@ const numeric numeric::Li2(const numeric &n, PyObject* parent) const { + + numeric rnum(ret); + if (is_real() and n.is_integer() and rnum.real()<(*_num1_p)) +- return rnum.real(); ++ return ex_to(rnum.real().evalf(0, parent)); + else +- return rnum; ++ return ex_to(rnum.evalf(0, parent)); + } + + const numeric numeric::lgamma() const { From 8ae3722130bd42d45c2919f45531a591244af2e7 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 16 May 2017 16:05:59 -0500 Subject: [PATCH 373/452] Fixing typo. --- src/sage/combinat/root_system/root_lattice_realizations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/root_system/root_lattice_realizations.py b/src/sage/combinat/root_system/root_lattice_realizations.py index a0e51363c69..2cdae2201a3 100644 --- a/src/sage/combinat/root_system/root_lattice_realizations.py +++ b/src/sage/combinat/root_system/root_lattice_realizations.py @@ -3448,7 +3448,7 @@ def orbit(self): EXAMPLES: `\rho` is a regular element whose orbit is in bijection - with the Weyl group. In particular, it as 6 elements for + with the Weyl group. In particular, it has 6 elements for the symmetric group `S_3`:: sage: L = RootSystem(["A", 2]).ambient_lattice() From 4de97cbe3cd17b13b9f82d42769ee5cb156edc41 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Tue, 16 May 2017 17:54:42 -0500 Subject: [PATCH 374/452] Use maximal_vector() in LocalEnergyFunction and define generic module_generator(). --- src/sage/categories/loop_crystals.py | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/sage/categories/loop_crystals.py b/src/sage/categories/loop_crystals.py index fa4781b3ee6..b85a878cfa9 100644 --- a/src/sage/categories/loop_crystals.py +++ b/src/sage/categories/loop_crystals.py @@ -285,6 +285,20 @@ def maximal_vector(self): assert False, "BUG: invalid Kirillov-Reshetikhin crystal" + def module_generator(self): + r""" + Return the unique module generator of classical weight + `s \Lambda_r` of the Kirillov-Reshetikhin crystal `B^{r,s}`. + + EXAMPLES:: + + sage: La = RootSystem(['G',2,1]).weight_space().fundamental_weights() + sage: K = crystals.ProjectedLevelZeroLSPaths(La[1]) + sage: K.module_generator() + (-Lambda[0] + Lambda[1],) + """ + return self.maximal_vector() + # TODO: Should this be in one of the super categories? def affinization(self): """ @@ -1102,12 +1116,23 @@ def __init__(self, B, Bp, normalization=0): sage: K2 = crystals.KirillovReshetikhin(['A',7,2], 2,1) sage: H = K.local_energy_function(K2) sage: TestSuite(H).run(skip=['_test_category', '_test_pickling']) + + TESTS: + + Check that :trac:`23014` is fixed:: + + sage: La = RootSystem(['G',2,1]).weight_space().fundamental_weights() + sage: K = crystals.ProjectedLevelZeroLSPaths(La[1]) + sage: H = K.local_energy_function(K) + sage: hw = H.domain().classically_highest_weight_vectors() + sage: [H(x) for x in hw] + [0, 1, 2, 1] """ self._B = B self._Bp = Bp self._R_matrix = self._B.R_matrix(self._Bp) T = B.tensor(Bp) - self._known_values = {T(*[K.module_generator() for K in T.crystals]): + self._known_values = {T(*[K.maximal_vector() for K in T.crystals]): ZZ(normalization)} self._I0 = T.cartan_type().classical().index_set() from sage.categories.homset import Hom From f85c130cdc59faa7ba9a92659530221ab804e9f1 Mon Sep 17 00:00:00 2001 From: Jeroen Demeyer Date: Thu, 2 Mar 2017 11:24:40 +0100 Subject: [PATCH 375/452] Upgrade pygments to version 2.2.0 --- build/pkgs/pygments/SPKG.txt | 28 +++++++++++-------------- build/pkgs/pygments/checksums.ini | 6 +++--- build/pkgs/pygments/package-version.txt | 2 +- 3 files changed, 16 insertions(+), 20 deletions(-) diff --git a/build/pkgs/pygments/SPKG.txt b/build/pkgs/pygments/SPKG.txt index b0b7e9a56f2..ae7f23d4cb9 100644 --- a/build/pkgs/pygments/SPKG.txt +++ b/build/pkgs/pygments/SPKG.txt @@ -4,9 +4,18 @@ Pygments is a syntax highlighting package written in Python. -It is a generic syntax highlighter for general use in all kinds of -software such as forum systems, wikis or other applications that need -to prettify source code. +It is a generic syntax highlighter suitable for use in code hosting, +forums, wikis or other applications that need to prettify source code. +Highlights are: + +* a wide range of over 300 languages and other text formats is + supported +* special attention is paid to details, increasing quality by a fair + amount +* support for new languages and formats are added easily +* a number of output formats, presently HTML, LaTeX, RTF, SVG, all image + formats that PIL supports and ANSI sequences +* it is usable as a command-line tool and as a library == License == @@ -28,16 +37,3 @@ Patches included: * sage_prompt.patch: patch pygments/lexers/agile.py to treat the "sage:" prompt like Python's ">>>" prompt. This allows a very kludgy patch to be removed from the Sphinx package (see #10118). - -== Changelog == - -=== pygments-1.3.1.p0 (Jeroen Demeyer, November 18th, 2010) === - - * Upgrade to Pygments 1.3.1 - - * Add sage_prompt.patch - -=== pygments-0.11.1.p0 (Mike Hansen, September 15th, 2008) === - - * Initial version. - diff --git a/build/pkgs/pygments/checksums.ini b/build/pkgs/pygments/checksums.ini index 4d54f5140f0..6b7ab23a910 100644 --- a/build/pkgs/pygments/checksums.ini +++ b/build/pkgs/pygments/checksums.ini @@ -1,4 +1,4 @@ tarball=Pygments-VERSION.tar.gz -sha1=ecc79e8a3cd5abbaffe33f78061be70a34ebe994 -md5=ed3fba2467c8afcda4d317e4ef2c6150 -cksum=1054380650 +sha1=5c6714bd6fd950c1478889f7b72fc7f6771d5163 +md5=13037baca42f16917cbd5ad2fab50844 +cksum=1747340458 diff --git a/build/pkgs/pygments/package-version.txt b/build/pkgs/pygments/package-version.txt index a37572fb25c..d2ccf5ed805 100644 --- a/build/pkgs/pygments/package-version.txt +++ b/build/pkgs/pygments/package-version.txt @@ -1 +1 @@ -2.1.3.p1 +2.2.0.p0 From aa28f4cba1d7589b5b3bd970311981c5fb9bf04d Mon Sep 17 00:00:00 2001 From: Jean-Pierre Flori Date: Wed, 17 May 2017 12:16:05 +0000 Subject: [PATCH 376/452] Bump to libpng 1.6.29. --- build/pkgs/libpng/checksums.ini | 6 +++--- build/pkgs/libpng/package-version.txt | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build/pkgs/libpng/checksums.ini b/build/pkgs/libpng/checksums.ini index a1f7ec7bd90..c6c7adab90b 100644 --- a/build/pkgs/libpng/checksums.ini +++ b/build/pkgs/libpng/checksums.ini @@ -1,4 +1,4 @@ tarball=libpng-VERSION.tar.gz -sha1=004556d65f21baed83755f8e094112711e39ebae -md5=897ccec1ebfb0922e83c2bfaa1be8748 -cksum=1138517817 +sha1=012c842e6454dc38c6390623ed31ec4005c00584 +md5=68553080685f812d1dd7a6b8215c37d8 +cksum=1294784956 diff --git a/build/pkgs/libpng/package-version.txt b/build/pkgs/libpng/package-version.txt index 10010a4bcea..69e4e62134a 100644 --- a/build/pkgs/libpng/package-version.txt +++ b/build/pkgs/libpng/package-version.txt @@ -1 +1 @@ -1.6.28 +1.6.29 From b0bd679bac601a58a56ea781ae5f3ec61180d3a0 Mon Sep 17 00:00:00 2001 From: Dima Pasechnik Date: Wed, 17 May 2017 13:27:58 +0100 Subject: [PATCH 377/452] obsoleted by github.com/madler/zlib/issues/45 package version changed to patch-less --- build/pkgs/zlib/package-version.txt | 2 +- build/pkgs/zlib/patches/cygwin_symbols.patch | 8 -------- 2 files changed, 1 insertion(+), 9 deletions(-) delete mode 100644 build/pkgs/zlib/patches/cygwin_symbols.patch diff --git a/build/pkgs/zlib/package-version.txt b/build/pkgs/zlib/package-version.txt index 624c12b0260..c11470058fa 100644 --- a/build/pkgs/zlib/package-version.txt +++ b/build/pkgs/zlib/package-version.txt @@ -1 +1 @@ -1.2.11.p0 +1.2.11 diff --git a/build/pkgs/zlib/patches/cygwin_symbols.patch b/build/pkgs/zlib/patches/cygwin_symbols.patch deleted file mode 100644 index 97754e4e53f..00000000000 --- a/build/pkgs/zlib/patches/cygwin_symbols.patch +++ /dev/null @@ -1,8 +0,0 @@ -from https://github.com/cygwinports/zlib/blob/master/1.2.11-gzopen_w.patch ---- origsrc/zlib-1.2.11/win32/zlib.def 2017-01-01 01:37:10.000000000 -0600 -+++ src/win32/zlib.def 2017-03-03 15:41:32.326386500 -0600 -@@ -91,4 +91,3 @@ EXPORTS - inflateCodesUsed - inflateResetKeep - deflateResetKeep -- gzopen_w From 68cdf6702c8e35ee97b5d9fa508821076b78b0e7 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 17 May 2017 10:59:35 -0500 Subject: [PATCH 378/452] Fixing things from testing. --- src/sage/algebras/free_algebra_element.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/sage/algebras/free_algebra_element.py b/src/sage/algebras/free_algebra_element.py index 00d88fdbaae..764181959a0 100644 --- a/src/sage/algebras/free_algebra_element.py +++ b/src/sage/algebras/free_algebra_element.py @@ -238,8 +238,7 @@ def _acted_upon_(self, scalar, self_on_left=False): if self_on_left: return Factorization([(self, 1)]) * scalar return scalar * Factorization([(self, 1)]) - ret = super(FreeAlgebraElement, self)._acted_upon_(scalar, self_on_left) - return ret + return super(FreeAlgebraElement, self)._acted_upon_(scalar, self_on_left) # For backward compatibility #_lmul_ = _acted_upon_ From 99c99bf5a7d34e8e691e2979c0138fd09728c3a4 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 17 May 2017 11:05:07 -0500 Subject: [PATCH 379/452] Moving _divide_if_possible to EuclideanDomains. --- src/sage/algebras/weyl_algebra.py | 3 +-- src/sage/categories/euclidean_domains.py | 25 ++++++++++++++++++ .../indexed_free_module_element.pyx | 26 +------------------ 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/sage/algebras/weyl_algebra.py b/src/sage/algebras/weyl_algebra.py index 7f5a632e7e7..daafa6d8eff 100644 --- a/src/sage/algebras/weyl_algebra.py +++ b/src/sage/algebras/weyl_algebra.py @@ -26,7 +26,6 @@ from sage.categories.algebras_with_basis import AlgebrasWithBasis from sage.sets.family import Family import sage.data_structures.blas_dict as blas -from sage.modules.with_basis.indexed_free_module_element import _divide_if_possible from sage.rings.ring import Algebra from sage.rings.polynomial.polynomial_ring import PolynomialRing_general from sage.rings.polynomial.multi_polynomial_ring_generic import MPolynomialRing_generic @@ -498,7 +497,7 @@ def __truediv__(self, x): return self.__class__(F, D) - return self.__class__(F, {t: _divide_if_possible(D[t], x) for t in D}) + return self.__class__(F, {t: D[t]._divide_if_possible(x) for t in D}) __div__ = __truediv__ diff --git a/src/sage/categories/euclidean_domains.py b/src/sage/categories/euclidean_domains.py index d88dc767caf..85a018bf076 100644 --- a/src/sage/categories/euclidean_domains.py +++ b/src/sage/categories/euclidean_domains.py @@ -273,3 +273,28 @@ def quo_rem(self, other): sage: x.quo_rem(x) (1, 0) """ + + def _divide_if_possible(self, y): + """ + Divide ``self`` by ``y`` if possible and raise a + ``ValueError`` otherwise. + + EXAMPLES:: + + sage: 4._divide_if_possible(2) + 2 + sage: _.parent() + Integer Ring + + :: + + sage: 4._divide_if_possible(3) + Traceback (most recent call last): + ... + ValueError: 4 is not divisible by 3 + """ + q, r = self.quo_rem(y) + if r != 0: + raise ValueError("%s is not divisible by %s"%(self, y)) + return q + diff --git a/src/sage/modules/with_basis/indexed_free_module_element.pyx b/src/sage/modules/with_basis/indexed_free_module_element.pyx index 356f0692374..2f562d94b99 100644 --- a/src/sage/modules/with_basis/indexed_free_module_element.pyx +++ b/src/sage/modules/with_basis/indexed_free_module_element.pyx @@ -823,7 +823,7 @@ cdef class IndexedFreeModuleElement(Element): B[2] + 2*B[3] """ if not self.base_ring().is_field(): - return self.map_coefficients(lambda c: _divide_if_possible(c, x)) + return self.map_coefficients(lambda c: c._divide_if_possible(x)) F = parent(self) x = self.base_ring()( x ) @@ -833,30 +833,6 @@ cdef class IndexedFreeModuleElement(Element): __div__ = __truediv__ - -def _divide_if_possible(x, y): - """ - EXAMPLES:: - - sage: from sage.modules.with_basis.indexed_free_module_element import _divide_if_possible - sage: _divide_if_possible(4, 2) - 2 - sage: _.parent() - Integer Ring - - :: - - sage: _divide_if_possible(4, 3) - Traceback (most recent call last): - ... - ValueError: 4 is not divisible by 3 - """ - q, r = x.quo_rem(y) - if r != 0: - raise ValueError("%s is not divisible by %s"%(x, y)) - else: - return q - def _unpickle_element(C, d): """ Unpickle an element in ``C`` given by ``d``. From cafb215ba2b808eb5207bf12aed48bb1e01bb235 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 17 May 2017 11:08:34 -0500 Subject: [PATCH 380/452] Remove map_coefficients call in __truediv__. --- .../modules/with_basis/indexed_free_module_element.pyx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/sage/modules/with_basis/indexed_free_module_element.pyx b/src/sage/modules/with_basis/indexed_free_module_element.pyx index 2f562d94b99..f8ef3d1048e 100644 --- a/src/sage/modules/with_basis/indexed_free_module_element.pyx +++ b/src/sage/modules/with_basis/indexed_free_module_element.pyx @@ -822,14 +822,15 @@ cdef class IndexedFreeModuleElement(Element): sage: f/2 B[2] + 2*B[3] """ + F = parent(self) if not self.base_ring().is_field(): - return self.map_coefficients(lambda c: c._divide_if_possible(x)) + return type(self)(F, {k: c._divide_if_possible(x) + for k,c in self._monomial_cofficients.iteritems()}) - F = parent(self) x = self.base_ring()( x ) x_inv = x ** -1 D = self._monomial_coefficients - return type(self)(parent(self), scal(x_inv, D)) + return type(self)(F, scal(x_inv, D)) __div__ = __truediv__ From a8eeca663681d30ea986fd15a5f90d30b5363059 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 17 May 2017 11:20:19 -0500 Subject: [PATCH 381/452] Remove comment and deprecate CombinatorialFreeModuleElement. --- src/sage/combinat/free_module.py | 30 +++++++++++++++++++ .../indexed_free_module_element.pyx | 1 - 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/sage/combinat/free_module.py b/src/sage/combinat/free_module.py index 5beb1f9f603..9ebbad0e3c3 100644 --- a/src/sage/combinat/free_module.py +++ b/src/sage/combinat/free_module.py @@ -1126,6 +1126,36 @@ def _from_dict(self, d, coerce=False, remove_zeros=True): d = {key: coeff for key, coeff in six.iteritems(d) if coeff} return self.element_class( self, d ) +class CombinatorialFreeModuleElement(CombinatorialFreeModule.Element): + """ + Deprecated. Use + :class:`sage.modules.with_basis.indexed_free_module_element.IndexedFreeModuleElement` + or :class:`CombinatorialFreeModule.Element` instead. + """ + def __init__(self, *args, **kwds): + """ + TESTS:: + + sage: from sage.combinat.free_module import CombinatorialFreeModuleElement + sage: class Test(CombinatorialFreeModule): + ....: class Element(CombinatorialFreeModuleElement): + ....: pass + sage: T = Test(QQ, (1,2)) + sage: T.an_element() + doctest:warning + ... + DeprecationWarning: CombinatorialFreeModuleElement is deprecated. + Use IndexedFreeModuleElement or CombinatorialFreeModule.Element instead. + See http://trac.sagemath.org/22632 for details. + 2*B[1] + 2*B[2] + """ + from sage.misc.superseded import deprecation + deprecation(22632, "CombinatorialFreeModuleElement is deprecated." + " Use IndexedFreeModuleElement" + " or CombinatorialFreeModule.Element instead.") + super(CombinatorialFreeModuleElement, self).__init__(*args, **kwds) + + class CombinatorialFreeModule_Tensor(CombinatorialFreeModule): """ Tensor Product of Free Modules diff --git a/src/sage/modules/with_basis/indexed_free_module_element.pyx b/src/sage/modules/with_basis/indexed_free_module_element.pyx index f8ef3d1048e..68f85b3f077 100644 --- a/src/sage/modules/with_basis/indexed_free_module_element.pyx +++ b/src/sage/modules/with_basis/indexed_free_module_element.pyx @@ -31,7 +31,6 @@ from sage.typeset.unicode_art import UnicodeArt, empty_unicode_art from sage.categories.all import Category, Sets, ModulesWithBasis from sage.data_structures.blas_dict cimport add, negate, scal, axpy -# TODO: move the content of this class to CombinatorialFreeModule.Element and ModulesWithBasis.Element cdef class IndexedFreeModuleElement(Element): def __init__(self, M, x): """ From 6b9694218d2cf7ba2ad82f9db3a9bd6c8d13f47b Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 17 May 2017 11:25:07 -0500 Subject: [PATCH 382/452] Rename indexed_free_module_element to indexed_element. --- src/module_list.py | 4 ++-- src/sage/algebras/free_algebra_element.py | 2 +- src/sage/algebras/steenrod/steenrod_algebra.py | 4 ++-- src/sage/categories/examples/filtered_modules_with_basis.py | 2 +- src/sage/categories/examples/graded_modules_with_basis.py | 2 +- src/sage/combinat/free_module.py | 6 +++--- ...{indexed_free_module_element.pxd => indexed_element.pxd} | 0 ...{indexed_free_module_element.pyx => indexed_element.pyx} | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) rename src/sage/modules/with_basis/{indexed_free_module_element.pxd => indexed_element.pxd} (100%) rename src/sage/modules/with_basis/{indexed_free_module_element.pyx => indexed_element.pyx} (99%) diff --git a/src/module_list.py b/src/module_list.py index f6a71765d8b..7b5f2fe7064 100644 --- a/src/module_list.py +++ b/src/module_list.py @@ -1034,8 +1034,8 @@ def uname_specific(name, value, alternative): Extension('sage.modules.vector_real_double_dense', ['sage/modules/vector_real_double_dense.pyx']), - Extension('sage.modules.with_basis.indexed_free_module_element', - sources = ['sage/modules/with_basis/indexed_free_module_element.pyx']), + Extension('sage.modules.with_basis.indexed_element', + sources = ['sage/modules/with_basis/indexed_element.pyx']), ################################ ## diff --git a/src/sage/algebras/free_algebra_element.py b/src/sage/algebras/free_algebra_element.py index 764181959a0..b719b53b733 100644 --- a/src/sage/algebras/free_algebra_element.py +++ b/src/sage/algebras/free_algebra_element.py @@ -37,7 +37,7 @@ from sage.misc.misc import repr_lincomb from sage.monoids.free_monoid_element import FreeMonoidElement -from sage.modules.with_basis.indexed_free_module_element import IndexedFreeModuleElement +from sage.modules.with_basis.indexed_element import IndexedFreeModuleElement from sage.combinat.free_module import CombinatorialFreeModule from sage.structure.element import AlgebraElement from sage.structure.sage_object import richcmp diff --git a/src/sage/algebras/steenrod/steenrod_algebra.py b/src/sage/algebras/steenrod/steenrod_algebra.py index b1f3b7262a7..243445657ef 100644 --- a/src/sage/algebras/steenrod/steenrod_algebra.py +++ b/src/sage/algebras/steenrod/steenrod_algebra.py @@ -3079,7 +3079,7 @@ class Element(CombinatorialFreeModule.Element): :class:`CombinatorialFreeModule `, this is based on :class:`IndexedFreeModuleElement - `. + `. It has new methods reflecting its role, like :meth:`degree` for computing the degree of an element. @@ -3087,7 +3087,7 @@ class Element(CombinatorialFreeModule.Element): Since this class inherits from :class:`IndexedFreeModuleElement - `, + `, elements can be used as iterators, and there are other useful methods:: diff --git a/src/sage/categories/examples/filtered_modules_with_basis.py b/src/sage/categories/examples/filtered_modules_with_basis.py index ed00ac97b57..e4f8a52dd9e 100644 --- a/src/sage/categories/examples/filtered_modules_with_basis.py +++ b/src/sage/categories/examples/filtered_modules_with_basis.py @@ -64,7 +64,7 @@ class FilteredPartitionModule(CombinatorialFreeModule): - There is a class for elements, which inherits from :class:`IndexedFreeModuleElement - `. + `. An element is determined by a dictionary whose keys are partitions and whose corresponding values are the coefficients. The class implements two things: an :meth:`is_homogeneous diff --git a/src/sage/categories/examples/graded_modules_with_basis.py b/src/sage/categories/examples/graded_modules_with_basis.py index 7af0ff2ed99..6e32d51601c 100644 --- a/src/sage/categories/examples/graded_modules_with_basis.py +++ b/src/sage/categories/examples/graded_modules_with_basis.py @@ -78,7 +78,7 @@ class GradedPartitionModule(CombinatorialFreeModule): - There is a class for elements, which inherits from :class:`IndexedFreeModuleElement - `. + `. An element is determined by a dictionary whose keys are partitions and whose corresponding values are the coefficients. The class implements two things: an :meth:`is_homogeneous diff --git a/src/sage/combinat/free_module.py b/src/sage/combinat/free_module.py index 9ebbad0e3c3..9d48fcbf119 100644 --- a/src/sage/combinat/free_module.py +++ b/src/sage/combinat/free_module.py @@ -19,7 +19,7 @@ from sage.modules.module import Module from sage.rings.all import Integer from sage.structure.element import parent -from sage.modules.with_basis.indexed_free_module_element import IndexedFreeModuleElement +from sage.modules.with_basis.indexed_element import IndexedFreeModuleElement from sage.sets.finite_enumerated_set import FiniteEnumeratedSet from sage.combinat.cartesian_product import CartesianProduct_iters from sage.sets.disjoint_union_enumerated_sets import DisjointUnionEnumeratedSets @@ -47,7 +47,7 @@ class CombinatorialFreeModule(UniqueRepresentation, Module, IndexedGenerators): - ``element_class`` - the class of which elements of this module should be instances (optional, default None, in which case the elements are instances of - :class:`~sage.modules.with_basis.indexed_free_module_element.IndexedFreeModuleElement`) + :class:`~sage.modules.with_basis.indexed_element.IndexedFreeModuleElement`) - ``category`` - the category in which this module lies (optional, default None, in which case use the "category of modules with @@ -1129,7 +1129,7 @@ def _from_dict(self, d, coerce=False, remove_zeros=True): class CombinatorialFreeModuleElement(CombinatorialFreeModule.Element): """ Deprecated. Use - :class:`sage.modules.with_basis.indexed_free_module_element.IndexedFreeModuleElement` + :class:`sage.modules.with_basis.indexed_element.IndexedFreeModuleElement` or :class:`CombinatorialFreeModule.Element` instead. """ def __init__(self, *args, **kwds): diff --git a/src/sage/modules/with_basis/indexed_free_module_element.pxd b/src/sage/modules/with_basis/indexed_element.pxd similarity index 100% rename from src/sage/modules/with_basis/indexed_free_module_element.pxd rename to src/sage/modules/with_basis/indexed_element.pxd diff --git a/src/sage/modules/with_basis/indexed_free_module_element.pyx b/src/sage/modules/with_basis/indexed_element.pyx similarity index 99% rename from src/sage/modules/with_basis/indexed_free_module_element.pyx rename to src/sage/modules/with_basis/indexed_element.pyx index 68f85b3f077..e3ef1aa95ca 100644 --- a/src/sage/modules/with_basis/indexed_free_module_element.pyx +++ b/src/sage/modules/with_basis/indexed_element.pyx @@ -839,7 +839,7 @@ def _unpickle_element(C, d): EXAMPLES:: - sage: from sage.modules.with_basis.indexed_free_module_element import _unpickle_element + sage: from sage.modules.with_basis.indexed_element import _unpickle_element sage: C = CombinatorialFreeModule(QQ, [1,2,3]) sage: _unpickle_element(C, {1: -2, 3: -12}) -2*B[1] - 12*B[3] From f66cb0d2a72a70fb65d22bc115d75d4e85614899 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 17 May 2017 11:28:15 -0500 Subject: [PATCH 383/452] Updating tutorial. --- .../en/thematic_tutorials/tutorial-objects-and-classes.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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 749ab5fd1da..ccf5ff9cc15 100644 --- a/src/doc/en/thematic_tutorials/tutorial-objects-and-classes.rst +++ b/src/doc/en/thematic_tutorials/tutorial-objects-and-classes.rst @@ -289,8 +289,9 @@ Some particular actions modify the data structure of ``el``:: Lots of Sage objects are not Python objects but compiled Cython objects. Python sees them as builtin objects and you don't have access to - the data structure. Examples include integers and permutation group - elements:: + the data structure. In particular, we do not see the + ``_monomial_coefficients`` in the ``__dict__`` above. Other examples + include integers and permutation group elements:: sage: e = Integer(9) sage: type(e) From e0553bef39dbcee0dbaf72e6e38f9ad93f87d1c3 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 17 May 2017 11:44:00 -0500 Subject: [PATCH 384/452] Adding comments about pickles. --- src/sage/combinat/free_module.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sage/combinat/free_module.py b/src/sage/combinat/free_module.py index 9d48fcbf119..00c2f77fa73 100644 --- a/src/sage/combinat/free_module.py +++ b/src/sage/combinat/free_module.py @@ -291,7 +291,8 @@ def __classcall_private__(cls, base_ring, basis_keys, category = None, prefix="B class Element(IndexedFreeModuleElement): def __setstate__(self, state): r""" - For unpickling. + For unpickling old ``CombinatorialFreeModuleElement`` classes. + See :trac:`22632`. EXAMPLES:: @@ -1796,6 +1797,7 @@ class Element(CombinatorialFreeModule.Element): # TODO: get rid of this inherita CombinatorialFreeModule.CartesianProduct = CombinatorialFreeModule_CartesianProduct +# Handle old CombinatorialFreeModuleElement pickles, see trac #22632 from sage.structure.sage_object import register_unpickle_override register_unpickle_override("sage.combinat.free_module", "CombinatorialFreeModuleElement", From c0596c1f88795b6f9d5720de3ea5b7a8a3d01f35 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 17 May 2017 11:55:53 -0500 Subject: [PATCH 385/452] Fixing typo in the references. --- src/doc/en/reference/references/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 88f3606f856..d6228ba45ed 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -1527,7 +1527,7 @@ REFERENCES: .. [SS2015II] Ben Salisbury and Travis Scrimshaw. *A rigged configuration model for* `B(\infty)`. - J. Combin. Theory Ser. A, ***133** (2015) pp. 29-75. + J. Combin. Theory Ser. A, **133** (2015) pp. 29-75. :arxiv:`1404.6539`. .. [SS2017] Ben Salisbury and Travis Scrimshaw. From 9ece935248c3d05af877b5d40b282718e3480a6a Mon Sep 17 00:00:00 2001 From: Emile Nadeau Date: Wed, 17 May 2017 13:54:35 -0400 Subject: [PATCH 386/452] 23019: documentation fix for ImplicitSuffixTree.transition_function --- src/sage/combinat/words/suffix_trees.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/words/suffix_trees.py b/src/sage/combinat/words/suffix_trees.py index 5802b9b7909..54ac719108b 100644 --- a/src/sage/combinat/words/suffix_trees.py +++ b/src/sage/combinat/words/suffix_trees.py @@ -937,7 +937,7 @@ def transition_function(self, word, node=0): r""" Returns the node obtained by starting from ``node`` and following the edges labelled by the letters of ``word``. Returns ``("explicit", - end_node)`` if we end at ``end_node``, or ``("implicit", (edge, d))`` + end_node)`` if we end at ``end_node``, or ``("implicit", edge, d)`` if we end `d` spots along an edge. INPUT: From 7f3aef2234d24c48fbdd91bf348443dee2393890 Mon Sep 17 00:00:00 2001 From: Ben Salisbury Date: Wed, 17 May 2017 16:32:58 -0400 Subject: [PATCH 387/452] fixed reference doc failures --- src/doc/en/reference/references/index.rst | 9 ++++----- src/sage/combinat/rigged_configurations/kr_tableaux.py | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index d6228ba45ed..2914ff8a9d0 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -821,8 +821,8 @@ REFERENCES: function fields and related topics," J. Symbolic Comput. 33 (2002), no. 4, 425--445. -.. [Hig2008] \N. J. Higham, "Functions of matrices: theory and computation", - Society for Industrial and Applied Mathematics (2008). +.. [Hig2008] \N. J. Higham, "Functions of matrices: theory and computation", + Society for Industrial and Applied Mathematics (2008). .. [HJ2004] Tom Hoeholdt and Joern Justesen, A Course In Error-Correcting Codes, EMS, 2004 @@ -1520,10 +1520,9 @@ REFERENCES: manifolds and complexes into a cubic lattice", *Uspekhi Mat. Nauk* 47 (1992), 219-220. - .. [SS2015] Anne Schilling and Travis Scrimshaw. *Crystal structure on rigged configurations and the filling map*. - Electon. J. Combin., **22**(1) (2015) #P1.73. :arxiv:`1409.2920`. + Electon. J. Combin., **22(1)** (2015) #P1.73. :arxiv:`1409.2920`. .. [SS2015II] Ben Salisbury and Travis Scrimshaw. *A rigged configuration model for* `B(\infty)`. @@ -1532,7 +1531,7 @@ REFERENCES: .. [SS2017] Ben Salisbury and Travis Scrimshaw. *Rigged configurations for all symmetrizable types*. - Electon. J. Combin., **24**(1) (2017) #P1.30. :arxiv:`1509.07833`. + Electon. J. Combin., **24(1)** (2017) #P1.30. :arxiv:`1509.07833`. .. [ST2011] \A. Schilling, P. Tingley. *Demazure crystals, Kirillov-Reshetikhin crystals, and the energy function*. diff --git a/src/sage/combinat/rigged_configurations/kr_tableaux.py b/src/sage/combinat/rigged_configurations/kr_tableaux.py index d17a30d98ef..e98ad5f0517 100644 --- a/src/sage/combinat/rigged_configurations/kr_tableaux.py +++ b/src/sage/combinat/rigged_configurations/kr_tableaux.py @@ -5,7 +5,7 @@ `s` columns that naturally arise under the bijection between rigged configurations and tableaux [RigConBijection]_. They are in bijection with the elements of the Kirillov-Reshetikhin crystal `B^{r,s}` under the (inverse) -filling map [OSS13]_ [SchScr]_. They do not have to satisfy the semistandard row or column +filling map [OSS13]_ [SS2015]_. They do not have to satisfy the semistandard row or column restrictions. These tensor products are the result from the bijection from rigged configurations [RigConBijection]_. From 484e33b02e75578590d9646b652135a885bd248a Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 17 May 2017 16:22:56 -0500 Subject: [PATCH 388/452] Fixing doctest failures due to coercion needing old RCs. --- .../lie/infinity_crystals.rst | 4 ++-- .../combinat/crystals/infinity_crystals.py | 7 ++++-- .../rigged_configurations/bij_infinity.py | 6 +++-- .../rigged_configurations/rc_infinity.py | 24 ++++++++++++++++++- 4 files changed, 34 insertions(+), 7 deletions(-) diff --git a/src/doc/en/thematic_tutorials/lie/infinity_crystals.rst b/src/doc/en/thematic_tutorials/lie/infinity_crystals.rst index 3cbce10f7b8..70b470a8dfb 100644 --- a/src/doc/en/thematic_tutorials/lie/infinity_crystals.rst +++ b/src/doc/en/thematic_tutorials/lie/infinity_crystals.rst @@ -298,8 +298,8 @@ See [SalisburyScrimshaw2015]_ for more information:: sage: RiggedConfigurations.options(display="horizontal") sage: RC = crystals.infinity.RiggedConfigurations(['C',3,1]) sage: nu = RC.highest_weight_vector().f_string([0,1,2,3,2,1,0]); nu - -2[ ]-1 2[ ][ ]1 0[ ][ ]0 0[ ]0 - -2[ ]-1 + -2[ ]-1 2[ ]1 0[ ]0 0[ ]0 + -2[ ]-1 2[ ]1 0[ ]0 sage: nu.weight() -2*Lambda[0] + 2*Lambda[1] - 2*delta sage: RiggedConfigurations.options._reset() diff --git a/src/sage/combinat/crystals/infinity_crystals.py b/src/sage/combinat/crystals/infinity_crystals.py index 84bedef47d8..545b597261f 100644 --- a/src/sage/combinat/crystals/infinity_crystals.py +++ b/src/sage/combinat/crystals/infinity_crystals.py @@ -294,8 +294,11 @@ def _coerce_map_from_(self, P): From: The infinity crystal of rigged configurations of type ['A', 3] To: The infinity crystal of tableaux of type ['A', 3] """ - from sage.combinat.rigged_configurations.rc_infinity import InfinityCrystalOfRiggedConfigurations - if isinstance(P, InfinityCrystalOfRiggedConfigurations): + from sage.combinat.rigged_configurations.rc_infinity import (InfinityCrystalOfRiggedConfigurations, + InfinityCrystalOfNonSimplyLacedRC) + if (isinstance(P, InfinityCrystalOfRiggedConfigurations) + and (self.cartan_type().is_simply_laced() + or isinstance(P, InfinityCrystalOfNonSimplyLacedRC))): from sage.combinat.rigged_configurations.bij_infinity import FromRCIsomorphism return FromRCIsomorphism(Hom(P, self)) return super(InfinityCrystalOfTableaux, self)._coerce_map_from_(P) diff --git a/src/sage/combinat/rigged_configurations/bij_infinity.py b/src/sage/combinat/rigged_configurations/bij_infinity.py index eef0e31695e..04e7494805a 100644 --- a/src/sage/combinat/rigged_configurations/bij_infinity.py +++ b/src/sage/combinat/rigged_configurations/bij_infinity.py @@ -214,7 +214,8 @@ def run(self): EXAMPLES:: - sage: RC = crystals.infinity.RiggedConfigurations(['B',4]) + sage: vct = CartanType(['B',4]).as_folding() + sage: RC = crystals.infinity.RiggedConfigurations(vct) sage: T = crystals.infinity.Tableaux(['B',4]) sage: Psi = T.crystal_morphism({T.module_generators[0]: RC.module_generators[0]}) sage: TS = [x.value for x in T.subcrystal(max_depth=4)] @@ -251,7 +252,8 @@ def run(self): EXAMPLES:: - sage: RC = crystals.infinity.RiggedConfigurations(['B',4]) + sage: vct = CartanType(['B',4]).as_folding() + sage: RC = crystals.infinity.RiggedConfigurations(vct) sage: T = crystals.infinity.Tableaux(['B',4]) sage: Psi = RC.crystal_morphism({RC.module_generators[0]: T.module_generators[0]}) sage: RCS = [x.value for x in RC.subcrystal(max_depth=4)] diff --git a/src/sage/combinat/rigged_configurations/rc_infinity.py b/src/sage/combinat/rigged_configurations/rc_infinity.py index 066723f6758..a5469197973 100644 --- a/src/sage/combinat/rigged_configurations/rc_infinity.py +++ b/src/sage/combinat/rigged_configurations/rc_infinity.py @@ -234,7 +234,8 @@ def _coerce_map_from_(self, P): """ if self.cartan_type().is_finite(): from sage.combinat.crystals.infinity_crystals import InfinityCrystalOfTableaux - if isinstance(P, InfinityCrystalOfTableaux): + if (isinstance(P, InfinityCrystalOfTableaux) + and self.cartan_type().is_simply_laced()): from sage.combinat.rigged_configurations.bij_infinity import FromTableauIsomorphism return FromTableauIsomorphism(Hom(P, self)) return super(InfinityCrystalOfRiggedConfigurations, self)._coerce_map_from_(P) @@ -332,6 +333,27 @@ def __init__(self, vct): self._folded_ct = vct InfinityCrystalOfRiggedConfigurations.__init__(self, vct._cartan_type) + def _coerce_map_from_(self, P): + """ + Return ``True`` or the coerce map from ``P`` if a map exists. + + EXAMPLES:: + + sage: T = crystals.infinity.Tableaux(['C',3]) + sage: vct = CartanType(['C',3]).as_folding() + sage: RC = crystals.infinity.RiggedConfigurations(vct) + sage: RC._coerce_map_from_(T) + Crystal Isomorphism morphism: + From: The infinity crystal of tableaux of type ['A', 3] + To: The infinity crystal of rigged configurations of type ['A', 3] + """ + if self.cartan_type().is_finite(): + from sage.combinat.crystals.infinity_crystals import InfinityCrystalOfTableaux + if isinstance(P, InfinityCrystalOfTableaux): + from sage.combinat.rigged_configurations.bij_infinity import FromTableauIsomorphism + return FromTableauIsomorphism(Hom(P, self)) + return super(InfinityCrystalOfNonSimplyLacedRC, self)._coerce_map_from_(P) + def _calc_vacancy_number(self, partitions, a, i): r""" Calculate the vacancy number `p_i^{(a)}(\nu)` in ``self``. From 9fd1172c37e5f9d71ee60c2e84f60119edf589e5 Mon Sep 17 00:00:00 2001 From: Ben Salisbury Date: Wed, 17 May 2017 21:40:48 -0400 Subject: [PATCH 389/452] Fixed a doctest failure --- src/sage/combinat/rigged_configurations/rc_infinity.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/combinat/rigged_configurations/rc_infinity.py b/src/sage/combinat/rigged_configurations/rc_infinity.py index a5469197973..fd9b60042bc 100644 --- a/src/sage/combinat/rigged_configurations/rc_infinity.py +++ b/src/sage/combinat/rigged_configurations/rc_infinity.py @@ -344,8 +344,8 @@ def _coerce_map_from_(self, P): sage: RC = crystals.infinity.RiggedConfigurations(vct) sage: RC._coerce_map_from_(T) Crystal Isomorphism morphism: - From: The infinity crystal of tableaux of type ['A', 3] - To: The infinity crystal of rigged configurations of type ['A', 3] + From: The infinity crystal of tableaux of type ['C', 3] + To: The infinity crystal of rigged configurations of type ['C', 3] """ if self.cartan_type().is_finite(): from sage.combinat.crystals.infinity_crystals import InfinityCrystalOfTableaux From ae3fe14d273598dd9f46fa9771b599fcacd114c9 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 17 May 2017 21:35:48 -0500 Subject: [PATCH 390/452] Added Essential quasisymmetric functions. --- src/sage/combinat/ncsf_qsym/qsym.py | 84 ++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) diff --git a/src/sage/combinat/ncsf_qsym/qsym.py b/src/sage/combinat/ncsf_qsym/qsym.py index 092d4c81c6f..4de96e98c9a 100644 --- a/src/sage/combinat/ncsf_qsym/qsym.py +++ b/src/sage/combinat/ncsf_qsym/qsym.py @@ -52,6 +52,11 @@ non-commutative symmetric functions*, :arxiv:`1208.5191v3`. +.. [Hoff2015] Michael Hoffman. + *Quasi-symmetric functions and mod* `p` *multiple harmonic sums*. + Kyushu J. Math. **69** (2015), pp. 345-366. + :doi:`10.2206/kyushujm.69.345`, :arxiv:`math/0401319v3`. + AUTHOR: - Jason Bandlow @@ -610,7 +615,7 @@ def a_realization(self): """ return self.Monomial() - _shorthands = tuple(['M', 'F', 'dI', 'QS']) + _shorthands = tuple(['M', 'F', 'E', 'dI', 'QS']) def dual(self): r""" @@ -2574,6 +2579,83 @@ def star_involution(self): F = Fundamental + class Essential(CombinatorialFreeModule, BindableClass): + r""" + The Hopf algebra of quasi-symmetric functions in the Essential basis. + + The Essential quasisymmetric functions are defined by + + .. MATH:: + + E_I = \sum_{J \geq I} M_J = \sum_{i_1 \leq \cdots \leq i_k} + x_{i_1}^{I_1} \cdots x_{i_k}^{I_k}, + + where `I = (I_1, \ldots, I_k)`. + + .. NOTE:: + + Our convention of `\leq` and `\geq` of compositions is + opposite that of [Hoff2015]_. + + EXAMPLES:: + + sage: QSym = QuasiSymmetricFunctions(QQ) + sage: E = QSym.E() + sage: M = QSym.M() + sage: E(M[2,2]) + E[2, 2] - E[4] + sage: s = SymmetricFunctions(QQ).s() + sage: E(s[3,2]) + 5*E[1, 1, 1, 1, 1] - 2*E[1, 1, 1, 2] - 2*E[1, 1, 2, 1] + - 2*E[1, 2, 1, 1] + E[1, 2, 2] - 2*E[2, 1, 1, 1] + + E[2, 1, 2] + E[2, 2, 1] + sage: (1 + E[1])^3 + E[] + 3*E[1] + 6*E[1, 1] + 6*E[1, 1, 1] - 3*E[1, 2] + - 3*E[2] - 3*E[2, 1] + E[3] + sage: E[1,2,1].coproduct() + E[] # E[1, 2, 1] + E[1] # E[2, 1] + E[1, 2] # E[1] + E[1, 2, 1] # E[] + + The following is an alias for this basis:: + + sage: QSym.Essential() + Quasisymmetric functions over the Rational Field in the Essential basis + + TESTS:: + + sage: E(M([])) + E[] + sage: E(M(0)) + 0 + sage: E(s([])) + E[] + sage: E(s(0)) + 0 + """ + def __init__(self, QSym): + """ + EXAMPLES:: + + sage: E = QuasiSymmetricFunctions(QQ).Essential(); E + Quasisymmetric functions over the Rational Field in the Essential basis + sage: TestSuite(E).run() + """ + CombinatorialFreeModule.__init__(self, QSym.base_ring(), Compositions(), + prefix='E', bracket=False, + category=QSym.Bases()) + + M = QSym.M() + category = self.realization_of()._category + # This changes Monomial into Essential + M.module_morphism(self.alternating_sum_of_fatter_compositions, + codomain=self, category=category + ).register_as_coercion() + # This changes Essential into Monomial + self.module_morphism(M.sum_of_fatter_compositions, + codomain=M, category=category + ).register_as_coercion() + + E = Essential + class Quasisymmetric_Schur(CombinatorialFreeModule, BindableClass): r""" The Hopf algebra of quasi-symmetric function in the Quasisymmetric From ee64266d0c7b7bd374d2c9cfdaa417ed5286de10 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Wed, 17 May 2017 22:13:45 -0500 Subject: [PATCH 391/452] Implementing operations directly on the Essential basis. --- src/sage/combinat/ncsf_qsym/qsym.py | 102 ++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/src/sage/combinat/ncsf_qsym/qsym.py b/src/sage/combinat/ncsf_qsym/qsym.py index 4de96e98c9a..f1ff6892bc1 100644 --- a/src/sage/combinat/ncsf_qsym/qsym.py +++ b/src/sage/combinat/ncsf_qsym/qsym.py @@ -2654,6 +2654,108 @@ def __init__(self, QSym): codomain=M, category=category ).register_as_coercion() + def antipode_on_basis(self, compo): + r""" + Return the result of the antipode applied to a quasi-symmetric + Essential basis element. + + INPUT: + + - ``compo`` -- composition + + OUTPUT: + + - The result of the antipode applied to the composition ``compo``, + expressed in the Essential basis. + + EXAMPLES:: + + sage: E = QuasiSymmetricFunctions(QQ).E() + sage: E.antipode_on_basis(Composition([2,1])) + E[1, 2] - E[3] + sage: E.antipode_on_basis(Composition([])) + E[] + + TESTS:: + + sage: E = QuasiSymmetricFunctions(QQ).E() + sage: M = QuasiSymmetricFunctions(QQ).M() + sage: all(E(M(E[c]).antipode()) == E[c].antipode() + ....: for n in range(5) for c in Compositions(n)) + True + """ + return (-1)**len(compo) * self.alternating_sum_of_fatter_compositions(compo.reversed()) + + def coproduct_on_basis(self, compo): + r""" + Return the coproduct of a Essential basis element. + + Combinatorial rule: deconcatenation. + + INPUT: + + - ``compo`` -- composition + + OUTPUT: + + - The coproduct applied to the Essential quasi-symmetric function + indexed by ``compo``, expressed in the Essential basis. + + EXAMPLES:: + + sage: E = QuasiSymmetricFunctions(QQ).Essential() + sage: E[4,2,3].coproduct() + E[] # E[4, 2, 3] + E[4] # E[2, 3] + E[4, 2] # E[3] + E[4, 2, 3] # E[] + sage: E.coproduct_on_basis(Composition([])) + E[] # E[] + """ + return self.tensor_square().sum_of_monomials((self._indices(compo[:i]), + self._indices(compo[i:])) + for i in range(0,len(compo)+1)) + + def product_on_basis(self, I, J): + """ + The product on Essential basis elements. + + The product of the basis elements indexed by two compositions + `I` and `J` is the sum of the basis elements indexed by + compositions in the stuffle product (also called the + overlapping shuffle product) of `I` and `J` with a + coefficient of `(-1)^L`, where `L` is the length of the composition. + + INPUT: + + - ``I``, ``J`` -- compositions + + OUTPUT: + + - The product of the Essential quasi-symmetric functions indexed + by ``I`` and ``J``, expressed in the Essential basis. + + EXAMPLES:: + + sage: E = QuasiSymmetricFunctions(QQ).E() + sage: c1 = Composition([2]) + sage: c2 = Composition([1,3]) + sage: E.product_on_basis(c1, c2) + E[1, 2, 3] + E[1, 3, 2] - E[1, 5] + E[2, 1, 3] - E[3, 3] + sage: E.product_on_basis(c1, Composition([])) + E[2] + sage: E.product_on_basis(c1, Composition([3])) + E[2, 3] + E[3, 2] - E[5] + + TESTS:: + + sage: E = QuasiSymmetricFunctions(QQ).E() + sage: M = QuasiSymmetricFunctions(QQ).M() + sage: all(E(M(E[cp])*M(E[c])) == E[cp]*E[c] # long time + ....: for c in Compositions(3) for cp in Compositions(5)) + True + """ + n = len(I) + len(J) + return self.sum_of_terms((K, (-1)**(n - len(K))) + for K in I.shuffle_product(J, overlap=True)) + E = Essential class Quasisymmetric_Schur(CombinatorialFreeModule, BindableClass): From 5e494ad504d2f86b56c1c956518ad7d48807f51c Mon Sep 17 00:00:00 2001 From: Jeroen Demeyer Date: Thu, 18 May 2017 09:21:06 +0200 Subject: [PATCH 392/452] Reformat Makefile rule --- src/Makefile.in | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Makefile.in b/src/Makefile.in index 49e18df2135..eba5e9a4c75 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -31,18 +31,18 @@ all: sage ## [sagelib-7.4.beta4] running install ## [sagelib-7.4.beta4] error: install-base or install-platbase supplied, but installation scheme is incomplete sage: - (cd $(srcdir) \ - && export SAGE_ROOT=/doesnotexist \ - SAGE_SRC=/doesnotexist \ - SAGE_SRC_ROOT=/doesnotexist \ - SAGE_DOC_SRC=/doesnotexist \ - SAGE_BUILD_DIR=/doesnotexist \ - SAGE_PKGS=$(abs_top_srcdir)/build/pkgs \ - SAGE_CYTHONIZED=$(abs_builddir)/build/cythonized \ - && sage-python23 -u setup.py --no-user-cfg build install \ - && if [ "$$UNAME" = "CYGWIN" ]; then \ - sage-rebase.sh "$$SAGE_LOCAL" 2>/dev/null; \ - fi) + cd $(srcdir) && export \ + SAGE_ROOT=/doesnotexist \ + SAGE_SRC=/doesnotexist \ + SAGE_SRC_ROOT=/doesnotexist \ + SAGE_DOC_SRC=/doesnotexist \ + SAGE_BUILD_DIR=/doesnotexist \ + SAGE_PKGS=$(abs_top_srcdir)/build/pkgs \ + SAGE_CYTHONIZED=$(abs_builddir)/build/cythonized \ + && sage-python23 -u setup.py --no-user-cfg build install + if [ "$$UNAME" = "CYGWIN" ]; then \ + sage-rebase.sh "$$SAGE_LOCAL" 2>/dev/null; \ + fi clean: @echo "Deleting Sage library build artifacts..." From cd4857df62368797028fdf15870d090b81bfb34d Mon Sep 17 00:00:00 2001 From: Jeroen Demeyer Date: Thu, 18 May 2017 10:37:35 +0200 Subject: [PATCH 393/452] Use patched Cython for farey_symbol --- src/sage/modular/arithgroup/farey.cpp | 8 +------- src/sage/modular/arithgroup/farey_symbol.pyx | 5 +++-- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/sage/modular/arithgroup/farey.cpp b/src/sage/modular/arithgroup/farey.cpp index 6e18266ef9f..142774d95c7 100644 --- a/src/sage/modular/arithgroup/farey.cpp +++ b/src/sage/modular/arithgroup/farey.cpp @@ -29,14 +29,8 @@ #include #include "farey.hpp" +#include "sage/modular/arithgroup/farey_symbol.h" -// The following functions are defined in farey_symbols.h, but direct inclusion -// of this file breaks compilation on cygwin, see trac #13336. -extern "C" long convert_to_long(PyObject *); -extern "C" PyObject *convert_to_Integer(mpz_class); -extern "C" PyObject *convert_to_rational(mpq_class); -extern "C" PyObject *convert_to_cusp(mpq_class); -extern "C" PyObject *convert_to_SL2Z(SL2Z); using namespace std; diff --git a/src/sage/modular/arithgroup/farey_symbol.pyx b/src/sage/modular/arithgroup/farey_symbol.pyx index cde53809c1e..7df08d4017a 100644 --- a/src/sage/modular/arithgroup/farey_symbol.pyx +++ b/src/sage/modular/arithgroup/farey_symbol.pyx @@ -1,3 +1,4 @@ +# distutils: sources = sage/modular/arithgroup/sl2z.cpp sage/modular/arithgroup/farey.cpp r""" Farey Symbol for arithmetic subgroups of `{\rm PSL}_2(\ZZ)` @@ -49,7 +50,7 @@ from sage.misc.cachefunc import cached_method from sage.structure.sage_object cimport richcmp_not_equal -cdef extern from "sage/modular/arithgroup/sl2z.cpp": +cdef extern from "sage/modular/arithgroup/sl2z.hpp": cppclass cpp_SL2Z "SL2Z": mpz_class a, b, c, d cpp_SL2Z(int, int, int, int) @@ -59,7 +60,7 @@ cdef extern from "sage/modular/arithgroup/sl2z.cpp": mpz_class c() mpz_class d() -cdef extern from "sage/modular/arithgroup/farey.cpp": +cdef extern from "sage/modular/arithgroup/farey.hpp": cppclass is_element_Gamma0: is_element_Gamma0(int) cppclass is_element_Gamma1: From 84ca0e88135280c791408cb18380eaf8e324cd67 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 18 May 2017 08:45:36 -0500 Subject: [PATCH 394/452] Addressing Darij's comments. --- src/sage/combinat/ncsf_qsym/qsym.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/src/sage/combinat/ncsf_qsym/qsym.py b/src/sage/combinat/ncsf_qsym/qsym.py index f1ff6892bc1..8c05a40d981 100644 --- a/src/sage/combinat/ncsf_qsym/qsym.py +++ b/src/sage/combinat/ncsf_qsym/qsym.py @@ -2635,9 +2635,19 @@ def __init__(self, QSym): """ EXAMPLES:: - sage: E = QuasiSymmetricFunctions(QQ).Essential(); E - Quasisymmetric functions over the Rational Field in the Essential basis + sage: E = QuasiSymmetricFunctions(QQ).Essential() sage: TestSuite(E).run() + + TESTS:: + + sage: E = QuasiSymmetricFunctions(QQ).E() + sage: M = QuasiSymmetricFunctions(QQ).M() + sage: all(E(M(E[c])) == E[c] for n in range(5) + ....: for c in Compositions(n)) + True + sage: all(M(E(M[c])) == M[c] for n in range(5) + ....: for c in Compositions(n)) + True """ CombinatorialFreeModule.__init__(self, QSym.base_ring(), Compositions(), prefix='E', bracket=False, @@ -2683,6 +2693,10 @@ def antipode_on_basis(self, compo): sage: all(E(M(E[c]).antipode()) == E[c].antipode() ....: for n in range(5) for c in Compositions(n)) True + + sage: all((-1)**len(I) * E[I] == M[I].star_involution().antipode() + ....: for k in [3,4] for I in Compositions(k)) + True """ return (-1)**len(compo) * self.alternating_sum_of_fatter_compositions(compo.reversed()) @@ -2719,9 +2733,10 @@ def product_on_basis(self, I, J): The product of the basis elements indexed by two compositions `I` and `J` is the sum of the basis elements indexed by - compositions in the stuffle product (also called the + compositions `K` in the stuffle product (also called the overlapping shuffle product) of `I` and `J` with a - coefficient of `(-1)^L`, where `L` is the length of the composition. + coefficient of `(-1)^{\ell(I) + \ell(J) - \ell(K)}`, + where `\ell(C)` is the length of the composition `C`. INPUT: From cf760648ef04af6712c69649ff019b477c05641b Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 18 May 2017 08:51:08 -0500 Subject: [PATCH 395/452] Fixing failing doctest in tutorial.py. --- src/sage/combinat/ncsf_qsym/tutorial.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/sage/combinat/ncsf_qsym/tutorial.py b/src/sage/combinat/ncsf_qsym/tutorial.py index 5cf429b0d17..59539ea11a2 100644 --- a/src/sage/combinat/ncsf_qsym/tutorial.py +++ b/src/sage/combinat/ncsf_qsym/tutorial.py @@ -48,6 +48,8 @@ sage: QSym.inject_shorthands() Injecting M as shorthand for Quasisymmetric functions over the Rational Field in the Monomial basis Injecting F as shorthand for Quasisymmetric functions over the Rational Field in the Fundamental basis + Injecting E as shorthand for Quasisymmetric functions over the Rational Field in the Essential basis + doctest:...: RuntimeWarning: redefining global value `E` Injecting dI as shorthand for Quasisymmetric functions over the Rational Field in the dualImmaculate basis Injecting QS as shorthand for Quasisymmetric functions over the Rational Field in the Quasisymmetric Schur basis From 7a36941ede54986bfa4dbc2b35d4aa3f0f8e693d Mon Sep 17 00:00:00 2001 From: Volker Braun Date: Thu, 18 May 2017 18:39:21 +0200 Subject: [PATCH 396/452] Updated SageMath version to 8.0.beta7 --- VERSION.txt | 2 +- build/pkgs/configure/checksums.ini | 6 +++--- build/pkgs/configure/package-version.txt | 2 +- src/bin/sage-banner | 2 +- src/bin/sage-version.sh | 4 ++-- src/sage/version.py | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/VERSION.txt b/VERSION.txt index 8518a1669ae..d2851eb5136 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -SageMath version 8.0.beta6, Release Date: 2017-05-12 +SageMath version 8.0.beta7, Release Date: 2017-05-18 diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index e7d57ea79f9..256d9172868 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,4 +1,4 @@ tarball=configure-VERSION.tar.gz -sha1=6a2d4b05426a912b1589d9213760a6438105a502 -md5=4175d83db6c8a9a2a229bdbb383a923d -cksum=2310778507 +sha1=fd1997a745b82e595f14eb5132da91d44fa27c7d +md5=5fc8d437722460aef07ebb3e5fe92b48 +cksum=1742974928 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index 3d4c7bfe8ef..7b473380d93 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -220 +221 diff --git a/src/bin/sage-banner b/src/bin/sage-banner index 0b69cae5c39..4843d4f39ee 100644 --- a/src/bin/sage-banner +++ b/src/bin/sage-banner @@ -1,5 +1,5 @@ ┌────────────────────────────────────────────────────────────────────┐ -│ SageMath version 8.0.beta6, Release Date: 2017-05-12 │ +│ SageMath version 8.0.beta7, Release Date: 2017-05-18 │ │ Type "notebook()" for the browser-based notebook interface. │ │ Type "help()" for help. │ └────────────────────────────────────────────────────────────────────┘ diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index caac449efca..5a3d0a08d6e 100644 --- a/src/bin/sage-version.sh +++ b/src/bin/sage-version.sh @@ -1,4 +1,4 @@ # Sage version information for shell scripts # This file is auto-generated by the sage-update-version script, do not edit! -SAGE_VERSION='8.0.beta6' -SAGE_RELEASE_DATE='2017-05-12' +SAGE_VERSION='8.0.beta7' +SAGE_RELEASE_DATE='2017-05-18' diff --git a/src/sage/version.py b/src/sage/version.py index 7ce1258f0fd..13aa5fd3c3b 100644 --- a/src/sage/version.py +++ b/src/sage/version.py @@ -1,4 +1,4 @@ # Sage version information for Python scripts # This file is auto-generated by the sage-update-version script, do not edit! -version = '8.0.beta6' -date = '2017-05-12' +version = '8.0.beta7' +date = '2017-05-18' From b21fb167ab9562160ba5650e03ffd44a68be2c37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=2E=20Thi=C3=A9ry?= Date: Thu, 18 May 2017 13:57:16 -0400 Subject: [PATCH 397/452] 22632: just a touch of polishing on the thematic tutorial change --- .../tutorial-objects-and-classes.rst | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) 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 ccf5ff9cc15..be07dc1467f 100644 --- a/src/doc/en/thematic_tutorials/tutorial-objects-and-classes.rst +++ b/src/doc/en/thematic_tutorials/tutorial-objects-and-classes.rst @@ -282,16 +282,19 @@ Some particular actions modify the data structure of ``el``:: sage: F = CombinatorialFreeModule(QQ, Permutations()) sage: el = 3*F([1,3,2])+ F([1,2,3]) sage: el.rename("foo") + sage: el.blah = 42 sage: el.__class__ sage: el.__dict__ - {'__custom_name': 'foo'} + {'__custom_name': 'foo', + 'blah': 42} Lots of Sage objects are not Python objects but compiled Cython - objects. Python sees them as builtin objects and you don't have access to - the data structure. In particular, we do not see the - ``_monomial_coefficients`` in the ``__dict__`` above. Other examples - include integers and permutation group elements:: + objects. Python sees them as builtin objects and you don't have + access to some of their data structure. In particular, we do not + see the attribute ``_monomial_coefficients`` in the ``__dict__`` + above. Other examples of compiled Cython objects include integers + and permutation group elements:: sage: e = Integer(9) sage: type(e) From b13a870be54a27bfa1f2f71230256defc5b0d3a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=2E=20Thi=C3=A9ry?= Date: Thu, 18 May 2017 14:03:37 -0400 Subject: [PATCH 398/452] 22632: use trac role instead of full url in doc --- src/sage/combinat/free_module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/free_module.py b/src/sage/combinat/free_module.py index 00c2f77fa73..9d9279b9d9e 100644 --- a/src/sage/combinat/free_module.py +++ b/src/sage/combinat/free_module.py @@ -1147,7 +1147,7 @@ def __init__(self, *args, **kwds): ... DeprecationWarning: CombinatorialFreeModuleElement is deprecated. Use IndexedFreeModuleElement or CombinatorialFreeModule.Element instead. - See http://trac.sagemath.org/22632 for details. + See :trac:`22632` for details. 2*B[1] + 2*B[2] """ from sage.misc.superseded import deprecation From dec9bd65d49e91af6c662b658e838b1476306ec5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=2E=20Thi=C3=A9ry?= Date: Thu, 18 May 2017 14:56:45 -0400 Subject: [PATCH 399/452] 22632: make CombinatorialFreeModule.Element an alias (and not subclass) of IndexedFreeModuleElement --- src/sage/combinat/free_module.py | 68 +++++++++---------- .../modules/with_basis/indexed_element.pyx | 38 +++++++++++ 2 files changed, 71 insertions(+), 35 deletions(-) diff --git a/src/sage/combinat/free_module.py b/src/sage/combinat/free_module.py index 9d9279b9d9e..3294686b9d3 100644 --- a/src/sage/combinat/free_module.py +++ b/src/sage/combinat/free_module.py @@ -288,43 +288,41 @@ def __classcall_private__(cls, base_ring, basis_keys, category = None, prefix="B # We make this explicitly a Python class so that the methods, # specifically _mul_, from category framework still works. -- TCS # We also need to deal with the old pickles too. -- TCS - class Element(IndexedFreeModuleElement): - def __setstate__(self, state): - r""" - For unpickling old ``CombinatorialFreeModuleElement`` classes. - See :trac:`22632`. + Element = IndexedFreeModuleElement - EXAMPLES:: + @lazy_attribute + def element_class(self): + """ + The (default) class for the elements of this parent - sage: loads('x\x9c\x95R\xcbn\x131\x14\xd5\x00\r\x89KK\xcb\xa3' - ....: '\xbc\xa1\xbc\xd3\xcd,\xe0\x0f\n\xad\xc4\xa2Y\x0c\xb2XZ' - ....: '\x8e\xe7N\xe6\x8a\xb1\xa7\xd7\x0f\x91,F\x82E&\xe2\xafq3' - ....: '\x13\xa4"X\xb0\xb1}\xae}\xce=\xf7\xc8\xdf\xaf(\'g\x90:o' - ....: '\x83\xf2\xc1B\x9a/\x8c\xd4\xa8\x84\xaa\xa4s\xec2\xa2d' - ....: '\xcc\xdf\x7f\xa8\xf5\x14\x8d\xf4\xb5EY\x9dZ\x80\xb3:' - ....: '\x0f\x15\x88o\xe8K\xa1\xa4\x87Ym\x17)T\xa0\xc1\xf8\x8eH}' - ....: '\x17\xd5S\xd3"\xd2\x84^\xf3\xd8?\xf4N:\x01FW\x95\x10\xd3' - ....: '\x80\x95G#\x04\x9b\x81\x97\xde[F\xd7:I\x8dN\xad\x17\xa6dU' - ....: '\t\r\xbe\xacsF[\xe5\xd6\x9f\x83\x05\x83\x14@X8\xb7\xe0' - ....: '\xa2\xb2\xf4X\x1b\x16\x8c\x85<(`4\xe8=v\x13 \xb8\xb43' - ....: '\xe8\xd8Y\xbf\xd3\xf5\xee\x89E3s)\x9a\xf8\x10\xac\xb8@' - ....: '\xecS\x07\xb2\x8b3\r\x8f2\x1a-\x1bb|\x98\xa3;\x97^\x95' - ....: '\xb4\xfd\xd3\xad\xe8FF;|\xbbKJ\xce\xb1\xd6\xb4\xcbG_":' - ....: '\x96\x0e\x1d\xdd\\e\xb4W\xee\xf2\xfdS4\xe8\xe1#\xc6\x00' - ....: '\\4)+\xda\x8fW\xb7\xf8\xce\xe5To\xb7\x19\xddi\xe9\xeed2' - ....: '\xf1\x19\x1d\x1c\xfd\xa0{\xe5\xe0\xff\x93ft\xbf\x1cm\x88' - ....: '\x0e\xbcK\x8bu\x7f\x01&h\xb01\x8f\\\xc42\xeb\\\x9d\xfc.~' - ....: '\x8e5z\xc0\x939O\x16-=\\6+z\x94\xd1\xe3\xb6\xa1\'c>\xdc' - ....: '\xfc\x04zZ\xee\xf1A\xcc\xbc\xc09=\xe3\xc9qX\xd1aF\xcf' - ....: '\x1bz\xc1\x0f\xa23S\xeb\xe8F\xa8\x1a\x8a\x02\x15\xc6\xe9' - ....: '\x1c\xbdl\xe8\xd58\xaa\xfe%n\xa6\xe5W\x10\x1b@\xafy\xf2n' - ....: '\x99\xd1\x9b\xe8\xa2\xec\xcfo\x83k\xa7\xe9/\xc1\xe1\t\x17') - 2*B['x'] + 2*B['y'] - """ - self._set_parent(state[0]) - d = state[1] - self._monomial_coefficients = d.pop('_monomial_coefficients') - self.__dict__ = d + Overrides :meth:`Parent.element_class` to force the + construction of Python class. This is currently needed to + inherit really all the features from categories, and in + particular the initialization of `_mul_` in + :meth:`Magmas.ParentMethods.__init_extra__`. + + EXAMPLES:: + + sage: A = Algebras(QQ).WithBasis().example(); A + An example of an algebra with basis: + the free algebra on the generators ('a', 'b', 'c') over Rational Field + + sage: A.element_class.mro() + [, + , + ...] + sage: a,b,c = A.algebra_generators() + sage: a * b + B[word: ab] + + TESTS:: + + sage: A.__class__.element_class.__module__ + 'sage.combinat.free_module' + """ + return self.__make_element_class__(self.Element, + "%s.element_class"%self.__class__.__name__, + inherit = True) def __init__(self, R, basis_keys, element_class = None, category = None, prefix="B", **kwds): r""" diff --git a/src/sage/modules/with_basis/indexed_element.pyx b/src/sage/modules/with_basis/indexed_element.pyx index e3ef1aa95ca..c0820d7389c 100644 --- a/src/sage/modules/with_basis/indexed_element.pyx +++ b/src/sage/modules/with_basis/indexed_element.pyx @@ -19,6 +19,8 @@ AUTHORS: from __future__ import print_function +from six import iteritems + from sage.structure.element cimport parent from sage.structure.sage_object cimport richcmp, richcmp_not_equal, rich_to_bool from cpython.object cimport Py_NE, Py_EQ @@ -145,6 +147,42 @@ cdef class IndexedFreeModuleElement(Element): """ return (_unpickle_element, (self._parent, self._monomial_coefficients)) + def __setstate__(self, state): + r""" + For unpickling old ``CombinatorialFreeModuleElement`` classes. + See :trac:`22632`. + + EXAMPLES:: + + sage: loads('x\x9c\x95R\xcbn\x131\x14\xd5\x00\r\x89KK\xcb\xa3' + ....: '\xbc\xa1\xbc\xd3\xcd,\xe0\x0f\n\xad\xc4\xa2Y\x0c\xb2XZ' + ....: '\x8e\xe7N\xe6\x8a\xb1\xa7\xd7\x0f\x91,F\x82E&\xe2\xafq3' + ....: '\x13\xa4"X\xb0\xb1}\xae}\xce=\xf7\xc8\xdf\xaf(\'g\x90:o' + ....: '\x83\xf2\xc1B\x9a/\x8c\xd4\xa8\x84\xaa\xa4s\xec2\xa2d' + ....: '\xcc\xdf\x7f\xa8\xf5\x14\x8d\xf4\xb5EY\x9dZ\x80\xb3:' + ....: '\x0f\x15\x88o\xe8K\xa1\xa4\x87Ym\x17)T\xa0\xc1\xf8\x8eH}' + ....: '\x17\xd5S\xd3"\xd2\x84^\xf3\xd8?\xf4N:\x01FW\x95\x10\xd3' + ....: '\x80\x95G#\x04\x9b\x81\x97\xde[F\xd7:I\x8dN\xad\x17\xa6dU' + ....: '\t\r\xbe\xacsF[\xe5\xd6\x9f\x83\x05\x83\x14@X8\xb7\xe0' + ....: '\xa2\xb2\xf4X\x1b\x16\x8c\x85<(`4\xe8=v\x13 \xb8\xb43' + ....: '\xe8\xd8Y\xbf\xd3\xf5\xee\x89E3s)\x9a\xf8\x10\xac\xb8@' + ....: '\xecS\x07\xb2\x8b3\r\x8f2\x1a-\x1bb|\x98\xa3;\x97^\x95' + ....: '\xb4\xfd\xd3\xad\xe8FF;|\xbbKJ\xce\xb1\xd6\xb4\xcbG_":' + ....: '\x96\x0e\x1d\xdd\\e\xb4W\xee\xf2\xfdS4\xe8\xe1#\xc6\x00' + ....: '\\4)+\xda\x8fW\xb7\xf8\xce\xe5To\xb7\x19\xddi\xe9\xeed2' + ....: '\xf1\x19\x1d\x1c\xfd\xa0{\xe5\xe0\xff\x93ft\xbf\x1cm\x88' + ....: '\x0e\xbcK\x8bu\x7f\x01&h\xb01\x8f\\\xc42\xeb\\\x9d\xfc.~' + ....: '\x8e5z\xc0\x939O\x16-=\\6+z\x94\xd1\xe3\xb6\xa1\'c>\xdc' + ....: '\xfc\x04zZ\xee\xf1A\xcc\xbc\xc09=\xe3\xc9qX\xd1aF\xcf' + ....: '\x1bz\xc1\x0f\xa23S\xeb\xe8F\xa8\x1a\x8a\x02\x15\xc6\xe9' + ....: '\x1c\xbdl\xe8\xd58\xaa\xfe%n\xa6\xe5W\x10\x1b@\xafy\xf2n' + ....: '\x99\xd1\x9b\xe8\xa2\xec\xcfo\x83k\xa7\xe9/\xc1\xe1\t\x17') + 2*B['x'] + 2*B['y'] + """ + self._set_parent(state[0]) + for k, v in iteritems(state[1]): + setattr(self, k, v) + cpdef dict monomial_coefficients(self, bint copy=True): """ Return the internal dictionary which has the combinatorial objects From e88762e299005b8f38aaf875179a5af3a44be06a Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 18 May 2017 14:12:34 -0500 Subject: [PATCH 400/452] Making things as consistent as possible. --- src/sage/combinat/ncsf_qsym/qsym.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/ncsf_qsym/qsym.py b/src/sage/combinat/ncsf_qsym/qsym.py index 8c05a40d981..fe850a03e37 100644 --- a/src/sage/combinat/ncsf_qsym/qsym.py +++ b/src/sage/combinat/ncsf_qsym/qsym.py @@ -2583,7 +2583,7 @@ class Essential(CombinatorialFreeModule, BindableClass): r""" The Hopf algebra of quasi-symmetric functions in the Essential basis. - The Essential quasisymmetric functions are defined by + The Essential quasi-symmetric functions are defined by .. MATH:: From 68fea61960a41972282076686c2c59611c496a07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Thu, 18 May 2017 21:18:36 +0200 Subject: [PATCH 401/452] trac 20084 back to just adding an example --- 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 f8fdab40318..9dafc17af15 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -4197,7 +4197,7 @@ cdef class Expression(CommutativeRingElement): a = 0 if a == infinity: return (-self.subs({x: 1/x}) / x**2).residue(x == 0) - return self.subs({x: x+a}).canonicalize_radical().series(x == 0, 0).coefficient(x, -1) + return self.subs({x: x + a}).series(x == 0, 0).coefficient(x, -1) def taylor(self, *args): r""" From 076d7cb3002acc3d2233756af99983b054ca4a32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=2E=20Thi=C3=A9ry?= Date: Thu, 18 May 2017 17:44:53 -0400 Subject: [PATCH 402/452] 22632: revert b13a870be: the trac link is in an error message! --- src/sage/combinat/free_module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/free_module.py b/src/sage/combinat/free_module.py index 3294686b9d3..2781583b7cc 100644 --- a/src/sage/combinat/free_module.py +++ b/src/sage/combinat/free_module.py @@ -1145,7 +1145,7 @@ def __init__(self, *args, **kwds): ... DeprecationWarning: CombinatorialFreeModuleElement is deprecated. Use IndexedFreeModuleElement or CombinatorialFreeModule.Element instead. - See :trac:`22632` for details. + See http://trac.sagemath.org/22632 for details. 2*B[1] + 2*B[2] """ from sage.misc.superseded import deprecation From 4a77584f43adbbc36b279591929a7a4370292ad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=2E=20Thi=C3=A9ry?= Date: Thu, 18 May 2017 17:45:05 -0400 Subject: [PATCH 403/452] 22632: let register_pickle_override refer to IndexedFreeModuleElement and move it close by --- src/sage/combinat/free_module.py | 7 ------- src/sage/modules/with_basis/indexed_element.pyx | 7 ++++++- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/sage/combinat/free_module.py b/src/sage/combinat/free_module.py index 2781583b7cc..1c0d8e81e76 100644 --- a/src/sage/combinat/free_module.py +++ b/src/sage/combinat/free_module.py @@ -1794,10 +1794,3 @@ class Element(CombinatorialFreeModule.Element): # TODO: get rid of this inherita pass CombinatorialFreeModule.CartesianProduct = CombinatorialFreeModule_CartesianProduct - -# Handle old CombinatorialFreeModuleElement pickles, see trac #22632 -from sage.structure.sage_object import register_unpickle_override -register_unpickle_override("sage.combinat.free_module", - "CombinatorialFreeModuleElement", - CombinatorialFreeModule.Element) - diff --git a/src/sage/modules/with_basis/indexed_element.pyx b/src/sage/modules/with_basis/indexed_element.pyx index c0820d7389c..161a2b46dee 100644 --- a/src/sage/modules/with_basis/indexed_element.pyx +++ b/src/sage/modules/with_basis/indexed_element.pyx @@ -150,7 +150,7 @@ cdef class IndexedFreeModuleElement(Element): def __setstate__(self, state): r""" For unpickling old ``CombinatorialFreeModuleElement`` classes. - See :trac:`22632`. + See :trac:`22632` and register_unpickle_override below. EXAMPLES:: @@ -884,3 +884,8 @@ def _unpickle_element(C, d): """ return C._from_dict(d, coerce=False, remove_zeros=False) +# Handle old CombinatorialFreeModuleElement pickles, see trac #22632 +from sage.structure.sage_object import register_unpickle_override +register_unpickle_override("sage.combinat.free_module", + "CombinatorialFreeModuleElement", + IndexedFreeModuleElement) From 06a299e1c6d6734ec4930dc4f720dca5a4ead6ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=2E=20Thi=C3=A9ry?= Date: Thu, 18 May 2017 18:05:30 -0400 Subject: [PATCH 404/452] 22632: fix typo in attribute name --- src/sage/modules/with_basis/indexed_element.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/modules/with_basis/indexed_element.pyx b/src/sage/modules/with_basis/indexed_element.pyx index 161a2b46dee..7e93a8bc522 100644 --- a/src/sage/modules/with_basis/indexed_element.pyx +++ b/src/sage/modules/with_basis/indexed_element.pyx @@ -862,7 +862,7 @@ cdef class IndexedFreeModuleElement(Element): F = parent(self) if not self.base_ring().is_field(): return type(self)(F, {k: c._divide_if_possible(x) - for k,c in self._monomial_cofficients.iteritems()}) + for k,c in self._monomial_coefficients.iteritems()}) x = self.base_ring()( x ) x_inv = x ** -1 From 66ce4a03b7b7a1905caac4a375387cbb6ae20a37 Mon Sep 17 00:00:00 2001 From: Ben Salisbury Date: Thu, 18 May 2017 20:55:19 -0400 Subject: [PATCH 405/452] Corrected documentation errors --- .../lie_algebras/poincare_birkhoff_witt.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py b/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py index 0cf869f5f1b..81d8cb70631 100644 --- a/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py +++ b/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py @@ -29,26 +29,25 @@ class PoincareBirkhoffWittBasis(CombinatorialFreeModule): The Poincare-Birkhoff-Witt (PBW) basis of the universal enveloping algebra of a Lie algebra. - Consider a Lie algebra `\mathfrak{g}` with basis `(b_i)_{i=1}^n`, - so the universal enveloping algebra `U(\mathfrak{g})` is generated - by `b_i` and subject to the relations + Consider a Lie algebra `\mathfrak{g}` with ordered basis + `(b_1,\dots,b_n)`. Then the universal enveloping algebra `U(\mathfrak{g})` + is generated by `b_1,\dots,b_n` and subject to the relations .. MATH:: - [b_i, b_j] = \sum_{k \in I} c_{ij}^k b_k + [b_i, b_j] = \sum_{k = 1}^n c_{ij}^k b_k where `c_{ij}^k` are the structure coefficients of `\mathfrak{g}`. The - Poincare-Birkhoff-Witt (PBW) basis is given by picking a particular - ordering of `(b_i)_{i \in I}` and is given by the monomials + Poincare-Birkhoff-Witt (PBW) basis is given by the monomials `b_1^{e_1} b_2^{e_2} \cdots b_n^{e_n}`. Specifically, we can rewrite `b_j b_i = b_i b_j + [b_j, b_i]` where `j > i`, and we can repeat - this to sort any monmoial into + this to sort any monomial into .. MATH:: b_{i_1} \cdots b_{i_k} = b_1^{e_1} \cdots b_n^{e_n} + LOT - where `LOT` are lower order terms. Thus the PBW is a filtered basis + where `LOT` are lower order terms. Thus the PBW basis is a filtered basis for `U(\mathfrak{g})`. EXAMPLES: @@ -58,7 +57,7 @@ class PoincareBirkhoffWittBasis(CombinatorialFreeModule): sage: L = lie_algebras.sl(QQ, 2) sage: PBW = L.pbw_basis() - We then do some computations, in particular, we check that `[E, F] = H`:: + We then do some computations; in particular, we check that `[E, F] = H`:: sage: E,F,H = PBW.algebra_generators() sage: E*F @@ -333,7 +332,7 @@ def product_on_basis(self, lhs, rhs): PBW['H'] sage: H * F * E PBW['E']*PBW['F']*PBW['H'] - PBW['H']^2 - sage: E * F * H * E + sage: E * F * H * E PBW['E']^2*PBW['F']*PBW['H'] + 2*PBW['E']^2*PBW['F'] - PBW['E']*PBW['H']^2 - 2*PBW['E']*PBW['H'] """ From 394083b21791cc865493924de3de9ab0c6ff41d6 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 18 May 2017 20:42:17 -0500 Subject: [PATCH 406/452] Fixing failures in PBW algebras. --- .../lie_algebras/classical_lie_algebra.py | 3 ++ .../lie_algebras/poincare_birkhoff_witt.py | 48 +++++++++++-------- 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/src/sage/algebras/lie_algebras/classical_lie_algebra.py b/src/sage/algebras/lie_algebras/classical_lie_algebra.py index ef99be1e6e8..9225da9b8c5 100644 --- a/src/sage/algebras/lie_algebras/classical_lie_algebra.py +++ b/src/sage/algebras/lie_algebras/classical_lie_algebra.py @@ -979,6 +979,9 @@ def e_coeff(r, s): names += ['h{}'.format(i) for i in range(1, num_sroots+1)] category = LieAlgebras(R).FiniteDimensional().WithBasis() index_set = p_roots + n_roots + list(alphacheck) + names = tuple(names) + from sage.sets.finite_enumerated_set import FiniteEnumeratedSet + index_set = FiniteEnumeratedSet(index_set) LieAlgebraWithStructureCoefficients.__init__(self, R, s_coeffs, names, index_set, category, prefix='E', bracket='[', sorting_key=self._basis_key) diff --git a/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py b/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py index 81d8cb70631..82b366196f0 100644 --- a/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py +++ b/src/sage/algebras/lie_algebras/poincare_birkhoff_witt.py @@ -54,7 +54,7 @@ class PoincareBirkhoffWittBasis(CombinatorialFreeModule): We construct the PBW basis of `\mathfrak{sl}_2`:: - sage: L = lie_algebras.sl(QQ, 2) + sage: L = lie_algebras.three_dimensional_by_rank(QQ, 3, names=['E','F','H']) sage: PBW = L.pbw_basis() We then do some computations; in particular, we check that `[E, F] = H`:: @@ -143,7 +143,7 @@ def _basis_key(self, x): TESTS:: - sage: L = lie_algebras.sl(QQ, 2) + sage: L = lie_algebras.three_dimensional_by_rank(QQ, 3, names=['E','F','H']) sage: PBW = L.pbw_basis() sage: PBW._basis_key('E') < PBW._basis_key('H') True @@ -155,7 +155,8 @@ def _basis_key(self, x): ....: return -L.basis().keys().index(x) sage: PBW = L.pbw_basis(basis_key=neg_key) sage: prod(PBW.gens()) # indirect doctest - PBW['H']*PBW['F']*PBW['E'] + PBW['H']^2 + PBW[alphacheck[1]]*PBW[-alpha[1]]*PBW[alpha[1]] + + PBW[alphacheck[1]]^2 """ K = self._g.basis().keys() if K.cardinality() == float('inf'): @@ -175,7 +176,7 @@ def _monoid_key(self, x): sage: PBW = L.pbw_basis(basis_key=neg_key) sage: M = PBW.basis().keys() sage: prod(M.gens()) # indirect doctest - PBW['H']*PBW['F']*PBW['E'] + PBW[alphacheck[1]]*PBW[-alpha[1]]*PBW[alpha[1]] """ return self._basis_key(x[0]) @@ -188,18 +189,23 @@ def _monomial_key(self, x): sage: L = lie_algebras.sl(QQ, 2) sage: PBW = L.pbw_basis() - sage: E,F,H = sorted(PBW.algebra_generators(), key=str) + sage: E,F,H = PBW.algebra_generators() sage: H*F*F*E # indirect doctest - PBW['E']*PBW['F']^2*PBW['H'] - 2*PBW['E']*PBW['F']^2 - - 2*PBW['F']*PBW['H']^2 + 6*PBW['F']*PBW['H'] - 4*PBW['F'] + PBW[alpha[1]]*PBW[-alpha[1]]^2*PBW[alphacheck[1]] + - 2*PBW[alpha[1]]*PBW[-alpha[1]]^2 + - 2*PBW[-alpha[1]]*PBW[alphacheck[1]]^2 + + 6*PBW[-alpha[1]]*PBW[alphacheck[1]] - 4*PBW[-alpha[1]] sage: def neg_key(x): ....: return -L.basis().keys().index(x) sage: PBW = L.pbw_basis(basis_key=neg_key) - sage: E,F,H = sorted(PBW.algebra_generators(), key=str) + sage: E,F,H = PBW.algebra_generators() sage: E*F*F*H # indirect doctest - PBW['H']*PBW['F']^2*PBW['E'] + 2*PBW['H']^2*PBW['F'] - + 2*PBW['F']^2*PBW['E'] + 6*PBW['H']*PBW['F'] + 4*PBW['F'] + PBW[alphacheck[1]]*PBW[-alpha[1]]^2*PBW[alpha[1]] + + 2*PBW[alphacheck[1]]^2*PBW[-alpha[1]] + + 2*PBW[-alpha[1]]^2*PBW[alpha[1]] + + 6*PBW[alphacheck[1]]*PBW[-alpha[1]] + 4*PBW[-alpha[1]] + """ return (-len(x), [self._basis_key(l) for l in x.to_word_list()]) @@ -211,7 +217,8 @@ def _repr_(self): sage: L = lie_algebras.sl(QQ, 2) sage: L.pbw_basis() - Universal enveloping algebra of sl2 over Rational Field + Universal enveloping algebra of + Lie algebra of ['A', 1] in the Chevalley basis in the Poincare-Birkhoff-Witt basis """ return "Universal enveloping algebra of {} in the Poincare-Birkhoff-Witt basis".format(self._g) @@ -228,17 +235,18 @@ def _coerce_map_from_(self, R): sage: PBW = L.pbw_basis() sage: PBW.has_coerce_map_from(L) True - sage: [PBW(g) for g in L.gens()] - [PBW['E'], PBW['F'], PBW['H']] + sage: [PBW(g) for g in L.basis()] + [PBW[alpha[1]], PBW[-alpha[1]], PBW[alphacheck[1]]] We can go between PBW bases under different sorting orders:: sage: def neg_key(x): ....: return -L.basis().keys().index(x) sage: PBW2 = L.pbw_basis(basis_key=neg_key) - sage: E,F,H = sorted(PBW.algebra_generators(), key=str) + sage: E,F,H = PBW.algebra_generators() sage: PBW2(E*F*H) - PBW['H']*PBW['F']*PBW['E'] + PBW['H']^2 + PBW[alphacheck[1]]*PBW[-alpha[1]]*PBW[alpha[1]] + + PBW[alphacheck[1]]^2 """ if R == self._g: # Make this into the lift map @@ -279,7 +287,9 @@ def algebra_generators(self): sage: L = lie_algebras.sl(QQ, 2) sage: PBW = L.pbw_basis() sage: PBW.algebra_generators() - Finite family {'H': PBW['H'], 'E': PBW['E'], 'F': PBW['F']} + Finite family {-alpha[1]: PBW[-alpha[1]], + alpha[1]: PBW[alpha[1]], + alphacheck[1]: PBW[alphacheck[1]]} """ G = self._indices.gens() return Family(self._indices._indices, lambda x: self.monomial(G[x]), @@ -294,7 +304,7 @@ def one_basis(self): EXAMPLES:: - sage: L = lie_algebras.sl(QQ, 2) + sage: L = lie_algebras.three_dimensional_by_rank(QQ, 3, names=['E','F','H']) sage: PBW = L.pbw_basis() sage: ob = PBW.one_basis(); ob 1 @@ -309,7 +319,7 @@ def product_on_basis(self, lhs, rhs): EXAMPLES:: - sage: L = lie_algebras.sl(QQ, 2) + sage: L = lie_algebras.three_dimensional_by_rank(QQ, 3, names=['E','F','H']) sage: PBW = L.pbw_basis() sage: I = PBW.indices() sage: PBW.product_on_basis(I.gen('E'), I.gen('F')) @@ -327,7 +337,7 @@ def product_on_basis(self, lhs, rhs): sage: PBW.product_on_basis(I.gen('H')**2, I.gen('F')**2) PBW['F']^2*PBW['H']^2 - 8*PBW['F']^2*PBW['H'] + 16*PBW['F']^2 - sage: E,F,H = sorted(PBW.algebra_generators(), key=str) + sage: E,F,H = PBW.algebra_generators() sage: E*F - F*E PBW['H'] sage: H * F * E From c889c4e9d791e692bec161f7c5bcc6afea8f4615 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=2E=20Thi=C3=A9ry?= Date: Thu, 18 May 2017 22:45:50 -0400 Subject: [PATCH 407/452] 22632: Fix the module part in dynamically created element classes, for consistency --- src/sage/combinat/free_module.py | 5 +++-- src/sage/structure/parent.pyx | 17 ++++++++++------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/sage/combinat/free_module.py b/src/sage/combinat/free_module.py index 1c0d8e81e76..005171bf142 100644 --- a/src/sage/combinat/free_module.py +++ b/src/sage/combinat/free_module.py @@ -321,8 +321,9 @@ def element_class(self): 'sage.combinat.free_module' """ return self.__make_element_class__(self.Element, - "%s.element_class"%self.__class__.__name__, - inherit = True) + name="%s.element_class"%self.__class__.__name__, + module=self.__class__.__module__, + inherit=True) def __init__(self, R, basis_keys, element_class = None, category = None, prefix="B", **kwds): r""" diff --git a/src/sage/structure/parent.pyx b/src/sage/structure/parent.pyx index 502818a2c93..a7ec72d0642 100644 --- a/src/sage/structure/parent.pyx +++ b/src/sage/structure/parent.pyx @@ -565,27 +565,30 @@ cdef class Parent(category_object.CategoryObject): - This should lookup for Element classes in all super classes """ try: #if hasattr(self, 'Element'): - return self.__make_element_class__(self.Element, "%s.element_class"%self.__class__.__name__) + return self.__make_element_class__(self.Element, + name="%s.element_class"%self.__class__.__name__, + module=self.__class__.__module__) except AttributeError: #else: return NotImplemented - def __make_element_class__(self, cls, name = None, inherit = None): + def __make_element_class__(self, cls, name = None, module=None, inherit = None): """ A utility to construct classes for the elements of this parent, with appropriate inheritance from the element class of the category (only for pure python types so far). """ - if name is None: - name = "%s_with_category"%cls.__name__ # By default, don't fiddle with extension types yet; inheritance from # categories will probably be achieved in a different way if inherit is None: inherit = not is_extension_type(cls) if inherit: - return dynamic_class(name, (cls, self._abstract_element_class)) - else: - return cls + if name is None: + name = "%s_with_category"%cls.__name__ + cls = dynamic_class(name, (cls, self._abstract_element_class)) + if module is not None: + cls.__module__ = module + return cls def _set_element_constructor(self): """ From 23f28c0f126b839b0d3b3f34dbc21fed24ae5e26 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Thu, 18 May 2017 21:47:26 -0500 Subject: [PATCH 408/452] Moving _divide_if_possible to Rings. --- src/sage/categories/euclidean_domains.py | 24 ------------------------ src/sage/categories/rings.py | 24 ++++++++++++++++++++++++ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/sage/categories/euclidean_domains.py b/src/sage/categories/euclidean_domains.py index 85a018bf076..25b9aa1d067 100644 --- a/src/sage/categories/euclidean_domains.py +++ b/src/sage/categories/euclidean_domains.py @@ -274,27 +274,3 @@ def quo_rem(self, other): (1, 0) """ - def _divide_if_possible(self, y): - """ - Divide ``self`` by ``y`` if possible and raise a - ``ValueError`` otherwise. - - EXAMPLES:: - - sage: 4._divide_if_possible(2) - 2 - sage: _.parent() - Integer Ring - - :: - - sage: 4._divide_if_possible(3) - Traceback (most recent call last): - ... - ValueError: 4 is not divisible by 3 - """ - q, r = self.quo_rem(y) - if r != 0: - raise ValueError("%s is not divisible by %s"%(self, y)) - return q - diff --git a/src/sage/categories/rings.py b/src/sage/categories/rings.py index 414a41bb134..8e1ff35786b 100644 --- a/src/sage/categories/rings.py +++ b/src/sage/categories/rings.py @@ -1015,6 +1015,30 @@ def is_unit(self): return False raise NotImplementedError + def _divide_if_possible(self, y): + """ + Divide ``self`` by ``y`` if possible and raise a + ``ValueError`` otherwise. + + EXAMPLES:: + + sage: 4._divide_if_possible(2) + 2 + sage: _.parent() + Integer Ring + + :: + + sage: 4._divide_if_possible(3) + Traceback (most recent call last): + ... + ValueError: 4 is not divisible by 3 + """ + q, r = self.quo_rem(y) + if r != 0: + raise ValueError("%s is not divisible by %s"%(self, y)) + return q + def _gen_names(elts): r""" Used to find a name for a generator when rings are created using the From 7cd9c4c0ad17ac6c4abe7a65082742c9ee99546b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=2E=20Thi=C3=A9ry?= Date: Fri, 19 May 2017 00:17:23 -0400 Subject: [PATCH 409/452] 22632: trivial doctest updates (element_class names) --- .../en/prep/Quickstarts/Linear-Algebra.rst | 2 +- src/doc/en/tutorial/tour_coercion.rst | 2 +- src/doc/fr/tutorial/tour_coercion.rst | 2 +- src/doc/ja/tutorial/tour_coercion.rst | 2 +- src/sage/categories/algebras_with_basis.py | 2 +- .../categories/hopf_algebras_with_basis.py | 2 +- src/sage/categories/primer.py | 2 +- src/sage/categories/sets_cat.py | 2 +- src/sage/combinat/free_module.py | 2 +- src/sage/combinat/posets/elements.py | 2 +- src/sage/combinat/posets/posets.py | 4 +- src/sage/geometry/polyhedron/backend_cdd.py | 4 +- src/sage/geometry/polyhedron/base_ZZ.py | 2 +- src/sage/geometry/polyhedron/palp_database.py | 2 +- .../additive_abelian_wrapper.py | 2 +- src/sage/groups/affine_gps/group_element.py | 2 +- src/sage/manifolds/continuous_map.py | 2 +- src/sage/manifolds/differentiable/curve.py | 4 +- src/sage/manifolds/differentiable/diff_map.py | 2 +- src/sage/manifolds/scalarfield.py | 2 +- src/sage/modular/abvar/torsion_point.py | 2 +- src/sage/modular/modform/element.py | 2 +- .../hecke_triangle_group_element.py | 2 +- src/sage/modular/modsym/ambient.py | 2 +- src/sage/modules/fg_pid/fgp_element.py | 4 +- src/sage/modules/fg_pid/fgp_module.py | 2 +- src/sage/modules/free_module_element.pyx | 4 +- src/sage/modules/vector_symbolic_dense.py | 12 ++--- .../function_field/function_field_element.pyx | 2 +- src/sage/rings/multi_power_series_ring.py | 2 +- .../polynomial/polynomial_element_generic.py | 6 +-- .../polynomial/polynomial_quotient_ring.py | 8 ++-- src/sage/rings/polynomial/polynomial_ring.py | 14 +++--- src/sage/rings/quotient_ring_element.py | 48 +++++++++---------- src/sage/schemes/generic/scheme.py | 2 +- src/sage/symbolic/expression.pyx | 2 +- .../tensor/modules/free_module_alt_form.py | 2 +- .../modules/free_module_linear_group.py | 2 +- .../tensor/modules/free_module_morphism.py | 2 +- 39 files changed, 83 insertions(+), 83 deletions(-) diff --git a/src/doc/en/prep/Quickstarts/Linear-Algebra.rst b/src/doc/en/prep/Quickstarts/Linear-Algebra.rst index d9ad58c1f45..3f6b6feb3c0 100644 --- a/src/doc/en/prep/Quickstarts/Linear-Algebra.rst +++ b/src/doc/en/prep/Quickstarts/Linear-Algebra.rst @@ -190,7 +190,7 @@ for our purposes. :: sage: type( ring_vec ) - + sage: type( field_vec ) diff --git a/src/doc/en/tutorial/tour_coercion.rst b/src/doc/en/tutorial/tour_coercion.rst index 8850341d674..0ee15f3c808 100644 --- a/src/doc/en/tutorial/tour_coercion.rst +++ b/src/doc/en/tutorial/tour_coercion.rst @@ -56,7 +56,7 @@ providing different implementations of the same mathematical structure 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 diff --git a/src/doc/fr/tutorial/tour_coercion.rst b/src/doc/fr/tutorial/tour_coercion.rst index 1be851e1976..43215c2a167 100644 --- a/src/doc/fr/tutorial/tour_coercion.rst +++ b/src/doc/fr/tutorial/tour_coercion.rst @@ -58,7 +58,7 @@ contre matrices creuses par exemple). 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 diff --git a/src/doc/ja/tutorial/tour_coercion.rst b/src/doc/ja/tutorial/tour_coercion.rst index f7194d4bd45..15c3ce07c3d 100644 --- a/src/doc/ja/tutorial/tour_coercion.rst +++ b/src/doc/ja/tutorial/tour_coercion.rst @@ -43,7 +43,7 @@ Pythonは(ダイナミックではあっても)強い型付けがなされる言 sage: R. = PolynomialRing(ZZ, implementation='NTL') sage: type(a); type(b); type(c) - + diff --git a/src/sage/categories/algebras_with_basis.py b/src/sage/categories/algebras_with_basis.py index 526ad8c9091..45f2b1d80a8 100644 --- a/src/sage/categories/algebras_with_basis.py +++ b/src/sage/categories/algebras_with_basis.py @@ -96,7 +96,7 @@ class AlgebrasWithBasis(CategoryWithAxiom_over_base_ring): sage: A.__class__ sage: A.element_class - + Please see the source code of `A` (with ``A??``) for how to implement other algebras with basis. diff --git a/src/sage/categories/hopf_algebras_with_basis.py b/src/sage/categories/hopf_algebras_with_basis.py index 8ce84dc4405..a3bf6777746 100644 --- a/src/sage/categories/hopf_algebras_with_basis.py +++ b/src/sage/categories/hopf_algebras_with_basis.py @@ -101,7 +101,7 @@ class HopfAlgebrasWithBasis(CategoryWithAxiom_over_base_ring): sage: A.__class__ sage: A.element_class - + Let us look at the code for implementing A:: diff --git a/src/sage/categories/primer.py b/src/sage/categories/primer.py index daec2127216..9926cd3d268 100644 --- a/src/sage/categories/primer.py +++ b/src/sage/categories/primer.py @@ -414,7 +414,7 @@ class implements: sage: R. = PolynomialRing(QQ, sparse=True) sage: pQ = R ( p ) sage: type(pQ) - + sage: pQ.factor() (6) * (x + 1)^2 diff --git a/src/sage/categories/sets_cat.py b/src/sage/categories/sets_cat.py index a44509d014e..297721a5405 100644 --- a/src/sage/categories/sets_cat.py +++ b/src/sage/categories/sets_cat.py @@ -965,7 +965,7 @@ def _element_constructor_(self): sage: B = GroupAlgebra(SymmetricGroup(3), ZZ) sage: B.element_class - + sage: B._element_constructor """ diff --git a/src/sage/combinat/free_module.py b/src/sage/combinat/free_module.py index 005171bf142..28601bd226c 100644 --- a/src/sage/combinat/free_module.py +++ b/src/sage/combinat/free_module.py @@ -308,7 +308,7 @@ def element_class(self): the free algebra on the generators ('a', 'b', 'c') over Rational Field sage: A.element_class.mro() - [, + [, , ...] sage: a,b,c = A.algebra_generators() diff --git a/src/sage/combinat/posets/elements.py b/src/sage/combinat/posets/elements.py index 9075256de8b..2fa5aa1ac2a 100644 --- a/src/sage/combinat/posets/elements.py +++ b/src/sage/combinat/posets/elements.py @@ -82,7 +82,7 @@ def _latex_(self): sage: P = Poset(([m],[]), facade = False) sage: [e] = P sage: type(e) - + sage: latex(e) #indirect doctest \left(\begin{array}{rr} 1 & 2 \\ diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index 48350ae59a9..602123a9fb0 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -1015,7 +1015,7 @@ def _list(self): sage: L = P._list; L (a, b, c, d) sage: type(L[0]) - + sage: L[0].parent() is P True @@ -1651,7 +1651,7 @@ def list(self): sage: D.list() [0, 1, 2, 3, 4] sage: type(D.list()[0]) - + """ return list(self._list) diff --git a/src/sage/geometry/polyhedron/backend_cdd.py b/src/sage/geometry/polyhedron/backend_cdd.py index 76b537ff6a1..9e0ca53ba7b 100644 --- a/src/sage/geometry/polyhedron/backend_cdd.py +++ b/src/sage/geometry/polyhedron/backend_cdd.py @@ -357,7 +357,7 @@ def __init__(self, parent, Vrep, Hrep, **kwds): sage: p = Polyhedron(backend='cdd', base_ring=QQ) sage: type(p) - + sage: TestSuite(p).run() """ Polyhedron_cdd.__init__(self, parent, Vrep, Hrep, **kwds) @@ -399,7 +399,7 @@ def __init__(self, parent, Vrep, Hrep, **kwds): sage: p = Polyhedron(backend='cdd', base_ring=RDF) sage: type(p) - + sage: TestSuite(p).run() """ Polyhedron_cdd.__init__(self, parent, Vrep, Hrep, **kwds) diff --git a/src/sage/geometry/polyhedron/base_ZZ.py b/src/sage/geometry/polyhedron/base_ZZ.py index 0408d91e77c..3bebca615c9 100644 --- a/src/sage/geometry/polyhedron/base_ZZ.py +++ b/src/sage/geometry/polyhedron/base_ZZ.py @@ -255,7 +255,7 @@ def polar(self): sage: p.polar() A 3-dimensional polyhedron in ZZ^3 defined as the convex hull of 4 vertices sage: type(_) - + sage: p.polar().base_ring() Integer Ring """ diff --git a/src/sage/geometry/polyhedron/palp_database.py b/src/sage/geometry/polyhedron/palp_database.py index 1cba7f96de4..fc74f17fda3 100644 --- a/src/sage/geometry/polyhedron/palp_database.py +++ b/src/sage/geometry/polyhedron/palp_database.py @@ -76,7 +76,7 @@ class PALPreader(SageObject): sage: next(iter(PALPreader(2, output='Polyhedron'))) A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 3 vertices sage: type(_) - + sage: next(iter(PALPreader(2, output='PPL'))) A 2-dimensional lattice polytope in ZZ^2 with 3 vertices diff --git a/src/sage/groups/additive_abelian/additive_abelian_wrapper.py b/src/sage/groups/additive_abelian/additive_abelian_wrapper.py index 65546236528..a1485095ef7 100644 --- a/src/sage/groups/additive_abelian/additive_abelian_wrapper.py +++ b/src/sage/groups/additive_abelian/additive_abelian_wrapper.py @@ -122,7 +122,7 @@ def element(self): sage: T = EllipticCurve('65a').torsion_subgroup().gen(0) sage: T; type(T) (0 : 0 : 1) - + sage: T.element(); type(T.element()) (0 : 0 : 1) diff --git a/src/sage/groups/affine_gps/group_element.py b/src/sage/groups/affine_gps/group_element.py index bc101a87edf..78622621a2f 100644 --- a/src/sage/groups/affine_gps/group_element.py +++ b/src/sage/groups/affine_gps/group_element.py @@ -80,7 +80,7 @@ class AffineGroupElement(MultiplicativeGroupElement): sage: G = AffineGroup(2, GF(3)) sage: g = G.random_element() sage: type(g) - + sage: G(g.matrix()) == g True sage: G(2) diff --git a/src/sage/manifolds/continuous_map.py b/src/sage/manifolds/continuous_map.py index 08eb1ca432a..f74e3e9f4df 100644 --- a/src/sage/manifolds/continuous_map.py +++ b/src/sage/manifolds/continuous_map.py @@ -112,7 +112,7 @@ class ContinuousMap(Morphism): sage: Phi.parent() is Hom(M, N) True sage: type(Phi) - + sage: Phi.display() Phi: S^2 --> R^3 on U: (x, y) |--> (X, Y, Z) = (2*x/(x^2 + y^2 + 1), 2*y/(x^2 + y^2 + 1), (x^2 + y^2 - 1)/(x^2 + y^2 + 1)) diff --git a/src/sage/manifolds/differentiable/curve.py b/src/sage/manifolds/differentiable/curve.py index 0bc6c4544bb..dd55b33ea32 100644 --- a/src/sage/manifolds/differentiable/curve.py +++ b/src/sage/manifolds/differentiable/curve.py @@ -82,7 +82,7 @@ class DifferentiableCurve(DiffMap): sage: c = M.curve({X: [sin(t), sin(2*t)/2]}, (t, 0, 2*pi), name='c') ; c Curve c in the 2-dimensional differentiable manifold M sage: type(c) - + Instead of declaring the parameter `t` as a symbolic variable by means of ``var('t')``, it is equivalent to get it as the canonical coordinate @@ -326,7 +326,7 @@ def __reduce__(self): sage: R. = RealLine() sage: c = M.curve([cos(t), sin(2*t)], (t, 0, 2*pi)) sage: c.__reduce__() - (, + (, (Set of Morphisms from Real interval (0, 2*pi) to 2-dimensional differentiable manifold M in Join of Category of subobjects of sets and Category of smooth manifolds over Real Field with 53 diff --git a/src/sage/manifolds/differentiable/diff_map.py b/src/sage/manifolds/differentiable/diff_map.py index 6740d021cdc..946c7eec565 100644 --- a/src/sage/manifolds/differentiable/diff_map.py +++ b/src/sage/manifolds/differentiable/diff_map.py @@ -117,7 +117,7 @@ class is sage: Phi.parent() is Hom(M, N) True sage: type(Phi) - + sage: Phi.display() Phi: S^2 --> R^3 on U: (x, y) |--> (X, Y, Z) = (2*x/(x^2 + y^2 + 1), 2*y/(x^2 + y^2 + 1), diff --git a/src/sage/manifolds/scalarfield.py b/src/sage/manifolds/scalarfield.py index 20f2485f034..c0bf02fd41e 100644 --- a/src/sage/manifolds/scalarfield.py +++ b/src/sage/manifolds/scalarfield.py @@ -946,7 +946,7 @@ def copy(self): sage: f = M.scalar_field(x*y^2) sage: g = f.copy() sage: type(g) - + sage: g.expr() x*y^2 sage: g == f diff --git a/src/sage/modular/abvar/torsion_point.py b/src/sage/modular/abvar/torsion_point.py index 9286260b4b0..9bcf5fb2f4d 100644 --- a/src/sage/modular/abvar/torsion_point.py +++ b/src/sage/modular/abvar/torsion_point.py @@ -44,7 +44,7 @@ class TorsionPoint(ModuleElement): sage: G = J.finite_subgroup([[1/3,0], [0,1/5]]); G Finite subgroup with invariants [15] over QQbar of Abelian variety J0(11) of dimension 1 sage: type(G.0) - + """ def __init__(self, parent, element, check=True): """ diff --git a/src/sage/modular/modform/element.py b/src/sage/modular/modform/element.py index 8b51d0bf2c5..1e95264a3b6 100644 --- a/src/sage/modular/modform/element.py +++ b/src/sage/modular/modform/element.py @@ -1271,7 +1271,7 @@ def element(self): q - 2*q^2 + (-a1 - 2)*q^3 + 4*q^4 + (2*a1 + 10)*q^5 + O(q^6), q + 2*q^2 + (1/2*a2 - 1)*q^3 + 4*q^4 + (-3/2*a2 + 12)*q^5 + O(q^6)] sage: type(ls2[0]) - + sage: ls2[2][3].minpoly() x^2 - 9*x + 2 """ diff --git a/src/sage/modular/modform_hecketriangle/hecke_triangle_group_element.py b/src/sage/modular/modform_hecketriangle/hecke_triangle_group_element.py index fc1019cb3b9..722bdb9e2cf 100644 --- a/src/sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +++ b/src/sage/modular/modform_hecketriangle/hecke_triangle_group_element.py @@ -124,7 +124,7 @@ def __init__(self, parent, M, check=True, **kwargs): sage: el == HeckeTriangleGroupElement(G, M) True sage: type(el) - + sage: el.category() Category of elements of Hecke triangle group for n = 10 sage: type(HeckeTriangleGroupElement(G, M)) diff --git a/src/sage/modular/modsym/ambient.py b/src/sage/modular/modsym/ambient.py index 2f4e04d8f66..cd7cdf1d152 100644 --- a/src/sage/modular/modsym/ambient.py +++ b/src/sage/modular/modsym/ambient.py @@ -412,7 +412,7 @@ def _element_constructor_(self, x, computed_with_hecke=False): sage: M(0) 0 sage: type(M(0)) - + From a vector of the correct dimension we construct the corresponding linear combination of the basis elements:: diff --git a/src/sage/modules/fg_pid/fgp_element.py b/src/sage/modules/fg_pid/fgp_element.py index 241fb3bbe80..1fd2a399652 100644 --- a/src/sage/modules/fg_pid/fgp_element.py +++ b/src/sage/modules/fg_pid/fgp_element.py @@ -43,7 +43,7 @@ class FGP_Element(ModuleElement): sage: isinstance(x, sage.modules.fg_pid.fgp_element.FGP_Element) True sage: type(x) - + sage: x is Q(x) True sage: x.parent() is Q @@ -70,7 +70,7 @@ def __init__(self, parent, x, check=DEBUG): sage: V = span([[1/2,1,1],[3/2,2,1],[0,0,1]],ZZ); W = V.span([2*V.0+4*V.1, 9*V.0+12*V.1, 4*V.2]) sage: Q = V/W sage: x = Q(V.0-V.1); type(x) - + sage: isinstance(x,sage.modules.fg_pid.fgp_element.FGP_Element) True diff --git a/src/sage/modules/fg_pid/fgp_module.py b/src/sage/modules/fg_pid/fgp_module.py index 37ce98f22ec..9ad0582e223 100644 --- a/src/sage/modules/fg_pid/fgp_module.py +++ b/src/sage/modules/fg_pid/fgp_module.py @@ -603,7 +603,7 @@ def _element_constructor_(self, x, check=True): sage: x = Q(V.0-V.1); x # indirect doctest (0, 3) sage: type(x) - + sage: x is Q(x) True sage: x.parent() is Q diff --git a/src/sage/modules/free_module_element.pyx b/src/sage/modules/free_module_element.pyx index 71e81cdb443..80e3138ba3a 100644 --- a/src/sage/modules/free_module_element.pyx +++ b/src/sage/modules/free_module_element.pyx @@ -4013,7 +4013,7 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): sage: v = vector([-1,0,3,pi]) sage: type(v) - + sage: v.__copy__() (-1, 0, 3, pi) sage: v.__copy__() is v @@ -4309,7 +4309,7 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): sage: g (2*x, 2*y) sage: type(g) - + sage: g(y=2, x=3) (6, 4) sage: f(x,y) = x^2 + y^2 diff --git a/src/sage/modules/vector_symbolic_dense.py b/src/sage/modules/vector_symbolic_dense.py index 5d771bc0265..74f3bfee004 100644 --- a/src/sage/modules/vector_symbolic_dense.py +++ b/src/sage/modules/vector_symbolic_dense.py @@ -15,7 +15,7 @@ sage: u = vector([sin(x)^2 + cos(x)^2, log(2*y) + log(3*y)]); u (cos(x)^2 + sin(x)^2, log(3*y) + log(2*y)) sage: type(u) - + sage: u.simplify_full() (1, log(3*y) + log(2*y)) @@ -27,15 +27,15 @@ sage: v = vector(SR, [1, 2]) sage: w = vector(SR, [sin(x), 0]) sage: type(v) - + sage: type(w) - + sage: type(v + w) - + sage: type(-v) - + sage: type(5*w) - + Test pickling/unpickling:: diff --git a/src/sage/rings/function_field/function_field_element.pyx b/src/sage/rings/function_field/function_field_element.pyx index 876c3de0e3f..802390328a1 100644 --- a/src/sage/rings/function_field/function_field_element.pyx +++ b/src/sage/rings/function_field/function_field_element.pyx @@ -333,7 +333,7 @@ cdef class FunctionFieldElement_polymod(FunctionFieldElement): sage: f.element() 1/x^2*y + x/(x^2 + 1) sage: type(f.element()) - + """ return self._x diff --git a/src/sage/rings/multi_power_series_ring.py b/src/sage/rings/multi_power_series_ring.py index 521d21eece5..6231c9e024f 100644 --- a/src/sage/rings/multi_power_series_ring.py +++ b/src/sage/rings/multi_power_series_ring.py @@ -165,7 +165,7 @@ sage: type(x) sage: type(S(x)) - + sage: f = S(2/7 -100*x^2 + 1/3*x*y + y^2).O(3); f 5 - x^2 + 4*x*y + y^2 + O(x, y)^3 diff --git a/src/sage/rings/polynomial/polynomial_element_generic.py b/src/sage/rings/polynomial/polynomial_element_generic.py index 6e8f4f22e8d..1aae2a1a41c 100644 --- a/src/sage/rings/polynomial/polynomial_element_generic.py +++ b/src/sage/rings/polynomial/polynomial_element_generic.py @@ -61,7 +61,7 @@ class Polynomial_generic_sparse(Polynomial): sage: R. = PolynomialRing(PolynomialRing(QQ, 'y'), sparse=True) sage: f = x^3 - x + 17 sage: type(f) - + sage: loads(f.dumps()) == f True @@ -694,7 +694,7 @@ def shift(self, n): sage: R. = PolynomialRing(ZZ, sparse=True) sage: p = x^100000 + 2*x + 4 sage: type(p) - + sage: p.shift(0) x^100000 + 2*x + 4 sage: p.shift(-1) @@ -1031,7 +1031,7 @@ class Polynomial_generic_sparse_field(Polynomial_generic_sparse, Polynomial_gene sage: R. = PolynomialRing(Frac(RR['t']), sparse=True) sage: f = x^3 - x + 17 sage: type(f) - + sage: loads(f.dumps()) == f True """ diff --git a/src/sage/rings/polynomial/polynomial_quotient_ring.py b/src/sage/rings/polynomial/polynomial_quotient_ring.py index 71db491b116..c527a2b861c 100644 --- a/src/sage/rings/polynomial/polynomial_quotient_ring.py +++ b/src/sage/rings/polynomial/polynomial_quotient_ring.py @@ -1139,7 +1139,7 @@ def S_class_group(self, S, proof=True): sage: CG = S.S_class_group([]) sage: type(CG[0][0][1]) - + sage: type(CG[0][1]) @@ -1265,7 +1265,7 @@ def class_group(self, proof=True): sage: CG = S.class_group() sage: type(CG[0][0][1]) - + sage: type(CG[0][1]) @@ -1332,7 +1332,7 @@ def S_units(self, S, proof=True): sage: U = L.S_units([]) sage: type(U[0][0]) - + sage: type(U[0][1]) sage: type(U[1][1]) @@ -1418,7 +1418,7 @@ def units(self, proof=True): sage: L. = K['y'].quotient(y^3 + 5) sage: U = L.units() sage: type(U[0][0]) - + sage: type(U[0][1]) sage: type(U[1][1]) diff --git a/src/sage/rings/polynomial/polynomial_ring.py b/src/sage/rings/polynomial/polynomial_ring.py index 353f249a841..c1b157c0e7a 100644 --- a/src/sage/rings/polynomial/polynomial_ring.py +++ b/src/sage/rings/polynomial/polynomial_ring.py @@ -1629,11 +1629,11 @@ def __init__(self, base_ring, name="x", sparse=False, element_class=None, catego sage: R = PRing(QQ, 'x', sparse=True); R Sparse Univariate Polynomial Ring in x over Rational Field sage: type(R.gen()) - + sage: R = PRing(CC, 'x'); R Univariate Polynomial Ring in x over Complex Field with 53 bits of precision sage: type(R.gen()) - + Demonstrate that :trac:`8762` is fixed:: @@ -2041,7 +2041,7 @@ def __init__(self, base_ring, name="x", element_class=None, implementation=None) sage: from sage.rings.polynomial.polynomial_ring import PolynomialRing_dense_finite_field sage: R = PolynomialRing_dense_finite_field(GF(5), implementation='generic') sage: type(R(0)) - + sage: S = PolynomialRing_dense_finite_field(GF(25, 'a'), implementation='NTL') sage: type(S(0)) @@ -2468,7 +2468,7 @@ def __init__(self, base_ring, name=None, element_class=None, category=None): sage: R = PRing(Zp(13), name='t'); R Univariate Polynomial Ring in t over 13-adic Ring with capped relative precision 20 sage: type(R.gen()) - + """ if element_class is None: from sage.rings.polynomial.padics.\ @@ -2487,7 +2487,7 @@ def __init__(self, base_ring, name=None, element_class=None, category=None): sage: R = PRing(Zp(13, type='capped-abs'), name='t'); R Univariate Polynomial Ring in t over 13-adic Ring with capped absolute precision 20 sage: type(R.gen()) - + """ if element_class is None: from sage.rings.polynomial.padics.polynomial_padic_flat import \ @@ -2506,7 +2506,7 @@ def __init__(self, base_ring, name=None, element_class=None, category=None): Univariate Polynomial Ring in t over 13-adic Ring of fixed modulus 13^20 sage: type(R.gen()) - + """ if element_class is None: from sage.rings.polynomial.padics.polynomial_padic_flat import \ @@ -2543,7 +2543,7 @@ def __init__(self, base_ring, name=None, element_class=None, category=None): sage: R = PRing(Qp(13), name='t'); R Univariate Polynomial Ring in t over 13-adic Field with capped relative precision 20 sage: type(R.gen()) - + """ if element_class is None: from sage.rings.polynomial.padics.\ diff --git a/src/sage/rings/quotient_ring_element.py b/src/sage/rings/quotient_ring_element.py index 17b95f8dd8d..b0ee6f634d5 100644 --- a/src/sage/rings/quotient_ring_element.py +++ b/src/sage/rings/quotient_ring_element.py @@ -102,7 +102,7 @@ def _reduce_(self): TESTS:: sage: R. = QQ[]; S. = R.quo(x^2 + y^2); type(a) - + sage: a._reduce_() sage: a._QuotientRingElement__rep x @@ -118,7 +118,7 @@ def lift(self): EXAMPLES:: sage: R. = QQ[]; S. = R.quo(x^2 + y^2); type(a) - + sage: a.lift() x sage: (3/5*(a + a^2 + b^2)).lift() @@ -135,7 +135,7 @@ def __bool__(self): EXAMPLES:: sage: R. = QQ[]; S. = R.quo(x^2 + y^2); type(a) - + sage: bool(a) # indirect docteest True sage: bool(S(0)) @@ -161,7 +161,7 @@ def is_unit(self): EXAMPLES:: sage: R. = QQ[]; S. = R.quo(1 - x*y); type(a) - + sage: a*b 1 sage: a.is_unit() @@ -185,7 +185,7 @@ def _repr_(self): TESTS:: sage: R. = QQ[]; S. = R.quo(x^2 + y^2); type(a) - + sage: a-2*a*b # indirect doctest -2*a*b + a @@ -255,7 +255,7 @@ def _add_(self, right): EXAMPLES:: sage: R. = QQ[]; S. = R.quo(x^2 + y^2); type(a) - + sage: a + b a + b @@ -275,7 +275,7 @@ def _sub_(self, right): EXAMPLES:: sage: R. = QQ[]; S. = R.quo(x^2 + y^2); type(a) - + sage: a - b a - b @@ -295,7 +295,7 @@ def _mul_(self, right): EXAMPLES:: sage: R. = QQ[]; S. = R.quo(x^2 + y^2); type(a) - + sage: a * b a*b @@ -338,7 +338,7 @@ def _div_(self, right): Another really easy example:: sage: R. = QQ[]; S. = R.quo(x^2 + y^2); type(a) - + sage: a / S(2) 1/2*a sage: (a*b)._div_(b) @@ -461,7 +461,7 @@ def __int__(self): EXAMPLES:: sage: R. = QQ[]; S. = R.quo(x^2 + y^2); type(a) - + sage: int(S(-3)) # indirect doctest -3 sage: type(int(S(-3))) @@ -478,7 +478,7 @@ def _integer_(self, Z=None): EXAMPLES:: sage: R. = QQ[]; S. = R.quo(x^2 + y^2); type(a) - + sage: ZZ(S(-3)) -3 @@ -497,7 +497,7 @@ def _rational_(self): EXAMPLES:: sage: R. = QQ[]; S. = R.quo(x^2 + y^2); type(a) - + sage: QQ(S(-2/3)) -2/3 @@ -516,7 +516,7 @@ def __long__(self): EXAMPLES:: sage: R. = QQ[]; S. = R.quo(x^2 + y^2); type(a) - + sage: long(S(-3)) # indirect doctest -3L """ @@ -527,7 +527,7 @@ def __neg__(self): EXAMPLES:: sage: R. = QQ[]; S. = R.quo(x^2 + y^2); type(a) - + sage: -a # indirect doctest -a sage: -(a+b) @@ -540,7 +540,7 @@ def __pos__(self): TESTS:: sage: R. = QQ[]; S. = R.quo(x^2 + y^2); type(a) - + sage: (a+b).__pos__() a + b sage: c = a+b; c.__pos__() is c @@ -553,7 +553,7 @@ def __invert__(self): EXAMPLES:: sage: R. = QQ[]; S. = R.quo(x^2 + y^2); type(a) - + sage: ~S(2/3) 3/2 @@ -580,7 +580,7 @@ def __float__(self): EXAMPLES:: sage: R. = QQ[]; S. = R.quo(x^2 + y^2); type(a) - + sage: float(S(2/3)) 0.6666666666666666 sage: float(a) @@ -607,7 +607,7 @@ def __cmp__(self, other): EXAMPLES:: sage: R. = QQ[]; S. = R.quo(x^2 + y^2); type(a) - + sage: a > b # indirect doctest True sage: b > a @@ -672,7 +672,7 @@ def lt(self): TESTS:: sage: R. = QQ[]; S. = R.quo(x^2 + y^2); type(a) - + sage: (a+3*a*b+b).lt() 3*a*b """ @@ -694,7 +694,7 @@ def lm(self): TESTS:: sage: R. = QQ[]; S. = R.quo(x^2 + y^2); type(a) - + sage: (a+3*a*b+b).lm() a*b @@ -717,7 +717,7 @@ def lc(self): TESTS:: sage: R. = QQ[]; S. = R.quo(x^2 + y^2); type(a) - + sage: (a+3*a*b+b).lc() 3 """ @@ -735,7 +735,7 @@ def variables(self): EXAMPLES:: sage: R. = QQ[]; S. = R.quo(x^2 + y^2); type(a) - + sage: a.variables() (a,) sage: b.variables() @@ -760,7 +760,7 @@ def monomials(self): EXAMPLES:: sage: R. = QQ[]; S. = R.quo(x^2 + y^2); type(a) - + sage: a.monomials() [a] sage: (a+a*b).monomials() @@ -804,7 +804,7 @@ def _singular_(self, singular=singular_default): TESTS:: sage: R. = QQ[]; S. = R.quo(x^2 + y^2); type(a) - + sage: (a-2/3*b)._singular_() x-2/3*y sage: S((a-2/3*b)._singular_()) diff --git a/src/sage/schemes/generic/scheme.py b/src/sage/schemes/generic/scheme.py index 6e3540ae01a..7b21af4c0d9 100644 --- a/src/sage/schemes/generic/scheme.py +++ b/src/sage/schemes/generic/scheme.py @@ -914,7 +914,7 @@ def __call__(self, *args): sage: P = S(ZZ.ideal(3)); P Point on Spectrum of Integer Ring defined by the Principal ideal (3) of Integer Ring sage: type(P) - + sage: S(ZZ.ideal(next_prime(1000000))) Point on Spectrum of Integer Ring defined by the Principal ideal (1000003) of Integer Ring diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 9148bdf32a5..2e99d4f73ce 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -6455,7 +6455,7 @@ cdef class Expression(CommutativeRingElement): sage: a x^3 + y + sqrt(2) sage: type(a) - + sage: a.degree() 0 diff --git a/src/sage/tensor/modules/free_module_alt_form.py b/src/sage/tensor/modules/free_module_alt_form.py index 3de40ee5916..4d7ef5321b9 100644 --- a/src/sage/tensor/modules/free_module_alt_form.py +++ b/src/sage/tensor/modules/free_module_alt_form.py @@ -75,7 +75,7 @@ class FreeModuleAltForm(FreeModuleTensor): Alternating form a of degree 2 on the Rank-3 free module M over the Integer Ring sage: type(a) - + sage: a.parent() 2nd exterior power of the dual of the Rank-3 free module M over the Integer Ring sage: a[1,2], a[2,3] = 4, -3 diff --git a/src/sage/tensor/modules/free_module_linear_group.py b/src/sage/tensor/modules/free_module_linear_group.py index 3a0254ff69b..c3e5abe7e62 100644 --- a/src/sage/tensor/modules/free_module_linear_group.py +++ b/src/sage/tensor/modules/free_module_linear_group.py @@ -124,7 +124,7 @@ class FreeModuleLinearGroup(UniqueRepresentation, Parent): sage: a.display(e) e_0*e^0 - e_1*e^1 + e_2*e^2 sage: type(a) - + As for any group, the identity element is obtained by the method :meth:`one`:: diff --git a/src/sage/tensor/modules/free_module_morphism.py b/src/sage/tensor/modules/free_module_morphism.py index bfdd00d829a..115eb53b44d 100644 --- a/src/sage/tensor/modules/free_module_morphism.py +++ b/src/sage/tensor/modules/free_module_morphism.py @@ -118,7 +118,7 @@ class FiniteRankFreeModuleMorphism(Morphism): is a derived class of :class:`FiniteRankFreeModuleMorphism`:: sage: type(phi) - + sage: isinstance(phi, sage.tensor.modules.free_module_morphism.FiniteRankFreeModuleMorphism) True From b11d26e6fbd0fa2668b242e13c006fe57510ebb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=2E=20Thi=C3=A9ry?= Date: Fri, 19 May 2017 00:20:45 -0400 Subject: [PATCH 410/452] 22632: trivial indentation fix --- src/sage/manifolds/differentiable/curve.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/manifolds/differentiable/curve.py b/src/sage/manifolds/differentiable/curve.py index dd55b33ea32..4c44dbcc919 100644 --- a/src/sage/manifolds/differentiable/curve.py +++ b/src/sage/manifolds/differentiable/curve.py @@ -326,7 +326,7 @@ def __reduce__(self): sage: R. = RealLine() sage: c = M.curve([cos(t), sin(2*t)], (t, 0, 2*pi)) sage: c.__reduce__() - (, + (, (Set of Morphisms from Real interval (0, 2*pi) to 2-dimensional differentiable manifold M in Join of Category of subobjects of sets and Category of smooth manifolds over Real Field with 53 From b410405da60f5aa1612ba1c8ab8d58bc9e45ff4a Mon Sep 17 00:00:00 2001 From: "Erik M. Bray" Date: Fri, 19 May 2017 14:11:33 +0200 Subject: [PATCH 411/452] Adds patch to fix https://trac.sagemath.org/ticket/23029 --- build/pkgs/linbox/package-version.txt | 2 +- build/pkgs/linbox/patches/ticket-23029.patch | 38 ++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 build/pkgs/linbox/patches/ticket-23029.patch diff --git a/build/pkgs/linbox/package-version.txt b/build/pkgs/linbox/package-version.txt index 2a175dcdb19..9c9dbee1221 100644 --- a/build/pkgs/linbox/package-version.txt +++ b/build/pkgs/linbox/package-version.txt @@ -1 +1 @@ -1.4.2.p0 +1.4.2.p1 diff --git a/build/pkgs/linbox/patches/ticket-23029.patch b/build/pkgs/linbox/patches/ticket-23029.patch new file mode 100644 index 00000000000..677f8ceca39 --- /dev/null +++ b/build/pkgs/linbox/patches/ticket-23029.patch @@ -0,0 +1,38 @@ +Do not use 'B0' as a variable name as it conflicts with a macro in the standard +header termios.h. See https://trac.sagemath.org/ticket/23029 +diff --git a/linbox/solutions/det.h b/linbox/solutions/det.h +index f3390be..2057234 100644 +--- a/linbox/solutions/det.h ++++ b/linbox/solutions/det.h +@@ -236,9 +236,9 @@ namespace LinBox + } + + Diagonal D (diag); +- Compose > B0 (&A, &D); ++ Compose > B_0 (&A, &D); + typedef Compose,Compose > > Blackbox1; +- Blackbox1 B(&D, &B0); ++ Blackbox1 B(&D, &B_0); + + BlackboxContainerSymmetric TF (&B, F, iter); + +diff --git a/linbox/solutions/rank.inl b/linbox/solutions/rank.inl +index fad66a8..7fa231d 100755 +--- a/linbox/solutions/rank.inl ++++ b/linbox/solutions/rank.inl +@@ -142,9 +142,9 @@ namespace LinBox + + + typedef Compose,Blackbox >, Diagonal > BlackBox1; +- Diagonal D0 (d1); +- Compose,Blackbox > B0 (&D0, &A); +- BlackBox1 B (&B0, &D0); ++ Diagonal D_0 (d1); ++ Compose,Blackbox > B_0 (&D_0, &A); ++ BlackBox1 B (&B_0, &D_0); + + BlackboxContainerSymmetric TF (&B, F, iter); + MasseyDomain > WD (&TF, M.earlyTermThreshold ()); +-- +2.8.3 + From 39700cedf1994bd63687ac2b83f69208625d4b33 Mon Sep 17 00:00:00 2001 From: "Erik M. Bray" Date: Fri, 19 May 2017 14:06:03 +0200 Subject: [PATCH 412/452] Force the needed flags for ECM to build on Cygwin --- build/pkgs/ecm/spkg-install | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/build/pkgs/ecm/spkg-install b/build/pkgs/ecm/spkg-install index f087ed4247d..ce92c947aa4 100755 --- a/build/pkgs/ecm/spkg-install +++ b/build/pkgs/ecm/spkg-install @@ -87,6 +87,11 @@ else echo "to, or '--with-pic' was given in ECM_CONFIGURE." fi +if [ "$UNAME" == "CYGWIN" ]; then + # Force shared library build only on Cygwin; it will not build otherwise + ECM_CONFIGURE="$ECM_CONFIGURE --enable-shared --disable-static" +fi + if [ "$SAGE_DEBUG" = yes ]; then # Add debug symbols and disable optimization: From 5b01423f3b027207fd3f0e5ca9064ccac45e6623 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 19 May 2017 14:19:21 +0200 Subject: [PATCH 413/452] trac 23030 removing bad apply --- src/sage/symbolic/expression.pyx | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 4fb099fcdbe..9b3e415121f 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -10463,13 +10463,19 @@ cdef class Expression(CommutativeRingElement): from sage.symbolic.operators import add_vararg as opadd, \ mul_vararg as opmul from sage.all import prod + def treat_term(op, term, args): - l=sage.all.copy(args) + l = sage.all.copy(args) l.insert(0, term) - return(apply(op, l)) - if self.parent() is not sage.all.SR: return self + return op(*l) + + if self.parent() is not sage.all.SR: + return self + op = self.operator() - if op is None : return self + if op is None: + return self + if op in {opsum, opdi, opii}: sa = self.operands()[0].expand() op1 = sa.operator() @@ -10490,11 +10496,12 @@ cdef class Expression(CommutativeRingElement): return prod(treat_term(op, t.distribute(), la) for t in aa) return prod(treat_term(op, t, la) for t in aa) return self + if recursive: - return apply(op, map(lambda t:t.distribute(), self.operands())) + done = [t.distribute() for t in self.operands()] + return op(*done) return self - def factor(self, dontfactor=[]): """ Factor the expression, containing any number of variables or functions, into From a066e1b1204c2c2ecb531270b1d41725b9689045 Mon Sep 17 00:00:00 2001 From: Johan Rosenkilde Date: Fri, 19 May 2017 15:30:50 +0200 Subject: [PATCH 414/452] Load Guava before calling its functions. A guard against too large fields. --- src/sage/coding/linear_code.py | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/sage/coding/linear_code.py b/src/sage/coding/linear_code.py index 4e24ceb6522..2e3e1b74e4b 100644 --- a/src/sage/coding/linear_code.py +++ b/src/sage/coding/linear_code.py @@ -228,6 +228,7 @@ class should inherit from this class. Also ``AbstractLinearCode`` should never from sage.misc.cachefunc import cached_method from sage.misc.superseded import deprecation, deprecated_function_alias from sage.misc.randstate import current_randstate +from sage.misc.package import is_package_installed from .encoder import Encoder from .decoder import Decoder, DecodingError from sage.combinat.subset import Subsets @@ -1279,15 +1280,33 @@ def covering_radius(self): If the covering radius a code equals its minimum distance, then the code is called perfect. + .. NOTE:: + + This method is currently not implemented on codes over base fields + of cardinality greater than 256 due to limitations in the underlying + algorithm of GAP. + EXAMPLES:: sage: C = codes.HammingCode(GF(2), 5) sage: C.covering_radius() # optional - gap_packages (Guava package) 1 + + sage: C = codes.random_linear_code(GF(263), 5, 1) + sage: C.covering_radius() # optional - gap_packages (Guava package) + Traceback (most recent call last): + ... + NotImplementedError: the GAP algorithm that Sage is using is limited to computing with fields of size at most 256 """ + if not is_package_installed('gap_packages'): + raise PackageNotFoundError('gap_packages') + gap.load_package("guava") F = self.base_ring() - G = self.generator_matrix() - gapG = gap(G) + if F.cardinality() > 256: + raise NotImplementedError("the GAP algorithm that Sage is using " + "is limited to computing with fields " + "of size at most 256") + gapG = gap(self.generator_matrix()) C = gapG.GeneratorMatCode(gap(F)) r = C.CoveringRadius() try: From ddf710f76dce71bbc5e61dfddcbc687d424ef61e Mon Sep 17 00:00:00 2001 From: Johan Rosenkilde Date: Fri, 19 May 2017 15:31:35 +0200 Subject: [PATCH 415/452] Better error messages when calling Guava functions without gap_packages --- src/sage/coding/databases.py | 8 ++++++-- src/sage/coding/guava.py | 5 +++++ src/sage/coding/linear_code.py | 18 +++++++++--------- 3 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/sage/coding/databases.py b/src/sage/coding/databases.py index 21c12e922ec..b5700aca512 100644 --- a/src/sage/coding/databases.py +++ b/src/sage/coding/databases.py @@ -3,6 +3,8 @@ Databases and accessors of online databases for coding theory """ from six.moves import range +from sage.interfaces.all import gap +from sage.misc.package import is_package_installed, PackageNotFoundError #Don't put any global imports here since this module is accessible as sage.codes.databases. @@ -40,7 +42,8 @@ def best_linear_code_in_guava(n, k, F): between 2 and 4. Use ``bounds_on_minimum_distance_in_guava(10,5,GF(2))`` for further details. """ - from sage.interfaces.all import gap + if not is_package_installed('gap_packages'): + raise PackageNotFoundError('gap_packages') gap.load_package("guava") q = F.order() C = gap("BestKnownLinearCode(%s,%s,GF(%s))"%(n,k,q)) @@ -107,7 +110,8 @@ def bounds_on_minimum_distance_in_guava(n, k, F): upperBound := 4, upperBoundExplanation := ... ) """ - from sage.interfaces.all import gap + if not is_package_installed('gap_packages'): + raise PackageNotFoundError('gap_packages') gap.load_package("guava") q = F.order() gap.eval("data := BoundsMinimumDistance(%s,%s,GF(%s))"%(n,k,q)) diff --git a/src/sage/coding/guava.py b/src/sage/coding/guava.py index bf1ccd8de58..0d1a7265881 100644 --- a/src/sage/coding/guava.py +++ b/src/sage/coding/guava.py @@ -40,6 +40,7 @@ from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF from sage.interfaces.gap import gfq_gap_to_sage from .linear_code import LinearCode +from sage.misc.package import is_package_installed, PackageNotFoundError def QuasiQuadraticResidueCode(p): @@ -70,6 +71,8 @@ def QuasiQuadraticResidueCode(p): AUTHOR: David Joyner (11-2005) """ + if not is_package_installed('gap_packages'): + raise PackageNotFoundError('gap_packages') F = GF(2) gap.load_package("guava") gap.eval("C:=QQRCode(" + str(p) + ")") @@ -110,6 +113,8 @@ def RandomLinearCodeGuava(n, k, F): current_randstate().set_seed_gap() q = F.order() + if not is_package_installed('gap_packages'): + raise PackageNotFoundError('gap_packages') gap.load_package("guava") gap.eval("C:=RandomLinearCode("+str(n)+","+str(k)+", GF("+str(q)+"))") gap.eval("G:=GeneratorMat(C)") diff --git a/src/sage/coding/linear_code.py b/src/sage/coding/linear_code.py index 2e3e1b74e4b..95ca3784fdd 100644 --- a/src/sage/coding/linear_code.py +++ b/src/sage/coding/linear_code.py @@ -228,7 +228,7 @@ class should inherit from this class. Also ``AbstractLinearCode`` should never from sage.misc.cachefunc import cached_method from sage.misc.superseded import deprecation, deprecated_function_alias from sage.misc.randstate import current_randstate -from sage.misc.package import is_package_installed +from sage.misc.package import is_package_installed, PackageNotFoundError from .encoder import Encoder from .decoder import Decoder, DecodingError from sage.combinat.subset import Subsets @@ -2505,6 +2505,8 @@ def minimum_distance(self, algorithm=None): NotImplementedError: the GAP algorithm that Sage is using is limited to computing with fields of size at most 256 """ + if algorithm == "guava" and not is_package_installed('gap_packages'): + raise PackageNotFoundError('gap_packages') # If the minimum distance has already been computed or provided by # the user then simply return the stored value. # This is done only if algorithm is None. @@ -2523,10 +2525,7 @@ def minimum_distance(self, algorithm=None): n = self.length() k = self.dimension() if (q == 2 or q == 3) and algorithm=="guava": - try: - gap.load_package("guava") - except RuntimeError: - raise ValueError("You have to install the optional package GUAVA to use algorithm=\"guava\"") + gap.load_package("guava") C = gap(G).GeneratorMatCode(gap(F)) d = C.MinimumWeight() return ZZ(d) @@ -2578,10 +2577,9 @@ def _minimum_weight_codeword(self, algorithm = None): current_randstate().set_seed_gap() if algorithm=="guava": - try: - gap.load_package("guava") - except RuntimeError: - raise ValueError("You have to install the optional package GUAVA to use algorithm=\"guava\"") + if not is_package_installed('gap_packages'): + raise PackageNotFoundError('gap_packages') + gap.load_package("guava") from sage.interfaces.gap import gfq_gap_to_sage gap.eval("G:="+Gmat) C = gap(Gmat).GeneratorMatCode(F) @@ -2745,6 +2743,8 @@ def permutation_automorphism_group(self, algorithm="partition"): n = len(G.columns()) k = len(G.rows()) if "gap" in algorithm: + if not is_package_installed('gap_packages'): + raise PackageNotFoundError('gap_packages') gap.load_package('guava') wts = self.weight_distribution() # bottleneck 1 nonzerowts = [i for i in range(len(wts)) if wts[i]!=0] From 6a78dc371d27f7bcda2c18324c68daa0fa062233 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 19 May 2017 16:41:11 +0200 Subject: [PATCH 416/452] preliminary work on unicode for interfaces --- src/sage/interfaces/expect.py | 29 ++++++++++++-------------- src/sage/interfaces/gap.py | 10 ++++----- src/sage/interfaces/giac.py | 21 +++++++++---------- src/sage/interfaces/interface.py | 10 ++++----- src/sage/interfaces/magma.py | 3 ++- src/sage/interfaces/maple.py | 18 ++++++++-------- src/sage/interfaces/maxima.py | 10 ++++----- src/sage/interfaces/maxima_abstract.py | 9 ++++---- src/sage/interfaces/maxima_lib.py | 3 ++- src/sage/interfaces/qepcad.py | 7 ++++--- src/sage/interfaces/r.py | 1 + src/sage/interfaces/sage0.py | 4 ++-- src/sage/interfaces/singular.py | 4 ++-- 13 files changed, 64 insertions(+), 65 deletions(-) diff --git a/src/sage/interfaces/expect.py b/src/sage/interfaces/expect.py index 4f420eca2d3..b5de3868d8e 100644 --- a/src/sage/interfaces/expect.py +++ b/src/sage/interfaces/expect.py @@ -38,8 +38,8 @@ # (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** -from __future__ import print_function -from __future__ import absolute_import +from __future__ import print_function, absolute_import +from six import string_types import os import signal @@ -49,7 +49,6 @@ import gc from . import quit from . import cleaner -import six from random import randrange import pexpect @@ -169,7 +168,7 @@ def __init__(self, name, prompt, command=None, server=None, self.__init_code = init_code #Handle the log file - if isinstance(logfile, six.string_types): + if isinstance(logfile, string_types): self.__logfile = None self.__logfilename = logfile else: @@ -773,9 +772,9 @@ def _eval_line_using_file(self, line, restart_if_needed=True): 3 """ - F = open(self._local_tmpfile(), 'w') - F.write(line+'\n') - F.close() + with open(self._local_tmpfile(), 'w') as F: + F.write(line + '\n') + tmp_to_use = self._local_tmpfile() if self.is_remote(): self._send_tmpfile_to_server() @@ -939,7 +938,7 @@ def _eval_line(self, line, allow_use_file=True, wait_for_prompt=True, restart_if if len(line)>0: try: - if isinstance(wait_for_prompt, six.string_types): + if isinstance(wait_for_prompt, string_types): E.expect(wait_for_prompt) else: E.expect(self._prompt) @@ -1139,16 +1138,14 @@ def _expect_expr(self, expr=None, timeout=None): self.interrupt() raise - def _sendstr(self, str): + def _sendstr(self, string): r""" Send a string to the pexpect interface, autorestarting the expect interface if anything goes wrong. INPUT: - - - ``str`` - a string - + - ``string`` -- a string EXAMPLES: We illustrate this function using the R interface:: @@ -1167,11 +1164,11 @@ def _sendstr(self, str): if self._expect is None: self._start() try: - os.write(self._expect.child_fd, str) + os.write(self._expect.child_fd, string) except OSError: self._crash_msg() self.quit() - self._sendstr(str) + self._sendstr(string) def _crash_msg(self): r""" @@ -1285,7 +1282,7 @@ def eval(self, code, strip=True, synchronize=False, locals=None, allow_use_file= except AttributeError: pass - if not isinstance(code, six.string_types): + if not isinstance(code, string_types): raise TypeError('input code must be a string.') #Remove extra whitespace @@ -1376,7 +1373,7 @@ def __init__(self, parent, value, is_name=False, name=None): # idea: Joe Wetherell -- try to find out if the output # is too long and if so get it using file, otherwise # don't. - if isinstance(value, six.string_types) and parent._eval_using_file_cutoff and \ + if isinstance(value, string_types) and parent._eval_using_file_cutoff and \ parent._eval_using_file_cutoff < len(value): self._get_using_file = True diff --git a/src/sage/interfaces/gap.py b/src/sage/interfaces/gap.py index 2f104974fe9..4699c54051c 100644 --- a/src/sage/interfaces/gap.py +++ b/src/sage/interfaces/gap.py @@ -174,8 +174,8 @@ # # http://www.gnu.org/licenses/ #***************************************************************************** - from __future__ import absolute_import, print_function +from six import string_types from .expect import Expect, ExpectElement, FunctionElement, ExpectFunction from .gap_workspace import gap_workspace_file, prepare_workspace_dir @@ -739,17 +739,17 @@ def _eval_line(self, line, allow_use_file=True, wait_for_prompt=True, restart_if (normal, error) = self._execute_line(line, wait_for_prompt=wait_for_prompt, expect_eof= (self._quit_string() in line)) - if len(error)> 0: + if len(error): if 'Error, Rebuild completion files!' in error: error += "\nRunning gap_reset_workspace()..." self.quit() gap_reset_workspace() error = error.replace('\r','') raise RuntimeError("%s produced error output\n%s\n executing %s"%(self, error,line)) - if len(normal) == 0: + if not len(normal): return '' - if isinstance(wait_for_prompt, str) and normal.ends_with(wait_for_prompt): + if isinstance(wait_for_prompt, string_types) and normal.ends_with(wait_for_prompt): n = len(wait_for_prompt) elif normal.endswith(self._prompt): n = len(self._prompt) @@ -758,7 +758,7 @@ def _eval_line(self, line, allow_use_file=True, wait_for_prompt=True, restart_if else: n = 0 out = normal[:-n] - if len(out) > 0 and out[-1] == "\n": + if len(out) and out[-1] == "\n": out = out[:-1] return out diff --git a/src/sage/interfaces/giac.py b/src/sage/interfaces/giac.py index ec56273b75f..ad232ef32e3 100644 --- a/src/sage/interfaces/giac.py +++ b/src/sage/interfaces/giac.py @@ -734,35 +734,34 @@ def _assign_symbol(self): """ return ":=" - def _help(self, str): + def _help(self, string): r""" - Returns the Giac help on ``str``. + Return the Giac help on ``string``. EXAMPLES:: sage: giac._help('gcd') # not tested ; output may vary (LANG) "...gcd - greatest common divisor of polynomials... """ - return os.popen('cas_help %s'%str).read() - # return os.popen('echo "?%s" | giac'%str).read() + return os.popen('cas_help %s' % string).read() + # return os.popen('echo "?%s" | giac' % string).read() - def help(self, str): + def help(self, string): """ - Display Giac help about str. This is the same as typing "?str" in - the Giac console. + Display Giac help about string. - INPUT: + This is the same as typing "?string" in the Giac console. - - ``str`` - a string to search for in the giac help - system + INPUT: + - ``string`` -- a string to search for in the giac help system EXAMPLES:: sage: giac.help('Psi') # not tested - depends of giac and $LANG Psi(a,n)=nth-derivative of the function DiGamma (=ln@Gamma) at point a (Psi(a,0)=Psi(a))... """ - pager()(self._help(str)) + pager()(self._help(string)) def clear(self, var): """ diff --git a/src/sage/interfaces/interface.py b/src/sage/interfaces/interface.py index ba93d58bfa4..e96d56bb5b1 100644 --- a/src/sage/interfaces/interface.py +++ b/src/sage/interfaces/interface.py @@ -38,9 +38,7 @@ # http://www.gnu.org/licenses/ #***************************************************************************** from __future__ import print_function -from six import iteritems -from six import integer_types -import six +from six import iteritems, integer_types, string_types import operator @@ -280,7 +278,7 @@ def __call__(self, x, name=None): except (NotImplementedError, TypeError): pass - if isinstance(x, six.string_types): + if isinstance(x, string_types): return cls(self, x, name=name) try: return self._coerce_from_special_method(x) @@ -1099,7 +1097,7 @@ def __repr__(self): except ValueError as msg: return '(invalid {} object -- {})'.format(self.parent() or type(self), msg) cr = getattr(self, '_cached_repr', None) - if isinstance(cr, six.string_types): + if isinstance(cr, string_types): s = cr else: s = self._repr_() @@ -1355,7 +1353,7 @@ def name(self, new_name=None): 's5' """ if new_name is not None: - if not isinstance(new_name, str): + if not isinstance(new_name, string_types): raise TypeError("new_name must be a string") p = self.parent() p.set(new_name, self._name) diff --git a/src/sage/interfaces/magma.py b/src/sage/interfaces/magma.py index ca8d4cbf649..78f87d27998 100644 --- a/src/sage/interfaces/magma.py +++ b/src/sage/interfaces/magma.py @@ -213,6 +213,7 @@ #***************************************************************************** from __future__ import print_function from __future__ import absolute_import +from six import string_types import re import sys @@ -457,7 +458,7 @@ def _post_process_from_file(self, s): sage: magma._post_process_from_file("Hello") '' """ - if not isinstance(s, str): + if not isinstance(s, string_types): raise RuntimeError("Error evaluating object in %s:\n%s" % (self, s)) # Chop off the annoying "Loading ... " message that Magma # always outputs no matter what. diff --git a/src/sage/interfaces/maple.py b/src/sage/interfaces/maple.py index 9ae7c5fd038..a2a901f8458 100644 --- a/src/sage/interfaces/maple.py +++ b/src/sage/interfaces/maple.py @@ -758,9 +758,9 @@ def source(self, s): except Exception: pager()('No source code could be found.') - def _help(self, str): + def _help(self, string): r""" - Return the Maple help on ``str``. + Return the Maple help on ``string``. EXAMPLES:: @@ -768,26 +768,26 @@ def _help(self, str): sage: txt.find('gcd - greatest common divisor') > 0 # optional - maple True """ - return os.popen('echo "?%s" | maple -q'%str).read() + return os.popen('echo "?%s" | maple -q' % string).read() - def help(self, str): + def help(self, string): """ - Display Maple help about ``str``. + Display Maple help about ``string``. - This is the same as typing "?str" in the Maple console. + This is the same as typing "?string" in the Maple console. INPUT: - - ``str`` - a string to search for in the maple help + - ``string`` - a string to search for in the maple help system EXAMPLES:: - sage: maple.help('digamma') #not tested + sage: maple.help('Psi') # not tested Psi - the Digamma and Polygamma functions ... """ - pager()(self._help(str)) + pager()(self._help(string)) def with_package(self, package): """ diff --git a/src/sage/interfaces/maxima.py b/src/sage/interfaces/maxima.py index 0da14f8786c..e5e7fef45e8 100644 --- a/src/sage/interfaces/maxima.py +++ b/src/sage/interfaces/maxima.py @@ -463,8 +463,8 @@ # # http://www.gnu.org/licenses/ #***************************************************************************** -from __future__ import print_function -from __future__ import absolute_import +from __future__ import print_function, absolute_import +from six import string_types import os import re @@ -639,7 +639,7 @@ def __reduce__(self): """ return reduce_load_Maxima, tuple([]) #(self.__init_code,) - def _sendline(self, str): + def _sendline(self, string): """ Send a string followed by a newline character. @@ -649,7 +649,7 @@ def _sendline(self, str): sage: maxima.get('t') '9' """ - self._sendstr(str) + self._sendstr(string) os.write(self._expect.child_fd, os.linesep) def _expect_expr(self, expr=None, timeout=None): @@ -995,7 +995,7 @@ def set(self, var, value): sage: maxima.get('xxxxx') '2' """ - if not isinstance(value, str): + if not isinstance(value, string_types): raise TypeError cmd = '%s : %s$'%(var, value.rstrip(';')) if len(cmd) > self.__eval_using_file_cutoff: diff --git a/src/sage/interfaces/maxima_abstract.py b/src/sage/interfaces/maxima_abstract.py index 84f6a44dbfa..46aaa0c7a15 100644 --- a/src/sage/interfaces/maxima_abstract.py +++ b/src/sage/interfaces/maxima_abstract.py @@ -50,6 +50,7 @@ #***************************************************************************** from __future__ import print_function from __future__ import absolute_import +from six import string_types import os import re @@ -637,13 +638,13 @@ def function(self, args, defn, rep=None, latex=None): name = self._next_var_name() if isinstance(defn, MaximaAbstractElement): defn = defn.str() - elif not isinstance(defn, str): + elif not isinstance(defn, string_types): defn = str(defn) if isinstance(args, MaximaAbstractElement): args = args.str() - elif not isinstance(args, str): + elif not isinstance(args, string_types): args = str(args) - cmd = '%s(%s) := %s'%(name, args, defn) + cmd = '%s(%s) := %s' % (name, args, defn) self._eval_line(cmd) if rep is None: rep = defn @@ -847,7 +848,7 @@ def de_solve(self, de, vars, ics=None): sage: maxima.de_solve('diff(y,x) + 3*x = y', ['x','y'],[1,1]) y=-%e^-1*(5*%e^x-3*%e*x-3*%e) """ - if not isinstance(vars, str): + if not isinstance(vars, string_types): str_vars = '%s, %s'%(vars[1], vars[0]) else: str_vars = vars diff --git a/src/sage/interfaces/maxima_lib.py b/src/sage/interfaces/maxima_lib.py index 4da64aa9657..cd7cf81795d 100644 --- a/src/sage/interfaces/maxima_lib.py +++ b/src/sage/interfaces/maxima_lib.py @@ -86,6 +86,7 @@ #***************************************************************************** from __future__ import print_function from __future__ import absolute_import +from six import string_types from sage.symbolic.ring import SR @@ -504,7 +505,7 @@ def set(self, var, value): sage: maxima_lib.get('xxxxx') '2' """ - if not isinstance(value, str): + if not isinstance(value, string_types): raise TypeError cmd = '%s : %s$'%(var, value.rstrip(';')) self.eval(cmd) diff --git a/src/sage/interfaces/qepcad.py b/src/sage/interfaces/qepcad.py index 00488e99398..f920633084c 100644 --- a/src/sage/interfaces/qepcad.py +++ b/src/sage/interfaces/qepcad.py @@ -605,6 +605,7 @@ #***************************************************************************** from __future__ import print_function from __future__ import absolute_import +from six import string_types from sage.env import SAGE_LOCAL import pexpect @@ -836,12 +837,12 @@ def __init__(self, formula, varlist = None if vars is not None: - if isinstance(vars, str): + if isinstance(vars, string_types): varlist = vars.strip('()').split(',') else: varlist = [str(v) for v in vars] - if isinstance(formula, str): + if isinstance(formula, string_types): if varlist is None: raise ValueError("vars must be specified if formula is a string") @@ -917,7 +918,7 @@ def assume(self, assume): sage: qe.finish() # optional - qepcad 4 a c - b^2 <= 0 """ - if not isinstance(assume, str): + if not isinstance(assume, string_types): assume = qepcad_formula.formula(assume) if len(assume.qvars): raise ValueError("assumptions cannot be quantified") diff --git a/src/sage/interfaces/r.py b/src/sage/interfaces/r.py index a03b5ed8001..9db603f8eb3 100644 --- a/src/sage/interfaces/r.py +++ b/src/sage/interfaces/r.py @@ -1,3 +1,4 @@ +# -*- coding: utf-8 -*- r""" Interfaces to R diff --git a/src/sage/interfaces/sage0.py b/src/sage/interfaces/sage0.py index a8e969cbf35..4ba76ab0b80 100644 --- a/src/sage/interfaces/sage0.py +++ b/src/sage/interfaces/sage0.py @@ -15,7 +15,7 @@ # # http://www.gnu.org/licenses/ #***************************************************************************** -from six import iteritems +from six import iteritems, string_types from six.moves import cPickle import os @@ -232,7 +232,7 @@ def __call__(self, x): else: return self(x.sage()) - if isinstance(x, str): + if isinstance(x, string_types): return SageElement(self, x) if self.is_local(): diff --git a/src/sage/interfaces/singular.py b/src/sage/interfaces/singular.py index b2da07f9590..e7dfab1940d 100644 --- a/src/sage/interfaces/singular.py +++ b/src/sage/interfaces/singular.py @@ -320,7 +320,7 @@ from __future__ import print_function from __future__ import absolute_import from six.moves import range -from six import integer_types +from six import integer_types, string_types import os import re @@ -903,7 +903,7 @@ def ideal(self, *gens): x0*x1-x0*x2-x1*x2, x0^2*x2-x0*x2^2-x1*x2^2 """ - if isinstance(gens, str): + if isinstance(gens, string_types): gens = self(gens) if isinstance(gens, SingularElement): From 5032c36e4c5c23e5f2775aa82aa0c315f7c3cce0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 19 May 2017 17:56:00 +0200 Subject: [PATCH 417/452] trac 22975 one more relative import --- src/sage/matrix/matrix0.pyx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/sage/matrix/matrix0.pyx b/src/sage/matrix/matrix0.pyx index a9c4837f360..a49ccde38a9 100644 --- a/src/sage/matrix/matrix0.pyx +++ b/src/sage/matrix/matrix0.pyx @@ -44,7 +44,7 @@ from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing import sage.modules.free_module -import matrix_misc +from .matrix_misc import row_iterator cdef class Matrix(sage.structure.element.Matrix): @@ -529,16 +529,15 @@ cdef class Matrix(sage.structure.element.Matrix): def __iter__(self): """ - Return an iterator for the rows of self + Return an iterator for the rows of self. EXAMPLES:: - sage: m=matrix(2,[1,2,3,4]) + sage: m = matrix(2,[1,2,3,4]) sage: next(m.__iter__()) (1, 2) """ - - return matrix_misc.row_iterator(self) + return row_iterator(self) def __getitem__(self, key): """ From f8cffe4140b81f8887b030a697cd6c084ed0bbf6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 19 May 2017 18:01:06 +0200 Subject: [PATCH 418/452] trac 22975 fixing some absolute imports --- src/sage/modules/vector_double_dense.pyx | 2 +- src/sage/rings/finite_rings/element_ntl_gf2e.pyx | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/sage/modules/vector_double_dense.pyx b/src/sage/modules/vector_double_dense.pyx index 93470d4dc6b..6e7ff809215 100644 --- a/src/sage/modules/vector_double_dense.pyx +++ b/src/sage/modules/vector_double_dense.pyx @@ -44,7 +44,7 @@ from __future__ import absolute_import cimport numpy import numpy -import free_module_element +from .free_module_element import FreeModuleElement from sage.structure.element cimport Element, ModuleElement, RingElement, Vector diff --git a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx index 96ae0da979e..c46207d8021 100644 --- a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx +++ b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx @@ -42,9 +42,9 @@ from sage.interfaces.gap import is_GapElement from sage.misc.randstate import current_randstate -from element_ext_pari import FiniteField_ext_pariElement -from element_pari_ffelt import FiniteFieldElement_pari_ffelt -from finite_field_ntl_gf2e import FiniteField_ntl_gf2e +from .element_ext_pari import FiniteField_ext_pariElement +from .element_pari_ffelt import FiniteFieldElement_pari_ffelt +from .finite_field_ntl_gf2e import FiniteField_ntl_gf2e from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing From 888553949c3872e9cd5813f71e41680f5ac76098 Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Fri, 19 May 2017 09:24:06 -0700 Subject: [PATCH 419/452] trac 23034: remove mention of "sage --bdist" from README.md --- README.md | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index e140caea73b..c5ca76a1fec 100644 --- a/README.md +++ b/README.md @@ -377,20 +377,10 @@ do. sage --sdist -2. To make a binary distribution with your currently installed packages, - type: + The result is placed in the directory "$SAGE_ROOT/dist/". - sage --bdist - -3. To make a binary that will run on the widest range of target - machines, set the SAGE_FAT_BINARY environment variable to "yes" - before building Sage: - - export SAGE_FAT_BINARY="yes" - make distclean && make - ./sage --bdist - -In all cases, the result is placed in the directory "$SAGE_ROOT/dist/". +2. To make a binary distribution with your currently installed packages, + visit https://github.com/sagemath/binary-pkg Changes to Included Software From c7df9e162e4412979919394ace2d699f1ff6a7ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Fri, 19 May 2017 20:03:38 +0200 Subject: [PATCH 420/452] a little bunch of typos --- src/doc/en/installation/source.rst | 2 +- src/sage/algebras/cluster_algebra.py | 2 +- src/sage/calculus/calculus.py | 3 --- src/sage/categories/commutative_rings.py | 2 +- src/sage/categories/fields.py | 2 +- .../categories/finite_dimensional_algebras_with_basis.py | 2 +- src/sage/categories/modules_with_basis.py | 2 +- src/sage/categories/unital_algebras.py | 2 +- src/sage/coding/bch.py | 2 +- src/sage/combinat/binary_recurrence_sequences.py | 2 +- src/sage/combinat/crystals/affine_factorization.py | 2 +- src/sage/combinat/designs/incidence_structures.py | 2 +- src/sage/combinat/designs/orthogonal_arrays.py | 2 +- src/sage/combinat/designs/twographs.py | 4 ++-- src/sage/combinat/finite_state_machine.py | 2 +- src/sage/combinat/ncsf_qsym/tutorial.py | 2 +- .../combinat/root_system/root_lattice_realizations.py | 2 +- src/sage/combinat/sf/witt.py | 2 +- src/sage/doctest/parsing.py | 6 +++--- src/sage/dynamics/interval_exchanges/labelled.py | 2 +- src/sage/dynamics/interval_exchanges/reduced.py | 2 +- src/sage/geometry/fan.py | 4 ++-- .../geometry/hyperbolic_space/hyperbolic_interface.py | 2 +- src/sage/geometry/hyperbolic_space/hyperbolic_model.py | 2 +- .../riemannian_manifolds/parametrized_surface3d.py | 2 +- src/sage/graphs/generic_graph.py | 8 ++++---- src/sage/graphs/graph.py | 2 +- src/sage/graphs/graph_generators.py | 2 +- src/sage/groups/libgap_wrapper.pyx | 2 +- src/sage/groups/matrix_gps/finitely_generated.py | 2 +- src/sage/groups/matrix_gps/unitary.py | 4 ++-- src/sage/groups/raag.py | 2 +- src/sage/homology/examples.py | 2 +- src/sage/homology/simplicial_complex.py | 2 +- src/sage/interfaces/polymake.py | 2 +- src/sage/libs/linkages/padics/API.pxi | 2 +- src/sage/libs/linkages/padics/fmpz_poly_unram.pxi | 2 +- src/sage/libs/linkages/padics/mpz.pxi | 2 +- src/sage/logic/logic.py | 2 +- src/sage/matroids/matroids_plot_helpers.py | 2 +- src/sage/misc/c3_controlled.pyx | 3 ++- src/sage/misc/converting_dict.py | 2 +- src/sage/monoids/automatic_semigroup.py | 2 +- src/sage/parallel/map_reduce.py | 6 +++--- src/sage/quadratic_forms/quadratic_form.py | 4 ++-- src/sage/repl/rich_output/preferences.py | 2 +- src/sage/rings/number_field/number_field.py | 4 ++-- src/sage/rings/polynomial/flatten.py | 4 ++-- src/sage/rings/polynomial/laurent_polynomial.pyx | 6 +++--- src/sage/rings/polynomial/laurent_polynomial_ring.py | 4 ++-- .../rings/polynomial/polynomial_quotient_ring_element.py | 2 +- src/sage/rings/polynomial/real_roots.pyx | 2 +- src/sage/sat/converters/polybori.py | 2 +- src/sage/schemes/affine/affine_morphism.py | 2 +- src/sage/schemes/elliptic_curves/ell_finite_field.py | 2 +- src/sage/schemes/elliptic_curves/isogeny_small_degree.py | 2 +- src/sage/schemes/elliptic_curves/padic_lseries.py | 3 ++- src/sage/schemes/projective/projective_morphism.py | 4 ++-- src/sage/schemes/projective/projective_space.py | 3 ++- src/sage/schemes/toric/points.py | 2 +- src/sage/symbolic/expression.pyx | 4 ++-- src/sage/symbolic/expression_conversions.py | 2 +- src/sage/tensor/modules/comp.py | 4 ++-- src/sage_setup/docbuild/__init__.py | 2 +- 64 files changed, 85 insertions(+), 85 deletions(-) diff --git a/src/doc/en/installation/source.rst b/src/doc/en/installation/source.rst index 49684ee743f..3d7c015017f 100644 --- a/src/doc/en/installation/source.rst +++ b/src/doc/en/installation/source.rst @@ -1033,7 +1033,7 @@ Here are some of the more commonly used variables affecting the build process: - :envvar:`SAGE_PROFILE` - controls profiling support. If this is set to ``yes``, profiling support is enabled where possible. Note that - Python-level profiling is always avaliable; This option enables + Python-level profiling is always available; This option enables profiling in Cython modules. - :envvar:`SAGE_SPKG_INSTALL_DOCS` - if set to ``yes``, then install diff --git a/src/sage/algebras/cluster_algebra.py b/src/sage/algebras/cluster_algebra.py index 1deae5fd5c5..02f61a8554b 100644 --- a/src/sage/algebras/cluster_algebra.py +++ b/src/sage/algebras/cluster_algebra.py @@ -1261,7 +1261,7 @@ def __init__(self, Q, **kwargs): # the result to polynomials but then we get "rational" coefficients self._U = PolynomialRing(QQ, ['u%s' % i for i in range(self._n)]) - # Setup infrastruture to store computed data + # Setup infrastructure to store computed data self.clear_computed_data() # Determine the names of the initial cluster variables diff --git a/src/sage/calculus/calculus.py b/src/sage/calculus/calculus.py index 5b52d189610..812d7ead863 100644 --- a/src/sage/calculus/calculus.py +++ b/src/sage/calculus/calculus.py @@ -15,9 +15,6 @@ - Tom Coates (2010-06-11): fixed :trac:`9217` -The Sage calculus module is loosely based on the Sage Enhancement -Proposal found at: http://www.sagemath.org:9001/CalculusSEP. - EXAMPLES: The basic units of the calculus package are symbolic expressions which diff --git a/src/sage/categories/commutative_rings.py b/src/sage/categories/commutative_rings.py index cc41fd0c463..19f3949b7f0 100644 --- a/src/sage/categories/commutative_rings.py +++ b/src/sage/categories/commutative_rings.py @@ -85,7 +85,7 @@ def cyclotomic_cosets(self, q, cosets=None): .. NOTE:: When `R = \ZZ / n \ZZ` the smallest element of each coset is - sometimes callled a *coset leader*. This function returns + sometimes called a *coset leader*. This function returns sorted lists so that the coset leader will always be the first element of the coset. diff --git a/src/sage/categories/fields.py b/src/sage/categories/fields.py index 2243bf31085..de4123ba6d3 100644 --- a/src/sage/categories/fields.py +++ b/src/sage/categories/fields.py @@ -313,7 +313,7 @@ def _squarefree_decomposition_univariate_polynomial(self, f): - ``f`` -- a univariate non-zero polynomial over this field ALGORITHM: For rings of characteristic zero, we use the algorithm - descriped in [Yun1976]_. Other fields may provide their own + described in [Yun1976]_. Other fields may provide their own implementation by overriding this method. EXAMPLES:: diff --git a/src/sage/categories/finite_dimensional_algebras_with_basis.py b/src/sage/categories/finite_dimensional_algebras_with_basis.py index e0c0951db95..d8ecb7d95df 100644 --- a/src/sage/categories/finite_dimensional_algebras_with_basis.py +++ b/src/sage/categories/finite_dimensional_algebras_with_basis.py @@ -641,7 +641,7 @@ def cartan_invariants_matrix(self): EXAMPLES: For a semisimple algebra, in particular for group algebras - in chararacteristic zero, the Cartan invariants matrix is + in characteristic zero, the Cartan invariants matrix is the identity:: sage: A3 = SymmetricGroup(3).algebra(QQ) diff --git a/src/sage/categories/modules_with_basis.py b/src/sage/categories/modules_with_basis.py index 21734e04131..96ad41ba971 100644 --- a/src/sage/categories/modules_with_basis.py +++ b/src/sage/categories/modules_with_basis.py @@ -1961,7 +1961,7 @@ def __call_on_basis__(self, **options): This method simply delegates the work to :meth:`ModulesWithBasis.ParentMethods.module_morphism`. It is used by :meth:`Homset.__call__` to handle the - ``on_basis`` argument, and will disapear as soon as + ``on_basis`` argument, and will disappear as soon as the logic will be generalized. EXAMPLES:: diff --git a/src/sage/categories/unital_algebras.py b/src/sage/categories/unital_algebras.py index abb60701dd2..166db1d0c2e 100644 --- a/src/sage/categories/unital_algebras.py +++ b/src/sage/categories/unital_algebras.py @@ -249,7 +249,7 @@ def from_base_ring(self): def from_base_ring_from_one_basis(self, r): """ - Implement the canonical embeding from the ground ring. + Implement the canonical embedding from the ground ring. INPUT: diff --git a/src/sage/coding/bch.py b/src/sage/coding/bch.py index c17b2d8ef89..126d919d2db 100644 --- a/src/sage/coding/bch.py +++ b/src/sage/coding/bch.py @@ -146,7 +146,7 @@ def __init__(self, base_field, length, designed_distance, s = Zmod(length)(q).multiplicative_order() if gcd(jump_size, q ** s - 1) != 1: raise ValueError("jump_size must be coprime with the order of " - "the multicative group of the splitting field") + "the multiplicative group of the splitting field") D = [(offset + jump_size * i) % length for i in range(designed_distance - 1)] diff --git a/src/sage/combinat/binary_recurrence_sequences.py b/src/sage/combinat/binary_recurrence_sequences.py index af61233a761..d944e615679 100644 --- a/src/sage/combinat/binary_recurrence_sequences.py +++ b/src/sage/combinat/binary_recurrence_sequences.py @@ -503,7 +503,7 @@ def period(self, m): n = b perp = n - #Now compute the period mod p^e by steping up by multiples of p + #Now compute the period mod p^e by stepping up by multiples of p F = A.change_ring(Integers(p**e)) v = w.change_ring(Integers(p**e)) FF = F**perp diff --git a/src/sage/combinat/crystals/affine_factorization.py b/src/sage/combinat/crystals/affine_factorization.py index b486f14042f..274dd309ff4 100644 --- a/src/sage/combinat/crystals/affine_factorization.py +++ b/src/sage/combinat/crystals/affine_factorization.py @@ -373,7 +373,7 @@ def affine_factorizations(w, l, weight=None): - ``w`` -- an (affine) permutation or element of the (affine) Weyl group - - ``l`` -- nonegative integer + - ``l`` -- nonnegative integer - ``weight`` -- (default: None) tuple of nonnegative integers specifying the length of the factors diff --git a/src/sage/combinat/designs/incidence_structures.py b/src/sage/combinat/designs/incidence_structures.py index 13f2339b216..ac88ef785bb 100644 --- a/src/sage/combinat/designs/incidence_structures.py +++ b/src/sage/combinat/designs/incidence_structures.py @@ -426,7 +426,7 @@ def is_isomorphic(self, other, certificate=False): - ``other`` -- an incidence structure. - ``certificate`` (boolean) -- whether to return an - insomorphism from ``self`` to ``other`` instead of a boolean + isomorphism from ``self`` to ``other`` instead of a boolean answer. EXAMPLES:: diff --git a/src/sage/combinat/designs/orthogonal_arrays.py b/src/sage/combinat/designs/orthogonal_arrays.py index 8e705557f0d..6f80263ee2a 100644 --- a/src/sage/combinat/designs/orthogonal_arrays.py +++ b/src/sage/combinat/designs/orthogonal_arrays.py @@ -1424,7 +1424,7 @@ def OA_find_disjoint_blocks(OA,k,n,x): `x` blocks of an `OA` are said to be disjoint if they all have different values for a every given index, i.e. if they correspond to - disjoint blocks in the `TD` assciated with the `OA`. + disjoint blocks in the `TD` associated with the `OA`. INPUT: diff --git a/src/sage/combinat/designs/twographs.py b/src/sage/combinat/designs/twographs.py index cc1d3c821c3..73d2f028fa3 100644 --- a/src/sage/combinat/designs/twographs.py +++ b/src/sage/combinat/designs/twographs.py @@ -153,7 +153,7 @@ def complement(self): """ The two-graph which is the complement of ``self`` - That is, the two-graph constisting exactly of triples not in ``self``. + That is, the two-graph consisting exactly of triples not in ``self``. Note that this is different from :meth:`complement ` of the :class:`parent class @@ -161,7 +161,7 @@ def complement(self): EXAMPLES:: - sage: p=graphs.CompleteGraph(8).line_graph().twograph() + sage: p = graphs.CompleteGraph(8).line_graph().twograph() sage: pc = p.complement(); pc Incidence structure with 28 points and 1260 blocks diff --git a/src/sage/combinat/finite_state_machine.py b/src/sage/combinat/finite_state_machine.py index 7cf09b4ea6d..34ef799599c 100644 --- a/src/sage/combinat/finite_state_machine.py +++ b/src/sage/combinat/finite_state_machine.py @@ -8795,7 +8795,7 @@ def final_components(self): leaving ``C``. The final components are the only parts of a transducer which - influence the main terms of the asympotic behaviour of the sum + influence the main terms of the asymptotic behaviour of the sum of output labels of a transducer, see [HKP2015]_ and [HKW2015]_. EXAMPLES:: diff --git a/src/sage/combinat/ncsf_qsym/tutorial.py b/src/sage/combinat/ncsf_qsym/tutorial.py index 5cf429b0d17..27c9aeebfda 100644 --- a/src/sage/combinat/ncsf_qsym/tutorial.py +++ b/src/sage/combinat/ncsf_qsym/tutorial.py @@ -3,7 +3,7 @@ Introduction to Quasisymmetric Functions In this document we briefly explain the quasisymmetric function bases and -related functionality in Sage. We assume the reader is familar with the +related functionality in Sage. We assume the reader is familiar with the package :class:`SymmetricFunctions`. Quasisymmetric functions, denoted `QSym`, form a subring of the power diff --git a/src/sage/combinat/root_system/root_lattice_realizations.py b/src/sage/combinat/root_system/root_lattice_realizations.py index 2cdae2201a3..cb8aea11801 100644 --- a/src/sage/combinat/root_system/root_lattice_realizations.py +++ b/src/sage/combinat/root_system/root_lattice_realizations.py @@ -2400,7 +2400,7 @@ def plot_fundamental_weights(self, **options): # We build the family of fundamental weights in this space, # indexed by the fundamental weights in the weight lattice. # - # To this end, we don't use the embdding of the weight + # To this end, we don't use the embedding of the weight # lattice into self as for the roots or coroots because # the ambient space can define the fundamental weights # slightly differently (the usual GL_n vs SL_n catch). diff --git a/src/sage/combinat/sf/witt.py b/src/sage/combinat/sf/witt.py index 5f9516a5fd1..46c591d16b4 100644 --- a/src/sage/combinat/sf/witt.py +++ b/src/sage/combinat/sf/witt.py @@ -994,7 +994,7 @@ def __init_extra__(self): # symmetric basis and the complete homogeneous basis (over the same base # ring as self), respectively (but they are only set if the respective # arguments ``coerce_p``, ``coerce_e`` and ``coerce_h`` are True). - # self._friendly will be the one avaliable basis which makes computations + # self._friendly will be the one available basis which makes computations # the easiest. self._friendly = None diff --git a/src/sage/doctest/parsing.py b/src/sage/doctest/parsing.py index edc883ff791..460da5618c4 100644 --- a/src/sage/doctest/parsing.py +++ b/src/sage/doctest/parsing.py @@ -218,9 +218,9 @@ def get_source(example): def reduce_hex(fingerprints): """ - Returns a symmetric function of the arguments as hex strings. + Return a symmetric function of the arguments as hex strings. - The arguments should be 32 character strings consiting of hex + The arguments should be 32 character strings consisting of hex digits: 0-9 and a-f. EXAMPLES:: @@ -464,7 +464,7 @@ def parse(self, string, *args): INPUT: - ``string`` -- the string to parse. - - ``name`` -- optional string giving the name indentifying string, + - ``name`` -- optional string giving the name identifying string, to be used in error messages. OUTPUT: diff --git a/src/sage/dynamics/interval_exchanges/labelled.py b/src/sage/dynamics/interval_exchanges/labelled.py index 12c2f6d7bc6..7ebe7fce497 100644 --- a/src/sage/dynamics/interval_exchanges/labelled.py +++ b/src/sage/dynamics/interval_exchanges/labelled.py @@ -337,7 +337,7 @@ def _reversed(self): r""" .. TODO:: - resolve properly the mutablility problem with the + resolve properly the mutability problem with the :meth:`_twin` attribute. TESTS:: diff --git a/src/sage/dynamics/interval_exchanges/reduced.py b/src/sage/dynamics/interval_exchanges/reduced.py index a4a8174ebaa..2a19e53f88a 100644 --- a/src/sage/dynamics/interval_exchanges/reduced.py +++ b/src/sage/dynamics/interval_exchanges/reduced.py @@ -904,7 +904,7 @@ class ReducedPermutationLI(ReducedPermutation, PermutationLI): sage: decomposition (['a'], ['c', 'a'], [], ['c']) - Rauzy movavability and Rauzy move:: + Rauzy movability and Rauzy move:: sage: p = iet.GeneralizedPermutation('a b b', 'c c a', reduced = True) sage: p.has_rauzy_move(0) diff --git a/src/sage/geometry/fan.py b/src/sage/geometry/fan.py index 51f5b986708..2685d5f2de1 100644 --- a/src/sage/geometry/fan.py +++ b/src/sage/geometry/fan.py @@ -45,7 +45,7 @@ But keep in mind that in higher dimensions the cone data is essential and cannot be omitted. Instead of building a fan from scratch, for -this tutorial we will use an easy way to get two fans assosiated to +this tutorial we will use an easy way to get two fans associated to :class:`lattice polytopes `: :func:`FaceFan` and :func:`NormalFan`:: @@ -589,7 +589,7 @@ def FaceFan(polytope, lattice=None): ` over `\QQ` or a :class:`lattice polytope `. A (not - necessarily full-dimensional) polytope contaning the origin in + necessarily full-dimensional) polytope containing the origin in its :meth:`relative interior `. diff --git a/src/sage/geometry/hyperbolic_space/hyperbolic_interface.py b/src/sage/geometry/hyperbolic_space/hyperbolic_interface.py index 5e7d78c7010..73dcee3fc50 100644 --- a/src/sage/geometry/hyperbolic_space/hyperbolic_interface.py +++ b/src/sage/geometry/hyperbolic_space/hyperbolic_interface.py @@ -22,7 +22,7 @@ in the hyperboloid model. Performing mapping this point to the upper half plane and performing computations there may return with vector whose components are unsimplified strings have several ``sqrt(2)``'s. - Presently, this drawback is outweighed by the rapidity with which new + Presently, this drawback is outweighted by the rapidity with which new models can be implemented. AUTHORS: diff --git a/src/sage/geometry/hyperbolic_space/hyperbolic_model.py b/src/sage/geometry/hyperbolic_space/hyperbolic_model.py index 3654c66ba21..08511406a80 100644 --- a/src/sage/geometry/hyperbolic_space/hyperbolic_model.py +++ b/src/sage/geometry/hyperbolic_space/hyperbolic_model.py @@ -674,7 +674,7 @@ def coords(x): return self._dist_points(coords(p), coords(q)) raise NotImplementedError("can only compute distance between" - " ultra-parallel and interecting geodesics") + " ultra-parallel and intersecting geodesics") # If only one is a geodesic, make sure it's b to make things easier a,b = b,a diff --git a/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py b/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py index c4195c8be65..d63551c42e4 100644 --- a/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py +++ b/src/sage/geometry/riemannian_manifolds/parametrized_surface3d.py @@ -842,7 +842,7 @@ def rotation(self,theta): [ 1/2 -1/2*sqrt(3)/cos(v)] [ 1/2*sqrt(3)*cos(v) 1/2] - We verify that three succesive rotations over $\pi/3$ yield minus the identity:: + We verify that three successive rotations over $\pi/3$ yield minus the identity:: sage: rotation^3 [-1 0] diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 5074df47bc9..7f3f41cd80f 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -979,9 +979,9 @@ def copy(self, weighted=None, implementation='c_graph', data_structure=None, sage: g is g.copy(data_structure='static_sparse') is g.copy(immutable=True) True - If a graph pretends to be immutable, but does not use the static sparse - backend, then the copy is not identic with the graph, even though it is - considered to be hashable:: + If a graph pretends to be immutable, but does not use the + static sparse backend, then the copy is not identical with the + graph, even though it is considered to be hashable:: sage: P = Poset(([1,2,3,4], [[1,3],[1,4],[2,3]]), linear_extension=True, facade = False) sage: H = P.hasse_diagram() @@ -15567,7 +15567,7 @@ def shortest_path_lengths(self, u, by_weight=False, algorithm=None, Computes the length of a shortest path from u to any other vertex. Returns a dictionary of shortest path lengths keyed by targets, - escluding all vertices that are not reachable from u. + excluding all vertices that are not reachable from u. For more information on the input variables and more examples, we refer to :meth:`~GenericGraph.shortest_paths` diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index 182660ccf3e..2f1193fda9e 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -3762,7 +3762,7 @@ def orientations(self, implementation='c_graph', data_structure=None, sparse=Non .. WARNING:: - This always considers mutliple edges of graphs as + This always considers multiple edges of graphs as distinguishable, and hence, may have repeated digraphs. EXAMPLES:: diff --git a/src/sage/graphs/graph_generators.py b/src/sage/graphs/graph_generators.py index 368be589194..161234dbaa5 100644 --- a/src/sage/graphs/graph_generators.py +++ b/src/sage/graphs/graph_generators.py @@ -926,7 +926,7 @@ def cospectral_graphs(self, vertices, matrix_function=lambda g: g.adjacency_matr OUTPUT: A list of lists of graphs. Each sublist will be a list of - cospectral graphs (lists of cadinality 1 being omitted). + cospectral graphs (lists of cardinality 1 being omitted). .. SEEALSO:: diff --git a/src/sage/groups/libgap_wrapper.pyx b/src/sage/groups/libgap_wrapper.pyx index 69c5e13840d..f31236bf74d 100644 --- a/src/sage/groups/libgap_wrapper.pyx +++ b/src/sage/groups/libgap_wrapper.pyx @@ -146,7 +146,7 @@ class ParentLibGAP(SageObject): Return whether the group was defined as a subgroup of a bigger group. - You can access the contaning group with :meth:`ambient`. + You can access the containing group with :meth:`ambient`. OUTPUT: diff --git a/src/sage/groups/matrix_gps/finitely_generated.py b/src/sage/groups/matrix_gps/finitely_generated.py index b6e868153f7..d40d7b5af81 100644 --- a/src/sage/groups/matrix_gps/finitely_generated.py +++ b/src/sage/groups/matrix_gps/finitely_generated.py @@ -819,7 +819,7 @@ def molien_series(self, xi=None, return_series=True, prec=20, variable='t'): \frac{1}{|G|}\sum_{g \in G} \frac{\xi(g)}{\text{det}(I-tg)}, - where `I` is the indentity matrix and `t` an indeterminant. + where `I` is the identity matrix and `t` an indeterminate. For characteristic `p` not dividing the order of `G`, let `k` be the base field and `N` the order of `G`. Define `\lambda` as a primitive `N`-th root of unity over `k` diff --git a/src/sage/groups/matrix_gps/unitary.py b/src/sage/groups/matrix_gps/unitary.py index 3b795a95a8b..237e37b3462 100644 --- a/src/sage/groups/matrix_gps/unitary.py +++ b/src/sage/groups/matrix_gps/unitary.py @@ -83,7 +83,7 @@ def GU(n, R, var='a'): Return the general unitary group. The general unitary group `GU( d, R )` consists of all `d \times - d` matrices that preserve a nondegenerate sequilinear form over + d` matrices that preserve a nondegenerate sesquilinear form over the ring `R`. .. note:: @@ -160,7 +160,7 @@ def GU(n, R, var='a'): def SU(n, R, var='a'): """ The special unitary group `SU( d, R )` consists of all `d \times d` - matrices that preserve a nondegenerate sequilinear form over the + matrices that preserve a nondegenerate sesquilinear form over the ring `R` and have determinant one. .. note:: diff --git a/src/sage/groups/raag.py b/src/sage/groups/raag.py index e744a1cf6c6..b3f434ba94b 100644 --- a/src/sage/groups/raag.py +++ b/src/sage/groups/raag.py @@ -4,7 +4,7 @@ A *right-angled Artin group* (often abbreviated as RAAG) is a group which has a presentation whose only relations are commutators between generators. These are also known as graph groups, since they are (uniquely) encoded by -(simple) graphs, or partially commmutative groups. +(simple) graphs, or partially commutative groups. AUTHORS: diff --git a/src/sage/homology/examples.py b/src/sage/homology/examples.py index 958c76d9371..760669aa3fb 100644 --- a/src/sage/homology/examples.py +++ b/src/sage/homology/examples.py @@ -699,7 +699,7 @@ def RealProjectiveSpace(n): sends any subset `U` to its complement. One can show that modding out by this action results in a triangulation for `\Bold{R}P^n`. To find the facets in this triangulation, find - the facets in `S`. These are indentified in pairs to form + the facets in `S`. These are identified in pairs to form `\Bold{R}P^n`, so choose a representative from each pair: for each facet in `S`, replace any vertex in `S` containing 0 with its complement. diff --git a/src/sage/homology/simplicial_complex.py b/src/sage/homology/simplicial_complex.py index c5447ee4154..aefe15563ae 100644 --- a/src/sage/homology/simplicial_complex.py +++ b/src/sage/homology/simplicial_complex.py @@ -1392,7 +1392,7 @@ def n_cells(self, n, subcomplex=None, sort=None): This list is sorted to provide reliable indexing for the rows and columns of the matrices of differentials in the - associateed chain complex. + associated chain complex. EXAMPLES:: diff --git a/src/sage/interfaces/polymake.py b/src/sage/interfaces/polymake.py index c6ddcfc113e..55d1c5a4821 100644 --- a/src/sage/interfaces/polymake.py +++ b/src/sage/interfaces/polymake.py @@ -1639,7 +1639,7 @@ def __getattr__(self, attrname): If the attribute name is known as the name of a property, it is interpreted as such. Otherwise, if it is known as a function in - the currenty application, the function is returned with this + the current application, the function is returned with this element inserted as first argument, and potential further arguments, when called. Otherwise, it is assumed that it is a member function of this element, and treated as such. Note that member functions diff --git a/src/sage/libs/linkages/padics/API.pxi b/src/sage/libs/linkages/padics/API.pxi index f15c50740b1..576d66b492d 100644 --- a/src/sage/libs/linkages/padics/API.pxi +++ b/src/sage/libs/linkages/padics/API.pxi @@ -329,7 +329,7 @@ cdef inline int cdivunit(celement out, celement a, celement b, long prec, PowCom """ Division. - The inversion is perfomed modulo p^prec. Note that no reduction + The inversion is performed modulo p^prec. Note that no reduction is performed after the product. INPUT: diff --git a/src/sage/libs/linkages/padics/fmpz_poly_unram.pxi b/src/sage/libs/linkages/padics/fmpz_poly_unram.pxi index f5915a824be..74284cd788c 100644 --- a/src/sage/libs/linkages/padics/fmpz_poly_unram.pxi +++ b/src/sage/libs/linkages/padics/fmpz_poly_unram.pxi @@ -370,7 +370,7 @@ cdef inline int cdivunit(celement out, celement a, celement b, long prec, PowCom """ Division. - The inversion is perfomed modulo p^prec. Note that no reduction + The inversion is performed modulo p^prec. Note that no reduction is performed after the product. INPUT: diff --git a/src/sage/libs/linkages/padics/mpz.pxi b/src/sage/libs/linkages/padics/mpz.pxi index 8bb4d23a232..f6e30f3abca 100644 --- a/src/sage/libs/linkages/padics/mpz.pxi +++ b/src/sage/libs/linkages/padics/mpz.pxi @@ -327,7 +327,7 @@ cdef inline int cdivunit(mpz_t out, mpz_t a, mpz_t b, long prec, PowComputer_ pr """ Division. - The inversion is perfomed modulo p^prec. Note that no reduction + The inversion is performed modulo p^prec. Note that no reduction is performed after the product. INPUT: diff --git a/src/sage/logic/logic.py b/src/sage/logic/logic.py index 1fc28582cfd..db4eb281c46 100644 --- a/src/sage/logic/logic.py +++ b/src/sage/logic/logic.py @@ -278,7 +278,7 @@ def combine(self, statement1, statement2): OUTPUT: - A new staement which or'd the given statements together. + A new statement which or'd the given statements together. EXAMPLES:: diff --git a/src/sage/matroids/matroids_plot_helpers.py b/src/sage/matroids/matroids_plot_helpers.py index 29c154cfc71..c8a45eba7af 100644 --- a/src/sage/matroids/matroids_plot_helpers.py +++ b/src/sage/matroids/matroids_plot_helpers.py @@ -22,7 +22,7 @@ curve containing the points in the specified line which inturn uses ``scipy.interpolate.splprep`` and ``scipy.interpolate.splev``. Then one can use sage's graphics primitives ``line``, ``point``, ``text`` and - ``points`` to produce graphics object containg points (ground set + ``points`` to produce graphics object containing points (ground set elements) and lines (for a rank 3 matroid, these are flats of rank 2 of size greater than equal to 3) of the geometric representation of the matroid. Loops and parallel elements are added as per conventions in diff --git a/src/sage/misc/c3_controlled.pyx b/src/sage/misc/c3_controlled.pyx index b4568c4204b..19c9ac3792d 100644 --- a/src/sage/misc/c3_controlled.pyx +++ b/src/sage/misc/c3_controlled.pyx @@ -892,7 +892,8 @@ cpdef tuple C3_sorted_merge(list lists, key=identity): # last list. Later, we will make sure that it is actually # in the tail of the last list. if not last_list_non_empty: - # Reinstate the last list for the suggestion if it had disapeared before + # Reinstate the last list for the suggestion + # if it had disappeared before heads.append(O) tails.append([]) tailsets.append(set()) diff --git a/src/sage/misc/converting_dict.py b/src/sage/misc/converting_dict.py index 5be3be1f64f..2902e2f8c6f 100644 --- a/src/sage/misc/converting_dict.py +++ b/src/sage/misc/converting_dict.py @@ -205,7 +205,7 @@ def has_key(self, key): def pop(self, key, *args): r""" - Remove and retreive a given element from the dictionary + Remove and retrieve a given element from the dictionary. INPUT: diff --git a/src/sage/monoids/automatic_semigroup.py b/src/sage/monoids/automatic_semigroup.py index 4c5656c6ac4..2de54a47b73 100644 --- a/src/sage/monoids/automatic_semigroup.py +++ b/src/sage/monoids/automatic_semigroup.py @@ -146,7 +146,7 @@ class AutomaticSemigroup(UniqueRepresentation, Parent): [[1, 0], [3, 1], [2, 0], [2, 1]] We can also use it to get submonoids from groups. We check that in the - symmetric group, a transposition and a cyle generate the whole group:: + symmetric group, a transposition and a long cycle generate the whole group:: sage: G5 = SymmetricGroup(5) sage: N = AutomaticSemigroup(Family({1: G5([2,1,3,4,5]), 2: G5([2,3,4,5,1])}), one=G5.one()) diff --git a/src/sage/parallel/map_reduce.py b/src/sage/parallel/map_reduce.py index a1df1e411c9..1b1d2d95503 100644 --- a/src/sage/parallel/map_reduce.py +++ b/src/sage/parallel/map_reduce.py @@ -452,7 +452,7 @@ nodes: the work is done. The worker executes :meth:`master._shutdown` which sends ``AbortError`` on all :meth:`worker._request` and :meth:`worker._write_task` Queues. Each worker or thief thread receiving such -a message raise the corresponding exception, stoping therefore its work. A +a message raise the corresponding exception, stopping therefore its work. A lock called ``master._done`` ensures that shutdown is only done once. Finally, it is also possible to interrupt the computation before its ends @@ -1574,11 +1574,11 @@ def _thief(self): def steal(self): r""" - Steal some node from another worker + Steal some node from another worker. OUTPUT: - a node stolen from another worker choosed at random + a node stolen from another worker chosen at random EXAMPLES:: diff --git a/src/sage/quadratic_forms/quadratic_form.py b/src/sage/quadratic_forms/quadratic_form.py index 2477451c30b..9fd853df2f5 100644 --- a/src/sage/quadratic_forms/quadratic_form.py +++ b/src/sage/quadratic_forms/quadratic_form.py @@ -1158,11 +1158,11 @@ def gcd(self): def polynomial(self,names='x'): r""" - Returns the polynomial in 'n' variables of the quadratic form in the ring 'R[names].' + Return the polynomial in 'n' variables of the quadratic form in the ring 'R[names].' INPUT: - -'self' - a quadratic form over a commatitive ring. + -'self' - a quadratic form over a commutative ring. -'names' - the name of the variables. Digits will be appended to the name for each different canonical variable e.g x1, x2, x3 etc. diff --git a/src/sage/repl/rich_output/preferences.py b/src/sage/repl/rich_output/preferences.py index 5af0ff6d89f..f7d9a8fe79d 100644 --- a/src/sage/repl/rich_output/preferences.py +++ b/src/sage/repl/rich_output/preferences.py @@ -25,7 +25,7 @@ * supplemental_plot is not specified * text = ascii_art -Properties can be unset by deleting them or by assinging ``None``:: +Properties can be unset by deleting them or by assigning ``None``:: sage: prefs.text = 'ascii_art' sage: del prefs.text diff --git a/src/sage/rings/number_field/number_field.py b/src/sage/rings/number_field/number_field.py index f0cb64b4d42..4f8ff2b76ec 100644 --- a/src/sage/rings/number_field/number_field.py +++ b/src/sage/rings/number_field/number_field.py @@ -676,7 +676,7 @@ def NumberFieldTower(polynomials, names, check=True, embeddings=None, latex_name from that string. - ``check`` - a boolean (default: ``True``), whether to check that the polynomials are irreducible - - ``embeddings`` - a list of elemenst or ``None`` (default: ``None``), + - ``embeddings`` - a list of elements or ``None`` (default: ``None``), embeddings of the relative number fields in an ambient field. - ``latex_names`` - a list of strings or ``None`` (default: ``None``), names used to print the generators for latex output. @@ -9497,7 +9497,7 @@ def _element_constructor_(self, x, check=True): ## d = sage.arith.all.gcd(m,n) ## r = n // d -## # Since we use the power basis for cyclomotic fields, if every +## # Since we use the power basis for cyclotomic fields, if every ## # v[i] with i not divisible by r is 0, then we're good. ## # If h generates self and has order m, then the element g^r diff --git a/src/sage/rings/polynomial/flatten.py b/src/sage/rings/polynomial/flatten.py index 86962ed44d4..6e8bee61c79 100644 --- a/src/sage/rings/polynomial/flatten.py +++ b/src/sage/rings/polynomial/flatten.py @@ -166,7 +166,7 @@ def __init__(self, domain): def _call_(self, p): r""" - Evaluate an flatenning morphism. + Evaluate an flattening morphism. EXAMPLES:: @@ -214,7 +214,7 @@ def _call_(self, p): @cached_method def section(self): """ - Inverse of this flattenning morphism. + Inverse of this flattening morphism. EXAMPLES:: diff --git a/src/sage/rings/polynomial/laurent_polynomial.pyx b/src/sage/rings/polynomial/laurent_polynomial.pyx index 3669b5b7da1..1204e629147 100644 --- a/src/sage/rings/polynomial/laurent_polynomial.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial.pyx @@ -2399,16 +2399,16 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial_generic): @coerce_binop def quo_rem(self, right): """ - Divide this laurent polynomial by ``right`` and return a quotient and + Divide this Laurent polynomial by ``right`` and return a quotient and a remainder. INPUT: - - ``right`` -- a laurent polynomial + - ``right`` -- a Laurent polynomial OUTPUT: - A pair of laurent polynomials. + A pair of Laurent polynomials. EXAMPLES:: diff --git a/src/sage/rings/polynomial/laurent_polynomial_ring.py b/src/sage/rings/polynomial/laurent_polynomial_ring.py index 411e84e44a2..4207fc0fcdf 100644 --- a/src/sage/rings/polynomial/laurent_polynomial_ring.py +++ b/src/sage/rings/polynomial/laurent_polynomial_ring.py @@ -470,7 +470,7 @@ def extract(T, indices): def _split_laurent_polynomial_dict_(P, M, d): r""" - Helper function for splitting a multivariate laurent polynomial + Helper function for splitting a multivariate Laurent polynomial during conversion. INPUT: @@ -620,7 +620,7 @@ def gen(self, i=0): def variable_names_recursive(self, depth=infinity): r""" Return the list of variable names of this ring and its base rings, - as if it were a single multi-variate laurent polynomial. + as if it were a single multi-variate Laurent polynomial. INPUT: diff --git a/src/sage/rings/polynomial/polynomial_quotient_ring_element.py b/src/sage/rings/polynomial/polynomial_quotient_ring_element.py index 99e4f3d82d5..2680215d099 100644 --- a/src/sage/rings/polynomial/polynomial_quotient_ring_element.py +++ b/src/sage/rings/polynomial/polynomial_quotient_ring_element.py @@ -371,7 +371,7 @@ def __invert__(self): TESTS: - An element is not invertable if the base ring is not a field + An element is not invertible if the base ring is not a field (see :trac:`13303`):: sage: Z16x. = Integers(16)[] diff --git a/src/sage/rings/polynomial/real_roots.pyx b/src/sage/rings/polynomial/real_roots.pyx index 821ee40276c..f55d7f2d113 100644 --- a/src/sage/rings/polynomial/real_roots.pyx +++ b/src/sage/rings/polynomial/real_roots.pyx @@ -32,7 +32,7 @@ algorithm in that paper: The best description of the algorithms used (other than this source code itself) is in the slides for my Sage Days 4 talk, currently available -from http://www.sagemath.org:9001/days4schedule . +from https://wiki.sagemath.org/days4schedule . """ ################################################################################ diff --git a/src/sage/sat/converters/polybori.py b/src/sage/sat/converters/polybori.py index 48ec81e26c3..2c38f0e9363 100644 --- a/src/sage/sat/converters/polybori.py +++ b/src/sage/sat/converters/polybori.py @@ -613,6 +613,6 @@ def product(l): product = self.ring(1) for v in c: if phi[abs(v)] is None: - raise ValueError("Clause containst an XOR glueing variable.") + raise ValueError("clause contains an XOR glueing variable") product *= phi[abs(v)] + int(v>0) return product diff --git a/src/sage/schemes/affine/affine_morphism.py b/src/sage/schemes/affine/affine_morphism.py index 611b274b729..de697c1e3d7 100644 --- a/src/sage/schemes/affine/affine_morphism.py +++ b/src/sage/schemes/affine/affine_morphism.py @@ -928,7 +928,7 @@ def global_height(self, prec=None): def jacobian (self): r""" - Returns the Jacobian matrix of partial derivitive of this map. + Return the Jacobian matrix of partial derivative of this map. The `(i, j)` entry of the Jacobian matrix is the partial derivative `diff(functions[i], variables[j])`. diff --git a/src/sage/schemes/elliptic_curves/ell_finite_field.py b/src/sage/schemes/elliptic_curves/ell_finite_field.py index 615bc1b938f..3104d20c2da 100644 --- a/src/sage/schemes/elliptic_curves/ell_finite_field.py +++ b/src/sage/schemes/elliptic_curves/ell_finite_field.py @@ -1923,7 +1923,7 @@ def supersingular_j_polynomial(p): First compute H(X) whose roots are the Legendre `\lambda`-invariants of supersingular curves (Silverman V.4.1(b)) - in charactersitic `p`. Then, using a resultant computation with + in characteristic `p`. Then, using a resultant computation with the polynomial relating `\lambda` and `j` (Silverman III.1.7(b)), we recover the polynomial (in variable ``j``) whose roots are the `j`-invariants. Factors of `j` and `j-1728` are removed if diff --git a/src/sage/schemes/elliptic_curves/isogeny_small_degree.py b/src/sage/schemes/elliptic_curves/isogeny_small_degree.py index 5f749daef94..cbfb3088528 100644 --- a/src/sage/schemes/elliptic_curves/isogeny_small_degree.py +++ b/src/sage/schemes/elliptic_curves/isogeny_small_degree.py @@ -307,7 +307,7 @@ def isogenies_prime_degree_genus_0(E, l=None): t_list = sorted((f-j*t).roots(multiplicities=False)) # The generic kernel polynomial applies to a standard curve # E_t with the correct j-invariant; we must compute the - # appropriate twising factor to scale X by: + # appropriate twisting factor to scale X by: c4, c6 = E.c_invariants() T = c4/(3*c6) jt = Fricke_module(l) diff --git a/src/sage/schemes/elliptic_curves/padic_lseries.py b/src/sage/schemes/elliptic_curves/padic_lseries.py index 56b585ec4f7..0470a493667 100644 --- a/src/sage/schemes/elliptic_curves/padic_lseries.py +++ b/src/sage/schemes/elliptic_curves/padic_lseries.py @@ -1120,7 +1120,8 @@ def series(self, n=3, quadratic_twist = +1, prec=5, eta = 0): ALIAS: power_series is identical to series. EXAMPLES: - A superingular example, where we must compute to higher precision to see anything:: + + A supersingular example, where we must compute to higher precision to see anything:: sage: e = EllipticCurve('37a') sage: L = e.padic_lseries(3); L diff --git a/src/sage/schemes/projective/projective_morphism.py b/src/sage/schemes/projective/projective_morphism.py index 0b3a76726fd..4bf08108a7d 100644 --- a/src/sage/schemes/projective/projective_morphism.py +++ b/src/sage/schemes/projective/projective_morphism.py @@ -939,7 +939,7 @@ def dynatomic_polynomial(self, period): sage: f.dynatomic_polynomial(-1) Traceback (most recent call last): ... - TypeError: period must be a postive integer + TypeError: period must be a positive integer :: @@ -984,7 +984,7 @@ def dynatomic_polynomial(self, period): m = period[0] n = int(period[1]) if n < 0: - raise TypeError("period must be a postive integer") + raise TypeError("period must be a positive integer") if n == 0: return self[0].parent().zero() if m == 0 and n == 1: diff --git a/src/sage/schemes/projective/projective_space.py b/src/sage/schemes/projective/projective_space.py index a6a6805cb33..d25b57622c5 100644 --- a/src/sage/schemes/projective/projective_space.py +++ b/src/sage/schemes/projective/projective_space.py @@ -568,7 +568,8 @@ def _linear_system_as_kernel(self, d, pt, m): [0] [0] - If the multiplcity ``m`` is 0, then the a matrix with zero rows is returned:: + If the multiplicity `m` is 0, then the a matrix with zero rows + is returned:: sage: P = ProjectiveSpace(GF(5), 2, names='x') sage: pt = P([1, 1, 1]) diff --git a/src/sage/schemes/toric/points.py b/src/sage/schemes/toric/points.py index a968d3b33f7..6d83d0af779 100644 --- a/src/sage/schemes/toric/points.py +++ b/src/sage/schemes/toric/points.py @@ -2,7 +2,7 @@ """ Enumerate Points of a Toric Variety -The classes here are not meant to be instatiated manually. Instead, +The classes here are not meant to be instantiated manually. Instead, you should always use the methods of the :class:`point set ` of the variety. diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 4fb099fcdbe..eff4a86f608 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -6418,7 +6418,7 @@ cdef class Expression(CommutativeRingElement): def laurent_polynomial(self, base_ring=None, ring=None): r""" - Return this symbolic expression as an laurent polynomial + Return this symbolic expression as a Laurent polynomial over the given base ring, if possible. INPUT: @@ -6428,7 +6428,7 @@ cdef class Expression(CommutativeRingElement): - ``ring`` - (optional) the parent for the polynomial You can specify either the base ring (``base_ring``) you want - the output laurent polynomial to be over, or you can specify the full + the output Laurent polynomial to be over, or you can specify the full laurent polynomial ring (``ring``) you want the output laurent polynomial to be an element of. diff --git a/src/sage/symbolic/expression_conversions.py b/src/sage/symbolic/expression_conversions.py index 16f7f3ebdf3..1774b053587 100644 --- a/src/sage/symbolic/expression_conversions.py +++ b/src/sage/symbolic/expression_conversions.py @@ -1244,7 +1244,7 @@ def laurent_polynomial(ex, base_ring=None, ring=None): - ``ex`` -- a symbolic expression - ``base_ring``, ``ring`` -- Either a - ``base_ring`` or a laurent polynomial ``ring`` can be + ``base_ring`` or a Laurent polynomial ``ring`` can be specified for the parent of result. If just a ``base_ring`` is given, then the variables of the ``base_ring`` will be the variables of the expression ``ex``. diff --git a/src/sage/tensor/modules/comp.py b/src/sage/tensor/modules/comp.py index 4d65c37b556..602e3a71531 100644 --- a/src/sage/tensor/modules/comp.py +++ b/src/sage/tensor/modules/comp.py @@ -1948,7 +1948,7 @@ def trace(self, pos1, pos2): """ if self._nid < 2: - raise ValueError("contraction can be perfomed only on " + + raise ValueError("contraction can be performed only on " + "components with at least 2 indices") if pos1 < 0 or pos1 > self._nid - 1: raise IndexError("pos1 out of range") @@ -3726,7 +3726,7 @@ def trace(self, pos1, pos2): """ if self._nid < 2: - raise TypeError("contraction can be perfomed only on " + + raise TypeError("contraction can be performed only on " + "components with at least 2 indices") if pos1 < 0 or pos1 > self._nid - 1: raise IndexError("pos1 out of range") diff --git a/src/sage_setup/docbuild/__init__.py b/src/sage_setup/docbuild/__init__.py index 70c3ef405ce..43156631ed3 100644 --- a/src/sage_setup/docbuild/__init__.py +++ b/src/sage_setup/docbuild/__init__.py @@ -654,7 +654,7 @@ def get_all_documents(self, refdir): class ReferenceSubBuilder(DocBuilder): """ This class builds sub-components of the reference manual. It is - resposible for making sure the auto generated ReST files for the + responsible for making sure the auto generated ReST files for the Sage library are up to date. When building any output, we must first go through and check From 3f7b75525c409d3a7b6cae5ded2a758fccf99050 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Fri, 19 May 2017 13:50:20 -0500 Subject: [PATCH 421/452] Remove calls to CartanType.classical() where possible. --- .../rigged_configuration_element.py | 12 ++++---- .../rigged_configurations.py | 28 +++++++++---------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/sage/combinat/rigged_configurations/rigged_configuration_element.py b/src/sage/combinat/rigged_configurations/rigged_configuration_element.py index 56e936faae7..441bde47c9e 100644 --- a/src/sage/combinat/rigged_configurations/rigged_configuration_element.py +++ b/src/sage/combinat/rigged_configurations/rigged_configuration_element.py @@ -1249,7 +1249,7 @@ def __init__(self, parent, rigged_partitions=[], **options): sage: TestSuite(elt).run() """ - n = parent._cartan_type.classical().rank() + n = len(parent._rc_index) if "KT_constructor" in options: # Used only by the Kleber tree # Not recommended to be called by the user since it avoids safety @@ -1457,7 +1457,7 @@ def weight(self): """ WLR = self.parent().weight_lattice_realization() La = WLR.fundamental_weights() - cl_index = self.parent()._cartan_type.classical().index_set() + cl_index = self.parent()._rc_index wt = WLR.sum((self.phi(i) - self.epsilon(i)) * La[i] for i in cl_index) return -wt.level() * La[0] + wt @@ -1917,7 +1917,7 @@ def right_column_box(self): if P.dims[-1][1] > 1: return self.right_split().right_column_box() - rc, e_string = self.to_highest_weight(P.cartan_type().classical().index_set()) + rc, e_string = self.to_highest_weight(P._rc_index) B = P.dims[:-1] + ([r-1,1], [1,1]) from sage.combinat.rigged_configurations.rigged_configurations import RiggedConfigurations @@ -2005,7 +2005,7 @@ def complement_rigging(self, reverse_factors=False): from sage.combinat.rigged_configurations.rigged_configurations import RiggedConfigurations P = RiggedConfigurations(P._cartan_type, reversed(P.dims)) - mg, e_str = self.to_highest_weight(P._cartan_type.classical().index_set()) + mg, e_str = self.to_highest_weight(P._rc_index) nu = [] rig = [] for a,p in enumerate(mg): @@ -2281,7 +2281,7 @@ def epsilon(self, a): epsilon = 0 else: epsilon = -min(0, min(self[a].rigging)) - n = self.parent().cartan_type().classical().rank() + n = len(self.parent()._rc_index) if a == n-1: # -1 for indexing epsilon *= 2 return Integer(epsilon) @@ -2315,7 +2315,7 @@ def phi(self, a): phi = p_inf else: phi = p_inf - min(0, min(self[a].rigging)) - n = self.parent().cartan_type().classical().rank() + n = len(self.parent()._rc_index) if a == n-1: # -1 for indexing phi *= 2 return Integer(phi) diff --git a/src/sage/combinat/rigged_configurations/rigged_configurations.py b/src/sage/combinat/rigged_configurations/rigged_configurations.py index ef0f8778b61..58bfba05a57 100644 --- a/src/sage/combinat/rigged_configurations/rigged_configurations.py +++ b/src/sage/combinat/rigged_configurations/rigged_configurations.py @@ -486,7 +486,7 @@ def __iter__(self): sage: len(L) 24 """ - index_set = self._cartan_type.classical().index_set() + index_set = self._rc_index from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet return RecursivelyEnumeratedSet(self.module_generators, lambda x: [x.f(i) for i in index_set], @@ -540,7 +540,7 @@ def module_generators(self): 2 """ module_gens = [] - n = self._cartan_type.classical().rank() + n = len(self._rc_index) for tree_node in self.kleber_tree(): shapes = [] @@ -1216,13 +1216,13 @@ def module_generators(self): # Convert from the virtual rigged configuration # As a special case, we do not need to do anything for type `A_{2n}^{(2)}` sigma = self._folded_ct.folding_orbit() - vindex = self._folded_ct.folding_of().classical().index_set() + vindex = self.virtual._rc_index shapes = [shapes[vindex.index(sigma[a][0])] for a in self._rc_index] if self._cartan_type.type() != 'BC': gamma = self._folded_ct.scaling_factors() - for a in range(len(shapes)): - for i in range(len(shapes[a])): - shapes[a][i] = shapes[a][i] // gamma[self._rc_index[a]] + for a,shape in enumerate(shapes): + for i in range(len(shape)): + shape[i] = shape[i] // gamma[self._rc_index[a]] # Start with a base to calculate the vacancy numbers # Make a copy just to be safe @@ -1327,7 +1327,7 @@ def to_virtual(self, rc): """ gamma = self._folded_ct.scaling_factors() sigma = self._folded_ct.folding_orbit() - n = self._folded_ct._folding.classical().rank() + n = len(self.virtual._rc_index) # +/- 1 for indexing partitions = [None] * n for a,rp in enumerate(rc): @@ -1362,7 +1362,7 @@ def from_virtual(self, vrc): """ gamma = self._folded_ct.scaling_factors() sigma = self._folded_ct.folding_orbit() - n = self._cartan_type.classical().rank() + n = len(self._rc_index) partitions = [None] * n # +/- 1 for indexing for a in range(n): @@ -1527,7 +1527,7 @@ def to_virtual(self, rc): """ gamma = self._folded_ct.scaling_factors() sigma = self._folded_ct.folding_orbit() - n = self._folded_ct._folding.classical().rank() + n = len(self.virtual._rc_index) partitions = [None] * n for a,rp in enumerate(rc): g = gamma[a+1] @@ -1563,7 +1563,7 @@ def from_virtual(self, vrc): """ gamma = self._folded_ct.scaling_factors() sigma = self._folded_ct.folding_orbit() - n = self._cartan_type.classical().rank() + n = len(self._cartan_type._rc_index) partitions = [None] * n # +/- 1 for indexing for a in range(n): @@ -1618,7 +1618,7 @@ def _calc_vacancy_number(self, partitions, a, i, **options): sage: RC._calc_vacancy_number(elt.nu(), 0, 1) -1 """ - if a != self._cartan_type.classical().rank()-1: + if a != len(self._rc_index) - 1: return RCTypeA2Even._calc_vacancy_number(self, partitions, a, i, **options) vac_num = 0 @@ -1689,7 +1689,7 @@ def module_generators(self): # We are not simply-laced, so convert from the virtual rigged configuration sigma = self._folded_ct.folding_orbit() - vindex = self._folded_ct.folding_of().classical().index_set() + vindex = self.virtual._rc_index shapes = [shapes[vindex.index(sigma[a][0])] for a in self._rc_index] # Nothing more to do since gamma[i] == 1 for all i >= 1 @@ -1848,7 +1848,7 @@ def to_virtual(self, rc): gammatilde = list(self._folded_ct.scaling_factors()) gammatilde[-1] = 2 sigma = self._folded_ct.folding_orbit() - n = self._folded_ct._folding.classical().rank() + n = len(self.virtual._rc_index) partitions = [None] * n for a,rp in enumerate(rc): g = gammatilde[a+1] @@ -1883,7 +1883,7 @@ def from_virtual(self, vrc): gammatilde = list(self._folded_ct.scaling_factors()) gammatilde[-1] = QQ(2) sigma = self._folded_ct.folding_orbit() - n = self._cartan_type.classical().rank() + n = len(self._rc_index) partitions = [None] * n # +/- 1 for indexing for a in range(n): From d6e79213aa483de4c95666050ca9b35069de03bf Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Fri, 19 May 2017 14:20:05 -0500 Subject: [PATCH 422/452] Right attribute, but wrong object. --- .../combinat/rigged_configurations/rigged_configurations.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/rigged_configurations/rigged_configurations.py b/src/sage/combinat/rigged_configurations/rigged_configurations.py index 58bfba05a57..5206f8047e7 100644 --- a/src/sage/combinat/rigged_configurations/rigged_configurations.py +++ b/src/sage/combinat/rigged_configurations/rigged_configurations.py @@ -1563,7 +1563,7 @@ def from_virtual(self, vrc): """ gamma = self._folded_ct.scaling_factors() sigma = self._folded_ct.folding_orbit() - n = len(self._cartan_type._rc_index) + n = len(self._rc_index) partitions = [None] * n # +/- 1 for indexing for a in range(n): From 32ddf358b8a059c25640f665ea932c129815a81f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jori=20M=C3=A4ntysalo?= Date: Sat, 20 May 2017 08:06:38 +0300 Subject: [PATCH 423/452] Some crosslinks. --- src/sage/categories/finite_lattice_posets.py | 24 ++++++++++++------- src/sage/categories/finite_posets.py | 6 +++++ src/sage/combinat/posets/lattices.py | 25 ++++++++++---------- 3 files changed, 34 insertions(+), 21 deletions(-) diff --git a/src/sage/categories/finite_lattice_posets.py b/src/sage/categories/finite_lattice_posets.py index 19330da28cc..1abf7841a5a 100644 --- a/src/sage/categories/finite_lattice_posets.py +++ b/src/sage/categories/finite_lattice_posets.py @@ -26,7 +26,7 @@ class FiniteLatticePosets(CategoryWithAxiom): .. SEEALSO:: - :class:`FinitePosets`, :class:`LatticePosets`, :class:`LatticePoset` + :class:`FinitePosets`, :class:`LatticePosets`, :class:`~sage.combinat.posets.lattices.FiniteLatticePoset` TESTS:: @@ -55,9 +55,9 @@ def join_irreducibles(self): .. SEEALSO:: - :meth:`meet_irreducibles`, - :meth:`~sage.combinat.posets.lattices.FiniteLatticePoset.double_irreducibles`, - :meth:`meet_irreducibles_poset` + - Dual function: :meth:`meet_irreducibles` + - Other: :meth:`~sage.combinat.posets.lattices.FiniteLatticePoset.double_irreducibles`, + :meth:`join_irreducibles_poset` """ return [x for x in self if len(self.lower_covers(x)) == 1] @@ -75,7 +75,10 @@ def join_irreducibles_poset(self): sage: L.join_irreducibles_poset() Finite poset containing 3 elements - .. SEEALSO:: :meth:`join_irreducibles` + .. SEEALSO:: + + - Dual function: :meth:`meet_irreducibles_poset` + - Other: :meth:`join_irreducibles` """ return self.subposet(self.join_irreducibles()) @@ -95,9 +98,9 @@ def meet_irreducibles(self): .. SEEALSO:: - :meth:`join_irreducibles`, - :meth:`~sage.combinat.posets.lattices.FiniteLatticePoset.double_irreducibles`, - :meth:`meet_irreducibles_poset` + - Dual function: :meth:`join_irreducibles` + - Other: :meth:`~sage.combinat.posets.lattices.FiniteLatticePoset.double_irreducibles`, + :meth:`meet_irreducibles_poset` """ return [x for x in self if len(self.upper_covers(x)) == 1] @@ -115,7 +118,10 @@ def meet_irreducibles_poset(self): sage: L.join_irreducibles_poset() Finite poset containing 3 elements - .. SEEALSO:: :meth:`meet_irreducibles` + .. SEEALSO:: + + - Dual function: :meth:`join_irreducibles_poset` + - Other: :meth:`meet_irreducibles` """ return self.subposet(self.meet_irreducibles()) diff --git a/src/sage/categories/finite_posets.py b/src/sage/categories/finite_posets.py index 3be703a291b..2d6f1c1d534 100644 --- a/src/sage/categories/finite_posets.py +++ b/src/sage/categories/finite_posets.py @@ -85,9 +85,15 @@ def is_selfdual(self): sage: P.is_selfdual() True + TESTS:: + sage: P = Poset( {} ) sage: P.is_selfdual() True + + .. SEEALSO:: + + - Stronger properties: :meth:`~sage.combinat.posets.lattices.FiniteLattice.is_orthocomplemented` """ # Two quick checks before full isomorphic test. if sorted(self._hasse_diagram.in_degree()) != sorted(self._hasse_diagram.out_degree()): diff --git a/src/sage/combinat/posets/lattices.py b/src/sage/combinat/posets/lattices.py index ad02ab6d80f..c49f2086fac 100644 --- a/src/sage/combinat/posets/lattices.py +++ b/src/sage/combinat/posets/lattices.py @@ -325,7 +325,7 @@ def atoms(self): .. SEEALSO:: - :meth:`~FiniteJoinSemilattice.coatoms()`. + - Dual function: :meth:`~FiniteJoinSemilattice.coatoms` EXAMPLES:: @@ -387,7 +387,7 @@ def pseudocomplement(self, element): sage: L.complements(2), L.pseudocomplement(2) ([3, 4], None) - .. SEEALSO:: :meth:`sage.combinat.posets.lattices.FiniteLatticePoset.is_pseudocomplemented()`. + .. SEEALSO:: :meth:`~sage.combinat.posets.lattices.FiniteLatticePoset.is_pseudocomplemented` TESTS:: @@ -577,7 +577,7 @@ def coatoms(self): .. SEEALSO:: - :meth:`~FiniteMeetSemilattice.atoms()`. + - Dual function: :meth:`~FiniteMeetSemilattice.atoms` EXAMPLES:: @@ -755,8 +755,8 @@ def join_primes(self): .. SEEALSO:: - :meth:`meet_primes`, - :meth:`~sage.categories.finite_lattice_posets.FiniteLatticePosets.ParentMethods.join_irreducibles` + - Dual function: :meth:`meet_primes` + - Other: :meth:`~sage.categories.finite_lattice_posets.FiniteLatticePosets.ParentMethods.join_irreducibles` EXAMPLES:: @@ -792,8 +792,8 @@ def meet_primes(self): .. SEEALSO:: - :meth:`join_primes`, - :meth:`~sage.categories.finite_lattice_posets.FiniteLatticePosets.ParentMethods.meet_irreducibles` + - Dual function: :meth:`join_primes` + - Other: :meth:`~sage.categories.finite_lattice_posets.FiniteLatticePosets.ParentMethods.meet_irreducibles` EXAMPLES:: @@ -1850,12 +1850,14 @@ def complements(self, element=None): complements for all elements having at least one complement is returned. + .. SEEALSO:: :meth:`is_complemented` + EXAMPLES:: sage: L=LatticePoset({0:['a','b','c'], 'a':[1], 'b':[1], 'c':[1]}) sage: C = L.complements() - Let us check that `'a'` and `'b'` are complements of each other:: + Let us check that 'a' and 'b' are complements of each other:: sage: 'a' in C['b'] True @@ -1864,11 +1866,11 @@ def complements(self, element=None): Full list of complements:: - sage: L.complements() # random + sage: L.complements() # random order {0: [1], 1: [0], 'a': ['b', 'c'], 'b': ['c', 'a'], 'c': ['b', 'a']} sage: L=LatticePoset({0:[1,2],1:[3],2:[3],3:[4]}) - sage: L.complements() # random + sage: L.complements() # random order {0: [4], 4: [0]} sage: L.complements(1) [] @@ -3580,6 +3582,7 @@ def is_subdirectly_reducible(self, certificate=False): - Stronger properties: :meth:`is_distributive`, :meth:`is_vertically_decomposable` + - Other: :meth:`subdirect_decomposition` EXAMPLES:: @@ -3602,8 +3605,6 @@ def is_subdirectly_reducible(self, certificate=False): sage: [Posets.ChainPoset(i).is_subdirectly_reducible() for i in range(5)] [False, False, False, True, True] """ - # Todo: Add seealso-link to subdirect_decomposition() when it is done. - H = self._hasse_diagram A = H.atoms_of_congruence_lattice() From 20cd0dafdc07517145c3d8a20cbf8baa08e334dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolas=20M=2E=20Thi=C3=A9ry?= Date: Sat, 20 May 2017 09:07:18 -0400 Subject: [PATCH 424/452] 22632: fixed ReST typo preventing the pdf doc compilation --- src/sage/combinat/free_module.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/free_module.py b/src/sage/combinat/free_module.py index 28601bd226c..73bfcbb93b9 100644 --- a/src/sage/combinat/free_module.py +++ b/src/sage/combinat/free_module.py @@ -298,7 +298,7 @@ def element_class(self): Overrides :meth:`Parent.element_class` to force the construction of Python class. This is currently needed to inherit really all the features from categories, and in - particular the initialization of `_mul_` in + particular the initialization of ``_mul_`` in :meth:`Magmas.ParentMethods.__init_extra__`. EXAMPLES:: From f3088680a90d6b517e0d5e85d2e40058424057cd Mon Sep 17 00:00:00 2001 From: Ben Salisbury Date: Sat, 20 May 2017 13:37:45 -0400 Subject: [PATCH 425/452] Changed naming conventions in the documentation introduction --- .../lie_algebras/affine_lie_algebra.py | 47 ++++++++++++------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/src/sage/algebras/lie_algebras/affine_lie_algebra.py b/src/sage/algebras/lie_algebras/affine_lie_algebra.py index df44fe3fc84..799ef87bb47 100644 --- a/src/sage/algebras/lie_algebras/affine_lie_algebra.py +++ b/src/sage/algebras/lie_algebras/affine_lie_algebra.py @@ -35,8 +35,10 @@ class AffineLieAlgebra(FinitelyGeneratedLieAlgebra): r""" An (untwisted) affine Lie algebra. - Given a finite dimensional simple Lie algebra `\mathfrak{g}` over `R`, - we construct an affine Lie algebra `\widehat{\mathfrak{g}}^{\prime}` as + Let `R` be a ring. Given a finite-dimensional simple Lie algebra + `\mathfrak{g}` over `R`, the affine Lie algebra + `\widehat{\mathfrak{g}}^{\prime}` associated to `\mathfrak{g}` is + defined as .. MATH:: @@ -44,33 +46,42 @@ class AffineLieAlgebra(FinitelyGeneratedLieAlgebra): R[t, t^{-1}] \bigr) \oplus R c, where `c` is the canonical central element and `R[t, t^{-1}]` is the - Laurent polynomial ring over `R`. We define the Lie bracket as + Laurent polynomial ring over `R`. The Lie bracket is defined as .. MATH:: - [a \otimes t^n + \alpha c, b \otimes t^m + \beta c] = - [a, b] \otimes t^{n+m} + \delta_{n+m,0} ( a | b ) n c + [x \otimes t^m + \lambda c, y \otimes t^n + \mu c] = + [x, y] \otimes t^{m+n} + m \delta_{m,-n} ( x | y ) c, - where `( a | b )` is the Killing form on `\mathfrak{g}`. + where `( x | y )` is the Killing form on `\mathfrak{g}`. - There is a canonical derivative on `\widehat{\mathfrak{g}}'` - known as the *Lie derivative* and is denoted by `\delta`. - The Lie derivative is defined as + There is a canonical derivation `d` on `\widehat{\mathfrak{g}}'` + that is defined by .. MATH:: - \delta(a \otimes t^m + \alpha c) = a \otimes m t^m, + d(x \otimes t^m + \lambda c) = a \otimes m t^m, - or equivalently by `\delta = t \frac{d}{dt}`. + or equivalently by `d = t \frac{d}{dt}`. - We can form the affine Kac-Moody algebra `\widehat{\mathfrak{g}}` - by adding the additional generator `d` such that `[d, x] = \delta(x)`, - where `\delta` is the Lie derivative. We note that the derived - subalgebra of the Kac-Moody algebra is the affine Lie algebra. + The affine Kac-Moody algebra `\widehat{\mathfrak{g}}` is formed by + adjoining the derivation `d` such that - .. NOTE:: + .. MATH:: + + \widehat{\mathfrak{g}} = \bigl( \mathfrak{g} \otimes R[t,t^{-1}] + \bigr) \oplus R c \oplus R d. + + Specifically, the bracket on `\widehat{\mathfrak{g}}` is defined as + + .. MATH:: + + [t^m \otimes x \oplus \lambda c \oplus \mu d, t^n \otimes y \oplus + \lambda_1 c \oplus \mu_1 d] = \bigl( t^{m+n} [x,y] + \mu n t^n \otimes + y - \mu_1 m t^m \otimes x\bigr) \oplus m \delta_{m,-n} (x|y) c . - Our terminology is following that of :wikipedia:`Affine_Lie_algebra`. + Note that the derived subalgebra of the Kac-Moody algebra is the + affine Lie algebra. INPUT: @@ -128,7 +139,7 @@ class AffineLieAlgebra(FinitelyGeneratedLieAlgebra): REFERENCES: - - :wikipedia:`Affine_Lie_algebra` + - [Ka1990]_ """ @staticmethod def __classcall_private__(cls, arg0, cartan_type=None, kac_moody=True): From e5a9a3b2e168946ab9011c4d5d7d7d687ab7a758 Mon Sep 17 00:00:00 2001 From: Ben Salisbury Date: Sat, 20 May 2017 14:10:12 -0400 Subject: [PATCH 426/452] Changed delta to d and Lie derivative to canonical derivation --- .../lie_algebras/affine_lie_algebra.py | 122 +++++++-------- .../lie_algebras/lie_algebra_element.pxd | 4 +- .../lie_algebras/lie_algebra_element.pyx | 148 +++++++++--------- 3 files changed, 137 insertions(+), 137 deletions(-) diff --git a/src/sage/algebras/lie_algebras/affine_lie_algebra.py b/src/sage/algebras/lie_algebras/affine_lie_algebra.py index 799ef87bb47..32c701b642a 100644 --- a/src/sage/algebras/lie_algebras/affine_lie_algebra.py +++ b/src/sage/algebras/lie_algebras/affine_lie_algebra.py @@ -103,22 +103,22 @@ class AffineLieAlgebra(FinitelyGeneratedLieAlgebra): We begin by constructing an affine Kac-Moody algebra of type `G_2^{(1)}` from the classical Lie algebra of type `G_2`:: - sage: L = LieAlgebra(QQ, cartan_type=['G',2]) - sage: A = L.affine() + sage: g = LieAlgebra(QQ, cartan_type=['G',2]) + sage: A = g.affine() sage: A Affine Kac-Moody algebra of ['G', 2] in the Chevalley basis Next, we construct the generators and perform some computations:: sage: A.inject_variables() - Defining e1, e2, f1, f2, h1, h2, e0, f0, c, delta + Defining e1, e2, f1, f2, h1, h2, e0, f0, c, d sage: e1.bracket(f1) (h1)#t^0 sage: e0.bracket(f0) (-h1 - 2*h2)#t^0 + 8*c sage: e0.bracket(f1) 0 - sage: A[delta, f0] + sage: A[d, f0] (-E[3*alpha[1] + 2*alpha[2]])#t^-1 sage: A([[e0, e2], [[[e1, e2], [e0, [e1, e2]]], e1]]) (-6*E[-3*alpha[1] - alpha[2]])#t^2 @@ -130,11 +130,11 @@ class AffineLieAlgebra(FinitelyGeneratedLieAlgebra): (E[-alpha[1]])#t^0 + (2*E[alpha[1]])#t^-1 We can construct its derived subalgebra, the affine Lie algebra - of type `G_2^{(1)}`. In this case, there is no Lie derivative, - so the generator `\delta` is `0`:: + of type `G_2^{(1)}`. In this case, there is no canonical derivation, + so the generator `d` is `0`:: sage: D = A.derived_subalgebra() - sage: D.delta() + sage: D.d() 0 REFERENCES: @@ -193,7 +193,7 @@ def __init__(self, g, kac_moody): names = list(g.variable_names()) + ['e0', 'f0', 'c'] if kac_moody: - names += ['delta'] + names += ['d'] self._kac_moody = kac_moody names = tuple(names) @@ -207,10 +207,10 @@ def _repr_(self): EXAMPLES:: - sage: L = LieAlgebra(QQ, cartan_type=['D',4,1]) - sage: L + sage: g = LieAlgebra(QQ, cartan_type=['D',4,1]) + sage: g Affine Kac-Moody algebra of ['D', 4] in the Chevalley basis - sage: L.derived_subalgebra() + sage: g.derived_subalgebra() Affine Lie algebra of ['D', 4] in the Chevalley basis """ base = "Affine " @@ -229,8 +229,8 @@ def basis(self): EXAMPLES:: - sage: L = LieAlgebra(QQ, cartan_type=['D',4,1]) - sage: B = L.basis() + sage: g = LieAlgebra(QQ, cartan_type=['D',4,1]) + sage: B = g.basis() sage: al = RootSystem(['D',4]).root_lattice().simple_roots() sage: B[al[1]+al[2]+al[4],4] (E[alpha[1] + alpha[2] + alpha[4]])#t^4 @@ -240,15 +240,15 @@ def basis(self): (E[alpha[4]])#t^-2 sage: B['c'] c - sage: B['delta'] - delta + sage: B['d'] + d """ K = cartesian_product([self._g.basis().keys(), ZZ]) from sage.sets.finite_enumerated_set import FiniteEnumeratedSet c = FiniteEnumeratedSet(['c']) if self._kac_moody: - delta = FiniteEnumeratedSet(['delta']) - keys = DisjointUnionEnumeratedSets([c, delta, K]) + d = FiniteEnumeratedSet(['d']) + keys = DisjointUnionEnumeratedSets([c, d, K]) else: keys = DisjointUnionEnumeratedSets([c, K]) return Family(keys, self.monomial) @@ -259,19 +259,19 @@ def _element_constructor_(self, x): EXAMPLES:: - sage: L = LieAlgebra(QQ, cartan_type=['A',1]) - sage: A = L.affine() + sage: g = LieAlgebra(QQ, cartan_type=['A',1]) + sage: A = g.affine() sage: D = A.derived_subalgebra() sage: A(D.an_element()) (E[alpha[1]] + h1 + E[-alpha[1]])#t^0 + (E[-alpha[1]])#t^1 + (E[alpha[1]])#t^-1 + c - sage: A(L.an_element()) + sage: A(g.an_element()) (E[alpha[1]] + h1 + E[-alpha[1]])#t^0 """ P = parent(x) if P is self.derived_subalgebra(): return self.element_class(self, x.t_dict(), x.c_coefficient(), - x.delta_coefficient()) + x.d_coefficient()) if P == self._g: zero = self.base_ring().zero() return self.element_class(self, {0: x}, zero, zero) @@ -284,9 +284,9 @@ def _coerce_map_from_(self, R): EXAMPLES:: - sage: L = LieAlgebra(QQ, cartan_type=['G',2]) - sage: A = L.affine() - sage: A.has_coerce_map_from(L) + sage: g = LieAlgebra(QQ, cartan_type=['G',2]) + sage: A = g.affine() + sage: A.has_coerce_map_from(g) True sage: D = A.derived_subalgebra() sage: A.has_coerce_map_from(D) @@ -302,10 +302,10 @@ def derived_subalgebra(self): EXAMPLES:: - sage: L = LieAlgebra(QQ, cartan_type=['B',3,1]) - sage: L + sage: g = LieAlgebra(QQ, cartan_type=['B',3,1]) + sage: g Affine Kac-Moody algebra of ['B', 3] in the Chevalley basis - sage: D = L.derived_subalgebra(); D + sage: D = g.derived_subalgebra(); D Affine Lie algebra of ['B', 3] in the Chevalley basis sage: D.derived_subalgebra() == D True @@ -320,15 +320,15 @@ def derived_series(self): EXAMPLES:: - sage: L = LieAlgebra(QQ, cartan_type=['B',3,1]) - sage: L.derived_series() + sage: g = LieAlgebra(QQ, cartan_type=['B',3,1]) + sage: g.derived_series() [Affine Kac-Moody algebra of ['B', 3] in the Chevalley basis, Affine Lie algebra of ['B', 3] in the Chevalley basis] - sage: L.lower_central_series() + sage: g.lower_central_series() [Affine Kac-Moody algebra of ['B', 3] in the Chevalley basis, Affine Lie algebra of ['B', 3] in the Chevalley basis] - sage: D = L.derived_subalgebra() + sage: D = g.derived_subalgebra() sage: D.derived_series() [Affine Lie algebra of ['B', 3] in the Chevalley basis] """ @@ -344,10 +344,10 @@ def is_nilpotent(self): EXAMPLES:: - sage: L = LieAlgebra(QQ, cartan_type=['B',3,1]) - sage: L.is_nilpotent() + sage: g = LieAlgebra(QQ, cartan_type=['B',3,1]) + sage: g.is_nilpotent() False - sage: L.is_solvable() + sage: g.is_solvable() False """ return False @@ -360,8 +360,8 @@ def cartan_type(self): EXAMPLES:: - sage: L = LieAlgebra(QQ, cartan_type=['C',3,1]) - sage: L.cartan_type() + sage: g = LieAlgebra(QQ, cartan_type=['C',3,1]) + sage: g.cartan_type() ['C', 3, 1] """ return self._cartan_type @@ -372,8 +372,8 @@ def classical(self): EXAMPLES:: - sage: L = LieAlgebra(QQ, cartan_type=['F',4,1]) - sage: L.classical() + sage: g = LieAlgebra(QQ, cartan_type=['F',4,1]) + sage: g.classical() Lie algebra of ['F', 4] in the Chevalley basis sage: so5 = lie_algebras.so(QQ, 5, 'matrix') @@ -390,8 +390,8 @@ def zero(self): EXAMPLES:: - sage: L = LieAlgebra(QQ, cartan_type=['F',4,1]) - sage: L.zero() + sage: g = LieAlgebra(QQ, cartan_type=['F',4,1]) + sage: g.zero() 0 """ zero = self.base_ring().zero() @@ -404,27 +404,27 @@ def c(self): EXAMPLES:: - sage: L = LieAlgebra(QQ, cartan_type=['A',3,1]) - sage: L.c() + sage: g = LieAlgebra(QQ, cartan_type=['A',3,1]) + sage: g.c() c """ R = self.base_ring() return self.element_class(self, {}, R.one(), R.zero()) @cached_method - def delta(self): + def d(self): r""" - Return the Lie derivative element `\delta` or ``self``. + Return the canonical derivation `d` of ``self``. If ``self`` is the affine Lie algebra, then this returns `0`. EXAMPLES:: - sage: L = LieAlgebra(QQ, cartan_type=['A',3,1]) - sage: L.delta() - delta + sage: g = LieAlgebra(QQ, cartan_type=['A',3,1]) + sage: g.d() + d sage: D = L.derived_subalgebra() - sage: D.delta() + sage: D.d() 0 """ if not self._kac_moody: @@ -439,21 +439,21 @@ def lie_algebra_generators(self): EXAMPLES:: - sage: L = LieAlgebra(QQ, cartan_type=['A',1,1]) - sage: list(L.lie_algebra_generators()) + sage: g = LieAlgebra(QQ, cartan_type=['A',1,1]) + sage: list(g.lie_algebra_generators()) [(E[alpha[1]])#t^0, (E[-alpha[1]])#t^0, (h1)#t^0, (E[-alpha[1]])#t^1, (E[alpha[1]])#t^-1, c, - delta] + d] """ zero = self.base_ring().zero() one = self.base_ring().one() d = {} if self._kac_moody: - d['delta'] = self.delta() + d['d'] = self.d() d['c'] = self.c() try: finite_gens = dict(self._g.lie_algebra_generators(True)) @@ -475,23 +475,23 @@ def monomial(self, m): EXAMPLES:: - sage: L = LieAlgebra(QQ, cartan_type=['B',4,1]) + sage: g = LieAlgebra(QQ, cartan_type=['B',4,1]) sage: al = RootSystem(['B',4]).root_lattice().simple_roots() - sage: L.monomial((al[1]+al[2]+al[3],4)) + sage: g.monomial((al[1]+al[2]+al[3],4)) (E[alpha[1] + alpha[2] + alpha[3]])#t^4 - sage: L.monomial((-al[1]-al[2]-2*al[3]-2*al[4],2)) + sage: g.monomial((-al[1]-al[2]-2*al[3]-2*al[4],2)) (E[-alpha[1] - alpha[2] - 2*alpha[3] - 2*alpha[4]])#t^2 - sage: L.monomial((al[4],-2)) + sage: g.monomial((al[4],-2)) (E[alpha[4]])#t^-2 - sage: L.monomial('c') + sage: g.monomial('c') c - sage: L.monomial('delta') - delta + sage: g.monomial('d') + d """ if m == 'c': return self.c() - if m == 'delta': - return self.delta() + if m == 'd': + return self.d() G = self._g.basis() zero = self.base_ring().zero() return self.element_class(self, {m[1]: G[m[0]]}, zero, zero) diff --git a/src/sage/algebras/lie_algebras/lie_algebra_element.pxd b/src/sage/algebras/lie_algebras/lie_algebra_element.pxd index 508721dc7c6..418a4f9c4df 100644 --- a/src/sage/algebras/lie_algebras/lie_algebra_element.pxd +++ b/src/sage/algebras/lie_algebras/lie_algebra_element.pxd @@ -23,10 +23,10 @@ cdef class UntwistedAffineLieAlgebraElement(Element): cpdef dict t_dict(self) cpdef c_coefficient(self) - cpdef delta_coefficient(self) + cpdef d_coefficient(self) cpdef bracket(self, y) cpdef _bracket_(self, y) - cpdef lie_derivative(self) + cpdef canonical_derivation(self) cpdef monomial_coefficients(self, bint copy=*) diff --git a/src/sage/algebras/lie_algebras/lie_algebra_element.pyx b/src/sage/algebras/lie_algebras/lie_algebra_element.pyx index 58f0aef5993..e8b8fe3f7eb 100644 --- a/src/sage/algebras/lie_algebras/lie_algebra_element.pyx +++ b/src/sage/algebras/lie_algebras/lie_algebra_element.pyx @@ -564,7 +564,7 @@ cdef class UntwistedAffineLieAlgebraElement(Element): """ An element of an untwisted affine Lie algebra. """ - def __init__(self, parent, dict t_dict, c_coeff, delta_coeff): + def __init__(self, parent, dict t_dict, c_coeff, d_coeff): """ Initialize ``self``. @@ -577,7 +577,7 @@ cdef class UntwistedAffineLieAlgebraElement(Element): Element.__init__(self, parent) self._t_dict = t_dict self._c_coeff = c_coeff - self._delta_coeff = delta_coeff + self._d_coeff = d_coeff self._hash = -1 def __reduce__(self): @@ -592,7 +592,7 @@ cdef class UntwistedAffineLieAlgebraElement(Element): True """ return (_build_untwisted_affine_element, - (self.parent(), self._t_dict, self._c_coeff, self._delta_coeff)) + (self.parent(), self._t_dict, self._c_coeff, self._d_coeff)) def _repr_(self): """ @@ -608,18 +608,18 @@ cdef class UntwistedAffineLieAlgebraElement(Element): (E[-alpha[1]])#t^1, (E[alpha[1]])#t^-1, c, - delta] + d] sage: L.an_element() (E[alpha[1]] + h1 + E[-alpha[1]])#t^0 + (E[-alpha[1]])#t^1 + (E[alpha[1]])#t^-1 - + c + delta + + c + d sage: L.zero() 0 - sage: e1,f1,h1,e0,f0,c,delta = list(L.lie_algebra_generators()) - sage: e1 + 2*f1 - h1 + e0 + 3*c - 2*delta + sage: e1,f1,h1,e0,f0,c,d = list(L.lie_algebra_generators()) + sage: e1 + 2*f1 - h1 + e0 + 3*c - 2*d (E[alpha[1]] - h1 + 2*E[-alpha[1]])#t^0 + (-E[-alpha[1]])#t^1 - + 3*c + -2*delta + + 3*c + -2*d """ ret = ' + '.join('({})#t^{}'.format(g, t) for t,g in self._t_dict.iteritems()) @@ -631,13 +631,13 @@ cdef class UntwistedAffineLieAlgebraElement(Element): else: ret += 'c' - if self._delta_coeff != 0: + if self._d_coeff != 0: if ret: ret += ' + ' - if self._delta_coeff != 1: - ret += repr(self._delta_coeff) + '*delta' + if self._d_coeff != 1: + ret += repr(self._d_coeff) + '*d' else: - ret += 'delta' + ret += 'd' if not ret: return '0' @@ -657,18 +657,18 @@ cdef class UntwistedAffineLieAlgebraElement(Element): (E_{-\alpha_{1}}) \otimes t^{1}, (E_{\alpha_{1}}) \otimes t^{-1}, c, - \delta] + d] sage: latex(L.an_element()) (E_{\alpha_{1}} + E_{\alpha^\vee_{1}} + E_{-\alpha_{1}}) \otimes t^{0} + (E_{-\alpha_{1}}) \otimes t^{1} + (E_{\alpha_{1}}) \otimes t^{-1} - + c + \delta + + c + d sage: latex(L.zero()) 0 - sage: e1,f1,h1,e0,f0,c,delta = list(L.lie_algebra_generators()) - sage: latex(e1 + 2*f1 - h1 + e0 + 3*c - 2*delta) + sage: e1,f1,h1,e0,f0,c,d = list(L.lie_algebra_generators()) + sage: latex(e1 + 2*f1 - h1 + e0 + 3*c - 2*d) (E_{\alpha_{1}} - E_{\alpha^\vee_{1}} + 2E_{-\alpha_{1}}) \otimes t^{0} - + (-E_{-\alpha_{1}}) \otimes t^{1} + 3 c + -2 \delta + + (-E_{-\alpha_{1}}) \otimes t^{1} + 3 c + -2 d """ from sage.misc.latex import latex ret = ' + '.join('({}) \otimes t^{{{}}}'.format(latex(g), t) @@ -681,13 +681,13 @@ cdef class UntwistedAffineLieAlgebraElement(Element): else: ret += 'c' - if self._delta_coeff != 0: + if self._d_coeff != 0: if ret: ret += ' + ' - if self._delta_coeff != 1: - ret += latex(self._delta_coeff) + ' \\delta' + if self._d_coeff != 1: + ret += latex(self._d_coeff) + ' d' else: - ret += '\\delta' + ret += 'd' if not ret: return '0' @@ -722,18 +722,18 @@ cdef class UntwistedAffineLieAlgebraElement(Element): """ return self._c_coeff - cpdef delta_coefficient(self): + cpdef d_coefficient(self): r""" - Return the coefficient of `\delta` of ``self``. + Return the coefficient of `d` of ``self``. EXAMPLES:: sage: L = lie_algebras.Affine(QQ, ['A',1,1]) - sage: x = L.an_element() + L.delta() - sage: x.delta_coefficient() + sage: x = L.an_element() + L.d() + sage: x.d_coefficient() 2 """ - return self._delta_coeff + return self._d_coeff cpdef _richcmp_(self, other, int op): """ @@ -744,23 +744,23 @@ cdef class UntwistedAffineLieAlgebraElement(Element): sage: L = lie_algebras.Affine(QQ, ['C',2,1]) sage: x = L.an_element() sage: c = L.basis()['c'] - sage: delta = L.basis()['delta'] - sage: c == delta + sage: d = L.basis()['d'] + sage: c == d False sage: x != c True - sage: 2*c - delta == c + c - delta + sage: 2*c - d == c + c - d True sage: x - c != x - c False - sage: x - c != x - delta + sage: x - c != x - d True """ if op != Py_EQ and op != Py_NE: return NotImplemented cdef UntwistedAffineLieAlgebraElement rt = other - return richcmp((self._t_dict, self._c_coeff, self._delta_coeff), - (rt._t_dict, rt._c_coeff, rt._delta_coeff), + return richcmp((self._t_dict, self._c_coeff, self._d_coeff), + (rt._t_dict, rt._c_coeff, rt._d_coeff), op) def __hash__(self): @@ -780,7 +780,7 @@ cdef class UntwistedAffineLieAlgebraElement(Element): self._hash = 0 if self._hash == -1: self._hash = hash((tuple(self._t_dict.iteritems()), - self._c_coeff, self._delta_coeff)) + self._c_coeff, self._d_coeff)) return self._hash def __nonzero__(self): @@ -796,7 +796,7 @@ cdef class UntwistedAffineLieAlgebraElement(Element): sage: bool(L.zero()) False """ - return bool(self._t_dict) or bool(self._c_coeff) or bool(self._delta_coeff) + return bool(self._t_dict) or bool(self._c_coeff) or bool(self._d_coeff) __bool__ = __nonzero__ @@ -807,14 +807,14 @@ cdef class UntwistedAffineLieAlgebraElement(Element): EXAMPLES:: sage: L = lie_algebras.Affine(QQ, ['A',1,1]) - sage: e1,f1,h1,e0,f0,c,delta = list(L.lie_algebra_generators()) - sage: e0.bracket(e1) + delta + e1 + c + 3*delta - (E[alpha[1]])#t^0 + (-h1)#t^1 + c + 4*delta + sage: e1,f1,h1,e0,f0,c,d = list(L.lie_algebra_generators()) + sage: e0.bracket(e1) + d + e1 + c + 3*d + (E[alpha[1]])#t^0 + (-h1)#t^1 + c + 4*d """ cdef UntwistedAffineLieAlgebraElement rt = other return type(self)(self._parent, axpy(1, self._t_dict, rt._t_dict.copy()), self._c_coeff + rt._c_coeff, - self._delta_coeff + rt._delta_coeff) + self._d_coeff + rt._d_coeff) cdef _sub_(self, other): """ @@ -823,9 +823,9 @@ cdef class UntwistedAffineLieAlgebraElement(Element): EXAMPLES:: sage: L = lie_algebras.Affine(QQ, ['A',1,1]) - sage: e1,f1,h1,e0,f0,c,delta = list(L.lie_algebra_generators()) - sage: e0.bracket(e1) + delta - e1 + c - 3*delta - (-E[alpha[1]])#t^0 + (-h1)#t^1 + c + -2*delta + sage: e1,f1,h1,e0,f0,c,d = list(L.lie_algebra_generators()) + sage: e0.bracket(e1) + d - e1 + c - 3*d + (-E[alpha[1]])#t^0 + (-h1)#t^1 + c + -2*d sage: e0.bracket(f0) - 4*c (h1)#t^0 sage: e0.bracket(f0) - 4*c - h1 @@ -836,7 +836,7 @@ cdef class UntwistedAffineLieAlgebraElement(Element): cdef UntwistedAffineLieAlgebraElement rt = other return type(self)(self._parent, axpy(-1, self._t_dict, rt._t_dict.copy()), self._c_coeff - rt._c_coeff, - self._delta_coeff - rt._delta_coeff) + self._d_coeff - rt._d_coeff) cdef _neg_(self): """ @@ -845,13 +845,13 @@ cdef class UntwistedAffineLieAlgebraElement(Element): EXAMPLES:: sage: L = lie_algebras.Affine(QQ, ['A',1,1]) - sage: e1,f1,h1,e0,f0,c,delta = list(L.lie_algebra_generators()) - sage: x = e0.bracket(e1) + delta + e1 + c + 3*delta + sage: e1,f1,h1,e0,f0,c,d = list(L.lie_algebra_generators()) + sage: x = e0.bracket(e1) + d + e1 + c + 3*d sage: -x - (-E[alpha[1]])#t^0 + (h1)#t^1 + -1*c + -4*delta + (-E[alpha[1]])#t^0 + (h1)#t^1 + -1*c + -4*d """ return type(self)(self._parent, negate(self._t_dict), - -self._c_coeff, -self._delta_coeff) + -self._c_coeff, -self._d_coeff) cpdef _acted_upon_(self, x, bint self_on_left): """ @@ -860,16 +860,16 @@ cdef class UntwistedAffineLieAlgebraElement(Element): EXAMPLES:: sage: L = lie_algebras.Affine(QQ, ['A',1,1]) - sage: e1,f1,h1,e0,f0,c,delta = list(L.lie_algebra_generators()) - sage: x = e1 + f0.bracket(f1) + 3*c - 2/5 * delta + sage: e1,f1,h1,e0,f0,c,d = list(L.lie_algebra_generators()) + sage: x = e1 + f0.bracket(f1) + 3*c - 2/5 * d sage: x - (-E[alpha[1]])#t^0 + (-h1)#t^-1 + 3*c + -2/5*delta + (-E[alpha[1]])#t^0 + (-h1)#t^-1 + 3*c + -2/5*d sage: -2 * x - (2*E[alpha[1]])#t^0 + (2*h1)#t^-1 + -6*c + 4/5*delta + (2*E[alpha[1]])#t^0 + (2*h1)#t^-1 + -6*c + 4/5*d """ return type(self)(self._parent, scal(x, self._t_dict, self_on_left), x * self._c_coeff, - x * self._delta_coeff) + x * self._d_coeff) cpdef monomial_coefficients(self, bint copy=True): """ @@ -889,7 +889,7 @@ cdef class UntwistedAffineLieAlgebraElement(Element): (alphacheck[1], 0), (alphacheck[2], 0), 'c', - 'delta'] + 'd'] """ cdef dict d = {} for t,g in self._t_dict.iteritems(): @@ -897,8 +897,8 @@ cdef class UntwistedAffineLieAlgebraElement(Element): d[k,t] = c if self._c_coeff: d['c'] = self._c_coeff - if self._delta_coeff: - d['delta'] = self._delta_coeff + if self._d_coeff: + d['d'] = self._d_coeff return d cpdef bracket(self, right): @@ -908,7 +908,7 @@ cdef class UntwistedAffineLieAlgebraElement(Element): EXAMPLES:: sage: L = LieAlgebra(QQ, cartan_type=['A',1,1]) - sage: e1,f1,h1,e0,f0,c,delta = list(L.lie_algebra_generators()) + sage: e1,f1,h1,e0,f0,c,d = list(L.lie_algebra_generators()) sage: e0.bracket(f0) (-h1)#t^0 + 4*c sage: e1.bracket(0) @@ -931,7 +931,7 @@ cdef class UntwistedAffineLieAlgebraElement(Element): EXAMPLES:: sage: L = LieAlgebra(QQ, cartan_type=['A',1,1]) - sage: e1,f1,h1,e0,f0,c,delta = list(L.lie_algebra_generators()) + sage: e1,f1,h1,e0,f0,c,d = list(L.lie_algebra_generators()) sage: al = RootSystem(['A',1]).root_lattice().simple_roots() sage: x = L.basis()[al[1], 5] sage: y = L.basis()[-al[1], -3] @@ -946,7 +946,7 @@ cdef class UntwistedAffineLieAlgebraElement(Element): (h1)#t^5 sage: x._bracket_(h1) (-2*E[alpha[1]])#t^5 - sage: x._bracket_(delta) + sage: x._bracket_(d) (-5*E[alpha[1]])#t^5 sage: all(c._bracket_(g) == 0 for g in L.lie_algebra_generators()) True @@ -959,12 +959,12 @@ cdef class UntwistedAffineLieAlgebraElement(Element): cdef UntwistedAffineLieAlgebraElement rt = (y) c = self._parent.base_ring().zero() for tl,gl in self._t_dict.iteritems(): - # \delta contribution from the left - if rt._delta_coeff: + # d contribution from the left + if rt._d_coeff: if tl in d: - d[tl] -= rt._delta_coeff * gl * tl + d[tl] -= rt._d_coeff * gl * tl else: - d[tl] = -rt._delta_coeff * gl * tl + d[tl] = -rt._d_coeff * gl * tl if not d[tl]: del d[tl] # main bracket of the central extension @@ -980,44 +980,44 @@ cdef class UntwistedAffineLieAlgebraElement(Element): if tl + tr == 0: c += gl.killing_form(gr) * tl - # \delta contribution from the right - if self._delta_coeff: + # d contribution from the right + if self._d_coeff: for tr,gr in rt._t_dict.iteritems(): if tr in d: - d[tr] += self._delta_coeff * gr * tr + d[tr] += self._d_coeff * gr * tr else: - d[tr] = self._delta_coeff * gr * tr + d[tr] = self._d_coeff * gr * tr if not d[tr]: del d[tr] return type(self)(self._parent, d, c, self._parent.base_ring().zero()) - cpdef lie_derivative(self): + cpdef canonical_derivation(self): r""" - Return the Lie derivative `\delta` applied to ``self``. + Return the canonical derivation `d` applied to ``self``. - The Lie derivative `\delta` is defined as + The canonical derivation `d` is defined as .. MATH:: - \delta(a \otimes t^m + \alpha c) = a \otimes m t^m. + d(a \otimes t^m + \alpha c) = a \otimes m t^m. - Another formulation is by `\delta = t \frac{d}{dt}`. + Another formulation is by `d = t \frac{d}{dt}`. EXAMPLES:: sage: L = lie_algebras.Affine(QQ, ['E',6,1]) sage: al = RootSystem(['E',6]).root_lattice().simple_roots() - sage: x = L.basis()[al[2]+al[3]+2*al[4]+al[5],5] + 4*L.c() + L.delta() - sage: x.lie_derivative() + sage: x = L.basis()[al[2]+al[3]+2*al[4]+al[5],5] + 4*L.c() + L.d() + sage: x.canonical_derivation() (5*E[alpha[2] + alpha[3] + 2*alpha[4] + alpha[5]])#t^5 """ cdef dict d = {tl: tl * gl for tl,gl in self._t_dict.iteritems() if tl != 0} zero = self._parent.base_ring().zero() return type(self)(self.parent(), d, zero, zero) -def _build_untwisted_affine_element(P, t_dict, c, delta): +def _build_untwisted_affine_element(P, t_dict, c, d): """ Used to unpickle an element. @@ -1031,5 +1031,5 @@ def _build_untwisted_affine_element(P, t_dict, c, delta): sage: loads(dumps(x)) == x # indirect doctest True """ - return P.element_class(P, t_dict, c, delta) + return P.element_class(P, t_dict, c, d) From edec0041a0ef6df6df2acba2f20caea1b043178f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sat, 20 May 2017 20:39:00 +0200 Subject: [PATCH 427/452] trac 20099 details --- src/sage/functions/log.py | 2 +- src/sage/functions/trig.py | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/sage/functions/log.py b/src/sage/functions/log.py index f37d63fcbea..1dc07354d02 100644 --- a/src/sage/functions/log.py +++ b/src/sage/functions/log.py @@ -74,7 +74,7 @@ def __init__(self): sage: exp(7*pi*I/2) -I - For the sake of simplification, the argument is reduced the + For the sake of simplification, the argument is reduced modulo the period of the complex exponential function, `2\pi i`:: sage: k = var('k', domain='integer') diff --git a/src/sage/functions/trig.py b/src/sage/functions/trig.py index a1380af62aa..088a3218948 100644 --- a/src/sage/functions/trig.py +++ b/src/sage/functions/trig.py @@ -44,7 +44,6 @@ def __init__(self): sage: sin(k*pi) 0 - TESTS:: sage: conjugate(sin(x)) @@ -160,11 +159,10 @@ def __init__(self): sage: cos(1 + 2*k*pi) cos(1) sage: cos(k*pi) - (-1)^k + cos(pi*k) sage: cos(pi/3 + 2*k*pi) 1/2 - TESTS:: sage: conjugate(cos(x)) From cbf09d3d3dc5e07c06b275610eb7334b6bf7e7ba Mon Sep 17 00:00:00 2001 From: Ben Salisbury Date: Sat, 20 May 2017 15:19:02 -0400 Subject: [PATCH 428/452] Fixed typo in pxd file --- src/sage/algebras/lie_algebras/affine_lie_algebra.py | 2 +- src/sage/algebras/lie_algebras/lie_algebra_element.pxd | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/algebras/lie_algebras/affine_lie_algebra.py b/src/sage/algebras/lie_algebras/affine_lie_algebra.py index 32c701b642a..727eabc4193 100644 --- a/src/sage/algebras/lie_algebras/affine_lie_algebra.py +++ b/src/sage/algebras/lie_algebras/affine_lie_algebra.py @@ -423,7 +423,7 @@ def d(self): sage: g = LieAlgebra(QQ, cartan_type=['A',3,1]) sage: g.d() d - sage: D = L.derived_subalgebra() + sage: D = g.derived_subalgebra() sage: D.d() 0 """ diff --git a/src/sage/algebras/lie_algebras/lie_algebra_element.pxd b/src/sage/algebras/lie_algebras/lie_algebra_element.pxd index 418a4f9c4df..c9a6484ea63 100644 --- a/src/sage/algebras/lie_algebras/lie_algebra_element.pxd +++ b/src/sage/algebras/lie_algebras/lie_algebra_element.pxd @@ -18,7 +18,7 @@ cdef class StructureCoefficientsElement(LieAlgebraMatrixWrapper): cdef class UntwistedAffineLieAlgebraElement(Element): cdef dict _t_dict cdef _c_coeff - cdef _delta_coeff + cdef _d_coeff cdef long _hash cpdef dict t_dict(self) From 092dc4da1176197c97ca623753d84ce44bfc4315 Mon Sep 17 00:00:00 2001 From: Volker Braun Date: Sun, 21 May 2017 00:33:44 +0200 Subject: [PATCH 429/452] Add the missing divisors of 999 in doctest --- src/sage/libs/libecm.pyx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/libs/libecm.pyx b/src/sage/libs/libecm.pyx index 2825542bf5e..d46154282c9 100644 --- a/src/sage/libs/libecm.pyx +++ b/src/sage/libs/libecm.pyx @@ -19,14 +19,14 @@ EXAMPLES:: sage: result = ecmfactor(999, 0.00) sage: result[0] True - sage: result[1] in [3, 9, 27, 37, 999] or result[1] + sage: result[1] in [3, 9, 27, 37, 111, 333, 999] or result[1] True sage: result = ecmfactor(999, 0.00, verbose=True) Performing one curve with B1=0 Found factor in step 1: ... sage: result[0] True - sage: result[1] in [3, 9, 27, 37, 999] or result[1] + sage: result[1] in [3, 9, 27, 37, 111, 333, 999] or result[1] True sage: ecmfactor(2^128+1,1000,sigma=227140902) (True, 5704689200685129054721, 227140902) From b94d06c668c4c10c776dd672c994cfc9a2836213 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sat, 20 May 2017 18:42:31 -0500 Subject: [PATCH 430/452] Fix trivial failing doctest. --- src/sage/categories/sets_cat.py | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/sage/categories/sets_cat.py b/src/sage/categories/sets_cat.py index a44509d014e..b6eb9803889 100644 --- a/src/sage/categories/sets_cat.py +++ b/src/sage/categories/sets_cat.py @@ -2581,29 +2581,33 @@ def inject_shorthands(self, verbose=True): INPUT: - - ``verbose`` -- boolean (default ``True``) if ``True``, prints the defined shorthands + - ``verbose`` -- boolean (default ``True``); if ``True``, + prints the defined shorthands EXAMPLES:: sage: Q = QuasiSymmetricFunctions(ZZ) sage: Q.inject_shorthands() Injecting M as shorthand for Quasisymmetric functions over - the Integer Ring in the Monomial basis + the Integer Ring in the Monomial basis Injecting F as shorthand for Quasisymmetric functions over - the Integer Ring in the Fundamental basis + the Integer Ring in the Fundamental basis + Injecting E as shorthand for Quasisymmetric functions over + the Integer Ring in the Essential basis + doctest:...: RuntimeWarning: redefining global value `E` Injecting dI as shorthand for Quasisymmetric functions over - the Integer Ring in the dualImmaculate basis + the Integer Ring in the dualImmaculate basis Injecting QS as shorthand for Quasisymmetric functions over - the Integer Ring in the Quasisymmetric Schur basis + the Integer Ring in the Quasisymmetric Schur basis sage: F[1,2,1] + 5*M[1,3] + F[2]^2 5*F[1, 1, 1, 1] - 5*F[1, 1, 2] - 3*F[1, 2, 1] + 6*F[1, 3] + 2*F[2, 2] + F[3, 1] + F[4] sage: F Quasisymmetric functions over the Integer Ring in the - Fundamental basis + Fundamental basis sage: M Quasisymmetric functions over the Integer Ring in the - Monomial basis + Monomial basis """ from sage.misc.misc import inject_variable if not hasattr(self, "_shorthands"): From 5ac024d6a5baf755b74cc667d861a29e10201452 Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Sat, 20 May 2017 18:16:51 -0700 Subject: [PATCH 431/452] trac 23040: conway_polynomials: spkg-install should use sage-python23 instead of python, for compatibility for building with SAGE_PYTHON=3. --- build/pkgs/conway_polynomials/spkg-install | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build/pkgs/conway_polynomials/spkg-install b/build/pkgs/conway_polynomials/spkg-install index 15ba836d6a9..bf8aab4fbaa 100755 --- a/build/pkgs/conway_polynomials/spkg-install +++ b/build/pkgs/conway_polynomials/spkg-install @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env sage-python23 import os from six.moves import cPickle as pickle from sage.env import SAGE_SHARE From 7bb6875728422d57e375242a00c93eb392adfbe8 Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Sun, 21 May 2017 08:11:40 -0700 Subject: [PATCH 432/452] trac 23040: conway_polynomials depends on python and six, not SAGERUNTIME --- build/pkgs/conway_polynomials/dependencies | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/build/pkgs/conway_polynomials/dependencies b/build/pkgs/conway_polynomials/dependencies index 8c8b7765a8d..3e374be7f45 100644 --- a/build/pkgs/conway_polynomials/dependencies +++ b/build/pkgs/conway_polynomials/dependencies @@ -1,7 +1,4 @@ -| $(SAGERUNTIME) - -CONWAY_POLYNOMIALS depends on SAGERUNTIME because it runs Sage code to -generate a Sage object (.sobj). +$(PYTHON) $(inst_six) ---------- All lines of this file are ignored except the first. From e41a5125373660ea215dc5d24664acd5c913afdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 21 May 2017 17:34:10 +0200 Subject: [PATCH 433/452] trac 22975 fixing 3 other imports --- src/sage/matrix/matrix0.pyx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/sage/matrix/matrix0.pyx b/src/sage/matrix/matrix0.pyx index a49ccde38a9..d48931b2cea 100644 --- a/src/sage/matrix/matrix0.pyx +++ b/src/sage/matrix/matrix0.pyx @@ -2148,7 +2148,7 @@ cdef class Matrix(sage.structure.element.Matrix): [ 5 25] [125 625] """ - from constructor import matrix + from .constructor import matrix return matrix(self.nrows(), self.ncols(), [e(*args, **kwargs) for e in self.list()]) ################################################### @@ -3556,9 +3556,9 @@ cdef class Matrix(sage.structure.element.Matrix): """ if len(v) > self._nrows: raise ValueError("length of v must be at most the number of rows of self") - if self._nrows == 0: + if not self._nrows: return self.parent().row_space().zero_vector() - from constructor import matrix + from .constructor import matrix v = matrix(list(v)+[0]*(self._nrows-len(v))) return (v * self)[0] @@ -3633,9 +3633,9 @@ cdef class Matrix(sage.structure.element.Matrix): """ if len(v) > self._ncols: raise ValueError("length of v must be at most the number of columns of self") - if self._ncols == 0: + if not self._ncols: return self.parent().column_space().zero_vector() - from constructor import matrix + from .constructor import matrix v = matrix(self._ncols, 1, list(v)+[0]*(self._ncols-len(v))) return (self * v).column(0) From 5924a34dc07910bf329680833130be81e04e1ec3 Mon Sep 17 00:00:00 2001 From: David Coudert Date: Sun, 21 May 2017 17:56:12 +0200 Subject: [PATCH 434/452] trac #22559: gathering all ticket comments up to 55 --- src/sage/graphs/bipartite_graph.py | 134 +++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) diff --git a/src/sage/graphs/bipartite_graph.py b/src/sage/graphs/bipartite_graph.py index d2ac8db761e..d6a16a7c4fa 100644 --- a/src/sage/graphs/bipartite_graph.py +++ b/src/sage/graphs/bipartite_graph.py @@ -33,9 +33,11 @@ #***************************************************************************** from __future__ import print_function from __future__ import absolute_import +from six import iteritems from six.moves import range from .graph import Graph +from sage.rings.integer import Integer class BipartiteGraph(Graph): r""" @@ -1281,3 +1283,135 @@ def reduced_adjacency_matrix(self, sparse=True): # now construct and return the matrix from the dictionary we created from sage.matrix.constructor import matrix return matrix(len(self.right), len(self.left), D, sparse=sparse) + + def matching(self, value_only=False, algorithm=None, + use_edge_labels=False, solver=None, verbose=0): + r""" + Return a maximum matching of the graph represented by the list of its + edges. + + Given a graph `G` such that each edge `e` has a weight `w_e`, a maximum + matching is a subset `S` of the edges of `G` of maximum weight such that + no two edges of `S` are incident with each other. + + INPUT: + + - ``value_only`` -- boolean (default: ``False``); when set to ``True``, + only the cardinal (or the weight) of the matching is returned + + - ``algorithm`` -- string (default: ``"Hopcroft-Karp"`` if + ``use_edge_labels==False``, otherwise ``"Edmonds"``) + + - ``"Hopcroft-Karp"`` selects the default bipartite graph algorithm as + implemented in NetworkX + + - ``"Eppstein"`` selects Eppstein's algorithm as implemented in + NetworkX + + - ``"Edmonds"`` selects Edmonds' algorithm as implemented in NetworkX + + - ``"LP"`` uses a Linear Program formulation of the matching problem + + - ``use_edge_labels`` -- boolean (default: ``False``) + + - when set to ``True``, computes a weighted matching where each edge + is weighted by its label (if an edge has no label, `1` is assumed); + only if ``algorithm`` is ``"Edmonds"``, ``"LP"`` + + - when set to ``False``, each edge has weight `1` + + - ``solver`` -- (default: ``None``) a specific Linear Program (LP) + solver to be used + + - ``verbose`` -- integer (default: ``0``); sets the level of verbosity: + set to 0 by default, which means quiet + + .. SEEALSO:: + + - :wikipedia:`Matching_(graph_theory)` + - :meth:`~Graph.matching` + + EXAMPLES: + + Maximum matching in a cycle graph:: + + sage: G = BipartiteGraph(graphs.CycleGraph(10)) + sage: G.matching() + [(0, 1, None), (2, 3, None), (4, 5, None), (6, 7, None), (8, 9, None)] + + The size of a maximum matching in a complete bipartite graph using + Eppstein:: + + sage: G = BipartiteGraph(graphs.CompleteBipartiteGraph(4,5)) + sage: G.matching(algorithm="Eppstein", value_only=True) + 4 + + TESTS: + + If ``algorithm`` is not set to one of the supported algorithms, an + exception is raised:: + + sage: G = BipartiteGraph(graphs.CompleteBipartiteGraph(4,5)) + sage: G.matching(algorithm="somethingdifferent") + Traceback (most recent call last): + ... + ValueError: algorithm must be "Hopcroft-Karp", "Eppstein", "Edmonds" or "LP" + + Maximum matching in a weighted bipartite graph:: + + sage: G = graphs.CycleGraph(4) + sage: B = BipartiteGraph([(u,v,2) for u,v in G.edges(labels=0)]) + sage: B.matching(use_edge_labels=True) + [(0, 3, 2), (1, 2, 2)] + sage: B.matching(use_edge_labels=True, value_only=True) + 4 + sage: B.matching(use_edge_labels=True, value_only=True, algorithm='Edmonds') + 4 + sage: B.matching(use_edge_labels=True, value_only=True, algorithm='LP') + 4.0 + sage: B.matching(use_edge_labels=True, value_only=True, algorithm='Eppstein') + Traceback (most recent call last): + ... + ValueError: use_edge_labels can not be used with "Hopcroft-Karp" or "Eppstein" + sage: B.matching(use_edge_labels=True, value_only=True, algorithm='Hopcroft-Karp') + Traceback (most recent call last): + ... + ValueError: use_edge_labels can not be used with "Hopcroft-Karp" or "Eppstein" + sage: B.matching(use_edge_labels=False, value_only=True, algorithm='Hopcroft-Karp') + 2 + sage: B.matching(use_edge_labels=False, value_only=True, algorithm='Eppstein') + 2 + sage: B.matching(use_edge_labels=False, value_only=True, algorithm='Edmonds') + 2 + sage: B.matching(use_edge_labels=False, value_only=True, algorithm='LP') + 2 + """ + self._scream_if_not_simple() + + if algorithm is None: + algorithm = "Edmonds" if use_edge_labels else "Hopcroft-Karp" + + if algorithm == "Hopcroft-Karp" or algorithm == "Eppstein": + if use_edge_labels: + raise ValueError('use_edge_labels can not be used with ' + + '"Hopcroft-Karp" or "Eppstein"') + import networkx + #this is necessary to call the methods for bipartite matchings + g = self.networkx_graph() + if algorithm == "Hopcroft-Karp": + d = networkx.bipartite.hopcroft_karp_matching(g) + else: + d = networkx.bipartite.eppstein_matching(g) + if value_only: + return Integer(len(d) // 2) + else: + return [(u, v, self.edge_label(u, v)) + for u, v in iteritems(d) if u < v] + elif algorithm == "Edmonds" or algorithm == "LP": + return Graph.matching(self, value_only=value_only, + algorithm=algorithm, + use_edge_labels=use_edge_labels, + solver=solver, verbose=verbose) + else: + raise ValueError('algorithm must be "Hopcroft-Karp", ' + + '"Eppstein", "Edmonds" or "LP"') From 8a9df66c18d842d6f15d0b141ad53ebcae63967c Mon Sep 17 00:00:00 2001 From: Marcelo Forets Date: Sun, 21 May 2017 18:11:02 +0200 Subject: [PATCH 435/452] update first exmample --- src/sage/numerical/mip.pyx | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/sage/numerical/mip.pyx b/src/sage/numerical/mip.pyx index 5976ceae2e8..a0f855e3987 100644 --- a/src/sage/numerical/mip.pyx +++ b/src/sage/numerical/mip.pyx @@ -49,15 +49,12 @@ A mixed integer linear program can give you an answer: #. You have to create an instance of :class:`MixedIntegerLinearProgram` and -- in our case -- specify that it is a minimization. - #. Create a dictionary ``w`` of integer variables ``w`` via ``w = - p.new_variable(integer=True)`` (note that **by default all variables are - non-negative**, cf :meth:`~MixedIntegerLinearProgram.new_variable`). + #. Create a dictionary ``w`` of non-negative integer variables ``w`` via ``w = + p.new_variable(integer=True, nonnegative=True)``. #. Add those three equations as equality constraints via :meth:`add_constraint `. #. Also add the inequality constraint. #. Add an inequality constraint `w_3 \geq 1` to exclude the trivial solution. - #. By default, all variables are non-negative. We remove that constraint - via ``p.set_min(variable, None)``, see :meth:`set_min `. #. Specify the objective function via :meth:`set_objective `. In our case that is just `w_3`. If it is a pure constraint satisfaction problem, specify it as ``None``. @@ -74,7 +71,6 @@ The following example shows all these steps:: sage: p.add_constraint(2*w[2] - 3*w[3] == 0) sage: p.add_constraint(w[0] - w[1] - w[2] >= 0) sage: p.add_constraint(w[3] >= 1) - sage: _ = [ p.set_min(w[i], None) for i in range(1,4) ] sage: p.set_objective(w[3]) sage: p.show() Minimization: @@ -87,9 +83,9 @@ The following example shows all these steps:: - x_3 <= -1.0 Variables: x_0 is an integer variable (min=0.0, max=+oo) - x_1 is an integer variable (min=-oo, max=+oo) - x_2 is an integer variable (min=-oo, max=+oo) - x_3 is an integer variable (min=-oo, max=+oo) + x_1 is an integer variable (min=0.0, max=+oo) + x_2 is an integer variable (min=0.0, max=+oo) + x_3 is an integer variable (min=0.0, max=+oo) sage: print('Objective Value: {}'.format(p.solve())) Objective Value: 2.0 sage: for i, v in p.get_values(w).iteritems(): From c3a920d22c3160b666c6a12dc5c9ac4c86e321d3 Mon Sep 17 00:00:00 2001 From: Marcelo Forets Date: Sun, 21 May 2017 18:33:05 +0200 Subject: [PATCH 436/452] update warning messages --- src/sage/numerical/mip.pyx | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/sage/numerical/mip.pyx b/src/sage/numerical/mip.pyx index a0f855e3987..c55b4028002 100644 --- a/src/sage/numerical/mip.pyx +++ b/src/sage/numerical/mip.pyx @@ -153,6 +153,12 @@ also allowed:: a[(4, 'string', Rational Field)] = x_2 is a continuous variable (min=-oo, max=+oo) b[2] = x_3 is a continuous variable (min=-oo, max=+oo) +Upper/lower bounds on a variable can be specified either as separate constraints +(see :meth:`add_constraint `) or +using the methods :meth:`set_min ` +and :meth:`set_min ` +respectively. + The default MIP variable ------------------------ @@ -294,11 +300,6 @@ cdef class MixedIntegerLinearProgram(SageObject): - Defaults to ``False``. - .. WARNING:: - - All LP variables are non-negative by default (see :meth:`new_variable` - and :meth:`set_min`). - .. SEEALSO:: - :func:`default_mip_solver` -- Returns/Sets the default MIP solver. @@ -2181,8 +2182,8 @@ cdef class MixedIntegerLinearProgram(SageObject): .. WARNING:: - By default, all variables of a LP are assumed to be - non-negative. See :meth:`set_min` to change it. + By default, no additional assumption is made on the domain of an LP + variable. See :meth:`set_min` to change it. EXAMPLES: From 5c7ab1b71d1a3222b59197332c7b031b73148ecf Mon Sep 17 00:00:00 2001 From: Marcelo Forets Date: Sun, 21 May 2017 18:36:17 +0200 Subject: [PATCH 437/452] mention set_max too --- src/sage/numerical/mip.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/numerical/mip.pyx b/src/sage/numerical/mip.pyx index c55b4028002..596a0c29d78 100644 --- a/src/sage/numerical/mip.pyx +++ b/src/sage/numerical/mip.pyx @@ -2183,7 +2183,7 @@ cdef class MixedIntegerLinearProgram(SageObject): .. WARNING:: By default, no additional assumption is made on the domain of an LP - variable. See :meth:`set_min` to change it. + variable. See :meth:`set_min` and :meth:`set_max` to change it. EXAMPLES: From 39f3fb6bbeca7d8d2f765c00b94f6afc17ee16bf Mon Sep 17 00:00:00 2001 From: Marcelo Forets Date: Sun, 21 May 2017 18:37:13 +0200 Subject: [PATCH 438/452] another outdated message --- src/sage/numerical/mip.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/numerical/mip.pyx b/src/sage/numerical/mip.pyx index 596a0c29d78..35da273df31 100644 --- a/src/sage/numerical/mip.pyx +++ b/src/sage/numerical/mip.pyx @@ -707,7 +707,7 @@ cdef class MixedIntegerLinearProgram(SageObject): .. SEEALSO:: - :meth:`set_min`, :meth:`get_min` -- set/get the lower bound of a - variable. Note that by default, all variables are non-negative. + variable. - :meth:`set_max`, :meth:`get_max` -- set/get the upper bound of a variable. From c08df92dd7e30fe156bf1f1a9fbed9f95de7f7c6 Mon Sep 17 00:00:00 2001 From: "John H. Palmieri" Date: Sun, 21 May 2017 09:45:53 -0700 Subject: [PATCH 439/452] trac 23040: don't use the module sage.env --- build/pkgs/conway_polynomials/spkg-install | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/build/pkgs/conway_polynomials/spkg-install b/build/pkgs/conway_polynomials/spkg-install index bf8aab4fbaa..b0fe157964c 100755 --- a/build/pkgs/conway_polynomials/spkg-install +++ b/build/pkgs/conway_polynomials/spkg-install @@ -1,11 +1,10 @@ #!/usr/bin/env sage-python23 import os from six.moves import cPickle as pickle -from sage.env import SAGE_SHARE +SAGE_SHARE = os.getenv('SAGE_SHARE') install_root = os.path.join(SAGE_SHARE, 'conway_polynomials') - def create_db(): db = {} from src import conway_polynomials From 1df79300864195584ee01b8588a3812797ec8175 Mon Sep 17 00:00:00 2001 From: Marcelo Forets Date: Sun, 21 May 2017 18:55:19 +0200 Subject: [PATCH 440/452] set_min and set_max respectively --- src/sage/numerical/mip.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/numerical/mip.pyx b/src/sage/numerical/mip.pyx index 35da273df31..fb1960a4b57 100644 --- a/src/sage/numerical/mip.pyx +++ b/src/sage/numerical/mip.pyx @@ -155,7 +155,7 @@ also allowed:: Upper/lower bounds on a variable can be specified either as separate constraints (see :meth:`add_constraint `) or -using the methods :meth:`set_min ` +using the methods :meth:`set_max ` and :meth:`set_min ` respectively. From 38edb49dd1f084dabd2e6683a7379ff0fc5a5d6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Sun, 21 May 2017 22:42:13 +0200 Subject: [PATCH 441/452] trac 21791 code cleanup --- src/sage/combinat/posets/linear_extensions.py | 106 ++++++++++-------- 1 file changed, 61 insertions(+), 45 deletions(-) diff --git a/src/sage/combinat/posets/linear_extensions.py b/src/sage/combinat/posets/linear_extensions.py index 7d5b81a70b0..58f15eee1c7 100644 --- a/src/sage/combinat/posets/linear_extensions.py +++ b/src/sage/combinat/posets/linear_extensions.py @@ -455,58 +455,74 @@ def cardinality(self): """ from sage.rings.integer import Integer - n=len(self._poset) - up=self._poset._hasse_diagram.to_dictionary() - # Convert to the Hasse diagram so our poset can be realized on the set {0,...,n-1} - # with a nice dictionary of edges - for i in range(0,n): - up[n-1-i]=sorted(set(up[n-1-i]+[item for x in up[n-1-i] for item in up[x] ])) - # Compute the principal order filter for each element. - Jup={1:[]} # Jup will be a dictionary giving up edges in J(P) - # We will perform a loop where after k loops, we will have a list of up edges - # for the lattice of order ideals for P restricted to entries 0,...,k. - loc=[1] * n - # This list will be indexed by entries in P. After k loops, the entry loc[i] - # will correspond to the element of J(P) that is the principal order ideal of i, - # restricted to the elements 0,...,k . - m=1 # m keeps track of how many elements we currently have in J(P). - # We start with just the empty order ideal, and no relations. + n = len(self._poset) + if not n: + return Integer(1) + + up = self._poset._hasse_diagram.to_dictionary() + # Convert to the Hasse diagram so our poset can be realized on + # the set {0,...,n-1} with a nice dictionary of edges + + for i in range(n): + up[n - 1 - i] = sorted(set(up[n - 1 - i] + + [item for x in up[n - 1 - i] + for item in up[x]])) + # Compute the principal order filter for each element. + + Jup = {1: []} + # Jup will be a dictionary giving up edges in J(P) + + # We will perform a loop where after k loops, we will have a + # list of up edges for the lattice of order ideals for P + # restricted to entries 0,...,k. + loc = [1] * n + + # This list will be indexed by entries in P. After k loops, + # the entry loc[i] will correspond to the element of J(P) that + # is the principal order ideal of i, restricted to the + # elements 0,...,k . + + m = 1 + # m keeps track of how many elements we currently have in J(P). + # We start with just the empty order ideal, and no relations. for x in range(n): - # Use the existing Jup table to compute all covering relations in J(P) - # for things that are above loc(x). - K=[[loc[x]]] - j=0 - while len(K[j])>0: + # Use the existing Jup table to compute all covering + # relations in J(P) for things that are above loc(x). + K = [[loc[x]]] + j = 0 + while K[j]: K.append([]) for a in K[j]: for b in Jup[a]: - K[j+1]=K[j+1]+[b] - j=j+1 - K=sorted(set([item for sublist in K for item in sublist])) - for j in range(0,len(K)): - i=m+j+1 - Jup[i]= [m+K.index(a)+1 for a in Jup[K[j]]] - # These are copies of the covering relations with elements from K, - # but now with the underlying elements containing x. - Jup[K[j]]= Jup[K[j]]+[i] - # There are the new covering relations we get between ideals that - # don't contain x and those that do. + K[j + 1] = K[j + 1] + [b] + j += 1 + K = sorted(set([item for sublist in K for item in sublist])) + for j in range(len(K)): + i = m + j + 1 + Jup[i] = [m + K.index(a) + 1 for a in Jup[K[j]]] + # These are copies of the covering relations with + # elements from K, but now with the underlying + # elements containing x. + Jup[K[j]] = Jup[K[j]] + [i] + # There are the new covering relations we get between + # ideals that don't contain x and those that do. for y in up[x]: - loc[y]=K.index(loc[y])+m+1 + loc[y] = K.index(loc[y]) + m + 1 # Updates loc[y] if y is above x. - m=m+len(K) - # Now we have a dictionary of covering relations for J(P). The following - # shortcut works to count maximal chains, since we made J(P) naturally - # labelled, and J(P) has a unique maximal element and minimum element. - Jup[m]=1 - while m>1: - m=m-1 - ct=0 + m += len(K) + # Now we have a dictionary of covering relations for J(P). The + # following shortcut works to count maximal chains, since we + # made J(P) naturally labelled, and J(P) has a unique maximal + # element and minimum element. + + Jup[m] = Integer(1) + while m > 1: + m -= 1 + ct = Integer(0) for j in Jup[m]: - ct=ct+Jup[j] - Jup[m]=ct - return ct - + ct += Jup[j] + Jup[m] = ct + return ct def __iter__(self): r""" From 3cf54ac6ef970d879e91b9e6c8cea37c25172040 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sun, 21 May 2017 18:33:15 -0500 Subject: [PATCH 442/452] Better hash test. --- src/sage/algebras/lie_algebras/lie_algebra_element.pyx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/sage/algebras/lie_algebras/lie_algebra_element.pyx b/src/sage/algebras/lie_algebras/lie_algebra_element.pyx index e8b8fe3f7eb..1162172fd3b 100644 --- a/src/sage/algebras/lie_algebras/lie_algebra_element.pyx +++ b/src/sage/algebras/lie_algebras/lie_algebra_element.pyx @@ -771,15 +771,15 @@ cdef class UntwistedAffineLieAlgebraElement(Element): sage: asl = lie_algebras.Affine(QQ, ['A',4,1]) sage: x = asl.an_element() - sage: hash(x) - 1782435762440299943 + sage: hash(x) == hash(x) + True sage: hash(asl.zero()) 0 """ if not self: self._hash = 0 if self._hash == -1: - self._hash = hash((tuple(self._t_dict.iteritems()), + self._hash = hash((tuple([self._t_dict[i] for i in sorted(self._t_dict)]), self._c_coeff, self._d_coeff)) return self._hash From 8bcf8cea235e43b3965f3da1c46ab90fceb2babf Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Sun, 21 May 2017 20:22:39 -0500 Subject: [PATCH 443/452] Using generator expressions for speed. --- src/sage/combinat/posets/linear_extensions.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/sage/combinat/posets/linear_extensions.py b/src/sage/combinat/posets/linear_extensions.py index 58f15eee1c7..f20cf51e1a6 100644 --- a/src/sage/combinat/posets/linear_extensions.py +++ b/src/sage/combinat/posets/linear_extensions.py @@ -491,10 +491,7 @@ def cardinality(self): K = [[loc[x]]] j = 0 while K[j]: - K.append([]) - for a in K[j]: - for b in Jup[a]: - K[j + 1] = K[j + 1] + [b] + K.append([b for a in K[j] for b in Jup[a]]) j += 1 K = sorted(set([item for sublist in K for item in sublist])) for j in range(len(K)): From 7e7ff269f2452db868ac5db74ebaff374ee600f7 Mon Sep 17 00:00:00 2001 From: Travis Scrimshaw Date: Mon, 22 May 2017 02:01:44 -0500 Subject: [PATCH 444/452] Getting a little bit of extra speed by not creating a list. --- src/sage/combinat/posets/linear_extensions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/combinat/posets/linear_extensions.py b/src/sage/combinat/posets/linear_extensions.py index f20cf51e1a6..00cdecfdb9e 100644 --- a/src/sage/combinat/posets/linear_extensions.py +++ b/src/sage/combinat/posets/linear_extensions.py @@ -493,7 +493,7 @@ def cardinality(self): while K[j]: K.append([b for a in K[j] for b in Jup[a]]) j += 1 - K = sorted(set([item for sublist in K for item in sublist])) + K = sorted(set(item for sublist in K for item in sublist)) for j in range(len(K)): i = m + j + 1 Jup[i] = [m + K.index(a) + 1 for a in Jup[K[j]]] From 02aad12dea392ea29d417ec4fae4f5d2063850dc Mon Sep 17 00:00:00 2001 From: Marcelo Forets Date: Mon, 22 May 2017 09:09:24 +0200 Subject: [PATCH 445/452] fix directions parsing --- src/sage/calculus/calculus.py | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/src/sage/calculus/calculus.py b/src/sage/calculus/calculus.py index 5b52d189610..cffef64c514 100644 --- a/src/sage/calculus/calculus.py +++ b/src/sage/calculus/calculus.py @@ -1136,8 +1136,8 @@ def limit(ex, dir=None, taylor=False, algorithm='maxima', **argv): INPUT: - ``dir`` - (default: None); dir may have the value - 'plus' (or '+' or 'right') for a limit from above, - 'minus' (or '-' or 'left') for a limit from below, or may be omitted + 'plus' (or '+' or 'right' or 'above') for a limit from above, + 'minus' (or '-' or 'left' or 'below') for a limit from below, or may be omitted (implying a two-sided limit is to be computed). - ``taylor`` - (default: False); if True, use Taylor @@ -1255,8 +1255,8 @@ def limit(ex, dir=None, taylor=False, algorithm='maxima', **argv): sage: lim(x^2, x=2, dir='nugget') Traceback (most recent call last): ... - ValueError: dir must be one of None, 'plus', '+', 'right', - 'minus', '-', 'left' + ValueError: dir must be one of None, 'plus', '+', 'above', 'right', + 'minus', '-', 'below', 'left' We check that :trac:`3718` is fixed, so that Maxima gives correct limits for the floor function:: @@ -1308,6 +1308,11 @@ def limit(ex, dir=None, taylor=False, algorithm='maxima', **argv): sage: sequence = -(3*n^2 + 1)*(-1)^n/sqrt(n^5 + 8*n^3 + 8) sage: limit(sequence, n=infinity) 0 + + Check if :trac:`23048` is fixed:: + + sage: (1/(x-3)).limit(x=3, dir='below') + -Infinity """ if not isinstance(ex, Expression): ex = SR(ex) @@ -1324,21 +1329,21 @@ def limit(ex, dir=None, taylor=False, algorithm='maxima', **argv): if dir not in [None, 'plus', '+', 'right', 'minus', '-', 'left', 'above', 'below']: - raise ValueError("dir must be one of None, 'plus', '+', 'right', 'minus', '-', 'left'") + raise ValueError("dir must be one of None, 'plus', '+', 'above', 'right', 'minus', '-', 'below', 'left'") if algorithm == 'maxima': if dir is None: l = maxima.sr_limit(ex, v, a) - elif dir in ['plus', '+', 'right']: + elif dir in ['plus', '+', 'right', 'above']: l = maxima.sr_limit(ex, v, a, 'plus') - elif dir in ['minus', '-', 'left']: + elif dir in ['minus', '-', 'left', 'below']: l = maxima.sr_limit(ex, v, a, 'minus') elif algorithm == 'maxima_taylor': if dir is None: l = maxima.sr_tlimit(ex, v, a) - elif dir == 'plus' or dir == 'above' or dir == 'from_right': + elif dir in ['plus', '+', 'right', 'above']: l = maxima.sr_tlimit(ex, v, a, 'plus') - elif dir == 'minus' or dir == 'below' or dir == 'from_left': + elif dir == ['minus', '-', 'left', 'below']: l = maxima.sr_tlimit(ex, v, a, 'minus') elif algorithm == 'sympy': if dir is None: From 59b9bdc4dc0063c4862417444d03d0a57ab29de5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Chapoton?= Date: Mon, 22 May 2017 09:52:01 +0200 Subject: [PATCH 446/452] trac 23049 fix print --- src/sage/categories/loop_crystals.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sage/categories/loop_crystals.py b/src/sage/categories/loop_crystals.py index fa4781b3ee6..df6e434d954 100644 --- a/src/sage/categories/loop_crystals.py +++ b/src/sage/categories/loop_crystals.py @@ -855,7 +855,7 @@ def energy_function(self, algorithm=None): sage: T = crystals.TensorProduct(K,K,K) sage: hw = T.classically_highest_weight_vectors() sage: for b in hw: - ....: print b, b.energy_function() + ....: print("{} {}".format(b, b.energy_function())) [[[1]], [[1]], [[1]]] 0 [[[2]], [[1]], [[1]]] 1 [[[1]], [[2]], [[1]]] 2 @@ -865,7 +865,7 @@ def energy_function(self, algorithm=None): sage: T = crystals.TensorProduct(K,K) sage: hw = T.classically_highest_weight_vectors() sage: for b in hw: - ....: print b, b.energy_function() + ....: print("{} {}".format(b, b.energy_function())) [[], []] 4 [[[1, 1]], []] 3 [[], [[1, 1]]] 1 From 65295478620b301cdceb36863e8964afd333e46f Mon Sep 17 00:00:00 2001 From: Marcelo Forets Date: Mon, 22 May 2017 16:56:31 +0200 Subject: [PATCH 447/452] fix typo --- src/sage/calculus/calculus.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/calculus/calculus.py b/src/sage/calculus/calculus.py index cffef64c514..702422fd55c 100644 --- a/src/sage/calculus/calculus.py +++ b/src/sage/calculus/calculus.py @@ -1343,7 +1343,7 @@ def limit(ex, dir=None, taylor=False, algorithm='maxima', **argv): l = maxima.sr_tlimit(ex, v, a) elif dir in ['plus', '+', 'right', 'above']: l = maxima.sr_tlimit(ex, v, a, 'plus') - elif dir == ['minus', '-', 'left', 'below']: + elif dir in ['minus', '-', 'left', 'below']: l = maxima.sr_tlimit(ex, v, a, 'minus') elif algorithm == 'sympy': if dir is None: From dbfaeaae1b7ca33276a4278ad4c58cd5e57d675a Mon Sep 17 00:00:00 2001 From: Vincent Delecroix <20100.delecroix@gmail.com> Date: Mon, 22 May 2017 09:54:26 +0200 Subject: [PATCH 448/452] 23050: reverse_rows_and_columns --- src/sage/matrix/matrix0.pyx | 60 ++++++++++++++++++++++++ src/sage/matrix/matrix_dense.pyx | 27 +++++++++++ src/sage/matrix/matrix_generic_dense.pyx | 13 +++++ src/sage/matrix/matrix_sparse.pyx | 43 +++++++++++++++++ 4 files changed, 143 insertions(+) diff --git a/src/sage/matrix/matrix0.pyx b/src/sage/matrix/matrix0.pyx index b1af13d9713..f03eeafa1ee 100644 --- a/src/sage/matrix/matrix0.pyx +++ b/src/sage/matrix/matrix0.pyx @@ -3283,6 +3283,66 @@ cdef class Matrix(sage.structure.element.Matrix): self.set_unsafe(i,l,-A.get_unsafe(r,k)) #self[i,l] = -A[r,k] l += 1 + def reverse_rows_and_columns(self): + r""" + Reverse the row order and column order of this matrix + + This method transforms a matrix `m_{i,j}` with `0 \leq i < nrows` and + `0 \leq j < ncols` into `m_{nrows - i - 1, ncols - j - 1}`. + + EXAMPLES:: + + sage: m = matrix(ZZ, 2, 2, range(4)) + sage: m.reverse_rows_and_columns() + sage: m + [3 2] + [1 0] + + sage: m = matrix(ZZ, 2, 3, range(6), sparse=True) + sage: m.reverse_rows_and_columns() + sage: m + [5 4 3] + [2 1 0] + sage: m = matrix(ZZ, 3, 2, range(6), sparse=True) + sage: m.reverse_rows_and_columns() + sage: m + [5 4] + [3 2] + [1 0] + sage: m.reverse_rows_and_columns() + sage: m + [0 1] + [2 3] + [4 5] + + sage: m = matrix(QQ, 3, 2, [1/i for i in range(1,7)]) + sage: m.reverse_rows_and_columns() + sage: m + [1/6 1/5] + [1/4 1/3] + [1/2 1] + + sage: R. = ZZ['x,y'] + sage: m = matrix(R, 3, 3, lambda i,j: x**i*y**j, sparse=True) + sage: m.reverse_rows_and_columns() + sage: m + [x^2*y^2 x^2*y x^2] + [ x*y^2 x*y x] + [ y^2 y 1] + + If the matrix is immutable, the method raises an error:: + + sage: m = matrix(ZZ, 2, [1, 3, -2, 4]) + sage: m.set_immutable() + sage: m.reverse_rows_and_columns() + Traceback (most recent call last): + ... + ValueError: matrix is immutable; please change a copy instead (i.e., use copy(M) to change a copy of M). + """ + self.check_mutability() + self.clear_cache() + self._reverse_unsafe() + ################################################### # Methods needed for quiver and cluster mutations # - mutate diff --git a/src/sage/matrix/matrix_dense.pyx b/src/sage/matrix/matrix_dense.pyx index bf357c4ee23..7f71a383565 100644 --- a/src/sage/matrix/matrix_dense.pyx +++ b/src/sage/matrix/matrix_dense.pyx @@ -225,6 +225,33 @@ cdef class Matrix_dense(matrix.Matrix): [nr - t for t in reversed(row_divs)]) return atrans + def _reverse_unsafe(self): + r""" + TESTS:: + + sage: m = matrix(QQ, 2, 3, range(6)) + sage: m._reverse_unsafe() + sage: m + [5 4 3] + [2 1 0] + """ + cdef Py_ssize_t i, j + cdef Py_ssize_t nrows = self._nrows + cdef Py_ssize_t ncols = self._ncols + for i in range(nrows // 2): + for j in range(ncols): + e1 = self.get_unsafe(i, j) + e2 = self.get_unsafe(nrows - i - 1, ncols - j - 1) + self.set_unsafe(i, j, e2) + self.set_unsafe(nrows - i - 1, ncols - j - 1, e1) + if nrows % 2 == 1: + i = nrows // 2 + for j in range(ncols // 2): + e1 = self.get_unsafe(i, j) + e2 = self.get_unsafe(nrows - i - 1, ncols - j - 1) + self.set_unsafe(i, j, e2) + self.set_unsafe(nrows - i - 1, ncols - j - 1, e1) + def _elementwise_product(self, right): r""" Returns the elementwise product of two dense diff --git a/src/sage/matrix/matrix_generic_dense.pyx b/src/sage/matrix/matrix_generic_dense.pyx index ae2179b4ba4..9a18f876257 100644 --- a/src/sage/matrix/matrix_generic_dense.pyx +++ b/src/sage/matrix/matrix_generic_dense.pyx @@ -146,6 +146,19 @@ cdef class Matrix_generic_dense(matrix_dense.Matrix_dense): cdef get_unsafe(self, Py_ssize_t i, Py_ssize_t j): return self._entries[i*self._ncols + j] + + def _reverse_unsafe(self): + r""" + TESTS:: + + sage: m = matrix(ZZ['x,y'], 2, 3, range(6)) + sage: m._reverse_unsafe() + sage: m + [5 4 3] + [2 1 0] + """ + self._entries.reverse() + def _pickle(self): """ EXAMPLES: diff --git a/src/sage/matrix/matrix_sparse.pyx b/src/sage/matrix/matrix_sparse.pyx index bb0ed441f8f..4cd99ca1788 100644 --- a/src/sage/matrix/matrix_sparse.pyx +++ b/src/sage/matrix/matrix_sparse.pyx @@ -423,6 +423,49 @@ cdef class Matrix_sparse(matrix.Matrix): list(reversed([self._nrows - t for t in row_divs]))) return A + + def _reverse_unsafe(self): + r""" + TESTS:: + + sage: m = matrix(QQ, 3, 3, {(2,2): 1}, sparse=True) + sage: m._reverse_unsafe() + sage: m + [1 0 0] + [0 0 0] + [0 0 0] + sage: m = matrix(QQ, 3, 3, {(2,2): 1, (0,0):2}, sparse=True) + sage: m._reverse_unsafe() + sage: m + [1 0 0] + [0 0 0] + [0 0 2] + sage: m = matrix(QQ, 3, 3, {(1,2): 1}, sparse=True) + sage: m._reverse_unsafe() + sage: m + [0 0 0] + [1 0 0] + [0 0 0] + sage: m = matrix(QQ, 3, 3, {(1,1): 1}, sparse=True) + sage: m._reverse_unsafe() + sage: m + [0 0 0] + [0 1 0] + [0 0 0] + """ + cdef Py_ssize_t i, j, ii, jj + for i,j in self.nonzero_positions(copy=False): + ii = self._nrows - i - 1 + jj = self._ncols - j - 1 + if (i > ii or (i == ii and j >= jj)) and self.get_unsafe(ii, jj): + # already swapped + continue + + e1 = self.get_unsafe(i, j) + e2 = self.get_unsafe(ii, jj) + self.set_unsafe(i, j, e2) + self.set_unsafe(ii, jj, e1) + def charpoly(self, var='x', **kwds): """ Return the characteristic polynomial of this matrix. From c1b5cdd5742ac79c9256a1be25df54bd45872eea Mon Sep 17 00:00:00 2001 From: Marcelo Forets Date: Mon, 22 May 2017 21:56:10 +0200 Subject: [PATCH 449/452] fix missing backtick --- src/sage/calculus/calculus.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/calculus/calculus.py b/src/sage/calculus/calculus.py index 12f55673810..652ea587497 100644 --- a/src/sage/calculus/calculus.py +++ b/src/sage/calculus/calculus.py @@ -1500,7 +1500,7 @@ def inverse_laplace(ex, s, t, algorithm='maxima'): .. SEEALSO:: - :func:`laplace + :func:`laplace` EXAMPLES:: From 75e1b247b02448b1fc14b34396feb35b58e7cf6c Mon Sep 17 00:00:00 2001 From: Marcelo Forets Date: Mon, 22 May 2017 21:57:13 +0200 Subject: [PATCH 450/452] fix unnecessary :: thing --- src/sage/calculus/calculus.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sage/calculus/calculus.py b/src/sage/calculus/calculus.py index 82b7c29a8f0..3b3a5fa851c 100644 --- a/src/sage/calculus/calculus.py +++ b/src/sage/calculus/calculus.py @@ -1644,7 +1644,7 @@ def inverse_laplace(ex, s, t, algorithm='maxima'): sage: inverse_laplace(1, s, t, algorithm='giac') dirac_delta(t) - TESTS:: + TESTS: Testing unevaluated expression from Maxima:: From e7d56d06f1a87290efddbbc68b2605d537cadc8a Mon Sep 17 00:00:00 2001 From: Vincent Delecroix <20100.delecroix@gmail.com> Date: Tue, 23 May 2017 08:27:50 +0200 Subject: [PATCH 451/452] 23050: documentation details --- src/sage/matrix/matrix0.pyx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/sage/matrix/matrix0.pyx b/src/sage/matrix/matrix0.pyx index f03eeafa1ee..b8dd44d1d0e 100644 --- a/src/sage/matrix/matrix0.pyx +++ b/src/sage/matrix/matrix0.pyx @@ -3285,7 +3285,7 @@ cdef class Matrix(sage.structure.element.Matrix): def reverse_rows_and_columns(self): r""" - Reverse the row order and column order of this matrix + Reverse the row order and column order of this matrix. This method transforms a matrix `m_{i,j}` with `0 \leq i < nrows` and `0 \leq j < ncols` into `m_{nrows - i - 1, ncols - j - 1}`. @@ -3337,7 +3337,8 @@ cdef class Matrix(sage.structure.element.Matrix): sage: m.reverse_rows_and_columns() Traceback (most recent call last): ... - ValueError: matrix is immutable; please change a copy instead (i.e., use copy(M) to change a copy of M). + ValueError: matrix is immutable; please change a copy + instead (i.e., use copy(M) to change a copy of M). """ self.check_mutability() self.clear_cache() From c011cfada9c95d0ded5057c8e88b1b1cfd9d7d31 Mon Sep 17 00:00:00 2001 From: Volker Braun Date: Wed, 24 May 2017 21:12:35 +0200 Subject: [PATCH 452/452] Updated SageMath version to 8.0.beta8 --- VERSION.txt | 2 +- build/pkgs/configure/checksums.ini | 6 +++--- build/pkgs/configure/package-version.txt | 2 +- src/bin/sage-banner | 2 +- src/bin/sage-version.sh | 4 ++-- src/sage/version.py | 4 ++-- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/VERSION.txt b/VERSION.txt index d2851eb5136..d2288b09f36 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -SageMath version 8.0.beta7, Release Date: 2017-05-18 +SageMath version 8.0.beta8, Release Date: 2017-05-24 diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index 256d9172868..df43fa28bbd 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,4 +1,4 @@ tarball=configure-VERSION.tar.gz -sha1=fd1997a745b82e595f14eb5132da91d44fa27c7d -md5=5fc8d437722460aef07ebb3e5fe92b48 -cksum=1742974928 +sha1=d19b80dca421a261fd1cf19be8c861aef46d403b +md5=5cfae5d5a32e87c9fff3215773b56dc8 +cksum=133013502 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index 7b473380d93..c200906efd2 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -221 +222 diff --git a/src/bin/sage-banner b/src/bin/sage-banner index 4843d4f39ee..8abb4ce9de3 100644 --- a/src/bin/sage-banner +++ b/src/bin/sage-banner @@ -1,5 +1,5 @@ ┌────────────────────────────────────────────────────────────────────┐ -│ SageMath version 8.0.beta7, Release Date: 2017-05-18 │ +│ SageMath version 8.0.beta8, Release Date: 2017-05-24 │ │ Type "notebook()" for the browser-based notebook interface. │ │ Type "help()" for help. │ └────────────────────────────────────────────────────────────────────┘ diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index 5a3d0a08d6e..f11eedfcf82 100644 --- a/src/bin/sage-version.sh +++ b/src/bin/sage-version.sh @@ -1,4 +1,4 @@ # Sage version information for shell scripts # This file is auto-generated by the sage-update-version script, do not edit! -SAGE_VERSION='8.0.beta7' -SAGE_RELEASE_DATE='2017-05-18' +SAGE_VERSION='8.0.beta8' +SAGE_RELEASE_DATE='2017-05-24' diff --git a/src/sage/version.py b/src/sage/version.py index 13aa5fd3c3b..58f993d5ce4 100644 --- a/src/sage/version.py +++ b/src/sage/version.py @@ -1,4 +1,4 @@ # Sage version information for Python scripts # This file is auto-generated by the sage-update-version script, do not edit! -version = '8.0.beta7' -date = '2017-05-18' +version = '8.0.beta8' +date = '2017-05-24'