diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000000..a279ad0bda2 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,10 @@ +# Documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + # Maintain dependencies for GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" diff --git a/.gitignore b/.gitignore index 2faf325a44c..cdb9c373c37 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,7 @@ /config.status /configure /conftest* +/confdefs.h /m4/sage_spkg_configures.m4 diff --git a/.zenodo.json b/.zenodo.json index 45c935970a7..91f308b7b75 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -1,10 +1,10 @@ { "description": "Mirror of the Sage https://sagemath.org/ source tree", "license": "other-open", - "title": "sagemath/sage: 10.0.beta1", - "version": "10.0.beta1", + "title": "sagemath/sage: 10.0.beta3", + "version": "10.0.beta3", "upload_type": "software", - "publication_date": "2023-02-19", + "publication_date": "2023-03-02", "creators": [ { "affiliation": "SageMath.org", @@ -15,7 +15,7 @@ "related_identifiers": [ { "scheme": "url", - "identifier": "https://github.com/sagemath/sage/tree/10.0.beta1", + "identifier": "https://github.com/sagemath/sage/tree/10.0.beta3", "relation": "isSupplementTo" }, { diff --git a/VERSION.txt b/VERSION.txt index 8b731a891fa..d3cf4ce44c4 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -SageMath version 10.0.beta1, Release Date: 2023-02-19 +SageMath version 10.0.beta3, Release Date: 2023-03-02 diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index 31e3b035d64..c08ada17ba4 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,4 +1,4 @@ tarball=configure-VERSION.tar.gz -sha1=0897c667d1327d2a51ea3d3bd1d9e1a3f5ca2606 -md5=a1f271e5ffcf558d054028839296a072 -cksum=437557471 +sha1=b9a6c30f4f1c828ca611527d104643d8c0b89ed9 +md5=37a7a99a528efa8a4eea1beff33985db +cksum=1112286999 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index 9462f03cbd2..82496e60715 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -08185d786047228caff879eba88a1f8148a49020 +a822a2132aa0e85069ec8b6efa48ad6db08cc044 diff --git a/build/pkgs/giac/checksums.ini b/build/pkgs/giac/checksums.ini index 2fb1d3fdf31..089c15f34b4 100644 --- a/build/pkgs/giac/checksums.ini +++ b/build/pkgs/giac/checksums.ini @@ -2,4 +2,3 @@ tarball=giac-VERSION.tar.bz2 sha1=78c15badd19b49b7d111ac204b611a4378ce3d15 md5=8fbd43a5c60848b6813b7fc8698a0199 cksum=1923149665 -upstream_url=https://trac.sagemath.org/raw-attachment/ticket/31563/giac-VERSION.tar.bz2 diff --git a/build/pkgs/iml/checksums.ini b/build/pkgs/iml/checksums.ini index d876ccb5b53..628d5461e70 100644 --- a/build/pkgs/iml/checksums.ini +++ b/build/pkgs/iml/checksums.ini @@ -2,4 +2,3 @@ tarball=iml-VERSION.tar.bz2 sha1=8aba468a62e6fb0584be9b014350b734663c0670 md5=a8083e70c0c4378f69eb772c1eeed6f0 cksum=2793221462 -upstream_url=https://trac.sagemath.org/raw-attachment/ticket/33195/iml-1.0.4p2.tar.bz2 diff --git a/build/pkgs/mathjax/checksums.ini b/build/pkgs/mathjax/checksums.ini index 76e362f6b28..6a6b233b2ae 100644 --- a/build/pkgs/mathjax/checksums.ini +++ b/build/pkgs/mathjax/checksums.ini @@ -2,4 +2,3 @@ tarball=mathjax-VERSION.tar.gz sha1=3f7abecf8cacd7f5d7f9ae6c3baca7739101c17d md5=ba1a65ab58aaad6c84f39735c619bc34 cksum=1142131398 -upstream_url=https://trac.sagemath.org/raw-attachment/ticket/25833/mathjax-3.2.0.tar.gz diff --git a/build/pkgs/msolve/checksums.ini b/build/pkgs/msolve/checksums.ini index 0b7558afd2b..e357a86bae4 100644 --- a/build/pkgs/msolve/checksums.ini +++ b/build/pkgs/msolve/checksums.ini @@ -2,4 +2,3 @@ tarball=msolve-VERSION.tar.gz sha1=5b227de8b222bfe8d143e1d7ea77ad71cd209dc8 md5=2f34bd9ccb089688ae169201281108dc cksum=941373315 -upstream_url=https://trac.sagemath.org/raw-attachment/ticket/31664/msolve-VERSION.tar.gz diff --git a/build/pkgs/sage_conf/install-requires.txt b/build/pkgs/sage_conf/install-requires.txt index 87a8f39f3f0..c1acbf5a6b3 100644 --- a/build/pkgs/sage_conf/install-requires.txt +++ b/build/pkgs/sage_conf/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-conf ~= 10.0b1 +sage-conf ~= 10.0b3 diff --git a/build/pkgs/sage_docbuild/install-requires.txt b/build/pkgs/sage_docbuild/install-requires.txt index dc1652133a1..4c0503af358 100644 --- a/build/pkgs/sage_docbuild/install-requires.txt +++ b/build/pkgs/sage_docbuild/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-docbuild ~= 10.0b1 +sage-docbuild ~= 10.0b3 diff --git a/build/pkgs/sage_setup/install-requires.txt b/build/pkgs/sage_setup/install-requires.txt index f418d8648ec..be67a744301 100644 --- a/build/pkgs/sage_setup/install-requires.txt +++ b/build/pkgs/sage_setup/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-setup ~= 10.0b1 +sage-setup ~= 10.0b3 diff --git a/build/pkgs/sage_sws2rst/install-requires.txt b/build/pkgs/sage_sws2rst/install-requires.txt index d62c0ef4662..b30f48ea38a 100644 --- a/build/pkgs/sage_sws2rst/install-requires.txt +++ b/build/pkgs/sage_sws2rst/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-sws2rst ~= 10.0b1 +sage-sws2rst ~= 10.0b3 diff --git a/build/pkgs/sagelib/install-requires.txt b/build/pkgs/sagelib/install-requires.txt index c231384faae..70aefd13369 100644 --- a/build/pkgs/sagelib/install-requires.txt +++ b/build/pkgs/sagelib/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagelib ~= 10.0b1 +sagelib ~= 10.0b3 diff --git a/build/pkgs/sagemath_categories/install-requires.txt b/build/pkgs/sagemath_categories/install-requires.txt index 1ddff9fc8f8..31553eaef51 100644 --- a/build/pkgs/sagemath_categories/install-requires.txt +++ b/build/pkgs/sagemath_categories/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-categories ~= 10.0b1 +sagemath-categories ~= 10.0b3 diff --git a/build/pkgs/sagemath_environment/install-requires.txt b/build/pkgs/sagemath_environment/install-requires.txt index 760c1dcf2e9..bcd541eea0b 100644 --- a/build/pkgs/sagemath_environment/install-requires.txt +++ b/build/pkgs/sagemath_environment/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-environment ~= 10.0b1 +sagemath-environment ~= 10.0b3 diff --git a/build/pkgs/sagemath_objects/install-requires.txt b/build/pkgs/sagemath_objects/install-requires.txt index 51e5c5a346d..1da2fc997e0 100644 --- a/build/pkgs/sagemath_objects/install-requires.txt +++ b/build/pkgs/sagemath_objects/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-objects ~= 10.0b1 +sagemath-objects ~= 10.0b3 diff --git a/build/pkgs/sagemath_repl/install-requires.txt b/build/pkgs/sagemath_repl/install-requires.txt index ca64cd6b39f..798c25aee10 100644 --- a/build/pkgs/sagemath_repl/install-requires.txt +++ b/build/pkgs/sagemath_repl/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-repl ~= 10.0b1 +sagemath-repl ~= 10.0b3 diff --git a/pkgs/sage-conf/VERSION.txt b/pkgs/sage-conf/VERSION.txt index 4ab501a9912..b3001ec9281 100644 --- a/pkgs/sage-conf/VERSION.txt +++ b/pkgs/sage-conf/VERSION.txt @@ -1 +1 @@ -10.0.beta1 +10.0.beta3 diff --git a/pkgs/sage-conf_pypi/VERSION.txt b/pkgs/sage-conf_pypi/VERSION.txt index 4ab501a9912..b3001ec9281 100644 --- a/pkgs/sage-conf_pypi/VERSION.txt +++ b/pkgs/sage-conf_pypi/VERSION.txt @@ -1 +1 @@ -10.0.beta1 +10.0.beta3 diff --git a/pkgs/sage-docbuild/VERSION.txt b/pkgs/sage-docbuild/VERSION.txt index 4ab501a9912..b3001ec9281 100644 --- a/pkgs/sage-docbuild/VERSION.txt +++ b/pkgs/sage-docbuild/VERSION.txt @@ -1 +1 @@ -10.0.beta1 +10.0.beta3 diff --git a/pkgs/sage-setup/VERSION.txt b/pkgs/sage-setup/VERSION.txt index 4ab501a9912..b3001ec9281 100644 --- a/pkgs/sage-setup/VERSION.txt +++ b/pkgs/sage-setup/VERSION.txt @@ -1 +1 @@ -10.0.beta1 +10.0.beta3 diff --git a/pkgs/sage-sws2rst/VERSION.txt b/pkgs/sage-sws2rst/VERSION.txt index 4ab501a9912..b3001ec9281 100644 --- a/pkgs/sage-sws2rst/VERSION.txt +++ b/pkgs/sage-sws2rst/VERSION.txt @@ -1 +1 @@ -10.0.beta1 +10.0.beta3 diff --git a/pkgs/sagemath-categories/VERSION.txt b/pkgs/sagemath-categories/VERSION.txt index 4ab501a9912..b3001ec9281 100644 --- a/pkgs/sagemath-categories/VERSION.txt +++ b/pkgs/sagemath-categories/VERSION.txt @@ -1 +1 @@ -10.0.beta1 +10.0.beta3 diff --git a/pkgs/sagemath-environment/VERSION.txt b/pkgs/sagemath-environment/VERSION.txt index 4ab501a9912..b3001ec9281 100644 --- a/pkgs/sagemath-environment/VERSION.txt +++ b/pkgs/sagemath-environment/VERSION.txt @@ -1 +1 @@ -10.0.beta1 +10.0.beta3 diff --git a/pkgs/sagemath-objects/VERSION.txt b/pkgs/sagemath-objects/VERSION.txt index 4ab501a9912..b3001ec9281 100644 --- a/pkgs/sagemath-objects/VERSION.txt +++ b/pkgs/sagemath-objects/VERSION.txt @@ -1 +1 @@ -10.0.beta1 +10.0.beta3 diff --git a/pkgs/sagemath-repl/VERSION.txt b/pkgs/sagemath-repl/VERSION.txt index 4ab501a9912..b3001ec9281 100644 --- a/pkgs/sagemath-repl/VERSION.txt +++ b/pkgs/sagemath-repl/VERSION.txt @@ -1 +1 @@ -10.0.beta1 +10.0.beta3 diff --git a/src/VERSION.txt b/src/VERSION.txt index 4ab501a9912..b3001ec9281 100644 --- a/src/VERSION.txt +++ b/src/VERSION.txt @@ -1 +1 @@ -10.0.beta1 +10.0.beta3 diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index d8c6b161134..9aab0c0fcc8 100644 --- a/src/bin/sage-version.sh +++ b/src/bin/sage-version.sh @@ -4,6 +4,6 @@ # which stops "setup.py develop" from rewriting it as a Python file. : # This file is auto-generated by the sage-update-version script, do not edit! -SAGE_VERSION='10.0.beta1' -SAGE_RELEASE_DATE='2023-02-19' -SAGE_VERSION_BANNER='SageMath version 10.0.beta1, Release Date: 2023-02-19' +SAGE_VERSION='10.0.beta3' +SAGE_RELEASE_DATE='2023-03-02' +SAGE_VERSION_BANNER='SageMath version 10.0.beta3, Release Date: 2023-03-02' diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 7bef2a9a4e5..04164b1b0b1 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -624,7 +624,7 @@ REFERENCES: and variants*. :arxiv:`1810.00789` -.. [BDKR2013] \D. Best, D.Z. Dokovic, H. Kharaghani and H. Ramp. +.. [BDKR2013] \D. Best, D.Ž. Đoković, H. Kharaghani and H. Ramp. *Turyn-Type Sequences: Classification, Enumeration, and Construction*, Journal of Combinatorial Designs 21(1) (2013): 24-35. :doi:`10.1002/jcd.21318` @@ -803,6 +803,10 @@ REFERENCES: Stein. strassen_window_multiply_c. strassen.pyx, Sage 3.0, 2008. http://www.sagemath.org +.. [BrHu2019] Petter Brändén, June Huh. *Lorentzian polynomials*. + Ann. Math. (2) 192, No. 3, 821-891 (2020). + :arxiv:`1902.03719`, :doi:`10.4007/annals.2020.192.3.4`. + .. [BHNR2004] \S. Brlek, S. Hamel, M. Nivat, C. Reutenauer, On the Palindromic Complexity of Infinite Words, in J. Berstel, J. Karhumaki, D. Perrin, Eds, @@ -1216,6 +1220,11 @@ REFERENCES: Proc. London Math. Soc. (3) **77** (1998), 551–581. :mathscinet:`MR1643413` +.. [BS1969] \D. Blatt, G. Szekeres. + *A Skew Hadamard Matrix of Order 52*, + Canadian Journal of Mathematics 21 (1969): 1319-1322. + :doi:`10.4153/CJM-1969-144-2` + .. [BS1996] Eric Bach, Jeffrey Shallit. *Algorithmic Number Theory, Vol. 1: Efficient Algorithms*. MIT Press, 1996. ISBN 978-0262024051. @@ -1794,6 +1803,11 @@ REFERENCES: *Tracking p-adic precision*, LMS J. Comput. Math. **17** (2014), 274-294. +.. [Connell1999] Ian Connell. + *Elliptic Curve Handbook*. + Online lecture notes, available at + https://git.hackade.org/ben/tinycrypt/raw/branch/master/docs/Elliptic%20Curve%20Handbook.pdf + .. [CS1986] \J. Conway and N. Sloane. *Lexicographic codes: error-correcting codes from game theory*, IEEE Trans. Infor. Theory **32** (1986) 337-348. @@ -2041,15 +2055,40 @@ REFERENCES: and some constructions of de Luca and Rauzy*, Theoret. Comput. Sci. 255 (2001) 539--553. -.. [Djo1992] \D. Đoković. +.. [Djo1992a] \D. Đoković. *Construction of some new Hadamard matrices*, Bulletin of the Australian Mathematical Society 45(2) (1992): 327-332. :doi:`10.1017/S0004972700030185` +.. [Djo1992b] \D. Đoković. + *Skew Hadamard matrices of order 4 x 37 and 4 x 43*, + Journal of Combinatorial Theory, Series A 61(2) (1992): 319-321. + :doi:`10.1016/0097-3165(92)90029-T` + +.. [Djo1992c] \D. Đoković. + *Ten New Orders for Hadamard Matrices of Skew Type*, + Publikacije Elektrotehničkog fakulteta. Serija Matematika 2 (1992): 47-59. + .. [Djo1994] \D. Đoković. *Five New Orders for Hadamard Matrices of Skew Type*, Australasian Journal of Combinatorics 10 (1994): 259-264. +.. [Djo2008a] \D. Đoković. + *Skew-Hadamard matrices of orders 188 and 388 exist*, + International Mathematical Forum 3 no.22 (2008): 1063-1068. + :arxiv:`0704.0640` + +.. [Djo2008b] \D. Đoković. + *Skew-Hadamard matrices of orders 436, 580 and 988 exist*, + Journal of Combinatorial Designs 16 (2008): 493-498. + :arxiv:`0706.1973` + +.. [Djo2023a] \D. Đoković. + *Skew-Hadamard matrices of order 276*. + :arxiv:`10.48550/ARXIV.2301.02751` + +.. [Djo2023b] \D. Đoković, Email Communication. 26 January 2023. + .. [DK2013] John R. Doyle and David Krumm, *Computing algebraic numbers of bounded height*, :arxiv:`1111.4963v4` (2013). @@ -2397,6 +2436,11 @@ REFERENCES: code, by I.A.Faradjev (with contributions by A.E.Brouwer, D.V.Pasechnik). https://github.com/dimpase/coco +.. [FKS2004] \R. J. Fletcher, C. Koukouvinos and J. Seberry. + *New skew-Hadamard matrices of order 4·59 and new D-optimal designs of order 2·59*, + Discrete Mathematics 286(3) (2004): 251-253. + :doi:`10.1016/j.disc.2004.05.009` + .. [FL2001] David Forge and Michel Las Vergnas. *Orlik-Solomon type algebras*. European J. Combin. **22** (5), (2001). pp. 699-704. @@ -3207,6 +3251,11 @@ REFERENCES: Designs, Codes and Cryptography 8 (1996) 145-157. :doi:`10.1023/A:1018037025910`. +.. [HMMS2019] June Huh, Jacob P. Matherne, Karola Mészáros, Avery St. Dizier. + *Logarithmic concavity of Schur and related polynomials*. + Trans. Am. Math. Soc. 375, No. 6, 4411-4427 (2022). + :arxiv:`1906.09633`, :doi:`10.1090/tran/8606`. + .. [Hutz2007] \B. Hutz. Arithmetic Dynamics on Varieties of dimension greater than one. PhD Thesis, Brown University 2007 @@ -5493,6 +5542,11 @@ REFERENCES: :doi:`10.1007/978-1-4684-9322-1`, ISBN 978-1-4684-9322-1. +.. [Spe1977] \E. Spence. + *Skew-Hadamard matrices of order 2(q + 1)*, + Discrete Mathematics 18(1) (1977): 79-85. + :doi:`10.1016/0012-365X(77)90009-7` + .. [Spe2013] \D. Speyer, *An infinitely generated upper cluster algebra*, :arxiv:`1305.6867`. @@ -5842,6 +5896,10 @@ REFERENCES: Hall-Littlewood vertex operators and generalized Kostka polynomials. Adv. Math. 158 (2001), no. 1, 66-85. +.. [Sze1988] \G. Szekeres. + *A note on skew type orthogonal ±1 matrices*, + Combinatorics, Colloquia Mathematica Societatis, Janos Bolyai, 52 (1988): 489-498. + .. _ref-T: **T** @@ -6122,6 +6180,11 @@ REFERENCES: pages 150--168, 1932, `available on JSTOR `_ +.. [Whi1971] \A. Whiteman. + *An infinite family of skew Hadamard matrices*, + Pacific Journal of Mathematics 38(3) (1971): 817-822. + :doi:`10.2140/pjm.1971.38.817` + .. [White2015] Noah White. *The monodromy of real Bethe vectors for the Gaudin model*. J. Combin. Algebra, **2** no. 3 (2018). pp. 259-300. diff --git a/src/sage/arith/long.pxd b/src/sage/arith/long.pxd index 4addc8cfc89..eda9d8c1f48 100644 --- a/src/sage/arith/long.pxd +++ b/src/sage/arith/long.pxd @@ -1,3 +1,4 @@ +# sage.doctest: optional - sage.misc.cython r""" Fast conversion of Python objects to C long """ @@ -113,7 +114,7 @@ cdef inline bint integer_check_long(x, long* value, int* err) except -1: We create a pure Python wrapper of this function:: - sage: cython(''' # optional - sage.misc.cython + sage: cython(''' ....: from sage.arith.long cimport * ....: from sage.rings.integer cimport smallInteger ....: def check_long(x): @@ -246,7 +247,7 @@ cdef inline bint integer_check_long_py(x, long* value, int* err): We create a pure Python wrapper of this function:: - sage: cython(''' # optional - sage.misc.cython + sage: cython(''' ....: from sage.arith.long cimport * ....: def check_long_py(x): ....: cdef long value @@ -270,6 +271,17 @@ cdef inline bint integer_check_long_py(x, long* value, int* err): sage: L += [-x for x in L] + [0, long_min()] sage: for v in L: ....: assert check_long_py(int(v)) == v + sage: check_long_py(int(2^60)) + 1152921504606846976 # 64-bit + 'Overflow (...)' # 32-bit + sage: check_long_py(int(2^61)) + 2305843009213693952 # 64-bit + 'Overflow (...)' # 32-bit + sage: check_long_py(int(2^62)) + 4611686018427387904 # 64-bit + 'Overflow (...)' # 32-bit + sage: check_long_py(int(2^63)) + 'Overflow (...)' sage: check_long_py(int(2^100)) 'Overflow (...)' sage: check_long_py(int(long_max() + 1)) @@ -309,7 +321,12 @@ cdef inline bint integer_check_long_py(x, long* value, int* err): cdef long lead cdef long lead_2_overflow = (1) << (BITS_IN_LONG - PyLong_SHIFT) - cdef long lead_3_overflow = (1) << (BITS_IN_LONG - 2 * PyLong_SHIFT) + cdef long lead_3_overflow + if BITS_IN_LONG < 2 * PyLong_SHIFT: + # in this case 3 digit is always overflow + lead_3_overflow = 0 + else: + lead_3_overflow = (1) << (BITS_IN_LONG - 2 * PyLong_SHIFT) if size == 0: value[0] = 0 err[0] = 0 @@ -371,7 +388,7 @@ cdef inline bint is_small_python_int(obj): EXAMPLES:: - sage: cython(''' # optional - sage.misc.cython + sage: cython(''' ....: from sage.arith.long cimport is_small_python_int ....: def is_small_wrapper(x): ....: return is_small_python_int(x) diff --git a/src/sage/categories/bialgebras.py b/src/sage/categories/bialgebras.py index e70914295af..441d924c964 100644 --- a/src/sage/categories/bialgebras.py +++ b/src/sage/categories/bialgebras.py @@ -10,7 +10,8 @@ # ***************************************************************************** from sage.categories.category_types import Category_over_base_ring -from sage.categories.all import Algebras, Coalgebras +from sage.categories.algebras import Algebras +from sage.categories.coalgebras import Coalgebras from sage.categories.super_modules import SuperModulesCategory from sage.misc.lazy_import import LazyImport diff --git a/src/sage/categories/category.py b/src/sage/categories/category.py index f70455cf1a0..0db7aa21a65 100644 --- a/src/sage/categories/category.py +++ b/src/sage/categories/category.py @@ -153,7 +153,7 @@ class Category(UniqueRepresentation, SageObject): This is achieved as follows:: - sage: from sage.categories.all import Category + sage: from sage.categories.category import Category sage: class EuclideanDomains(Category): ....: # operations on the category itself ....: def super_categories(self): @@ -201,7 +201,7 @@ class inheritance from ``C.parent_class``. :: - sage: from sage.categories.all import Category + sage: from sage.categories.category import Category sage: from sage.misc.lazy_attribute import lazy_attribute sage: class As (Category): ....: def super_categories(self): diff --git a/src/sage/categories/chain_complexes.py b/src/sage/categories/chain_complexes.py index 531fc48e4cd..b1d8c578e60 100644 --- a/src/sage/categories/chain_complexes.py +++ b/src/sage/categories/chain_complexes.py @@ -46,7 +46,9 @@ def super_categories(self): [Category of modules over Ring of integers modulo 9] """ - from sage.categories.all import Fields, Modules, VectorSpaces + from sage.categories.fields import Fields + from sage.categories.modules import Modules + from sage.categories.vector_spaces import VectorSpaces base_ring = self.base_ring() if base_ring in Fields(): return [VectorSpaces(base_ring)] diff --git a/src/sage/categories/coalgebras.py b/src/sage/categories/coalgebras.py index 22a385d5f0d..3a7f8c6213a 100644 --- a/src/sage/categories/coalgebras.py +++ b/src/sage/categories/coalgebras.py @@ -10,7 +10,7 @@ # ***************************************************************************** from .category_types import Category_over_base_ring -from sage.categories.all import Modules +from sage.categories.modules import Modules from sage.categories.category_with_axiom import CategoryWithAxiom_over_base_ring from sage.categories.tensor import TensorProductsCategory from sage.categories.dual import DualObjectsCategory diff --git a/src/sage/categories/coalgebras_with_basis.py b/src/sage/categories/coalgebras_with_basis.py index b672c37dd27..5518804d649 100644 --- a/src/sage/categories/coalgebras_with_basis.py +++ b/src/sage/categories/coalgebras_with_basis.py @@ -13,7 +13,9 @@ from sage.misc.lazy_attribute import lazy_attribute from sage.misc.lazy_import import LazyImport from sage.categories.category_with_axiom import CategoryWithAxiom_over_base_ring -from sage.categories.all import ModulesWithBasis, tensor, Hom +from sage.categories.modules_with_basis import ModulesWithBasis +from sage.categories.tensor import tensor +from sage.categories.homset import Hom from sage.categories.super_modules import SuperModulesCategory from sage.categories.filtered_modules import FilteredModulesCategory diff --git a/src/sage/categories/examples/algebras_with_basis.py b/src/sage/categories/examples/algebras_with_basis.py index 7ad85cb82ed..f1d05839e2a 100644 --- a/src/sage/categories/examples/algebras_with_basis.py +++ b/src/sage/categories/examples/algebras_with_basis.py @@ -10,7 +10,7 @@ from sage.misc.cachefunc import cached_method from sage.sets.family import Family -from sage.categories.all import AlgebrasWithBasis +from sage.categories.algebras_with_basis import AlgebrasWithBasis from sage.combinat.free_module import CombinatorialFreeModule from sage.combinat.words.words import Words diff --git a/src/sage/categories/examples/commutative_additive_monoids.py b/src/sage/categories/examples/commutative_additive_monoids.py index 945826c22a5..7422604e8e9 100644 --- a/src/sage/categories/examples/commutative_additive_monoids.py +++ b/src/sage/categories/examples/commutative_additive_monoids.py @@ -10,7 +10,7 @@ from sage.misc.cachefunc import cached_method from sage.structure.parent import Parent -from sage.categories.all import CommutativeAdditiveMonoids +from sage.categories.commutative_additive_monoids import CommutativeAdditiveMonoids from .commutative_additive_semigroups import FreeCommutativeAdditiveSemigroup class FreeCommutativeAdditiveMonoid(FreeCommutativeAdditiveSemigroup): diff --git a/src/sage/categories/examples/commutative_additive_semigroups.py b/src/sage/categories/examples/commutative_additive_semigroups.py index ea2fde99bb4..fdda759869a 100644 --- a/src/sage/categories/examples/commutative_additive_semigroups.py +++ b/src/sage/categories/examples/commutative_additive_semigroups.py @@ -12,7 +12,7 @@ from sage.structure.parent import Parent from sage.structure.element_wrapper import ElementWrapper from sage.structure.unique_representation import UniqueRepresentation -from sage.categories.all import CommutativeAdditiveSemigroups +from sage.categories.commutative_additive_semigroups import CommutativeAdditiveSemigroups from sage.sets.family import Family class FreeCommutativeAdditiveSemigroup(UniqueRepresentation, Parent): diff --git a/src/sage/categories/examples/finite_coxeter_groups.py b/src/sage/categories/examples/finite_coxeter_groups.py index 71ca54c8a5b..c7937688ef8 100644 --- a/src/sage/categories/examples/finite_coxeter_groups.py +++ b/src/sage/categories/examples/finite_coxeter_groups.py @@ -11,7 +11,7 @@ from sage.misc.cachefunc import cached_method from sage.structure.parent import Parent from sage.structure.element_wrapper import ElementWrapper -from sage.categories.all import FiniteCoxeterGroups +from sage.categories.finite_coxeter_groups import FiniteCoxeterGroups from sage.structure.unique_representation import UniqueRepresentation from sage.misc.functional import is_odd, is_even from sage.combinat.root_system.coxeter_matrix import CoxeterMatrix diff --git a/src/sage/categories/examples/finite_dimensional_algebras_with_basis.py b/src/sage/categories/examples/finite_dimensional_algebras_with_basis.py index a3721f106b7..f51b66c49dd 100644 --- a/src/sage/categories/examples/finite_dimensional_algebras_with_basis.py +++ b/src/sage/categories/examples/finite_dimensional_algebras_with_basis.py @@ -9,7 +9,7 @@ #***************************************************************************** from sage.misc.cachefunc import cached_method -from sage.categories.all import FiniteDimensionalAlgebrasWithBasis +from sage.categories.finite_dimensional_algebras_with_basis import FiniteDimensionalAlgebrasWithBasis from sage.combinat.free_module import CombinatorialFreeModule diff --git a/src/sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py b/src/sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py index 306e0091e12..a975d902e14 100644 --- a/src/sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py +++ b/src/sage/categories/examples/finite_dimensional_lie_algebras_with_basis.py @@ -10,7 +10,7 @@ from sage.misc.cachefunc import cached_method from sage.sets.family import Family -from sage.categories.all import LieAlgebras +from sage.categories.lie_algebras import LieAlgebras from sage.modules.free_module import FreeModule from sage.structure.parent import Parent from sage.structure.unique_representation import UniqueRepresentation diff --git a/src/sage/categories/examples/finite_monoids.py b/src/sage/categories/examples/finite_monoids.py index f61c28a4032..4d3e8fa7029 100644 --- a/src/sage/categories/examples/finite_monoids.py +++ b/src/sage/categories/examples/finite_monoids.py @@ -13,7 +13,7 @@ from sage.structure.parent import Parent from sage.structure.unique_representation import UniqueRepresentation from sage.structure.element_wrapper import ElementWrapper -from sage.categories.all import Monoids +from sage.categories.monoids import Monoids from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ diff --git a/src/sage/categories/examples/finite_weyl_groups.py b/src/sage/categories/examples/finite_weyl_groups.py index a17a48c142e..535d5101101 100644 --- a/src/sage/categories/examples/finite_weyl_groups.py +++ b/src/sage/categories/examples/finite_weyl_groups.py @@ -11,7 +11,7 @@ from sage.misc.cachefunc import cached_method from sage.structure.parent import Parent from sage.structure.element_wrapper import ElementWrapper -from sage.categories.all import FiniteWeylGroups +from sage.categories.finite_weyl_groups import FiniteWeylGroups from sage.structure.unique_representation import UniqueRepresentation class SymmetricGroup(UniqueRepresentation, Parent): diff --git a/src/sage/categories/examples/hopf_algebras_with_basis.py b/src/sage/categories/examples/hopf_algebras_with_basis.py index 16bd866c9c6..35b61f3c085 100644 --- a/src/sage/categories/examples/hopf_algebras_with_basis.py +++ b/src/sage/categories/examples/hopf_algebras_with_basis.py @@ -10,9 +10,9 @@ from sage.misc.cachefunc import cached_method from sage.sets.family import Family -from sage.categories.all import HopfAlgebrasWithBasis +from sage.categories.hopf_algebras_with_basis import HopfAlgebrasWithBasis from sage.combinat.free_module import CombinatorialFreeModule -from sage.categories.all import tensor +from sage.categories.tensor import tensor class MyGroupAlgebra(CombinatorialFreeModule): r""" diff --git a/src/sage/categories/examples/lie_algebras.py b/src/sage/categories/examples/lie_algebras.py index 3eafe0787f3..135a665cfa3 100644 --- a/src/sage/categories/examples/lie_algebras.py +++ b/src/sage/categories/examples/lie_algebras.py @@ -10,7 +10,7 @@ #from sage.misc.cachefunc import cached_method from sage.sets.family import Family -from sage.categories.all import LieAlgebras +from sage.categories.lie_algebras import LieAlgebras from sage.structure.parent import Parent from sage.structure.unique_representation import UniqueRepresentation from sage.structure.element_wrapper import ElementWrapper diff --git a/src/sage/categories/examples/magmas.py b/src/sage/categories/examples/magmas.py index 5139041cef0..a4858bc2606 100644 --- a/src/sage/categories/examples/magmas.py +++ b/src/sage/categories/examples/magmas.py @@ -15,7 +15,7 @@ from sage.structure.parent import Parent from sage.structure.unique_representation import UniqueRepresentation from sage.structure.element_wrapper import ElementWrapper -from sage.categories.all import Magmas +from sage.categories.magmas import Magmas from sage.sets.family import Family diff --git a/src/sage/categories/examples/monoids.py b/src/sage/categories/examples/monoids.py index c2919a8cc28..7336c680bdf 100644 --- a/src/sage/categories/examples/monoids.py +++ b/src/sage/categories/examples/monoids.py @@ -11,7 +11,7 @@ from sage.misc.cachefunc import cached_method from sage.structure.parent import Parent from sage.structure.element_wrapper import ElementWrapper -from sage.categories.all import Monoids +from sage.categories.monoids import Monoids from .semigroups import FreeSemigroup from sage.sets.family import Family diff --git a/src/sage/categories/examples/posets.py b/src/sage/categories/examples/posets.py index 5041df19835..20f461860c9 100644 --- a/src/sage/categories/examples/posets.py +++ b/src/sage/categories/examples/posets.py @@ -10,7 +10,7 @@ from sage.structure.parent import Parent from sage.structure.unique_representation import UniqueRepresentation -from sage.categories.all import Posets +from sage.categories.posets import Posets from sage.structure.element_wrapper import ElementWrapper from sage.sets.set import Set, Set_object_enumerated from sage.sets.positive_integers import PositiveIntegers diff --git a/src/sage/categories/examples/semigroups.py b/src/sage/categories/examples/semigroups.py index 4c4d9a1f4df..5502215ef8a 100644 --- a/src/sage/categories/examples/semigroups.py +++ b/src/sage/categories/examples/semigroups.py @@ -12,7 +12,7 @@ from sage.structure.parent import Parent from sage.structure.unique_representation import UniqueRepresentation from sage.structure.element_wrapper import ElementWrapper -from sage.categories.all import Semigroups +from sage.categories.semigroups import Semigroups from sage.sets.family import Family class LeftZeroSemigroup(UniqueRepresentation, Parent): diff --git a/src/sage/categories/examples/semigroups_cython.pyx b/src/sage/categories/examples/semigroups_cython.pyx index ee7a03ddc82..b456c2868f8 100644 --- a/src/sage/categories/examples/semigroups_cython.pyx +++ b/src/sage/categories/examples/semigroups_cython.pyx @@ -4,7 +4,8 @@ Examples of semigroups in cython from sage.structure.parent cimport Parent from sage.structure.element cimport Element -from sage.categories.all import Category, Semigroups +from sage.categories.category import Category +from sage.categories.semigroups import Semigroups from sage.categories.examples.semigroups import LeftZeroSemigroup as LeftZeroSemigroupPython from cpython.object cimport PyObject_RichCompare diff --git a/src/sage/categories/examples/sets_cat.py b/src/sage/categories/examples/sets_cat.py index 93cc264580d..c4df13b1357 100644 --- a/src/sage/categories/examples/sets_cat.py +++ b/src/sage/categories/examples/sets_cat.py @@ -13,7 +13,7 @@ from sage.categories.sets_cat import Sets from sage.rings.integer import Integer, IntegerWrapper from sage.rings.integer_ring import IntegerRing -from sage.arith.all import is_prime +from sage.arith.misc import is_prime from sage.structure.unique_representation import UniqueRepresentation diff --git a/src/sage/categories/examples/with_realizations.py b/src/sage/categories/examples/with_realizations.py index 06e060f8925..2b75946b1d2 100644 --- a/src/sage/categories/examples/with_realizations.py +++ b/src/sage/categories/examples/with_realizations.py @@ -10,7 +10,9 @@ from sage.misc.cachefunc import cached_method from sage.misc.bindable_class import BindableClass -from sage.categories.all import Rings, Algebras, AlgebrasWithBasis +from sage.categories.rings import Rings +from sage.categories.algebras import Algebras +from sage.categories.algebras_with_basis import AlgebrasWithBasis from sage.categories.realizations import Category_realization_of_parent from sage.structure.unique_representation import UniqueRepresentation from sage.structure.parent import Parent diff --git a/src/sage/categories/finite_complex_reflection_groups.py b/src/sage/categories/finite_complex_reflection_groups.py index 9c91c2af549..f1897267140 100644 --- a/src/sage/categories/finite_complex_reflection_groups.py +++ b/src/sage/categories/finite_complex_reflection_groups.py @@ -523,7 +523,7 @@ def base_change_matrix(self): [ 1 0] [E(4) 1] """ - from sage.matrix.all import Matrix + from sage.matrix.constructor import Matrix return Matrix(list(self.independent_roots())).inverse() class ElementMethods: @@ -1187,7 +1187,7 @@ def rational_catalan_number(self, p, polynomial=False): sage: W.rational_catalan_number(3, polynomial=True) q^6 + q^4 + q^3 + q^2 + 1 """ - from sage.arith.all import gcd + from sage.arith.misc import GCD as gcd from sage.combinat.q_analogues import q_int h = self.coxeter_number() diff --git a/src/sage/categories/finite_dimensional_bialgebras_with_basis.py b/src/sage/categories/finite_dimensional_bialgebras_with_basis.py index 086892237e6..02f1005e0de 100644 --- a/src/sage/categories/finite_dimensional_bialgebras_with_basis.py +++ b/src/sage/categories/finite_dimensional_bialgebras_with_basis.py @@ -27,5 +27,5 @@ def FiniteDimensionalBialgebrasWithBasis(base_ring): sage: TestSuite(C).run() """ - from sage.categories.all import BialgebrasWithBasis + from sage.categories.bialgebras_with_basis import BialgebrasWithBasis return BialgebrasWithBasis(base_ring).FiniteDimensional() diff --git a/src/sage/categories/finite_dimensional_coalgebras_with_basis.py b/src/sage/categories/finite_dimensional_coalgebras_with_basis.py index 9d1eecf556d..60b135080da 100644 --- a/src/sage/categories/finite_dimensional_coalgebras_with_basis.py +++ b/src/sage/categories/finite_dimensional_coalgebras_with_basis.py @@ -27,5 +27,5 @@ def FiniteDimensionalCoalgebrasWithBasis(base_ring): sage: TestSuite(C).run() """ - from sage.categories.all import CoalgebrasWithBasis + from sage.categories.coalgebras_with_basis import CoalgebrasWithBasis return CoalgebrasWithBasis(base_ring).FiniteDimensional() diff --git a/src/sage/categories/graded_bialgebras.py b/src/sage/categories/graded_bialgebras.py index 6c751db558b..eff325b320e 100644 --- a/src/sage/categories/graded_bialgebras.py +++ b/src/sage/categories/graded_bialgebras.py @@ -26,5 +26,5 @@ def GradedBialgebras(base_ring): sage: TestSuite(C).run() """ - from sage.categories.all import Bialgebras + from sage.categories.bialgebras import Bialgebras return Bialgebras(base_ring).Graded() diff --git a/src/sage/categories/graded_bialgebras_with_basis.py b/src/sage/categories/graded_bialgebras_with_basis.py index 326e32b735d..d1727c0f40c 100644 --- a/src/sage/categories/graded_bialgebras_with_basis.py +++ b/src/sage/categories/graded_bialgebras_with_basis.py @@ -26,5 +26,5 @@ def GradedBialgebrasWithBasis(base_ring): sage: TestSuite(C).run() """ - from sage.categories.all import BialgebrasWithBasis + from sage.categories.bialgebras_with_basis import BialgebrasWithBasis return BialgebrasWithBasis(base_ring).Graded() diff --git a/src/sage/categories/graded_hopf_algebras.py b/src/sage/categories/graded_hopf_algebras.py index ad350212725..c4d5a24e3fe 100644 --- a/src/sage/categories/graded_hopf_algebras.py +++ b/src/sage/categories/graded_hopf_algebras.py @@ -35,5 +35,5 @@ def GradedHopfAlgebras(base_ring): :class:`super Hopf algebras `. """ - from sage.categories.all import HopfAlgebras + from sage.categories.hopf_algebras import HopfAlgebras return HopfAlgebras(base_ring).Graded() diff --git a/src/sage/categories/map.pyx b/src/sage/categories/map.pyx index a569cc83849..5b3a00a2328 100644 --- a/src/sage/categories/map.pyx +++ b/src/sage/categories/map.pyx @@ -1331,7 +1331,7 @@ cdef class Section(Map): To: Multivariate Polynomial Ring in x, y over Rational Field """ from sage.categories.homset import Hom - from sage.categories.all import SetsWithPartialMaps + from sage.categories.sets_with_partial_maps import SetsWithPartialMaps Map.__init__(self, Hom(map.codomain(), map.domain(), SetsWithPartialMaps())) self._inverse = map # TODO: Use this attribute somewhere! diff --git a/src/sage/categories/monoid_algebras.py b/src/sage/categories/monoid_algebras.py index f51a8d01ce1..a387d7f74f4 100644 --- a/src/sage/categories/monoid_algebras.py +++ b/src/sage/categories/monoid_algebras.py @@ -33,5 +33,5 @@ def MonoidAlgebras(base_ring): sage: TestSuite(MonoidAlgebras(ZZ)).run() """ - from sage.categories.all import Monoids + from sage.categories.monoids import Monoids return Monoids().Algebras(base_ring) diff --git a/src/sage/categories/schemes.py b/src/sage/categories/schemes.py index df2ec0603cf..aad5a48b7e9 100644 --- a/src/sage/categories/schemes.py +++ b/src/sage/categories/schemes.py @@ -140,7 +140,7 @@ def _call_(self, x): from sage.categories.commutative_rings import CommutativeRings from sage.schemes.generic.spec import Spec from sage.categories.map import Map - from sage.categories.all import Rings + from sage.categories.rings import Rings if x in CommutativeRings(): return Spec(x) elif isinstance(x, Map) and x.category_for().is_subcategory(Rings()): diff --git a/src/sage/combinat/alternating_sign_matrix.py b/src/sage/combinat/alternating_sign_matrix.py index fba8f842fc8..921320fe22e 100644 --- a/src/sage/combinat/alternating_sign_matrix.py +++ b/src/sage/combinat/alternating_sign_matrix.py @@ -1197,7 +1197,7 @@ def _element_constructor_(self, asm, check=True): if isinstance(asm, AlternatingSignMatrix): if asm.parent() is self: return asm - raise ValueError("Cannot convert between alternating sign matrices of different sizes") + raise ValueError("cannot convert between alternating sign matrices of different sizes") try: m = self._matrix_space(asm) except (TypeError, ValueError): diff --git a/src/sage/combinat/decorated_permutation.py b/src/sage/combinat/decorated_permutation.py index f8ca5c8b78b..2ca513767c4 100644 --- a/src/sage/combinat/decorated_permutation.py +++ b/src/sage/combinat/decorated_permutation.py @@ -213,7 +213,7 @@ def _element_constructor_(self, pi, check=True): if isinstance(pi, DecoratedPermutation): if pi.parent() is self: return pi - raise ValueError("Cannot convert between decorated permutations of different sizes") + raise ValueError("cannot convert between decorated permutations of different sizes") pi = tuple(pi) if check and pi not in self: diff --git a/src/sage/combinat/derangements.py b/src/sage/combinat/derangements.py index eeeb73fb7ce..1645ff2d53b 100644 --- a/src/sage/combinat/derangements.py +++ b/src/sage/combinat/derangements.py @@ -199,7 +199,7 @@ def _element_constructor_(self, der): if isinstance(der, Derangement): if der.parent() is self: return der - raise ValueError("Cannot convert %s to an element of %s" % (der, self)) + raise ValueError("cannot convert %s to an element of %s" % (der, self)) return self.element_class(self, der) Element = Derangement diff --git a/src/sage/combinat/designs/difference_family.py b/src/sage/combinat/designs/difference_family.py index 410bb446fee..609cdf6542e 100644 --- a/src/sage/combinat/designs/difference_family.py +++ b/src/sage/combinat/designs/difference_family.py @@ -1294,24 +1294,24 @@ def _is_periodic_sequence(seq, period): first = seq[:per] periodic = True for j in range(1, len(seq)//per): - if seq[j*per:(j+1)*per] != first: + if seq[j*per : (j+1)*per] != first: periodic = False break if periodic: return False - if seq[:period] != seq[period:2*period]: + if seq[:period] != seq[period : 2*period]: return False return True def _create_m_sequence(q, n, check=True): - r"""Create an m-sequence over GF(q) with period `q^n-1`. + r"""Create an m-sequence over GF(q) with period `q^n - 1`. Given a prime power `q`, the m-sequence is created as described by [Zie1959]_ from a primitive function over the finite field `GF(q)`. - Given a primitive function `f=c_0+c_1x+...+c_nx^n` over `K=GF(q)` of degree `n`, - the recurrence is given by: `a_i = -c_0^{-1}(c_1a_{i-1}+...+c_na{i-n})`. - The first `n` elements will be `0,0,...,0,1` and these will give a maximal length recurrence sequence + Given a primitive function `f=c_0+c_1x+...+c_nx^n` over `K = GF(q)` of degree `n`, + the recurrence is given by: `a_i = -c_0^{-1}(c_1a_{i-1} + ... + c_na{i-n})`. + The first `n` elements will be `0, 0, ..., 0, 1` and these will give a maximal length recurrence sequence as shown in [Mit2008]_. INPUT: @@ -1320,7 +1320,7 @@ def _create_m_sequence(q, n, check=True): - ``n`` -- a nonnegative number. - - ``check`` -- boolean (dafault True): if true, check that the result is a seqauence with correct period. + - ``check`` -- boolean (default True): if true, check that the result is a seqauence with correct period. Setting it to false may speed up considerably the computation. EXAMPLES:: @@ -1354,13 +1354,13 @@ def _create_m_sequence(q, n, check=True): period = q**n - 1 seq_len = period*2 if check else period - seq = [1]+[0]*(n-1) + seq = [1] + [0]*(n-1) while len(seq) < seq_len: nxt = 0 for i, coeff in zip(exps[1:], coeffs[1:]): - nxt += coeff*seq[-i] - seq.append(-coeffs[0].inverse()*nxt) + nxt += coeff * seq[-i] + seq.append(-coeffs[0].inverse() * nxt) if check: assert _is_periodic_sequence(seq, period) @@ -1444,14 +1444,14 @@ def relative_difference_set_from_m_sequence(q, N, check=True): raise ValueError('N must be at least 2') m_seq = _create_m_sequence(q, N, check=False) - period = q**N-1 + period = q**N - 1 G = AdditiveAbelianGroup([period]) set1 = [i for i in G if m_seq[i[0]] == 1] if check: H = _get_submodule_of_order(G, q-1) - assert is_relative_difference_set(set1, G, H, (period//(q-1), q-1, q**(N-1), q**(N-2))) + assert is_relative_difference_set(set1, G, H, (period // (q-1), q - 1, q**(N-1), q**(N-2))) return set1 def relative_difference_set_from_homomorphism(q, N, d, check=True): @@ -1506,7 +1506,7 @@ def relative_difference_set_from_homomorphism(q, N, d, check=True): if (q-1)%d != 0: raise ValueError('q-1 must be a multiple of d') - G = AdditiveAbelianGroup([q**N-1]) + G = AdditiveAbelianGroup([q**N - 1]) K = _get_submodule_of_order(G, d) assert K is not None, 'Could not find kernel' @@ -1517,11 +1517,11 @@ def relative_difference_set_from_homomorphism(q, N, d, check=True): second_diff_set = [theta(x) for x in diff_set] if check: - H = _get_submodule_of_order(G2, (q-1)//d) - assert is_relative_difference_set(second_diff_set, G2, H, ((q**N-1)//(q-1), (q-1)//d, q**(N-1), q**(N-2)*d)) + H = _get_submodule_of_order(G2, (q-1) // d) + assert is_relative_difference_set(second_diff_set, G2, H, ((q**N-1) // (q-1), (q-1) // d, q**(N-1), q**(N-2) * d)) return second_diff_set -def is_relative_difference_set(R, G, H, params, verbose =False): +def is_relative_difference_set(R, G, H, params, verbose=False): r"""Check if `R` is a difference set of `G` relative to `H`, with the given parameters. This function checks that `G`, `H` and `R` have the orders specified in the parameters, and @@ -1546,9 +1546,9 @@ def is_relative_difference_set(R, G, H, params, verbose =False): sage: from sage.combinat.designs.difference_family import _get_submodule_of_order, relative_difference_set_from_m_sequence, is_relative_difference_set sage: q, N = 5, 2 - sage: G = AdditiveAbelianGroup([q^N-1]) - sage: H = _get_submodule_of_order(G, q-1) - sage: params = ((q^N-1)//(q-1), q-1, q^(N-1), q^(N-2)) + sage: G = AdditiveAbelianGroup([q^N - 1]) + sage: H = _get_submodule_of_order(G, q - 1) + sage: params = ((q^N-1) // (q-1), q - 1, q^(N-1), q^(N-2)) sage: R = relative_difference_set_from_m_sequence(q, N) sage: is_relative_difference_set(R, G, H, params) True @@ -1561,7 +1561,7 @@ def is_relative_difference_set(R, G, H, params, verbose =False): False """ m, n, k, d = params - if G.order() != m*n: + if G.order() != m * n: if verbose: print('Incorrect order of G:', G.order()) return False @@ -1579,7 +1579,7 @@ def is_relative_difference_set(R, G, H, params, verbose =False): for el1 in R: for el2 in R: if el1 != el2: - idx = el1-el2 + idx = el1 - el2 if idx not in diff_set: diff_set[idx] = 0 diff_set[idx] += 1 @@ -1602,11 +1602,11 @@ def is_relative_difference_set(R, G, H, params, verbose =False): return True def is_supplementary_difference_set(Ks, v, lmbda): - r"""Check that the sets in ``Ks`` are `n-\{v; k_1,...,k_n; \lambda \}` supplementary difference sets. - + r"""Check that the sets in ``Ks`` are `n-\{v; k_1, ..., k_n; \lambda \}` supplementary difference sets. + From the definition in [Spe1975]_: let `S_1, S_2, ..., S_n` be `n` subsets of an additive abelian group `G` of order `v` - such that `|S_i|= k_i`. If, for each `g\in G`, `g \neq 0`, the total number of solutions of `a_i-a'_i = g`, with - `a_i,a'_i \in S_i` is `\lambda`, then `S_1, S_2, ..., S_n` are `n-\{v; k_1,...,k_n;\lambda\}` supplementary difference sets. + such that `|S_i| = k_i`. If, for each `g \in G`, `g \neq 0`, the total number of solutions of `a_i - a'_i = g`, with + `a_i, a'_i \in S_i` is `\lambda`, then `S_1, S_2, ..., S_n` are `n-\{v; k_1, ..., k_n; \lambda\}` supplementary difference sets. INPUT: @@ -1638,8 +1638,7 @@ def is_supplementary_difference_set(Ks, v, lmbda): for K in Ks: for el1 in K: for el2 in K: - diff = G[el1]-G[el2] - + diff = G[el1] - G[el2] if diff not in differences_counter: differences_counter[diff] = 0 differences_counter[diff] += 1 @@ -1722,13 +1721,12 @@ def supplementary_difference_set(q, existence=False, check=True): .. SEEALSO:: :func:`is_supplementary_difference_set` - """ s = 0 m = -1 while q > 2**(s+1) and (q-1) % 2**(s+1) == 0: - prime_pow = (q-1)//2**(s+1)-1 + prime_pow = (q-1)//2**(s+1) - 1 if is_prime_power(prime_pow) and prime_pow % 2 == 1: m = (q - (2**(s+1) + 1)) // 2**(s+1) + 1 break @@ -1742,7 +1740,7 @@ def supplementary_difference_set(q, existence=False, check=True): if m == -1: raise ValueError('There is no s for which m-1 is an odd prime power') - set1 = relative_difference_set_from_homomorphism(m-1, 2, (m-2)//2, check=False) + set1 = relative_difference_set_from_homomorphism(m - 1, 2, (m-2) // 2, check=False) from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing P = PolynomialRing(ZZ, 'x') @@ -1753,15 +1751,15 @@ def supplementary_difference_set(q, existence=False, check=True): hall += P.monomial(d[0]) T_2m = 0 - for i in range(2*m): + for i in range(2 * m): T_2m += P.monomial(i) - modulo = P.monomial(2*m)-1 + modulo = P.monomial(2*m) - 1 diff = T_2m - (1+P.monomial(m))*hall diff = diff.mod(modulo) exp1, exp2 = diff.exponents() - a = (exp1+exp2-m)//2 + a = (exp1+exp2-m) // 2 alfa3 = (P.monomial(a) + hall).mod(modulo) alfa4 = (P.monomial(a+m) + hall).mod(modulo) @@ -1769,22 +1767,22 @@ def supplementary_difference_set(q, existence=False, check=True): psi3 = alfa3 psi4 = alfa4 for i in range(s): - psi3 = (alfa3(P.monomial(2))+P.monomial(1)*alfa4(P.monomial(2))).mod(P.monomial(4*m)-1) + psi3 = (alfa3(P.monomial(2)) + P.monomial(1)*alfa4(P.monomial(2))).mod(P.monomial(4*m)-1) psi4 = (alfa3(P.monomial(2)) + P.monomial(1)*(T_2m(P.monomial(2)) - alfa4(P.monomial(2)))).mod(P.monomial(4*m)-1) # Construction of psi1, psi2 set2 = relative_difference_set_from_m_sequence(q, 2, check=False) - s3 = _get_fixed_relative_difference_set(set2) + s3 = get_fixed_relative_difference_set(set2) phi_exps = [] for i in range(len(s3)): for j in range(i+1, len(s3)): - diff = (s3[i]-s3[j]) - if diff%(q-1) == 0 and diff%(q**2-1) != 0: + diff = s3[i] - s3[j] + if diff % (q-1) == 0 and diff % (q**2-1) != 0: phi_exps.append(s3[i]) - exps1 = [(x+1)//2 for x in phi_exps if x%2 == 1] - exps2 = [x//2 for x in phi_exps if x%2 == 0] + exps1 = [(x+1)//2 for x in phi_exps if x % 2 == 1] + exps2 = [x//2 for x in phi_exps if x % 2 == 0] theta1 = 0 for exp in exps1: @@ -1794,12 +1792,12 @@ def supplementary_difference_set(q, existence=False, check=True): theta2 = 0 for exp in exps2: theta2 += P.monomial(exp) - theta2 = theta2.mod(P.monomial(q-1)-1) + theta2 = theta2.mod(P.monomial(q-1) - 1) phi1 = 0 phi2 = 0 for exp in phi_exps: - if exp%2 == 0: + if exp % 2 == 0: phi2 += P.monomial(exp) else: phi1 += P.monomial(exp) @@ -1817,8 +1815,8 @@ def supplementary_difference_set(q, existence=False, check=True): return K1, K2, K3, K4 -def _get_fixed_relative_difference_set(rel_diff_set, as_elements=False): - r"""Contruct an equivalent relative difference set fixed by the size of the set. +def get_fixed_relative_difference_set(rel_diff_set, as_elements=False): + r"""Construct an equivalent relative difference set fixed by the size of the set. Given a relative difference set `R(q+1, q-1, q, 1)`, it is possible to find a translation of this set fixed by `q` (see Section 3 of [Spe1975]_). We say that a set is fixed by `t` if @@ -1842,30 +1840,30 @@ def _get_fixed_relative_difference_set(rel_diff_set, as_elements=False): EXAMPLES:: - sage: from sage.combinat.designs.difference_family import relative_difference_set_from_m_sequence, _get_fixed_relative_difference_set + sage: from sage.combinat.designs.difference_family import relative_difference_set_from_m_sequence, get_fixed_relative_difference_set sage: s1 = relative_difference_set_from_m_sequence(5, 2) - sage: _get_fixed_relative_difference_set(s1) #random + sage: get_fixed_relative_difference_set(s1) #random [2, 10, 19, 23, 0] If ``as_elements`` is true, the reuslt will contain elements of the group:: - sage: _get_fixed_relative_difference_set(s1, as_elements=True) #random + sage: get_fixed_relative_difference_set(s1, as_elements=True) #random [(2), (10), (19), (23), (0)] TESTS:: - sage: from sage.combinat.designs.difference_family import _is_fixed_relative_difference_set + sage: from sage.combinat.designs.difference_family import is_fixed_relative_difference_set sage: s1 = relative_difference_set_from_m_sequence(5, 2) - sage: s2 = _get_fixed_relative_difference_set(s1, as_elements=True) - sage: _is_fixed_relative_difference_set(s2, len(s2)) + sage: s2 = get_fixed_relative_difference_set(s1, as_elements=True) + sage: is_fixed_relative_difference_set(s2, len(s2)) True sage: s1 = relative_difference_set_from_m_sequence(9, 2) - sage: s2 = _get_fixed_relative_difference_set(s1, as_elements=True) - sage: _is_fixed_relative_difference_set(s2, len(s2)) + sage: s2 = get_fixed_relative_difference_set(s1, as_elements=True) + sage: is_fixed_relative_difference_set(s2, len(s2)) True sage: type(s2[0]) - sage: s2 = _get_fixed_relative_difference_set(s1) + sage: s2 = get_fixed_relative_difference_set(s1) sage: type(s2[0]) """ @@ -1875,14 +1873,14 @@ def _get_fixed_relative_difference_set(rel_diff_set, as_elements=False): s2 = None for el in G: fixed_set = [el+x for x in rel_diff_set] - if _is_fixed_relative_difference_set(fixed_set, q): + if is_fixed_relative_difference_set(fixed_set, q): s2 = fixed_set break assert s2 is not None, 'Cannot find fixed translation of the set' s3 = None for i in range(G.order()): - temp = [((q+1)*i+x[0])%G.order() for x in s2] + temp = [((q+1)*i+x[0]) % G.order() for x in s2] if 0 in temp: s3 = temp break @@ -1892,10 +1890,10 @@ def _get_fixed_relative_difference_set(rel_diff_set, as_elements=False): return [G[x] for x in s3] return s3 -def _is_fixed_relative_difference_set(R, q): +def is_fixed_relative_difference_set(R, q): r"""Check if the relative difference set `R` is fixed by `q`. - A relative difference set `R` is fixed by `q` if `\{qd | d\in R\}= R` (see Section 3 of [Spe1975]_). + A relative difference set `R` is fixed by `q` if `\{qd | d \in R\}= R` (see Section 3 of [Spe1975]_). INPUT: @@ -1905,40 +1903,45 @@ def _is_fixed_relative_difference_set(R, q): EXAMPLES:: - sage: from sage.combinat.designs.difference_family import relative_difference_set_from_m_sequence, _get_fixed_relative_difference_set, _is_fixed_relative_difference_set + sage: from sage.combinat.designs.difference_family import relative_difference_set_from_m_sequence, get_fixed_relative_difference_set, is_fixed_relative_difference_set sage: s1 = relative_difference_set_from_m_sequence(7, 2) - sage: s2 = _get_fixed_relative_difference_set(s1, as_elements=True) - sage: _is_fixed_relative_difference_set(s2, len(s2)) + sage: s2 = get_fixed_relative_difference_set(s1, as_elements=True) + sage: is_fixed_relative_difference_set(s2, len(s2)) True sage: G = AdditiveAbelianGroup([15]) sage: s3 = [G[1], G[2], G[3], G[4]] - sage: _is_fixed_relative_difference_set(s3, len(s3)) + sage: is_fixed_relative_difference_set(s3, len(s3)) False If the relative difference set does not contain elements of the group, the method returns false:: sage: s1 = relative_difference_set_from_m_sequence(7, 2) - sage: s2 = _get_fixed_relative_difference_set(s1, as_elements=False) - sage: _is_fixed_relative_difference_set(s2, len(s2)) + sage: s2 = get_fixed_relative_difference_set(s1, as_elements=False) + sage: is_fixed_relative_difference_set(s2, len(s2)) False - - """ for el in R: - if q*el not in R: + if q * el not in R: return False return True def skew_supplementary_difference_set(n, existence=False, check=True): - r"""Construct `4-\{n; n_1, n_2, n_3, n_4; \lambda\}` supplementary difference sets where `S_1` is skew and `n_1+n_2+n_3+n_4= n+\lambda`. + r"""Construct `4-\{n; n_1, n_2, n_3, n_4; \lambda\}` supplementary difference sets where `S_1` is skew and `n_1 + n_2 + n_3 + n_4 = n+\lambda`. These sets are constructed from available data, as described in [Djo1994]_. The set `S_1 \subset G` is - always skew, i.e. `S_1 \cap (-S_1) = \emptyset` and `S_1 \cup (-S_1) = G\setminus\{0\}`. - - The data for `n = 103, 151` is taken from [Djo1994]_ and the data for `n = 67, 113, 127, 157, 163, 181, 241` - is taken from [Djo1992]_. - + always skew, i.e. `S_1 \cap (-S_1) = \emptyset` and `S_1 \cup (-S_1) = G \setminus \{0\}`. + + The data is taken from: + + * `n = 103, 151`: [Djo1994]_ + * `n = 67, 113, 127, 157, 163, 181, 241`: [Djo1992a]_ + * `n = 37, 43`: [Djo1992b]_ + * `n = 39, 49, 65, 93, 121, 129, 133, 217, 219, 267`: [Djo1992c]_ + * `n = 97`: [Djo2008a]_ + * `n = 109, 145, 247`: [Djo2008b]_ + * `n = 73`: [Djo2023b]_ + INPUT: - ``n`` -- integer, the parameter of the supplementary difference set. @@ -1989,79 +1992,178 @@ def skew_supplementary_difference_set(n, existence=False, check=True): False sage: skew_supplementary_difference_set(127, existence=True) True - """ + .. NOTE:: + + The data for `n=247` in [Djo2008b]_ contains a typo: the set `\alpha_2` should contain `223` instead of `233`. + This can be verified by checking the resulting sets, which are given explicitly in the paper. + """ + # If -1 is present in an index set, it means that {0} should be added to that set indices = { - 67: [[0,3,5,6,9,10,13,14,17,18,20], - [0,2,4,9,11,12,13,16,19,21], - [1,3,6,10,11,13,14,16,20,21], - [2,4,6,8,9,11,14,17,19]], - 103: [[1,3,4,6,8,11,12,14,17,18,20,22,25,27,28,30,32], - [2,9,10,12,13,14,15,16,20,21,22,23,24,26,28,29,30], - [0,1,2,3,4,11,12,13,16,17,19,20,21,24,25,26,28,30,31], - [0,1,2,3,4,5,6,13,15,18,19,20,23,24,25,26,27,28,29,31]], - 113: [[0,3,4,6,8,10,13,14], - [1,3,8,9,10,11,12,13], - [0,2,3,5,6,7,12], - [1,2,3,5,8,9,15]], - 127: [[0,3,5,7,8,10,12,14,16], - [0,1,3,6,7,9,10,12,14,15], - [0,1,3,4,5,7,8,9,15,16], - [1,4,5,6,9,10,13,14,15,16]], - 151: [[0,3,5,6,8,11,13,14,16,19,21,23,25,27,28], - [2,3,6,13,16,17,20,23,25,26,27,28,29], - [0,1,2,3,4,6,7,8,9,10,11,12,23,24,27,28], - [1,4,5,10,11,12,13,14,16,18,19,22,25,26,27,28]], - 157:[[0,2,5,7,8,11], - [0,4,5,6,9,11], - [6,7,8,9,10,11], - [0,5,6,7,8,10,11]], - 163: [[0,2,5,6,9,10,13,14,17], - [0,1,7,10,12,15,16,17], - [0,1,3,5,8,13,15,16,17], - [3,6,7,8,11,12,13,14,16,17]], - 181: [[0,3,5,6,8,10,13,15,16,19], - [4,5,7,8,11,14,15,16,18,19], - [0,4,10,11,13,15,16,18,19], - [2,4,5,7,11,13,15,17,19]], - 241: [[0,2,4,6,8,11,12,14], - [1,3,4,6,7,13,14,15], - [6,8,9,10,12,13,14,15], - [3,4,5,9,10,13,14]], + 37: [[0, 3, 5, 7, 9, 10], [0, 5, 6, 7, 8], + [1, 2, 6, 7, 9], [2, 6, 8, 9, 10]], + 39: [[1, 3, 5, 6, 8, 10, 12], [0, 1, 5, 8, 12, 13], + [1, 3, 4, 7, 9, 12, 13], [0, 1, 2, 3, 7, 8]], + 43: [[1, 2, 4], [1, 2, 4], [0, 2, 3], [3, 4, -1]], + 49: [[1, 2, 5, 7, 8, 10, 13, 14], [4, 5, 6, 7, 10, 11], + [0, 1, 2, 4, 6, 7, 12, 14], [1, 2, 3, 5, 6, 10, 12, 13, 14]], + 65: [[1, 3, 5, 6, 8, 10, 13, 14, 17, 18, 20, 22], + [0, 3, 7, 10, 16, 17, 18, 20, 21], + [2, 4, 6, 8, 9, 10, 14, 15, 16, 17, 18, 20], + [5, 7, 8, 9, 11, 12, 13, 14, 16, 18, 19, 20, 21]], + 67: [[0, 3, 5, 6, 9, 10, 13, 14, 17, 18, 20], + [0, 2, 4, 9, 11, 12, 13, 16, 19, 21], + [1, 3, 6, 10, 11, 13, 14, 16, 20, 21], + [2, 4, 6, 8, 9, 11, 14, 17, 19]], + 73: [[4, 6, 8, 14], [8, 10, 12, 14], [4, 6, 10, 12], [-1, 0, 2, 10]], + 93: [[0, 3, 4, 6, 9, 10, 12, 14, 17, 18], + [2, 3, 4, 5, 9, 13, 15, 18, 19], + [1, 2, 3, 4, 5, 6, 7, 8, 16], + [1, 4, 6, 11, 12, 13, 15, 16, 17, 18]], + 97: [[1, 2, 4, 6, 9, 11, 13, 14, 17, 18, 21, 23, 25, 27, 29, 30], + [1, 2, 6, 7, 8, 9, 10, 11, 12, 13, 23, 27, 29], + [0, 1, 2, 5, 6, 12, 13, 15, 16, 20, 24, 25, 26, 29, 30, 31], + [0, 2, 3, 4, 7, 8, 9, 11, 12, 13, 15, 16, 17, 18, 23, 28, 29]], + 103: [[1, 3, 4, 6, 8, 11, 12, 14, 17, 18, 20, 22, 25, 27, 28, 30, 32], + [2, 9, 10, 12, 13, 14, 15, 16, 20, 21, 22, 23, 24, 26, 28, 29, 30], + [0, 1, 2, 3, 4, 11, 12, 13, 16, 17, 19, 20, 21, 24, 25, 26, 28, 30, 31], + [0, 1, 2, 3, 4, 5, 6, 13, 15, 18, 19, 20, 23, 24, 25, 26, 27, 28, 29, 31]], + 109: [[0, 2, 5, 7, 8, 10, 12, 15, 16, 19, 20, 23, 24, 26, 29, 30, 33, 34], + [4, 5, 6, 7, 11, 15, 18, 19, 20, 22, 25, 30, 32, 33, 35], + [0, 1, 5, 6, 9, 10, 11, 14, 17, 20, 24, 26, 27, 28, 29, 31, 32], + [0, 3, 4, 6, 7, 9, 10, 12, 13, 22, 24, 25, 26, 27, 28, 29, 31, 33, 35]], + 113: [[0, 3, 4, 6, 8, 10, 13, 14], + [1, 3, 8, 9, 10, 11, 12, 13], + [0, 2, 3, 5, 6, 7, 12], + [1, 2, 3, 5, 8, 9, 15]], + 121: [[0, 2, 4, 7, 8, 11, 13, 14, 16, 19, 20, 22], + [0, 1, 4, 5, 8, 9, 10, 15, 17, 20, 23], + [1, 2, 3, 7, 9, 16, 18, 19, 20, 21, 22, 23], + [0, 2, 9, 10, 11, 12, 13, 14, 15, 17, 18, 21, 22, 23]], + 127: [[0, 3, 5, 7, 8, 10, 12, 14, 16], + [0, 1, 3, 6, 7, 9, 10, 12, 14, 15], + [0, 1, 3, 4, 5, 7, 8, 9, 15, 16], + [1, 4, 5, 6, 9, 10, 13, 14, 15, 16]], + 129: [[1, 2, 4, 7, 9, 11, 12, 14,16,18], + [0, 1, 2, 3, 9, 11, 14, 15, 19], + [0, 1, 3, 6, 8, 10, 12, 16, 18, 19], + [0, 3, 7, 8, 9, 10, 12, 14, 15, 17]], + 133: [[1, 2, 5, 6, 9, 11, 12, 14], [1, 4, 7, 9, 10, 12, 13, 15], + [0, 5, 6, 8, 11, 12, 13, 15], [0, 1, 2, 5, 7, 8, 9, 13, 14, 15]], + 145: [[1, 2, 4, 7, 9, 10, 13, 14, 16, 19, 20, 22], [0, 2, 4, 7, 10, 11, 14, 18, 19, 20, 21, 22], + [1, 3, 6, 9, 12, 13, 14, 17, 19, 20, 21, 22, 23], [2, 3, 5, 6, 7, 9, 12, 13, 15, 16, 19, 20, 21, 22, 23]], + 151: [[0, 3, 5, 6, 8, 11, 13, 14, 16, 19, 21, 23, 25, 27, 28], + [2, 3, 6, 13, 16, 17, 20, 23, 25, 26, 27, 28, 29], + [0, 1, 2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 23, 24, 27, 28], + [1, 4, 5, 10, 11, 12, 13, 14, 16, 18, 19, 22, 25, 26, 27, 28]], + 157: [[0, 2, 5, 7, 8, 11], + [0, 4, 5, 6, 9, 11], + [6, 7, 8, 9, 10, 11], + [0, 5, 6, 7, 8, 10, 11]], + 163: [[0, 2, 5, 6, 9, 10, 13, 14, 17], + [0, 1, 7, 10, 12, 15, 16, 17], + [0, 1, 3, 5, 8, 13, 15, 16, 17], + [3, 6, 7, 8, 11, 12, 13, 14, 16, 17]], + 181: [[0, 3, 5, 6, 8, 10, 13, 15, 16, 19], + [4, 5, 7, 8, 11, 14, 15, 16, 18, 19], + [0, 4, 10, 11, 13, 15, 16, 18, 19], + [2, 4, 5, 7, 11, 13, 15, 17, 19]], + 217: [[0, 3, 5, 7, 8, 11, 12, 14], [1, 3, 4, 7, 9, 11, 12, 15], + [3, 4, 5, 6, 7, 9, 10, 14, 15], [1, 3, 4, 5, 7, 8, 11, 13, 14]], + 219: [[1, 3, 5, 6, 8, 11, 12, 15, 17, 18, 21, 22, 24], + [2, 6, 8, 10, 11, 12, 13, 16, 19, 22, 23, 24], + [0, 1, 5, 6, 10, 11, 13, 14, 17, 20, 21, 24, 25], + [0, 2, 3, 4, 5, 6, 7, 11, 12, 13, 16, 20, 23]], + 241: [[0, 2, 4, 6, 8, 11, 12, 14], + [1, 3, 4, 6, 7, 13, 14, 15], + [6, 8, 9, 10, 12, 13, 14, 15], + [3, 4, 5, 9, 10, 13, 14]], + 247: [[0, 2, 4, 7, 8, 10, 12, 15, 16, 18, 20, 23, 25, 27, 29], + [0, 2, 7, 9, 11, 12, 14, 15, 16, 18, 20, 22, 26], + [2, 3, 4, 12, 13, 14, 15, 16, 18, 20, 23, 24, 26, 27, 29], + [0, 3, 4, 6, 10, 11, 12, 14, 18, 19, 20, 22, 25, 29]], + 267: [[0, 3, 4, 7, 8, 11, 13, 15, 16, 19, 21, 22, 25], + [0, 1, 4, 5, 6, 8, 14, 15, 18, 21, 23], + [0, 2, 4, 5, 7, 9, 10, 11, 14, 15, 16, 17, 25], + [0, 1, 3, 4, 6, 14, 15, 16, 17, 18, 20, 22, 23, 25]], } + # If the element is a list, that is the coset. cosets_gens = { - 67: [1,2,3,4,5,6,8,10,12,15,17], + 37: [1, 2, 3, 5, 6, 9], + 39: [1, 2, 3, 4, 6, 8, [13]], + 43: [1, 3, 7], + 49: [1, 2, 3, 4, 6, 7, 9, 12], + 65: [1, 2, 3, 5, 6, 7, 9, 10, 11, [13], 22, [26]], + 67: [1, 2, 3, 4, 5, 6, 8, 10, 12, 15, 17], + 73: [1, 3, 5, 9, 11, 13, 17, 25], + 93: [1, 2, 3, 5, 7, 9, 10, 14, 15, [31]], + 97: [1, 2, 3, 4, 5, 6, 7, 9, 10, 12, 13, 15, 18, 20, 23, 26], 103: [1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 15, 17, 19, 21, 23, 30], + 109: [1, 2, 3, 4, 5, 6, 8, 9, 10, 11, 13, 15, 16, 18, 20, 23, 25, 30], 113: [1, 2, 3, 5, 6, 9, 10, 13], + 121: [1, 2, 4, 5, 7, 8, 10, 11, 16, 17, 19, 20], 127: [1, 3, 5, 7, 9, 11, 13, 19, 21], - 151: [1, 2, 3 ,4, 5, 6, 9, 10, 11, 12, 15, 22, 27, 29, 30], + 129: [1, 3, 5, 7, 9, 11, 13, 19, 21, [43]], + 133: [1, 2, 3, 6, 7, 9, 18, [19, 38, 76]], + 145: [1, [2, 17, 32, 72, 77, 127, 137], [3, 43, 48, 98, 108, 118, 133], [6, 51, 71, 86, 91, 96, 121], + [7, 52, 82, 107, 112, 117, 132], [11, 21, 31, 46, 61, 101, 106], [14, 19, 69, 79, 89, 104, 119], + [22, 42, 57, 62, 67, 92, 122], [5, 35, 80, 100, 115, 120, 125], [10, 15, 55, 70, 85, 95, 105], + [29], [58]], + 151: [1, 2, 3, 4, 5, 6, 9, 10, 11, 12, 15, 22, 27, 29, 30], 157: [1, 2, 3, 5, 9, 15], 163: [1, 2, 3, 5, 6, 9, 10, 15, 18], 181: [1, 2, 3, 4, 6, 7, 8, 12, 13, 24], + 217: [1, 2, 4, 5, 7, 10, 19, [31, 62, 124]], + 219: [1, 2, 3, 5, 7, 9, 11, 15, 19, 22, 23, 33, [73]], 241: [1, 2, 4, 5, 7, 13, 19, 35], + 247: [1, [2, 18, 31, 32, 41, 110, 122, 162, 223], [3, 27, 48, 165, 170, 183, 185, 211, 243], + [5, 28, 45, 58, 80, 158, 187, 201, 226], [6, 54, 83, 93, 96, 119, 123, 175, 239], [7, 20, 63, 73, 112, 138, 163, 180, 232], + [10, 56, 69, 90, 116, 127, 155, 160, 205], [11, 47, 99, 102, 111, 115, 150, 176, 177], [13, 52, 65, 78, 91, 117, 143, 208, 221], + [14, 29, 40, 79, 113, 126, 146, 217, 224], [17, 25, 43, 49, 140, 142, 153, 194, 225], [19, 57, 171], + [33, 34, 37, 50, 59, 86, 98, 141, 203], [35, 66, 68, 74, 100, 118, 159, 172, 196], [38, 95, 114]], + 267: [1, 2, 3, 5, 7, 9, 10, 13, 14, 15, 19, 39, [89]], } H_db = { + 37: [1, 10, -11], + 39: [1, 16, 22], + 43: [1, 4, 11, 16, 21, -2, -8], + 49: [1, 18, 30], + 65: [1, 16, 61], 67: [1, 29, 37], + 73: [1, 2, 4, 8, 16, 32, 64, 55, 37], + 93: [1, 4, 16, 64, 70], + 97: [1, 35, 61], 103: [1, 46, 56], - 113: [1,16,28,30,49,106,109], - 127: [1,2,4,8,16,32,64], - 151: [1, 8,19,59, 64], - 157: [1,14,16,39,46,67,75,93,99,101,108,130,153], - 163: [1,38,40,53,58,85,104,133,140], - 181: [1,39,43,48,62,65,73,80,132], - 241: [1,15,24,54,87,91,94,98,100,119,160,183,205,225,231], + 109: [1, 45, 63], + 113: [1, 16, 28, 30, 49, 106, 109], + 121: [1, 3, 9, 27, 81], + 127: [1, 2, 4, 8, 16, 32, 64], + 129: [1, 4, 16, 64, 97, 121, 127], + 133: [1, 4, 16, 25, 64, 93, 100, 106, 123], + 145: [1, 16, 36, 81, 111, 136, 141], + 151: [1, 8, 19, 59, 64], + 157: [1, 14, 16, 39, 46, 67, 75, 93, 99, 101, 108, 130, 153], + 163: [1, 38, 40, 53, 58, 85, 104, 133, 140], + 181: [1, 39, 43, 48, 62, 65, 73, 80, 132], + 217: [1, 8, 9, 25, 51, 64, 72, 78, 81, 142, 190, 191, 193, 200, 214], + 219: [1, 4, 16, 37, 55, 64, 148, 154, 178], + 241: [1, 15, 24, 54, 87, 91, 94, 98, 100, 119, 160, 183, 205, 225, 231], + 247: [1, 9, 16, 55, 61, 81, 139, 144, 235], + 267: [1, 4, 16, 64, 67, 91, 97, 121, 217, 223, 256], } def generate_set(index_set, cosets): S = [] for idx in index_set: - S += cosets[idx] + if idx == -1: + S.append(Z(0)) + else: + S += cosets[idx] return S - if existence: return n in indices @@ -2073,11 +2175,11 @@ def generate_set(index_set, cosets): cosets = [] for el in cosets_gens[n]: - even_coset = [] - odd_coset = [] - for x in H: - even_coset.append(x*el) - odd_coset.append(-x*el) + if isinstance(el, list): + even_coset = [Z(x) for x in el] + else: + even_coset = [x*el for x in H] + odd_coset = [-x for x in even_coset] cosets.append(even_coset) cosets.append(odd_coset) @@ -2087,7 +2189,7 @@ def generate_set(index_set, cosets): S4 = generate_set(indices[n][3], cosets) if check: - lmbda = len(S1)+len(S2)+len(S3)+len(S4) - n + lmbda = len(S1) + len(S2) + len(S3) + len(S4) - n assert is_supplementary_difference_set([S1, S2, S3, S4], n, lmbda) assert _is_skew_set(S1, n) diff --git a/src/sage/combinat/matrices/hadamard_matrix.py b/src/sage/combinat/matrices/hadamard_matrix.py index 91f73d29101..bf915399d20 100644 --- a/src/sage/combinat/matrices/hadamard_matrix.py +++ b/src/sage/combinat/matrices/hadamard_matrix.py @@ -46,16 +46,16 @@ - [Hora]_ """ -#***************************************************************************** +# ***************************************************************************** # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # https://www.gnu.org/licenses/ -#***************************************************************************** +# ***************************************************************************** from urllib.request import urlopen -from sage.combinat.designs.difference_family import skew_supplementary_difference_set +from sage.combinat.designs.difference_family import get_fixed_relative_difference_set, relative_difference_set_from_homomorphism, skew_supplementary_difference_set from sage.rings.integer_ring import ZZ from sage.matrix.constructor import matrix, block_matrix, block_diagonal_matrix, diagonal_matrix @@ -63,34 +63,53 @@ from math import sqrt from sage.matrix.constructor import identity_matrix as I from sage.matrix.constructor import ones_matrix as J -from sage.matrix.constructor import zero_matrix +from sage.matrix.constructor import zero_matrix, matrix_method from sage.misc.unknown import Unknown from sage.cpython.string import bytes_to_str from sage.modules.free_module_element import vector from sage.combinat.t_sequences import T_sequences_smallcases +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing -def normalise_hadamard(H): +def normalise_hadamard(H, skew=False): r""" Return the normalised Hadamard matrix corresponding to ``H``. The normalised Hadamard matrix corresponding to a Hadamard matrix `H` is a matrix whose every entry in the first row and column is +1. + If ``skew`` is True, the matrix returned will be skew-normal: a skew Hadamard + matrix with first row of all `+1`. + EXAMPLES:: - sage: from sage.combinat.matrices.hadamard_matrix import normalise_hadamard + sage: from sage.combinat.matrices.hadamard_matrix import normalise_hadamard, is_hadamard_matrix, skew_hadamard_matrix sage: H = normalise_hadamard(hadamard_matrix(4)) sage: H == hadamard_matrix(4) True + sage: H = normalise_hadamard(skew_hadamard_matrix(20, skew_normalize=False), skew=True) + sage: is_hadamard_matrix(H, skew=True, normalized=True) + True + + If ``skew`` is True but the Hadamard matrix is not skew, the matrix returned + will not be normalized:: + + sage: H = normalise_hadamard(hadamard_matrix(92), skew=True) + sage: is_hadamard_matrix(H, normalized=True) + False """ - for i in range(H.ncols()): - if H[0, i] < 0: - H.rescale_col(i, -1) - for i in range(H.nrows()): - if H[i, 0] < 0: - H.rescale_row(i, -1) - return H + + if skew: + dd = diagonal_matrix(H[0]) + return dd*H*dd + else: + for i in range(H.ncols()): + if H[0, i] < 0: + H.rescale_col(i, -1) + for i in range(H.nrows()): + if H[i, 0] < 0: + H.rescale_row(i, -1) + return H def hadamard_matrix_paleyI(n, normalize=True): @@ -140,22 +159,22 @@ def hadamard_matrix_paleyI(n, normalize=True): True """ p = n - 1 - if not(is_prime_power(p) and (p % 4 == 3)): + if not (is_prime_power(p) and (p % 4 == 3)): raise ValueError("The order %s is not covered by the Paley type I construction." % n) from sage.rings.finite_rings.finite_field_constructor import FiniteField - K = FiniteField(p,'x') + K = FiniteField(p, 'x') K_list = list(K) - K_list.insert(0,K.zero()) + K_list.insert(0, K.zero()) H = matrix(ZZ, [[(1 if (x-y).is_square() else -1) for x in K_list] for y in K_list]) for i in range(n): - H[i,0] = -1 - H[0,i] = 1 + H[i, 0] = -1 + H[0, i] = 1 if normalize: for i in range(n): - H[i,i] = -1 + H[i, i] = -1 H = normalise_hadamard(H) return H @@ -204,29 +223,30 @@ def hadamard_matrix_paleyII(n): True """ q = n//2 - 1 - if not(n%2==0 and is_prime_power(q) and (q % 4 == 1)): + if not (n % 2 == 0 and is_prime_power(q) and (q % 4 == 1)): raise ValueError("The order %s is not covered by the Paley type II construction." % n) from sage.rings.finite_rings.finite_field_constructor import FiniteField - K = FiniteField(q,'x') + K = FiniteField(q, 'x') K_list = list(K) - K_list.insert(0,K.zero()) + K_list.insert(0, K.zero()) H = matrix(ZZ, [[(1 if (x-y).is_square() else -1) for x in K_list] for y in K_list]) for i in range(q+1): - H[0,i] = 1 - H[i,0] = 1 - H[i,i] = 0 + H[0, i] = 1 + H[i, 0] = 1 + H[i, i] = 0 - tr = { 0: matrix(2,2,[ 1,-1,-1,-1]), - 1: matrix(2,2,[ 1, 1, 1,-1]), - -1: matrix(2,2,[-1,-1,-1, 1])} + tr = { 0: matrix(2, 2, [ 1, -1, -1, -1]), + 1: matrix(2, 2, [ 1, 1, 1, -1]), + -1: matrix(2, 2, [-1, -1, -1, 1])} - H = block_matrix(q+1,q+1,[tr[v] for r in H for v in r]) + H = block_matrix(q+1, q+1, [tr[v] for r in H for v in r]) return normalise_hadamard(H) + def hadamard_matrix_williamson_type(a, b, c, d, check=True): r""" Construction of Williamson type Hadamard matrix. @@ -280,16 +300,17 @@ def hadamard_matrix_williamson_type(a, b, c, d, check=True): n = len(a) assert len(a) == len(b) == len(c) == len(d) - assert A*A.T+B*B.T+C*C.T+D*D.T==4*n*I(n) + assert A*A.T+B*B.T+C*C.T+D*D.T == 4*n*I(n) M = block_matrix([[ A, B, C, D], [-B, A, -D, C], [-C, D, A, -B], - [-D, -C, B, A]]) + [-D, -C, B, A]]) if check: assert is_hadamard_matrix(M, normalized=False, skew=False) return M + def williamson_type_quadruples_smallcases(n, existence=False): r""" Quadruples of matrices that can be used to construct Williamson type Hadamard matrices. @@ -342,14 +363,14 @@ def williamson_type_quadruples_smallcases(n, existence=False): [1, -1, -1, 1, -1, -1, 1, -1, -1], [1, -1, 1, -1, -1, -1, -1, 1, -1], [1, 1, -1, -1, -1, -1, -1, -1, 1]), - 29: ([1, 1, 1,-1,-1,-1, 1, 1,-1,-1, 1,-1, 1,-1,-1,-1,-1, 1,-1, 1,-1,-1, 1, 1,-1,-1,-1, 1, 1], - [1,-1, 1,-1,-1,-1, 1, 1,-1,-1, 1,-1, 1, 1, 1, 1, 1, 1,-1, 1,-1,-1, 1, 1,-1,-1,-1, 1,-1], - [1, 1, 1, 1,-1, 1, 1,-1, 1,-1,-1,-1, 1, 1, 1, 1, 1, 1,-1,-1,-1, 1,-1, 1, 1,-1, 1, 1, 1], - [1, 1,-1,-1, 1,-1,-1, 1,-1, 1, 1, 1,-1, 1, 1, 1, 1,-1, 1, 1, 1,-1, 1,-1,-1, 1,-1,-1, 1]), + 29: ([1, 1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, 1], + [1, -1, 1, -1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, 1, -1], + [1, 1, 1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, 1, 1], + [1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1]), 43: ([1, 1, -1, -1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1], - [1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, 1], - [1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1], - [1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1]), + [1, 1, 1, -1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 1, 1], + [1, 1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, 1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1], + [1, -1, -1, -1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1]), } if existence: @@ -360,6 +381,7 @@ def williamson_type_quadruples_smallcases(n, existence=False): a, b, c, d = map(vector, db[n]) return a, b, c, d + def williamson_hadamard_matrix_smallcases(n, existence=False, check=True): r""" Construct Williamson type Hadamard matrices for some small values of n. @@ -389,9 +411,9 @@ def williamson_hadamard_matrix_smallcases(n, existence=False, check=True): ... ValueError: The Williamson type Hadamard matrix of order 100 is not yet implemented. """ - assert n%4 == 0 + assert n % 4 == 0 - if not williamson_type_quadruples_smallcases(n//4, existence=True): + if not williamson_type_quadruples_smallcases(n//4, existence=True): if existence: return False raise ValueError("The Williamson type Hadamard matrix of order %s is not yet implemented." % n) @@ -419,25 +441,26 @@ def hadamard_matrix_156(): sage: hadamard_matrix_156() 156 x 156 dense matrix over Integer Ring... """ - a = [1, 1,-1,-1, 1,-1, 1, 1,-1, 1,-1,-1, 1] - b = [1,-1,-1,-1, 1, 1, 1, 1, 1, 1,-1,-1,-1] - c = [1, 1, 1,-1, 1, 1,-1,-1, 1, 1,-1, 1, 1] - d = [1, 1,-1, 1,-1, 1, 1, 1, 1,-1, 1,-1, 1] + a = [1, 1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1] + b = [1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, -1] + c = [1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1] + d = [1, 1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, 1] A, B, C, D = map(matrix.circulant, [a, b, c, d]) - return block_matrix([[ A, A, A, B,-B, C,-C,-D, B, C,-D,-D], - [ A,-A, B,-A,-B,-D, D,-C,-B,-D,-C,-C], - [ A,-B,-A, A,-D, D,-B, B,-C,-D, C,-C], - [ B, A,-A,-A, D, D, D, C, C,-B,-B,-C], - [ B,-D, D, D, A, A, A, C,-C, B,-C, B], - [ B, C,-D, D, A,-A, C,-A,-D, C, B,-B], - [ D,-C, B,-B, A,-C,-A, A, B, C, D,-D], - [-C,-D,-C,-D, C, A,-A,-A,-D, B,-B,-B], - [ D,-C,-B,-B,-B, C, C,-D, A, A, A, D], - [-D,-B, C, C, C, B, B,-D, A,-A, D,-A], - [ C,-B,-C, C, D,-B,-D,-B, A,-D,-A, A], - [-C,-D,-D, C,-C,-B, B, B, D, A,-A,-A]]) + return block_matrix([[ A, A, A, B, -B, C, -C, -D, B, C, -D, -D], + [ A, -A, B, -A, -B, -D, D, -C, -B, -D, -C, -C], + [ A, -B, -A, A, -D, D, -B, B, -C, -D, C, -C], + [ B, A, -A, -A, D, D, D, C, C, -B, -B, -C], + [ B, -D, D, D, A, A, A, C, -C, B, -C, B], + [ B, C, -D, D, A, -A, C, -A, -D, C, B, -B], + [ D, -C, B, -B, A, -C, -A, A, B, C, D, -D], + [-C, -D, -C, -D, C, A, -A, -A, -D, B, -B, -B], + [ D, -C, -B, -B, -B, C, C, -D, A, A, A, D], + [-D, -B, C, C, C, B, B, -D, A, -A, D, -A], + [ C, -B, -C, C, D, -B, -D, -B, A, -D, -A, A], + [-C, -D, -D, C, -C, -B, B, B, D, A, -A, -A]]) + def construction_four_symbol_delta_code_I(X, Y, Z, W): r""" @@ -500,7 +523,8 @@ def construction_four_symbol_delta_code_I(X, Y, Z, W): n = len(X) assert len(Y) == n and len(Z) == n-1 and len(W) == n-1 - autocorrelation = lambda seq, j: sum([seq[i]*seq[i+j] for i in range(len(seq)-j)]) + def autocorrelation(seq, j): + return sum([seq[i]*seq[i+j] for i in range(len(seq)-j)]) for j in range(1, n): assert sum(map(lambda seq: autocorrelation(seq, j), [X, Y, Z, W])) == 0 @@ -577,12 +601,14 @@ def construction_four_symbol_delta_code_II(X, Y, Z, W): n = len(Z) assert len(X) == n+1 and len(Y) == n+1 and len(W) == n - autocorrelation = lambda seq, j: sum([seq[i]*seq[i+j] for i in range(len(seq)-j)]) + def autocorrelation(seq, j): + return sum([seq[i]*seq[i+j] for i in range(len(seq)-j)]) + for j in range(1, n): assert sum(map(lambda seq: autocorrelation(seq, j), [X, Y, Z, W])) == 0 def alternate(seq1, seq2): - return [seq1[i//2] if i%2 == 0 else seq2[(i-1)//2] for i in range(len(seq1)+len(seq2))] + return [seq1[i//2] if i % 2 == 0 else seq2[(i-1)//2] for i in range(len(seq1)+len(seq2))] XaltZ = alternate(X, Z) Wneg = [-w for w in W] @@ -594,6 +620,7 @@ def alternate(seq1, seq2): T4 = XaltZ + alternate(Yneg, W) + [-1] return T1, T2, T3, T4 + def four_symbol_delta_code_smallcases(n, existence=False): r""" Return the 4-symobl `\delta` code of length `n` if available. @@ -628,18 +655,18 @@ def four_symbol_delta_code_smallcases(n, existence=False): db = { 1: ([1, -1], [1, 1], [1], [1]), 14: ([1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, 1], - [1, 1, 1,-1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1], - [1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1], - [1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1]) + [1, 1, 1, -1, 1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1], + [1, 1, 1, 1, -1, -1, 1, -1, 1, 1, -1, -1, -1, -1], + [1, -1, -1, -1, -1, 1, -1, 1, -1, 1, 1, 1, 1, -1]) } T1, T2, T3, T4 = None, None, None, None - if n%2 == 1 and (n-1)//2 in db: + if n % 2 == 1 and (n-1)//2 in db: if existence: return True X, Y, Z, W = db[(n-1)//2] T1, T2, T3, T4 = construction_four_symbol_delta_code_I(X, Y, Z, W) - elif n%4 == 3 and (n-3)//4 in db: + elif n % 4 == 3 and (n-3) // 4 in db: if existence: return True X, Y, Z, W = db[(n-3)//4] @@ -653,7 +680,8 @@ def four_symbol_delta_code_smallcases(n, existence=False): return T1, T2, T3, T4 -def _construction_goethals_seidel_matrix(A, B ,C, D): + +def _construction_goethals_seidel_matrix(A, B, C, D): r""" Construct the Goethals Seidel matrix. @@ -703,12 +731,13 @@ def _construction_goethals_seidel_matrix(A, B ,C, D): [-1 1| 1 -1| 1 -1| 1 1] """ n = len(A[0]) - R = matrix(ZZ, n, n, lambda i,j: 1 if i+j==n-1 else 0) + R = matrix(ZZ, n, n, lambda i, j: 1 if i+j == n-1 else 0) return block_matrix([[ A, B*R, C*R, D*R], [-B*R, A, -D.T*R, C.T*R], [-C*R, D.T*R, A, -B.T*R], [-D*R, -C.T*R, B.T*R, A]]) + def hadamard_matrix_cooper_wallis_construction(x1, x2, x3, x4, A, B, C, D, check=True): r""" Create an Hadamard matrix using the contruction detailed in [CW1972]_. @@ -797,6 +826,7 @@ def hadamard_matrix_cooper_wallis_construction(x1, x2, x3, x4, A, B, C, D, check assert is_hadamard_matrix(H) return H + def hadamard_matrix_cooper_wallis_smallcases(n, check=True, existence=False): r""" Construct Hadamard matrices using the Cooper-Wallis construction for some small values of `n`. @@ -856,7 +886,7 @@ def hadamard_matrix_cooper_wallis_smallcases(n, check=True, existence=False): ... AssertionError """ - assert n%4 == 0 and n > 0 + assert n % 4 == 0 and n > 0 db = { 67: ( @@ -868,7 +898,7 @@ def hadamard_matrix_cooper_wallis_smallcases(n, check=True, existence=False): } for T_seq_len in divisors(n//4): - will_size = n//(4* T_seq_len) + will_size = n // (4*T_seq_len) if (T_seq_len in db or T_sequences_smallcases(T_seq_len, existence=True)) and williamson_type_quadruples_smallcases(will_size, existence=True): if existence: return True @@ -891,6 +921,7 @@ def hadamard_matrix_cooper_wallis_smallcases(n, check=True, existence=False): return False raise ValueError("The Cooper-Wallis construction for Hadamard matrices of order %s is not yet implemented." % n) + def _get_baumert_hall_units(n, existence=False): r""" Construct Baumert-Hall units of size `n` from available 4-symbol `\delta` codes. @@ -935,8 +966,7 @@ def _get_baumert_hall_units(n, existence=False): ... ValueError: The Baumert-Hall units of size 200 have not yet been implemented """ - assert n%4 == 0 and n > 0 - + assert n % 4 == 0 and n > 0 delta_codes_len = n//4 if not four_symbol_delta_code_smallcases(delta_codes_len, existence=True): @@ -964,6 +994,7 @@ def _get_baumert_hall_units(n, existence=False): e4 = _construction_goethals_seidel_matrix(M4hat, M3hat, -M2hat, M1hat) return e1, e2, e3, e4 + def hadamard_matrix_turyn_type(a, b, c, d, e1, e2, e3, e4, check=True): r""" Construction of Turyn type Hadamard matrix. @@ -1019,11 +1050,11 @@ def hadamard_matrix_turyn_type(a, b, c, d, e1, e2, e3, e4, check=True): n = len(a) assert len(a) == len(b) == len(c) == len(d) - assert A*A.T+B*B.T+C*C.T+D*D.T==4*n*I(n) + assert A*A.T+B*B.T+C*C.T+D*D.T == 4*n*I(n) t4 = len(e1[0]) - assert t4 %4 == 0 - t = t4//4 + assert t4 % 4 == 0 + t = t4 // 4 # Check that e1, e2, e3, e4 are valid Baumert-Hall units for i in range(t4): @@ -1037,12 +1068,12 @@ def hadamard_matrix_turyn_type(a, b, c, d, e1, e2, e3, e4, check=True): for j in range(i+1, len(units)): assert units[i]*units[j].T + units[j]*units[i].T == 0*I(t4) - H = e1.tensor_product(A) + e2.tensor_product(B) + e3.tensor_product(C) + e4.tensor_product(D) if check: assert is_hadamard_matrix(H) return H + def turyn_type_hadamard_matrix_smallcases(n, existence=False, check=True): r""" Construct an Hadamard matrix of order `n` from available 4-symbol `\delta` codes and Williamson quadruples. @@ -1058,7 +1089,7 @@ def turyn_type_hadamard_matrix_smallcases(n, existence=False, check=True): - ``existence`` -- boolean (default False): if True, only check if matrix exists. - - ``check`` -- bolean: if True (default), check the the matrix is an Hadamard matrix before returning. + - ``check`` -- boolean: if True (default), check the the matrix is an Hadamard matrix before returning. EXAMPLES:: @@ -1080,7 +1111,7 @@ def turyn_type_hadamard_matrix_smallcases(n, existence=False, check=True): ... ValueError: The Turyn type construction for Hadamard matrices of order 64 is not yet implemented. """ - assert n%4 == 0 and n > 0 + assert n % 4 == 0 and n > 0 for delta_code_len in divisors(n//4): units_size = delta_code_len*4 @@ -1097,6 +1128,7 @@ def turyn_type_hadamard_matrix_smallcases(n, existence=False, check=True): return False raise ValueError("The Turyn type construction for Hadamard matrices of order %s is not yet implemented." % n) + def hadamard_matrix_spence_construction(n, existence=False, check=True): r"""Create an Hadamard matrix of order `n` using Spence construction. @@ -1150,7 +1182,7 @@ def hadamard_matrix_spence_construction(n, existence=False, check=True): """ from sage.combinat.designs.difference_family import supplementary_difference_set - assert n%4 == 0 and n > 0 + assert n % 4 == 0 and n > 0 q = n//4 @@ -1167,7 +1199,7 @@ def hadamard_matrix_spence_construction(n, existence=False, check=True): A3 = matrix.circulant([1 if j in S3 else -1 for j in range(q-1)]) A4 = matrix.circulant([1 if j in S2 else -1 for j in range(q-1)]) - P = matrix(ZZ, [[1 if (i + j)%(q-1) == 0 else 0 for i in range(1, q)] for j in range(1, q)]) + P = matrix(ZZ, [[1 if (i + j) % (q-1) == 0 else 0 for i in range(1, q)] for j in range(1, q)]) e = matrix([1]*(q-1)) m1 = matrix([-1]) @@ -1185,6 +1217,7 @@ def hadamard_matrix_spence_construction(n, existence=False, check=True): return H + def is_hadamard_matrix(M, normalized=False, skew=False, verbose=False): r""" Test if `M` is a Hadamard matrix. @@ -1243,6 +1276,14 @@ def is_hadamard_matrix(M, normalized=False, skew=False, verbose=False): False sage: is_hadamard_matrix(h, skew=False, verbose=True) True + sage: h = skew_hadamard_matrix(20, skew_normalize=False) + sage: is_hadamard_matrix(h, skew=True, normalized=True, verbose=True) + The matrix is not skew-normalized + False + sage: from sage.combinat.matrices.hadamard_matrix import normalise_hadamard + sage: h = normalise_hadamard(h, skew=True) + sage: is_hadamard_matrix(h, skew=True, normalized=True, verbose=True) + True """ n = M.ncols() if n != M.nrows(): @@ -1261,16 +1302,17 @@ def is_hadamard_matrix(M, normalized=False, skew=False, verbose=False): return False prod = (M*M.transpose()).dict() - if (len(prod) != n or - set(prod.values()) != {n} or - any((i, i) not in prod for i in range(n))): + if (len(prod) != n or set(prod.values()) != {n} or any((i, i) not in prod for i in range(n))): if verbose: print("The product M*M.transpose() is not equal to nI") return False if normalized: - if (set(M.row(0) ) != {1} or - set(M.column(0)) != {1}): + if skew and (set(M.row(0)) != {1}): + if verbose: + print("The matrix is not skew-normalized") + return False + elif not skew and (set(M.row(0)) != {1} or set(M.column(0)) != {1}): if verbose: print("The matrix is not normalized") return False @@ -1278,20 +1320,54 @@ def is_hadamard_matrix(M, normalized=False, skew=False, verbose=False): if skew: for i in range(n-1): for j in range(i+1, n): - if M[i,j] != -M[j,i]: + if M[i, j] != -M[j, i]: if verbose: print("The matrix is not skew") return False for i in range(n): - if M[i,i] != 1: + if M[i, i] != 1: if verbose: print("The matrix is not skew - diagonal entries must be all 1") return False return True -from sage.matrix.constructor import matrix_method + +def is_skew_hadamard_matrix(M, normalized=False, verbose=False): + r""" + Test if `M` is a skew Hadamard matrix. + + this is a wrapper around the function :func:`is_hadamard_matrix` + + INPUT: + + - ``M`` -- a matrix + + - ``normalized`` (boolean) -- whether to test if ``M`` is a skew-normalized + Hadamard matrix, i.e. has its first row filled with +1. + + - ``verbose`` (boolean) -- whether to be verbose when the matrix is not + skew Hadamard. + + EXAMPLES:: + + sage: from sage.combinat.matrices.hadamard_matrix import is_skew_hadamard_matrix, skew_hadamard_matrix + sage: h = matrix.hadamard(12) + sage: is_skew_hadamard_matrix(h, verbose=True) + The matrix is not skew + False + sage: h = skew_hadamard_matrix(12) + sage: is_skew_hadamard_matrix(h) + True + sage: from sage.combinat.matrices.hadamard_matrix import normalise_hadamard + sage: h = normalise_hadamard(skew_hadamard_matrix(12), skew=True) + sage: is_skew_hadamard_matrix(h, verbose=True, normalized=True) + True + """ + return is_hadamard_matrix(M, skew=True, normalized=normalized, verbose=verbose) + + @matrix_method -def hadamard_matrix(n,existence=False, check=True): +def hadamard_matrix(n, existence=False, check=True): r""" Tries to construct a Hadamard matrix using the available methods. @@ -1379,7 +1455,7 @@ def hadamard_matrix(n,existence=False, check=True): sage: matrix.hadamard(324, existence=True) True """ - if not(n % 4 == 0) and (n > 2): + if not (n % 4 == 0) and (n > 2): if existence: return False raise ValueError("The Hadamard matrix of order %s does not exist" % n) @@ -1395,10 +1471,10 @@ def hadamard_matrix(n,existence=False, check=True): if existence: return True M = hadamard_matrix_paleyII(n) - elif n == 4 or n % 8 == 0 and hadamard_matrix(n//2,existence=True) is True: + elif n == 4 or n % 8 == 0 and hadamard_matrix(n//2, existence=True) is True: if existence: return True - had = hadamard_matrix(n//2,check=False) + had = hadamard_matrix(n//2, check=False) chad1 = matrix([list(r) + list(r) for r in had.rows()]) mhad = (-1) * had R = len(had.rows()) @@ -1425,7 +1501,7 @@ def hadamard_matrix(n,existence=False, check=True): if existence: return True M = turyn_type_hadamard_matrix_smallcases(n, check=False) - elif hadamard_matrix_spence_construction(n ,existence=True): + elif hadamard_matrix_spence_construction(n, existence=True): if existence: return True M = hadamard_matrix_spence_construction(n, check=False) @@ -1504,7 +1580,7 @@ def hadamard_matrix_www(url_file, comments=False): _rshcd_cache = {} -def regular_symmetric_hadamard_matrix_with_constant_diagonal(n,e,existence=False): +def regular_symmetric_hadamard_matrix_with_constant_diagonal(n, e, existence=False): r""" Return a Regular Symmetric Hadamard Matrix with Constant Diagonal. @@ -1573,13 +1649,13 @@ def regular_symmetric_hadamard_matrix_with_constant_diagonal(n,e,existence=False - [HX2010]_ """ - if existence and (n,e) in _rshcd_cache: - return _rshcd_cache[n,e] + if existence and (n, e) in _rshcd_cache: + return _rshcd_cache[n, e] from sage.graphs.strongly_regular_db import strongly_regular_graph def true(): - _rshcd_cache[n,e] = True + _rshcd_cache[n, e] = True return True M = None @@ -1588,7 +1664,7 @@ def true(): sqn = None if is_square(n): sqn = int(sqrt(n)) - if n<0: + if n < 0: if existence: return False raise ValueError @@ -1596,31 +1672,31 @@ def true(): if existence: return true() if e == 1: - M = J(4)-2*matrix(4,[[int(i+j == 3) for i in range(4)] for j in range(4)]) + M = J(4)-2*matrix(4, [[int(i+j == 3) for i in range(4)] for j in range(4)]) else: M = -J(4)+2*I(4) - elif n == 36: + elif n == 36: if existence: return true() if e == 1: M = strongly_regular_graph(36, 15, 6, 6).adjacency_matrix() M = J(36) - 2*M else: - M = strongly_regular_graph(36,14,4,6).adjacency_matrix() - M = -J(36) + 2*M + 2*I(36) + M = strongly_regular_graph(36, 14, 4, 6).adjacency_matrix() + M = -J(36) + 2*M + 2*I(36) elif n == 100: if existence: return true() if e == -1: - M = strongly_regular_graph(100,44,18,20).adjacency_matrix() + M = strongly_regular_graph(100, 44, 18, 20).adjacency_matrix() M = 2*M - J(100) + 2*I(100) else: - M = strongly_regular_graph(100,45,20,20).adjacency_matrix() + M = strongly_regular_graph(100, 45, 20, 20).adjacency_matrix() M = J(100) - 2*M elif n == 196 and e == 1: if existence: return true() - M = strongly_regular_graph(196,91,42,42).adjacency_matrix() + M = strongly_regular_graph(196, 91, 42, 42).adjacency_matrix() M = J(196) - 2*M elif n == 324: if existence: @@ -1638,7 +1714,7 @@ def true(): elif (e == 1 and sqn is not None and sqn % 4 == 2 and - strongly_regular_graph(sqn-1,(sqn-2)//2,(sqn-6)//4, + strongly_regular_graph(sqn-1, (sqn-2)//2, (sqn-6)//4, existence=True) is True and is_prime_power(ZZ(sqn + 1))): if existence: @@ -1648,30 +1724,31 @@ def true(): # Recursive construction: the Kronecker product of two RSHCD is a RSHCD else: from itertools import product - for n1,e1 in product(divisors(n)[1:-1],[-1,1]): + for n1, e1 in product(divisors(n)[1:-1], [-1, 1]): e2 = e1*e n2 = n//n1 - if (regular_symmetric_hadamard_matrix_with_constant_diagonal(n1,e1,existence=True) is True and - regular_symmetric_hadamard_matrix_with_constant_diagonal(n2,e2,existence=True)) is True: + if (regular_symmetric_hadamard_matrix_with_constant_diagonal(n1, e1, existence=True) is True and + regular_symmetric_hadamard_matrix_with_constant_diagonal(n2, e2, existence=True)) is True: if existence: return true() - M1 = regular_symmetric_hadamard_matrix_with_constant_diagonal(n1,e1) - M2 = regular_symmetric_hadamard_matrix_with_constant_diagonal(n2,e2) - M = M1.tensor_product(M2) + M1 = regular_symmetric_hadamard_matrix_with_constant_diagonal(n1, e1) + M2 = regular_symmetric_hadamard_matrix_with_constant_diagonal(n2, e2) + M = M1.tensor_product(M2) break if M is None: from sage.misc.unknown import Unknown - _rshcd_cache[n,e] = Unknown + _rshcd_cache[n, e] = Unknown if existence: return Unknown - raise ValueError("I do not know how to build a {}-RSHCD".format((n,e))) + raise ValueError("I do not know how to build a {}-RSHCD".format((n, e))) assert M*M.transpose() == n*I(n) - assert set(map(sum,M)) == {ZZ(e*sqn)} + assert set(map(sum, M)) == {ZZ(e*sqn)} return M + def RSHCD_324(e): r""" Return a size 324x324 Regular Symmetric Hadamard Matrix with Constant Diagonal. @@ -1717,15 +1794,16 @@ def RSHCD_324(e): from sage.graphs.generators.smallgraphs import JankoKharaghaniTonchevGraph as JKTG M = JKTG().adjacency_matrix() M = J(324) - 2*M - if e==-1: - M1=M[:162].T - M2=M[162:].T - M11=M1[:162] - M12=M1[162:].T - M21=M2[:162].T - M=block_matrix([[M12,-M11],[-M11.T,M21]]) + if e == -1: + M1 = M[:162].T + M2 = M[162:].T + M11 = M1[:162] + M12 = M1[162:].T + M21 = M2[:162].T + M = block_matrix([[M12, -M11], [-M11.T, M21]]) return M + def _helper_payley_matrix(n, zero_position=True): r""" Return the matrix constructed in Lemma 1.19 page 291 of [SWW1972]_. @@ -1852,23 +1930,23 @@ def rshcd_from_close_prime_powers(n): - [SWW1972]_ """ - if n%4: + if n % 4: raise ValueError("n(={}) must be congruent to 0 mod 4") - a,b = sorted([n-1,n+1],key=lambda x:-x%4) - Sa = _helper_payley_matrix(a) - Sb = _helper_payley_matrix(b) - U = matrix(a,[[int(i+j == a-1) for i in range(a)] for j in range(a)]) + a, b = sorted([n-1, n+1], key=lambda x: -x % 4) + Sa = _helper_payley_matrix(a) + Sb = _helper_payley_matrix(b) + U = matrix(a, [[int(i+j == a-1) for i in range(a)] for j in range(a)]) K = (U*Sa).tensor_product(Sb) + U.tensor_product(J(b)-I(b)) - J(a).tensor_product(I(b)) - F = lambda x:diagonal_matrix([-(-1)**i for i in range(x)]) - G = block_diagonal_matrix([J(1),I(a).tensor_product(F(b))]) - e = matrix(a*b,[1]*(a*b)) - H = block_matrix(2,[-J(1),e.transpose(),e,K]) + F = lambda x: diagonal_matrix([-(-1)**i for i in range(x)]) + G = block_diagonal_matrix([J(1), I(a).tensor_product(F(b))]) + e = matrix(a*b, [1]*(a*b)) + H = block_matrix(2, [-J(1), e.transpose(), e, K]) HH = G*H*G - assert len(set(map(sum,HH))) == 1 + assert len(set(map(sum, HH))) == 1 assert HH**2 == n**2*I(n**2) return HH @@ -1909,16 +1987,103 @@ def williamson_goethals_seidel_skew_hadamard_matrix(a, b, c, d, check=True): - [KoSt08]_ """ n = len(a) - A,B,C,D=map(matrix.circulant, [a,b,c,d]) + A, B, C, D = map(matrix.circulant, [a, b, c, d]) if check: - assert A*A.T+B*B.T+C*C.T+D*D.T==4*n*I(n) - assert A+A.T==2*I(n) + assert A*A.T+B*B.T+C*C.T+D*D.T == 4*n*I(n) + assert A+A.T == 2*I(n) M = _construction_goethals_seidel_matrix(A, B, C, D) if check: assert is_hadamard_matrix(M, normalized=False, skew=True) return M + +def skew_hadamard_matrix_spence_construction(n, check=True): + r""" + Construct skew Hadamard matrix of order `n` using Spence constrution. + + This function will construct skew Hadamard matrix of order `n=2(q+1)` where `q` is + a prime power with `q = 5` (mod 8). The construction is taken from [Spe1977]_, and the + relative difference sets are constructed using :func:`sage.combinat.designs.difference_family.relative_difference_set_from_homomorphism`. + + INPUT: + + - ``n`` -- A positive integer. + + - ``check`` -- boolean. If true (default), check that the resulting matrix is Hadamard + before returning it. + + OUTPUT: + + If `n` satisfies the requirements described above, the function returns a `n\times n` Hadamard matrix. + Otherwise, an exception is raised. + + EXAMPLES:: + + sage: from sage.combinat.matrices.hadamard_matrix import skew_hadamard_matrix_spence_construction + sage: skew_hadamard_matrix_spence_construction(28) + 28 x 28 dense matrix over Integer Ring... + + TESTS:: + + sage: from sage.combinat.matrices.hadamard_matrix import is_hadamard_matrix + sage: is_hadamard_matrix(skew_hadamard_matrix_spence_construction(12, check=False), skew=True) + True + sage: is_hadamard_matrix(skew_hadamard_matrix_spence_construction(60, check=False), skew=True) + True + sage: skew_hadamard_matrix_spence_construction(31) + Traceback (most recent call last): + ... + ValueError: The order 31 is not covered by the Spence construction. + sage: skew_hadamard_matrix_spence_construction(16) + Traceback (most recent call last): + ... + ValueError: The order 16 is not covered by the Spence construction. + """ + q = n//2 - 1 + m = (q+1)//2 + if n % 4 != 0 or not is_prime_power(q) or q % 8 != 5: + raise ValueError(f'The order {n} is not covered by the Spence construction.') + + D = relative_difference_set_from_homomorphism(q, 2, (q-1)//4, check=False) + D_fixed = get_fixed_relative_difference_set(D) + D_union = D_fixed + [q+1+el for el in D_fixed] + D_union = list(set([el % (4*(q+1)) for el in D_union])) + + def find_a(i): + for a in range(8): + if (a*(q+1)//2+i) % 8 == 0: + return a + + ai = [find_a(0), find_a(1), find_a(2), find_a(3)] + P = PolynomialRing(ZZ, 'x') + + Tm = 0 + for i in range(m): + Tm += P.monomial(i) + + Ds = [[] for i in range(4)] + + for el in D_union: + i = el % 8 + if i > 3: + continue + Ds[i].append(((el + ai[i] * m) // 8) % m) + + psis = [0 for i in range(4)] + for i in range(4): + for el in Ds[i]: + psis[i] += P.monomial(el) + + diffs = [(2*psis[i] - Tm).mod(P.monomial(m)-1) for i in range(4)] + a = [-el for el in diffs[1].coefficients()] + b = diffs[0].coefficients() + c = diffs[2].coefficients() + d = diffs[3].coefficients() + + return williamson_goethals_seidel_skew_hadamard_matrix(a, b, c, d, check=check) + + def GS_skew_hadamard_smallcases(n, existence=False, check=True): r""" Data for Williamson-Goethals-Seidel construction of skew Hadamard matrices @@ -1926,12 +2091,17 @@ def GS_skew_hadamard_smallcases(n, existence=False, check=True): Here we keep the data for this construction. Namely, it needs 4 circulant matrices with extra properties, as described in :func:`sage.combinat.matrices.hadamard_matrix.williamson_goethals_seidel_skew_hadamard_matrix` - Matrices for `n=36` and `52` are given in [GS70s]_. Matrices for `n=92` are given - in [Wall71]_. + Matrices are taken from: + + * `n=36, 52`: [GS70s]_ + * `n=92`: [Wall71]_ + * `n=188`: [Djo2008a]_ + * `n=236`: [FKS2004]_ + * `n=276`: [Djo2023a]_ Additional data is obtained from skew supplementary difference sets contained in :func:`sage.combinat.designs.difference_family.skew_supplementary_difference_set`, using the - construction described in [Djo1992]_. + construction described in [Djo1992a]_. INPUT: @@ -1957,27 +2127,29 @@ def GS_skew_hadamard_smallcases(n, existence=False, check=True): def pmtoZ(s): return [1 if x == '+' else -1 for x in s] - if existence: - return n in [36, 52, 92] or skew_supplementary_difference_set(n//4, existence=True) + db = { + 36: ['+++-+-+--', '+-++--++-', '--++++++-', '+++-++-++'], + 52: ['++++-++--+---', '-+-++----++-+', '--+-+++++-+++', '--+-+++++-+++'], + 92: ['+-------++-+-+--+++++++', '++--+--++++--++++--+--+', '++---+-+-+-++-+-+-+---+', '+----+--+--++--+--+----'], + 188: ['+----+----++-+-+---++-++--+--+++-+-+--++++-++++', + '++--+---+------++------++-+-++--+-+-+----+---++', + '+-+-++---++-+---+++---++-++-++-++-+++++-+-+----', + '+++-++-+-+---+-+++++--+-----++---+--+++++--++-+'], + 236: ['+-+---+-+-++-++---+----++-----+++++--++++-+++--+--+-+-+++-+', + '+-+---+-+-++-++---+----++-----+++++--++++-+++--+--+-+-+++-+', + '+++-++----+++-+-+++--+--++------+---+-----+--+-+--+---+----', + '++++++--+++--+---++-+-+-+---+-+----++++-++-+--++-+--+------'], + 276: ['+--+++--+-+++--+---++-+++++-+++-++-+--+---+-----+--+++-++---+-++---++', + '+-++--+-+----++-+---++++-+---+-++++++++-+---+-++++---+-++----+-+--++-', + '--+--+-++---+--++--+-+-+++-+--++---++++-+-+-+--+-++-+++++++--+--+++++', + '-+---+++-----++---+++-+++--+++++--+---+-+-++++-++++-++-++-+-+++++++++'] + } - if n == 36: - a = [ 1, 1, 1, -1, 1, -1, 1, -1, -1] - b = [ 1, -1, 1, 1, -1, -1, 1, 1, -1] - c = [-1, -1]+[1]*6+[-1] - d = [ 1, 1, 1, -1, 1, 1, -1, 1, 1] - return WGS(a, b, c, d, check=check) + if existence: + return n in db or skew_supplementary_difference_set(n//4, existence=True) - if n == 52: - a = pmtoZ('++++-++--+---') - b = pmtoZ('-+-++----++-+') - c = pmtoZ('--+-+++++-+++') - return WGS(a, b, c, c, check=check) - - if n == 92: - a = [1,-1,-1,-1,-1,-1,-1,-1, 1, 1,-1, 1,-1, 1,-1,-1, 1, 1, 1, 1, 1, 1, 1] - b = [1, 1,-1,-1, 1,-1,-1, 1, 1, 1, 1,-1,-1, 1, 1, 1, 1,-1,-1, 1,-1,-1, 1] - c = [1, 1,-1,-1,-1, 1,-1, 1,-1, 1,-1, 1, 1,-1, 1,-1, 1,-1, 1,-1,-1,-1, 1] - d = [1,-1,-1,-1,-1, 1,-1,-1, 1,-1,-1, 1, 1,-1,-1, 1,-1,-1, 1,-1,-1,-1,-1] + if n in db: + a, b, c, d = map(pmtoZ, db[n]) return WGS(a, b, c, d, check=check) if skew_supplementary_difference_set(n//4, existence=True): @@ -1991,9 +2163,348 @@ def pmtoZ(s): return None -_skew_had_cache={} -def skew_hadamard_matrix(n,existence=False, skew_normalize=True, check=True): +def skew_hadamard_matrix_whiteman_construction(n, existence=False, check=True): + r""" + Construct a skew Hadamard matrix of order `n=2(q+1)` where `q=p^t` is a prime power with `p \cong 5 \mod 8` and `t \cong 2 \mod 4`. + + Assuming `n` satisfies the conditions above, it is possible to construct two supplementary difference sets + `A, B` (see [Whi1971]_), and these can be used to construct a skew Hadamard matrix, as described in [BS1969]_. + + INPUT: + + - ``n`` -- A positive integer, the order of the matrix to be constructed. + + - ``existence`` -- boolean (default False). If True, only return whether the Hadamard matrix can be constructed. + + - ``check`` -- boolean: if True (default), check the the result is a skew Hadamard matrix + before returning it. + + OUTPUT: + + If ``existence`` is false, returns the skew Hadamard matrix of order `n`. It raises an error if `n` does + not satisfy the required conditions. + If ``existence`` is true, returns a boolean representing whether the matrix can be constructed or not. + + EXAMPLES:: + + sage: from sage.combinat.matrices.hadamard_matrix import skew_hadamard_matrix_whiteman_construction + sage: skew_hadamard_matrix_whiteman_construction(52) + 52 x 52 dense matrix over Integer Ring... + sage: skew_hadamard_matrix_whiteman_construction(52, existence=True) + True + + TESTS:: + + sage: from sage.combinat.matrices.hadamard_matrix import is_hadamard_matrix + sage: is_hadamard_matrix(skew_hadamard_matrix_whiteman_construction(52, check=False), skew=True) + True + sage: is_hadamard_matrix(skew_hadamard_matrix_whiteman_construction(340, check=False), skew=True) + True + sage: skew_hadamard_matrix_whiteman_construction(31) + Traceback (most recent call last): + ... + ValueError: The order 31 is not covered by the Whiteman construction. + sage: skew_hadamard_matrix_whiteman_construction(100) + Traceback (most recent call last): + ... + ValueError: The order 100 is not covered by the Whiteman construction. + sage: skew_hadamard_matrix_whiteman_construction(100, existence=True) + False + """ + + q = n // 2 - 1 + p, t = is_prime_power(q, get_data=True) + + is_order_valid = n % 4 == 0 and t > 0 and p % 8 == 5 and t % 4 == 2 + if existence: + return is_order_valid + + if not is_order_valid: + raise ValueError(f'The order {n} is not covered by the Whiteman construction.') + + from sage.rings.finite_rings.finite_field_constructor import GF + G = GF(q) + f = (q-1) // 8 + Cs = {i: [G.gen()**(8*s+i) for s in range(f)] for i in [0, 1, 2, 3, 6, 7]} + A = Cs[0] + Cs[1] + Cs[2] + Cs[3] + B = Cs[0] + Cs[1] + Cs[6] + Cs[7] + + m = n//4 - 1 + Glist = list(G) + + S = [[0 for i in range(n)] for j in range(n)] + for i in range(2*m + 1): + for j in range(2*m + 1): + S[2*m + 1 + i][2*m + 1 + j] = -1 if Glist[j] - Glist[i] in A else 1 + S[i][j] = -S[2*m + 1 + i][2*m + 1 + j] + S[2*m + 1 + j][i] = -1 if Glist[j] - Glist[i] in B else 1 + S[i][2*m + 1 + j] = -S[2*m + 1 + j][i] + S[4*m + 2][i] = -1 + S[4*m + 2][2*m + 1 + i] = 1 + S[i][4*m + 2] = 1 + S[i + 2*m + 1][4*m + 2] = -1 + for i in range(4*m + 3): + S[4*m + 3][i] = 1 + S[i][4*m + 3] = -1 + for i in range(4*m + 4): + S[i][i] = 1 + + H = matrix(S) + + if check: + assert is_hadamard_matrix(H, skew=True) + return H + + +def skew_hadamard_matrix_324(): + r""" + Construct a skew Hadamard matrix of order 324. + + The construction is taken from [Djo1994]_. It uses four supplementary difference sets `S_1, S_2, S_3, S_4`, + with `S_1` of skew type. These are then used to generate four matrices of order `81`, which are + inserted into the Goethals-Seidel array. + + EXAMPLES:: + + sage: from sage.combinat.matrices.hadamard_matrix import skew_hadamard_matrix_324 + sage: skew_hadamard_matrix_324() + 324 x 324 dense matrix over Integer Ring... + + TESTS:: + + sage: from sage.combinat.matrices.hadamard_matrix import is_hadamard_matrix + sage: is_hadamard_matrix(skew_hadamard_matrix_324(), skew=True) + True + """ + from sage.symbolic.ring import SymbolicRing + from sage.rings.finite_rings.integer_mod_ring import Zmod + + R = SymbolicRing() + x = R.var('x') + Z3 = Zmod(3) + F = Z3.extension(x**4 - x**3 - 1) + H = [(F.gen()**16)**i for i in range(10)] + + cosets = [] + for i in range(8): + cosets.append([F.gen()**i * el for el in H]) + cosets.append([-F.gen()**i * el for el in H]) + + def generate_set(index_set, cosets): + S = [] + for idx in index_set: + S += cosets[idx] + return S + + S1 = generate_set([1, 2, 4, 6, 8, 10, 12, 14], cosets) + S2 = generate_set([1, 2, 3, 4, 10, 11, 13], cosets) + S3 = generate_set([4, 5, 6, 8, 12, 13, 14], cosets) + S4 = generate_set([2, 4, 5, 6, 7, 11, 12, 13, 15], cosets) + + A = matrix([[-1 if y-x in S1 else +1 for y in F] for x in F]) + B = matrix([[-1 if y-x in S2 else +1 for y in F] for x in F]) + C = matrix([[-1 if y-x in S3 else +1 for y in F] for x in F]) + D = matrix([[-1 if y-x in S4 else +1 for y in F] for x in F]) + + return _construction_goethals_seidel_matrix(A, B, C, D) + + +def skew_hadamard_matrix_from_good_matrices(a, b, c, d, check=True): + r""" + Construct skew Hadamard matrix from good matrices. + + Given good matrices `A`, `B`, `C`, `D` (`A` circulant, `B, C, D` back-circulant) they can be used to construct + a skew Hadamard matrix using the following block matrix (as described in [Sze1988]_): + + .. MATH:: + + \left(\begin{array}{rrrr} + A & B & C & D \\ + -B & A & D & -C \\ + -C & -D & A & B \\ + -D & C & -B & A + \end{array}\right) + + INPUT: + + - ``a`` -- (1,-1) list specifying the 1st row of `A`. + + - ``b`` -- (1,-1) list specifying the 1st row of `B`. + + - ``d`` -- (1,-1) list specifying the 1st row of `C`. + + - ``c`` -- (1,-1) list specifying the 1st row of `D`. + + - ``check`` -- boolean: if True (default), check that the matrix is a skew Hadamard matrix before returning it. + + EXAMPLES:: + + sage: from sage.combinat.matrices.hadamard_matrix import skew_hadamard_matrix_from_good_matrices + sage: a, b, c, d = ([1, 1, 1, -1, -1], [1, -1, 1, 1, -1], [1, -1, -1, -1, -1], [1, -1, -1, -1, -1]) + sage: skew_hadamard_matrix_from_good_matrices(a, b, c, d) + 20 x 20 dense matrix over Integer Ring... + + TESTS:: + + sage: from sage.combinat.matrices.hadamard_matrix import is_hadamard_matrix + sage: a, b, c, d = ([1, 1, 1, -1, -1], [1, -1, 1, 1, -1], [1, -1, -1, -1, -1], [1, -1, -1, -1, -1]) + sage: is_hadamard_matrix(skew_hadamard_matrix_from_good_matrices(a, b, c, d, check=False), skew=True) + True + sage: a, b, c, d = ([1, 1, 1, -1, -1], [1, -1, 1, 1, -1], [1, -1, -1, -1, -1], [1, -1, -1, -1, 1]) + sage: skew_hadamard_matrix_from_good_matrices(a, b, c, d) + Traceback (most recent call last): + ... + AssertionError + sage: a, b, c, d = ([1, 1, 1], [1, -1, 1, 1, -1], [1, -1, -1, -1, -1], [1, -1, -1, -1, -1]) + sage: skew_hadamard_matrix_from_good_matrices(a, b, c, d) + Traceback (most recent call last): + ... + AssertionError + """ + n = len(a) + m = (n-1) // 2 + + assert len(a) == len(b) == len(c) == len(d) + assert a[0] == 1 and b[0] == 1 and c[0] == 1 and d[0] == 1 + for i in range(1, m+1): + assert a[i] == -a[n-i] and b[i] == b[n-i] and c[i] == c[n-i] and d[i] == d[n-i] + + def back_circulant(row): + length = len(row) + return matrix([[row[(j+i) % length] for j in range(length)] for i in range(length)]) + + A = matrix.circulant(a) + B = back_circulant(b) + C = back_circulant(c) + D = back_circulant(d) + + H = block_matrix([[ A, B, C, D], + [-B, A, D, -C], + [-C, -D, A, B], + [-D, C, -B, A]]) + + if check: + assert is_hadamard_matrix(H, skew=True) + return H + + +def skew_hadamard_matrix_from_good_matrices_smallcases(n, existence=False, check=True): + r""" + Construct skew Hadamard matrices from good matrices for some small values of `n=4m`, with `m` odd. + + The function stores good matrices of odd orders `\le 31`, taken from [Sze1988]_. + These are used to create skew Hadamard matrices of order `4m`, `1 \le m \le 31` (`m` odd), using the function + :func:`skew_hadamard_matrix_from_good_matrices`. + + ALGORITHM: + + Given four sequences (stored in ``E_sequences``) of length `m`, they can be used to construct four `E-sequences` + of length `n=2m+1`, as follows: + + .. MATH:: + + \begin{aligned} + a &= 1, a_0, a_1, ..., a_m, -a_m, -a_{m-1}, ..., -a_0 \\ + b &= 1, b_0, b_1, ..., b_m, b_m, b_{m-1}, ..., b_0 \\ + c &= 1, c_0, c_1, ..., c_m, c_m, c_{m-1}, ..., c_0 \\ + d &= 1, d_0, d_1, ..., d_m, d_m, d_{m-1}, ..., d_0 \\ + \end{aligned} + + These E-sequences will be the first rows of the four good matrices needed to construct a skew Hadamard matrix + of order `4n`. + + INPUT: + + - ``n`` -- the order of the skew Hadamard matrix to be constructed. + + - ``existence`` -- boolean (default False). If True, only return whether the Hadamard matrix can be constructed. + + - ``check`` -- boolean: if True (default), check the the matrix is an Hadamard matrix before returning it. + + OUTPUT: + + If ``existence`` is false, returns the skew Hadamard matrix of order `n`. It raises an error if no data + is available to construct the matrix of the given order. + If ``existence`` is true, returns a boolean representing whether the matrix can be constructed or not. + + EXAMPLES:: + + sage: from sage.combinat.matrices.hadamard_matrix import skew_hadamard_matrix_from_good_matrices_smallcases + sage: skew_hadamard_matrix_from_good_matrices_smallcases(20) + 20 x 20 dense matrix over Integer Ring... + sage: skew_hadamard_matrix_from_good_matrices_smallcases(20, existence=True) + True + + TESTS:: + + sage: from sage.combinat.matrices.hadamard_matrix import is_hadamard_matrix + sage: is_hadamard_matrix(skew_hadamard_matrix_from_good_matrices_smallcases(28, check=False), skew=True) + True + sage: skew_hadamard_matrix_from_good_matrices_smallcases(140) + Traceback (most recent call last): + ... + ValueError: The Good matrices of order 35 are not yet implemented. + sage: skew_hadamard_matrix_from_good_matrices_smallcases(14) + Traceback (most recent call last): + ... + ValueError: The skew Hadamard matrix of order 14 from good matrices does not exist. + sage: skew_hadamard_matrix_from_good_matrices_smallcases(140, existence=True) + False + sage: skew_hadamard_matrix_from_good_matrices_smallcases(14, existence=True) + False + """ + E_sequences = { + 0: ['', '', '', ''], + 1: ['+', '-', '-', '+'], + 2: ['++', '-+', '--', '--'], + 3: ['++-', '++-', '+-+', '-++'], + 4: ['+++-', '+-+-', '---+', '++-+'], + 5: ['+-+--', '+++--', '-+++-', '---+-'], + 6: ['+-+---', '---+++', '+-+--+', '----+-'], + 7: ['+++++--', '-++--++', '----+-+', '-+---+-'], + 8: ['+--++-+-', '+--+----', '++----+-', '+---+-+-'], + 9: ['-+-----++', '+-+++++--', '-+----++-', '--+-+-++-'], + 10: ['+--+++++++', '++--++++-+', '--++-+-+-+', '---+++-+-+'], + 11: ['++-+-------', '+----+--+--', '+-+--++---+', '--++-+-+-++'], + 12: ['+-----+-+---', '+-++++-+-++-', '---+--++++--', '--+-+++--+--'], + 13: ['+---+-+--++-+', '+++---++-++-+', '+++-+++-++---', '+---++++-+-+-'], + 14: ['+--+----+-+-++', '+---++++-++--+', '+-+----++-+--+', '++++++---+-+-+'], + 15: ['+--++----+---+-', '-++-+---+-+++--', '++---+--+--+++-', '-++++++++--+-+-'] + } + + def pm_to_good_matrix(s, sign=1): + e1 = [1 if x == '+' else -1 for x in s] + e2 = [sign * (1 if x == '+' else -1) for x in s] + e2.reverse() + return [1] + e1 + e2 + + if not (n % 4 == 0 and (n//4) % 2 == 1): + if existence: + return False + raise ValueError("The skew Hadamard matrix of order %s from good matrices does not exist." % n) + + m = n//4 + l = (m-1) // 2 + + if existence: + return l in E_sequences + + if l not in E_sequences: + raise ValueError("The Good matrices of order %s are not yet implemented." % m) + + e1, e2, e3, e4 = E_sequences[l] + a = pm_to_good_matrix(e1, sign=-1) + b = pm_to_good_matrix(e2) + c = pm_to_good_matrix(e3) + d = pm_to_good_matrix(e4) + return skew_hadamard_matrix_from_good_matrices(a, b, c, d, check=check) + + +_skew_had_cache = {} + + +def skew_hadamard_matrix(n, existence=False, skew_normalize=True, check=True): r""" Tries to construct a skew Hadamard matrix @@ -2059,11 +2570,11 @@ def skew_hadamard_matrix(n,existence=False, skew_normalize=True, check=True): 92 x 92 dense matrix over Integer Ring... sage: skew_hadamard_matrix(816) # long time 816 x 816 dense matrix over Integer Ring... - sage: skew_hadamard_matrix(100) + sage: skew_hadamard_matrix(356) Traceback (most recent call last): ... - ValueError: A skew Hadamard matrix of order 100 is not yet implemented. - sage: skew_hadamard_matrix(100,existence=True) + ValueError: A skew Hadamard matrix of order 356 is not yet implemented. + sage: skew_hadamard_matrix(356,existence=True) Unknown Check that :trac:`28526` is fixed:: @@ -2086,7 +2597,7 @@ def true(): M = None if existence and n in _skew_had_cache: return True - if not(n % 4 == 0) and (n > 2): + if not (n % 4 == 0) and (n > 2): if existence: return False raise ValueError("A skew Hadamard matrix of order %s does not exist" % n) @@ -2098,35 +2609,50 @@ def true(): if existence: return true() M = matrix([1]) + elif n == 324: + if existence: + return true() + M = skew_hadamard_matrix_324() + elif skew_hadamard_matrix_from_good_matrices_smallcases(n, existence=True): + if existence: + return true() + M = skew_hadamard_matrix_from_good_matrices_smallcases(n, check=False) elif is_prime_power(n - 1) and ((n - 1) % 4 == 3): if existence: return true() M = hadamard_matrix_paleyI(n, normalize=False) - + elif is_prime_power(n//2 - 1) and (n//2 - 1) % 8 == 5: + if existence: + return true() + M = skew_hadamard_matrix_spence_construction(n, check=False) + elif skew_hadamard_matrix_whiteman_construction(n, existence=True): + if existence: + return true() + M = skew_hadamard_matrix_whiteman_construction(n, check=False) elif n % 8 == 0: - if skew_hadamard_matrix(n//2,existence=True) is True: # (Lemma 14.1.6 in [Ha83]_) + if skew_hadamard_matrix(n//2, existence=True) is True: # (Lemma 14.1.6 in [Ha83]_) if existence: return true() - H = skew_hadamard_matrix(n//2,check=False) - M = block_matrix([[H,H], [-H.T,H.T]]) + H = skew_hadamard_matrix(n//2, check=False) + M = block_matrix([[H, H], [-H.T, H.T]]) - else: # try Williamson construction (Lemma 14.1.5 in [Ha83]_) - for d in divisors(n)[2:-2]: # skip 1, 2, n/2, and n + else: # try Williamson construction (Lemma 14.1.5 in [Ha83]_) + for d in divisors(n)[2:-2]: # skip 1, 2, n/2, and n n1 = n//d if is_prime_power(d - 1) and (d % 4 == 0) and (n1 % 4 == 0)\ - and skew_hadamard_matrix(n1,existence=True) is True: + and skew_hadamard_matrix(n1, existence=True) is True: if existence: return true() H = skew_hadamard_matrix(n1, check=False)-I(n1) - U = matrix(ZZ, d, lambda i, j: -1 if i==j==0 else\ - 1 if i==j==1 or (i>1 and j-1==d-i)\ + U = matrix(ZZ, d, lambda i, j: -1 if i == j == 0 else + 1 if i == j == 1 or (i > 1 and j-1 == d-i) else 0) - A = block_matrix([[matrix([0]), matrix(ZZ,1,d-1,[1]*(d-1))], - [ matrix(ZZ,d-1,1,[-1]*(d-1)), - _helper_payley_matrix(d-1,zero_position=0)]])+I(d) + A = block_matrix([[matrix([0]), matrix(ZZ, 1, d-1, [1]*(d-1))], + [matrix(ZZ, d-1, 1, [-1]*(d-1)), + _helper_payley_matrix(d-1, zero_position=0)]])+I(d) M = A.tensor_product(I(n1))+(U*A).tensor_product(H) break - if M is None: # try Williamson-Goethals-Seidel construction + if M is None: # try Williamson-Goethals-Seidel construction if GS_skew_hadamard_smallcases(n, existence=True) is True: if existence: return true() @@ -2137,15 +2663,13 @@ def true(): return Unknown raise ValueError("A skew Hadamard matrix of order %s is not yet implemented." % n) if skew_normalize: - dd = diagonal_matrix(M[0]) - M = dd*M*dd + M = normalise_hadamard(M, skew=True) if check: - assert is_hadamard_matrix(M, normalized=False, skew=True) - if skew_normalize: - assert M[0]==vector([1]*n) - _skew_had_cache[n]=True + assert is_hadamard_matrix(M, normalized=skew_normalize, skew=True) + _skew_had_cache[n] = True return M + def symmetric_conference_matrix(n, check=True): r""" Tries to construct a symmetric conference matrix @@ -2185,12 +2709,12 @@ def symmetric_conference_matrix(n, check=True): """ from sage.graphs.strongly_regular_db import strongly_regular_graph as srg try: - m = srg(n-1,(n-2)/2,(n-6)/4,(n-2)/4) + m = srg(n-1, (n-2)/2, (n-6)/4, (n-2)/4) except ValueError: raise C = matrix([0]+[1]*(n-1)).stack(matrix([1]*(n-1)).stack(m.seidel_adjacency_matrix()).T) if check: - assert (C==C.T and C**2==(n-1)*I(n)) + assert (C == C.T and C**2 == (n-1)*I(n)) return C @@ -2235,16 +2759,16 @@ def szekeres_difference_set_pair(m, check=True): B = [b for b in G if b + F.one() in sG] if check: from itertools import product, chain - assert(len(A) == len(B) == m) + assert (len(A) == len(B) == m) if m > 1: - assert(sG == set([xy[0] / xy[1] + assert (sG == set([xy[0] / xy[1] for xy in chain(product(A, A), product(B, B))])) - assert(all(F.one() / b + F.one() in sG for b in B)) - assert(not any(F.one() / a - F.one() in sG for a in A)) + assert (all(F.one() / b + F.one() in sG for b in B)) + assert (not any(F.one() / a - F.one() in sG for a in A)) return G, A, B -def typeI_matrix_difference_set(G,A): +def typeI_matrix_difference_set(G, A): r""" (1,-1)-incidence type I matrix of a difference set `A` in `G` @@ -2264,7 +2788,8 @@ def typeI_matrix_difference_set(G,A): [-1 -1 1 1 -1] """ n = len(G) - return matrix(n,n, lambda i,j: 1 if G[i]/G[j] in A else -1) + return matrix(n, n, lambda i, j: 1 if G[i]/G[j] in A else -1) + def rshcd_from_prime_power_and_conference_matrix(n): r""" @@ -2317,27 +2842,27 @@ def rshcd_from_prime_power_and_conference_matrix(n): - [WW1972]_ """ from sage.graphs.strongly_regular_db import strongly_regular_graph as srg - if is_prime_power(n) and 2==(n-1)%4: + if is_prime_power(n) and 2 == (n-1) % 4: try: - M = srg(n-2,(n-3)//2,(n-7)//4) + M = srg(n-2, (n-3)//2, (n-7)//4) except ValueError: return m = (n-3)//4 - Q,X,Y = szekeres_difference_set_pair(m) - B = typeI_matrix_difference_set(Q,X) - A = -typeI_matrix_difference_set(Q,Y) # must be symmetric + Q, X, Y = szekeres_difference_set_pair(m) + B = typeI_matrix_difference_set(Q, X) + A = -typeI_matrix_difference_set(Q, Y) # must be symmetric W = M.seidel_adjacency_matrix() - f = J(1,4*m+1) - e = J(1,2*m+1) + f = J(1, 4*m+1) + e = J(1, 2*m+1) JJ = J(2*m+1, 2*m+1) II = I(n-2) Ib = I(2*m+1) - J4m = J(4*m+1,4*m+1) + J4m = J(4*m+1, 4*m+1) H34 = -(B+Ib).tensor_product(W)+Ib.tensor_product(J4m)+(Ib-JJ).tensor_product(II) A_t_W = A.tensor_product(W) e_t_f = e.tensor_product(f) H = block_matrix([ - [J(1,1), f, e_t_f, -e_t_f], + [J(1, 1), f, e_t_f, -e_t_f], [f.T, J4m, e.tensor_product(W-II), e.tensor_product(W+II)], [ e_t_f.T, (e.T).tensor_product(W-II), A_t_W+JJ.tensor_product(II), H34], [-e_t_f.T, (e.T).tensor_product(W+II), H34.T, -A_t_W+JJ.tensor_product(II)]]) diff --git a/src/sage/cpython/cython_metaclass.pyx b/src/sage/cpython/cython_metaclass.pyx index a846884093e..744d6e54791 100644 --- a/src/sage/cpython/cython_metaclass.pyx +++ b/src/sage/cpython/cython_metaclass.pyx @@ -61,7 +61,8 @@ In Python, this would be ``meta.__init__(cls, name, bases, dict)``. EXAMPLES:: - sage: cython(''' # optional - sage.misc.cython + sage: cython( # optional - sage.misc.cython + ....: ''' ....: cimport sage.cpython.cython_metaclass ....: cdef class MyCustomType(): ....: def __getmetaclass__(_): @@ -75,9 +76,9 @@ EXAMPLES:: ....: ''') Calling MyMetaclass.__init__(, None, None, None) Calling MyMetaclass.__init__(, None, None, None) - sage: MyCustomType.__class__ + sage: MyCustomType.__class__ # optional - sage.misc.cython - sage: class MyPythonType(MyDerivedType): + sage: class MyPythonType(MyDerivedType): # optional - sage.misc.cython ....: pass Calling MyMetaclass.__init__(, 'MyPythonType', (,), {...}) @@ -98,7 +99,8 @@ TESTS: Check that a proper exception is raised if ``__getmetaclass__`` returns a non-type:: - sage: cython(''' # optional - sage.misc.cython + sage: cython( # optional - sage.misc.cython + ....: ''' ....: cimport sage.cpython.cython_metaclass ....: cdef class MyCustomType(): ....: def __getmetaclass__(_): diff --git a/src/sage/cpython/string.pyx b/src/sage/cpython/string.pyx index 2bd86dbfcf6..bc5fc6f2398 100644 --- a/src/sage/cpython/string.pyx +++ b/src/sage/cpython/string.pyx @@ -6,7 +6,8 @@ TESTS: Check that this can be used outside of Sage (see :trac:`25549`):: - sage: cython(''' # optional - sage.misc.cython + sage: cython( # optional - sage.misc.cython + ....: ''' ....: from sage.cpython.string cimport char_to_str ....: print(char_to_str("hello world!")) ....: ''') diff --git a/src/sage/cpython/wrapperdescr.pxd b/src/sage/cpython/wrapperdescr.pxd index fe0a0618a17..d7e67a48ac6 100644 --- a/src/sage/cpython/wrapperdescr.pxd +++ b/src/sage/cpython/wrapperdescr.pxd @@ -39,24 +39,25 @@ cdef inline wrapperbase* get_slotdef(wrapper_descriptor slotwrapper) except NULL TESTS:: - sage: cython(''' # optional - sage.misc.cython + sage: cython( # optional - sage.misc.cython + ....: ''' ....: from sage.cpython.wrapperdescr cimport get_slotdef ....: from cpython.long cimport PyLong_FromVoidPtr ....: def py_get_slotdef(slotwrapper): ....: return PyLong_FromVoidPtr(get_slotdef(slotwrapper)) ....: ''') - sage: py_get_slotdef(object.__init__) # random + sage: py_get_slotdef(object.__init__) # random # optional - sage.misc.cython 140016903442416 - sage: py_get_slotdef(bytes.__lt__) # random + sage: py_get_slotdef(bytes.__lt__) # random # optional - sage.misc.cython 140016903441800 - sage: py_get_slotdef(bytes.__lt__) == py_get_slotdef(Integer.__lt__) + sage: py_get_slotdef(bytes.__lt__) == py_get_slotdef(Integer.__lt__) # optional - sage.misc.cython True - sage: py_get_slotdef(bytes.__lt__) == py_get_slotdef(bytes.__gt__) + sage: py_get_slotdef(bytes.__lt__) == py_get_slotdef(bytes.__gt__) # optional - sage.misc.cython False sage: class X(): ....: def __eq__(self, other): ....: return False - sage: py_get_slotdef(X.__eq__) + sage: py_get_slotdef(X.__eq__) # optional - sage.misc.cython Traceback (most recent call last): ... TypeError: Cannot convert ... to wrapper_descriptor diff --git a/src/sage/data_structures/bounded_integer_sequences.pyx b/src/sage/data_structures/bounded_integer_sequences.pyx index 724f296eae2..d431c71f663 100644 --- a/src/sage/data_structures/bounded_integer_sequences.pyx +++ b/src/sage/data_structures/bounded_integer_sequences.pyx @@ -1212,7 +1212,7 @@ cdef class BoundedIntegerSequence: sage: T+None Traceback (most recent call last): ... - TypeError: Cannot concatenate bounded integer sequence and None + TypeError: cannot concatenate bounded integer sequence and None TESTS: @@ -1228,7 +1228,7 @@ cdef class BoundedIntegerSequence: """ cdef BoundedIntegerSequence myself, right, out if other is None or self is None: - raise TypeError('Cannot concatenate bounded integer sequence and None') + raise TypeError('cannot concatenate bounded integer sequence and None') myself = self # may result in a type error right = other # --"-- if right.data.itembitsize != myself.data.itembitsize: diff --git a/src/sage/docs/instancedoc.py b/src/sage/docs/instancedoc.py index e24368e4943..5b03886ef02 100644 --- a/src/sage/docs/instancedoc.py +++ b/src/sage/docs/instancedoc.py @@ -36,7 +36,8 @@ For a Cython ``cdef class``, a decorator cannot be used. Instead, call :func:`instancedoc` as a function after defining the class:: - sage: cython(''' # optional - sage.misc.cython + sage: cython( # optional - sage.misc.cython + ....: ''' ....: from sage.misc.instancedoc import instancedoc ....: cdef class Y: ....: "Class docstring" diff --git a/src/sage/env.py b/src/sage/env.py index ac279ed5da3..d1a87df74ce 100644 --- a/src/sage/env.py +++ b/src/sage/env.py @@ -449,7 +449,8 @@ def cython_aliases(required_modules=None, We can use ``cython.parallel`` regardless of whether OpenMP is supported. This will run in parallel, if OpenMP is supported:: - sage: cython(''' # optional - sage.misc.cython + sage: cython( # optional - sage.misc.cython + ....: ''' ....: #distutils: extra_compile_args = OPENMP_CFLAGS ....: #distutils: extra_link_args = OPENMP_CFLAGS ....: from cython.parallel import prange diff --git a/src/sage/ext/memory_allocator.pxd b/src/sage/ext/memory_allocator.pxd index 5ada54f9535..c4f2028f4e4 100644 --- a/src/sage/ext/memory_allocator.pxd +++ b/src/sage/ext/memory_allocator.pxd @@ -56,7 +56,8 @@ cdef class MemoryAllocator: TESTS:: - sage: cython(''' # optional - sage.misc.cython + sage: cython( # optional - sage.misc.cython + ....: ''' ....: from sage.ext.memory_allocator cimport MemoryAllocator ....: cdef MemoryAllocator mem = MemoryAllocator() ....: cdef void* ptr @@ -64,7 +65,8 @@ cdef class MemoryAllocator: ....: ptr = mem.aligned_malloc(2**i, 4048) ....: assert ptr == ( ptr) & ~(2**i-1) ....: ''') - doctest:...: DeprecationWarning: this class is deprecated; use the class from the python package `memory_allocator` + doctest:...: DeprecationWarning: this class is deprecated; + use the class from the python package `memory_allocator` See https://github.com/sagemath/sage/issues/31591 for details. """ cdef size_t extra = alignment - 1 @@ -85,7 +87,8 @@ cdef class MemoryAllocator: TESTS:: - sage: cython(''' # optional - sage.misc.cython + sage: cython( # optional - sage.misc.cython + ....: ''' ....: from sage.ext.memory_allocator cimport MemoryAllocator ....: def foo(): ....: cdef MemoryAllocator mem = MemoryAllocator() @@ -94,8 +97,9 @@ cdef class MemoryAllocator: ....: ptr = mem.aligned_calloc(2**i, i, 2**i) ....: assert ptr == ( ptr) & ~(2**i-1) ....: ''') - sage: foo() - doctest:...: DeprecationWarning: this class is deprecated; use the class from the python package `memory_allocator` + sage: foo() # optional - sage.misc.cython + doctest:...: DeprecationWarning: this class is deprecated; + use the class from the python package `memory_allocator` See https://github.com/sagemath/sage/issues/31591 for details. """ # Find extra such that (nmemb + extra) * size >= nmemb * size + alignment - 1 @@ -120,7 +124,8 @@ cdef class MemoryAllocator: TESTS:: - sage: cython(''' # optional - sage.misc.cython + sage: cython( # optional - sage.misc.cython + ....: ''' ....: from sage.ext.memory_allocator cimport MemoryAllocator ....: def foo(): ....: cdef MemoryAllocator mem = MemoryAllocator() @@ -129,8 +134,8 @@ cdef class MemoryAllocator: ....: ptr = mem.aligned_allocarray(2**i, i, 2**i) ....: assert ptr == ( ptr) & ~(2**i-1) ....: ''') - sage: foo() # random # might raise deprecation warning - sage: foo() + sage: foo() # random # might raise deprecation warning # optional - sage.misc.cython + sage: foo() # optional - sage.misc.cython """ # Find extra such that (nmemb + extra) * size >= nmemb * size + alignment - 1 # ⇔ extra * size >= alignment - 1 diff --git a/src/sage/geometry/lattice_polytope.py b/src/sage/geometry/lattice_polytope.py index 939564dd73f..3a043815a38 100644 --- a/src/sage/geometry/lattice_polytope.py +++ b/src/sage/geometry/lattice_polytope.py @@ -5251,8 +5251,8 @@ def from_palp_index(i): elif o in range(65, 91): i = o - 28 else: - raise ValueError('Cannot convert PALP index ' - + i + ' to number.') + raise ValueError('cannot convert PALP index ' + + i + ' to number') return i n = len(permutation) domain = [from_palp_index(i) for i in permutation] @@ -5261,6 +5261,7 @@ def from_palp_index(i): S = SymmetricGroup(n) return make_permgroup_element(S, domain) + def _read_nef_x_partitions(data): r""" Read all nef-partitions for one polytope from a string or an open diff --git a/src/sage/geometry/polyhedron/parent.py b/src/sage/geometry/polyhedron/parent.py index 8c4905b4b91..3f79008908d 100644 --- a/src/sage/geometry/polyhedron/parent.py +++ b/src/sage/geometry/polyhedron/parent.py @@ -697,7 +697,7 @@ def convert_base_ring_Hrep(lstlst): return self._element_constructor_polyhedron(polyhedron, mutable=mutable, **kwds) if nargs == 1 and args[0] == 0: return self.zero() - raise ValueError('Cannot convert to polyhedron object.') + raise ValueError('cannot convert to polyhedron object') def _element_constructor_polyhedron(self, polyhedron, **kwds): """ diff --git a/src/sage/groups/perm_gps/permgroup_element.pyx b/src/sage/groups/perm_gps/permgroup_element.pyx index 6582bd16c00..c08442d60af 100644 --- a/src/sage/groups/perm_gps/permgroup_element.pyx +++ b/src/sage/groups/perm_gps/permgroup_element.pyx @@ -86,6 +86,14 @@ We create element of a permutation group of large degree:: sage: G = SymmetricGroup(30) sage: s = G(srange(30,0,-1)); s (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) + +TESTS: + +Check that :trac:`13569` is fixed:: + + sage: [g*h for g in SymmetricGroup(3) for h in AlternatingGroup(3)] + [(), (1,2,3), (1,3,2), (1,3,2), (), (1,2,3), (1,2,3), (1,3,2), (), (2,3), + (1,2), (1,3), (1,3), (2,3), (1,2), (1,2), (1,3), (2,3)] """ # **************************************************************************** diff --git a/src/sage/interfaces/tachyon.py b/src/sage/interfaces/tachyon.py index a7e45c3c294..6dd359d9e36 100644 --- a/src/sage/interfaces/tachyon.py +++ b/src/sage/interfaces/tachyon.py @@ -683,12 +683,14 @@ #***************************************************************************** import os +import re from sage.cpython.string import bytes_to_str from sage.misc.pager import pager from sage.misc.superseded import deprecation from sage.misc.temporary_file import tmp_filename from sage.structure.sage_object import SageObject +from sage.misc.cachefunc import cached_method class TachyonRT(SageObject): @@ -799,6 +801,11 @@ def __call__(self, model, outfile='sage.png', verbose=1, extra_opts=''): Parser failed due to an input file syntax error. Aborting render. """ + if self.version() >= '0.99.2': + # this keyword was changed in 0.99.2 + model = model.replace( + " focallength ", + " focaldist ") modelfile = tmp_filename(ext='.dat') with open(modelfile, 'w') as file: file.write(model) @@ -851,6 +858,25 @@ def usage(self, use_pager=True): else: print(r) + @cached_method + def version(self): + """ + Returns the version of the Tachyon raytracer being used. + + TESTS:: + + sage: tachyon_rt.version() # random + 0.98.9 + sage: tachyon_rt.version() >= '0.98.9' + True + """ + with os.popen('tachyon') as f: + r = f.readline() + res = re.search(r"Version ([\d.]*)", r) + # debian patches tachyon so it won't report the version + # we hardcode '0.99' since that's indeed the version they ship + return res[1] if res else '0.99' + def help(self, use_pager=True): """ Deprecated: type 'sage.interfaces.tachyon?' for help diff --git a/src/sage/libs/giac/giac.pyx b/src/sage/libs/giac/giac.pyx index ccad5169836..990114fb4a5 100644 --- a/src/sage/libs/giac/giac.pyx +++ b/src/sage/libs/giac/giac.pyx @@ -1408,7 +1408,7 @@ cdef class Pygen(GiacMethods_base): return result else: - raise TypeError("Cannot convert non giac integers to Integer") + raise TypeError("cannot convert non giac integers to Integer") def _rational_(self,Z=None): @@ -1433,7 +1433,7 @@ cdef class Pygen(GiacMethods_base): # giac _RAT_ return ZZ(self.numer()) / ZZ(self.denom()) else: - raise TypeError("Cannot convert non giac _FRAC_ to QQ") + raise TypeError("cannot convert non giac _FRAC_ to QQ") def sage(self): @@ -1735,7 +1735,7 @@ cdef class Pygen(GiacMethods_base): sig_off() return result else: - raise TypeError("Cannot convert non _INT_ giac gen") + raise TypeError("cannot convert non _INT_ giac gen") property _double: # immediate double (type _DOUBLE_) @@ -1749,7 +1749,7 @@ cdef class Pygen(GiacMethods_base): sig_off() return result else: - raise TypeError("Cannot convert non _DOUBLE_ giac gen") + raise TypeError("cannot convert non _DOUBLE_ giac gen") property help: def __get__(self): diff --git a/src/sage/libs/pari/convert_sage.pyx b/src/sage/libs/pari/convert_sage.pyx index 62fe5185cfb..96bce94ad5f 100644 --- a/src/sage/libs/pari/convert_sage.pyx +++ b/src/sage/libs/pari/convert_sage.pyx @@ -352,7 +352,7 @@ cpdef set_integer_from_gen(Integer self, Gen x): break elif paritype == t_PADIC: if x._valp() < 0: - raise TypeError("Cannot convert p-adic with negative valuation to an integer") + raise TypeError("cannot convert p-adic with negative valuation to an integer") # Lifting a PADIC yields an integer x = x.lift() break diff --git a/src/sage/libs/singular/function.pyx b/src/sage/libs/singular/function.pyx index f103a3b8654..906f1e6c860 100644 --- a/src/sage/libs/singular/function.pyx +++ b/src/sage/libs/singular/function.pyx @@ -1304,7 +1304,7 @@ cdef class SingularFunction(SageObject): dummy_ring = PolynomialRing(QQ, "dummy", implementation="singular") # seems a reasonable default ring = dummy_ring if not (isinstance(ring, MPolynomialRing_libsingular) or isinstance(ring, NCPolynomialRing_plural)): - raise TypeError("Cannot call Singular function '%s' with ring parameter of type '%s'"%(self._name,type(ring))) + raise TypeError("cannot call Singular function '%s' with ring parameter of type '%s'" % (self._name,type(ring))) return call_function(self, args, ring, interruptible, attributes) def _instancedoc_(self): diff --git a/src/sage/matrix/matrix2.pyx b/src/sage/matrix/matrix2.pyx index ab96459e66e..7fd2108e4d2 100644 --- a/src/sage/matrix/matrix2.pyx +++ b/src/sage/matrix/matrix2.pyx @@ -86,7 +86,8 @@ from sage.structure.coerce cimport coercion_model from sage.structure.element import is_Vector from sage.structure.element cimport have_same_parent from sage.misc.verbose import verbose, get_verbose -from sage.categories.all import Fields, IntegralDomains +from sage.categories.fields import Fields +from sage.categories.integral_domains import IntegralDomains from sage.rings.ring import is_Ring from sage.rings.number_field.number_field_base import is_NumberField from sage.rings.integer_ring import ZZ, is_IntegerRing @@ -16878,7 +16879,7 @@ cdef class Matrix(Matrix1): ... ValueError: 'subdivide' keyword must be True or False, not garbage """ - from sage.arith.all import gcd + from sage.arith.misc import GCD as gcd import sage.rings.polynomial.polynomial_ring_constructor from sage.matrix.constructor import (block_diagonal_matrix, companion_matrix) diff --git a/src/sage/matrix/matrix_cdv.pyx b/src/sage/matrix/matrix_cdv.pyx index a964b242c0f..43421c74cb9 100644 --- a/src/sage/matrix/matrix_cdv.pyx +++ b/src/sage/matrix/matrix_cdv.pyx @@ -30,7 +30,7 @@ cpdef hessenbergize_cdvf(Matrix_generic_dense H): a complete discrete valuation field. The pivot on each column is always chosen - with maximal relative precision, which ensures + with maximal relative precision, which ensures the numerical stability of the algorithm. TESTS:: diff --git a/src/sage/matrix/matrix_complex_ball_dense.pyx b/src/sage/matrix/matrix_complex_ball_dense.pyx index 2a9f00d19ad..8ba87305636 100644 --- a/src/sage/matrix/matrix_complex_ball_dense.pyx +++ b/src/sage/matrix/matrix_complex_ball_dense.pyx @@ -776,7 +776,7 @@ cdef class Matrix_complex_ball_dense(Matrix_dense): EXAMPLES:: sage: from sage.matrix.benchmark import hilbert_matrix - sage: mat = hilbert_matrix(3).change_ring(CBF) + sage: mat = hilbert_matrix(3).change_ring(CBF) sage: eigval, eigvec, _ = mat.eigenvectors_right_approx()[0] doctest:...: FutureWarning: This class/method/function is marked as experimental. ... @@ -834,7 +834,7 @@ cdef class Matrix_complex_ball_dense(Matrix_dense): EXAMPLES:: sage: from sage.matrix.benchmark import hilbert_matrix - sage: mat = hilbert_matrix(3).change_ring(CBF) + sage: mat = hilbert_matrix(3).change_ring(CBF) sage: eigval, eigvec, _ = mat.eigenvectors_right()[0] doctest:...: FutureWarning: This class/method/function is marked as experimental. ... diff --git a/src/sage/matrix/matrix_cyclo_dense.pyx b/src/sage/matrix/matrix_cyclo_dense.pyx index 55e1b7d739e..29456daabfe 100644 --- a/src/sage/matrix/matrix_cyclo_dense.pyx +++ b/src/sage/matrix/matrix_cyclo_dense.pyx @@ -65,9 +65,9 @@ from .matrix_integer_dense cimport _lift_crt from sage.structure.element cimport Matrix as baseMatrix from .misc import matrix_integer_dense_rational_reconstruction +from sage.arith.misc import binomial, previous_prime from sage.rings.rational_field import QQ from sage.rings.integer_ring import ZZ -from sage.arith.all import previous_prime, binomial from sage.rings.real_mpfr import create_RealNumber as RealNumber from sage.rings.integer cimport Integer from sage.rings.rational cimport Rational diff --git a/src/sage/matrix/matrix_integer_dense.pyx b/src/sage/matrix/matrix_integer_dense.pyx index b9f9d5791b4..9b5a5676764 100644 --- a/src/sage/matrix/matrix_integer_dense.pyx +++ b/src/sage/matrix/matrix_integer_dense.pyx @@ -78,7 +78,7 @@ from sage.modules.vector_integer_dense cimport Vector_integer_dense from sage.misc.misc import cputime from sage.misc.verbose import verbose, get_verbose -from sage.arith.all import previous_prime +from sage.arith.misc import previous_prime from sage.arith.long cimport integer_check_long_py from sage.arith.power cimport generic_power from sage.structure.element cimport Element diff --git a/src/sage/matrix/matrix_integer_dense_hnf.py b/src/sage/matrix/matrix_integer_dense_hnf.py index acdb0f09cc4..41fd6ca8dde 100644 --- a/src/sage/matrix/matrix_integer_dense_hnf.py +++ b/src/sage/matrix/matrix_integer_dense_hnf.py @@ -8,14 +8,13 @@ from copy import copy +from sage.arith.misc import CRT_list, previous_prime +from sage.matrix.constructor import identity_matrix, matrix, random_matrix from sage.misc.misc import cputime from sage.misc.verbose import verbose -from sage.matrix.constructor import (random_matrix, matrix, identity_matrix) - +from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ from sage.rings.real_mpfr import RR -from sage.rings.integer import Integer -from sage.arith.all import previous_prime, CRT_list def max_det_prime(n): diff --git a/src/sage/matrix/matrix_integer_dense_saturation.py b/src/sage/matrix/matrix_integer_dense_saturation.py index a7ce81fc86a..365c8d830bf 100644 --- a/src/sage/matrix/matrix_integer_dense_saturation.py +++ b/src/sage/matrix/matrix_integer_dense_saturation.py @@ -2,14 +2,15 @@ Saturation over ZZ """ -from sage.rings.integer_ring import ZZ -from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF -from sage.arith.all import binomial, gcd +from copy import copy + +from sage.arith.misc import binomial, GCD as gcd +from sage.matrix import matrix_integer_dense_hnf from sage.matrix.constructor import identity_matrix, random_matrix -from sage.misc.verbose import verbose from sage.misc.randstate import current_randstate -from . import matrix_integer_dense_hnf -from copy import copy +from sage.misc.verbose import verbose +from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF +from sage.rings.integer_ring import ZZ def p_saturation(A, p, proof=True): diff --git a/src/sage/matrix/matrix_modn_dense_template.pxi b/src/sage/matrix/matrix_modn_dense_template.pxi index 2f2acfd562a..abf29badce6 100644 --- a/src/sage/matrix/matrix_modn_dense_template.pxi +++ b/src/sage/matrix/matrix_modn_dense_template.pxi @@ -109,7 +109,7 @@ from libc.stdio cimport snprintf from sage.modules.vector_modn_dense cimport Vector_modn_dense -from sage.arith.all import is_prime +from sage.arith.misc import is_prime from sage.structure.element cimport (Element, Vector, Matrix, ModuleElement, RingElement) from sage.matrix.matrix_dense cimport Matrix_dense diff --git a/src/sage/matrix/matrix_modn_sparse.pyx b/src/sage/matrix/matrix_modn_sparse.pyx index 1bf2255b8f3..8e7e49cd90c 100644 --- a/src/sage/matrix/matrix_modn_sparse.pyx +++ b/src/sage/matrix/matrix_modn_sparse.pyx @@ -113,7 +113,7 @@ from sage.misc.verbose import verbose, get_verbose from sage.matrix.matrix2 import Matrix as Matrix2 from .args cimport SparseEntry, MatrixArgs_init -from sage.arith.all import is_prime +from sage.arith.misc import is_prime from sage.structure.element import is_Vector diff --git a/src/sage/matrix/matrix_polynomial_dense.pyx b/src/sage/matrix/matrix_polynomial_dense.pyx index 92502d9632b..cc44242131f 100644 --- a/src/sage/matrix/matrix_polynomial_dense.pyx +++ b/src/sage/matrix/matrix_polynomial_dense.pyx @@ -224,7 +224,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): return self.apply_map(lambda x: x.degree()) from sage.matrix.constructor import matrix zero_degree = min(shifts) - 1 - if row_wise: + if row_wise: return matrix( ZZ, [[ self[i,j].degree() + shifts[j] if self[i,j] != 0 else zero_degree for j in range(self.ncols()) ] for i in range(self.nrows())] ) @@ -1116,7 +1116,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): The row degrees of an empty matrix (`0\times n` or `m\times 0`) is not defined:: - + sage: M = Matrix( pR, 0, 3 ) sage: M.row_degrees() Traceback (most recent call last): @@ -1215,7 +1215,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): n}`. Working row-wise and without shifts, its leading matrix is the matrix in `\Bold{K}^{m \times n}` formed by the leading coefficients of the entries of `M` which reach the degree of the corresponding row. - + More precisely, if working row-wise, let `s_1,\ldots,s_n \in \ZZ` be a shift, and let `(d_1,\ldots,d_m)` denote the shifted row degrees of `M`. Then, the shifted leading matrix of `M` is the matrix in @@ -1239,7 +1239,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): OUTPUT: a matrix over the base field. REFERENCES: - + [Wol1974]_ (Section 2.5, without shifts) and [VBB1992]_ (Section 3). EXAMPLES:: @@ -1335,7 +1335,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): False .. SEEALSO:: - + :meth:`is_popov` . """ if include_zero_vectors: @@ -1385,7 +1385,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): OUTPUT: a boolean value. REFERENCES: - + [Wol1974]_ (Section 2.5, without shifts) and [VBB1992]_ (Section 3). EXAMPLES:: @@ -1441,7 +1441,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): this vector is the index `j` of the rightmost nonzero entry `p_j` such that `\deg(p_j) + s_j` is equal to the shifted row degree of the vector. Then the pivot degree of the vector is the degree `\deg(p_j)`. - + For the zero row, both the leading positions and degree are `-1`. For a `m \times n` polynomial matrix, the leading positions and pivot degrees are the two lists containing the leading positions and the @@ -1465,7 +1465,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): of integers otherwise. REFERENCES: - + [Kai1980]_ (Section 6.7.2, without shifts). EXAMPLES:: @@ -1541,7 +1541,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): self[i,pivot_index[i]].degree()) for i in range(self.nrows()) ] return (pivot_index,pivot_degree) if return_degree else pivot_index - + # now in the column-wise case column_degrees = self.column_degrees(shifts) if shifts is None: @@ -1595,7 +1595,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): OUTPUT: a boolean. REFERENCES: - + [Kai1980]_ (Section 6.7.2, square case without shifts), [MS2003]_ (without shifts), [BLV1999]_ . @@ -1646,7 +1646,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): sage: M = Matrix([ ....: [ 6*x+4, 0, 5*x+1, 0], ....: [ 2, 5*x + 1, 6*x^2+3*x+1, 0], - ....: [2*x^2+5*x+5, 1, 2*x^3+4*x^2+6*x+4, 0] + ....: [2*x^2+5*x+5, 1, 2*x^3+4*x^2+6*x+4, 0] ....: ]) sage: M.is_weak_popov(shifts=[2,1,0], row_wise=False, ordered=True) True @@ -1724,7 +1724,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): OUTPUT: a boolean. REFERENCES: - + For the square case, without shifts: [Pop1972]_ and [Kai1980]_ (Section 6.7.2). For the general case: [BLV2006]_ . @@ -1908,7 +1908,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): False .. SEEALSO:: - + :meth:`hermite_form` . """ # shift for lower echelon @@ -2564,7 +2564,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): - the Hermite normal form `H` of this matrix `A` . - (optional) transformation matrix `U` such that `UA = H` . - + EXAMPLES:: sage: M. = GF(7)[] @@ -2594,7 +2594,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): True .. SEEALSO:: - + :meth:`is_hermite` , :meth:`popov_form` . """ @@ -2923,7 +2923,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): return (self.parent().zero().__copy__(), self) # Step 1: reverse input matrices # Brev = B(1/x) diag(x^(cdeg[i])) - # Arev = A(1/x) diag(x^(d+cdeg[i]-1)) + # Arev = A(1/x) diag(x^(d+cdeg[i]-1)) Brev = B.reverse(degree=cdeg, row_wise=False) Arev = self.reverse(degree=[d+c-1 for c in cdeg], row_wise=False) # Step 2: compute quotient @@ -2953,7 +2953,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): and such a quotient and remainder is returned by the method. Or this matrix equation has no solution and this method fails: this raises ``ValueError``; however this is not a proof that there is no valid - division with remainder (see the last example below). + division with remainder (see the last example below). EXAMPLES:: @@ -3245,12 +3245,12 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): Return ``True`` if and only if this matrix is an approximant basis in ``shifts``-ordered weak Popov form for the polynomial matrix ``pmat`` at order ``order``. - + If ``normal_form`` is ``True``, then the polynomial matrix must furthermore be in ``shifts``-Popov form. An error is raised if the input dimensions are not sound. If a single integer is provided for ``order``, then it is interpreted as a list of repeated integers with - this value. (See :meth:`minimal_approximant_basis` for definitions and + this value. (See :meth:`minimal_approximant_basis` for definitions and more details.) INPUT: @@ -3327,14 +3327,14 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): sage: appbas.is_minimal_approximant_basis(pmat, [8,8], shifts) Traceback (most recent call last): ... - ValueError: order length should be the column dimension + ValueError: order length should be the column dimension of the input matrix sage: appbas.is_minimal_approximant_basis(pmat, \ order, shifts, row_wise=False) Traceback (most recent call last): ... - ValueError: shifts length should be the column dimension + ValueError: shifts length should be the column dimension of the input matrix sage: Matrix(pR, [x^8]).is_minimal_approximant_basis(pmat, 8) @@ -3612,7 +3612,7 @@ cdef class Matrix_polynomial_dense(Matrix_generic_dense): def _approximant_basis_iterative(self, order, shifts): r""" Return a ``shifts``-ordered weak Popov approximant basis for this - polynomial matrix at order ``order`` + polynomial matrix at order ``order`` (see :meth:`minimal_approximant_basis` for definitions). The output basis is considered row-wise, that is, its rows are diff --git a/src/sage/matrix/matrix_rational_dense.pyx b/src/sage/matrix/matrix_rational_dense.pyx index 93efb95781f..10fd2dcabcc 100644 --- a/src/sage/matrix/matrix_rational_dense.pyx +++ b/src/sage/matrix/matrix_rational_dense.pyx @@ -111,7 +111,7 @@ from sage.rings.integer_ring import ZZ, is_IntegerRing from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF import sage.rings.abc from sage.rings.rational_field import QQ -from sage.arith.all import gcd +from sage.arith.misc import GCD as gcd from .matrix2 import decomp_seq from .matrix0 import Matrix as Matrix_base diff --git a/src/sage/matrix/matrix_space.py b/src/sage/matrix/matrix_space.py index 73c5b445de7..afd06c9db20 100644 --- a/src/sage/matrix/matrix_space.py +++ b/src/sage/matrix/matrix_space.py @@ -679,7 +679,8 @@ def __init__(self, base_ring, nrows, ncols, sparse, implementation): self.__ncols = ncols self.__is_sparse = sparse - from sage.categories.all import Modules, Algebras + from sage.categories.modules import Modules + from sage.categories.algebras import Algebras if nrows == ncols: category = Algebras(base_ring.category()) else: diff --git a/src/sage/matrix/misc.pyx b/src/sage/matrix/misc.pyx index 220f8866b0e..25cffdeef0a 100644 --- a/src/sage/matrix/misc.pyx +++ b/src/sage/matrix/misc.pyx @@ -12,21 +12,26 @@ relevant classes and this file deleted. from cysignals.signals cimport sig_check -from sage.ext.mod_int cimport * -from sage.libs.gmp.mpz cimport * -from sage.libs.gmp.mpq cimport * -from sage.libs.mpfr cimport * - -from sage.libs.flint.fmpz cimport fmpz_set_mpz, fmpz_one -from sage.libs.flint.fmpq cimport fmpq_set_mpq, fmpq_canonicalise -from sage.libs.flint.fmpq_mat cimport fmpq_mat_entry_num, fmpq_mat_entry_den, fmpq_mat_entry +cimport sage.rings.abc +from sage.arith.misc import CRT_basis, previous_prime from sage.arith.rational_reconstruction cimport mpq_rational_reconstruction - from sage.data_structures.binary_search cimport * +from sage.ext.mod_int cimport * +from sage.libs.flint.fmpq cimport fmpq_set_mpq, fmpq_canonicalise +from sage.libs.flint.fmpq_mat cimport fmpq_mat_entry_num, fmpq_mat_entry_den, fmpq_mat_entry +from sage.libs.flint.fmpz cimport fmpz_set_mpz, fmpz_one +from sage.libs.gmp.mpq cimport * +from sage.libs.gmp.mpz cimport * +from sage.libs.mpfr cimport * +from sage.misc.verbose import get_verbose, verbose from sage.modules.vector_integer_sparse cimport * -from sage.modules.vector_rational_sparse cimport * from sage.modules.vector_modn_sparse cimport * +from sage.modules.vector_rational_sparse cimport * +from sage.rings.integer cimport Integer +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ +from sage.rings.real_mpfr cimport RealNumber from .matrix0 cimport Matrix from .matrix_integer_dense cimport Matrix_integer_dense @@ -34,17 +39,6 @@ from .matrix_integer_sparse cimport Matrix_integer_sparse from .matrix_rational_dense cimport Matrix_rational_dense from .matrix_rational_sparse cimport Matrix_rational_sparse -from sage.rings.integer_ring import ZZ -from sage.rings.rational_field import QQ - -from sage.rings.integer cimport Integer -from sage.arith.all import previous_prime, CRT_basis - -cimport sage.rings.abc -from sage.rings.real_mpfr cimport RealNumber - - -from sage.misc.verbose import verbose, get_verbose def matrix_integer_dense_rational_reconstruction(Matrix_integer_dense A, Integer N): """ diff --git a/src/sage/misc/cython.py b/src/sage/misc/cython.py index 3f02e9e3a70..109e555abe4 100644 --- a/src/sage/misc/cython.py +++ b/src/sage/misc/cython.py @@ -171,7 +171,7 @@ def cython(filename, verbose=0, compile_message=False, sage: os.chdir(d) sage: with open("helper.pxd", 'w') as f: ....: _ = f.write("cdef inline int the_answer(): return 42") - sage: cython(''' # optional - sage.misc.cython + sage: cython(''' ....: from helper cimport the_answer ....: print(the_answer()) ....: ''') @@ -208,7 +208,7 @@ def cython(filename, verbose=0, compile_message=False, As of :trac:`29139` the default is ``cdivision=True``:: - sage: cython(''' # optional - sage.misc.cython + sage: cython(''' ....: cdef size_t foo = 3/2 ....: ''') """ diff --git a/src/sage/misc/persist.pyx b/src/sage/misc/persist.pyx index 5362ffa9c51..ca9b2894469 100644 --- a/src/sage/misc/persist.pyx +++ b/src/sage/misc/persist.pyx @@ -157,7 +157,7 @@ def load(*filename, compress=True, verbose=True, **kwargs): ....: _ = f.write(code) sage: load(t) sage: hello - + """ import sage.repl.load if len(filename) != 1: diff --git a/src/sage/misc/sageinspect.py b/src/sage/misc/sageinspect.py index 83ad5d8d4c0..5099351a9c2 100644 --- a/src/sage/misc/sageinspect.py +++ b/src/sage/misc/sageinspect.py @@ -1372,13 +1372,14 @@ def sage_getfile(obj): A problem fixed in :trac:`16309`:: - sage: cython(''' # optional - sage.misc.cython + sage: cython( # optional - sage.misc.cython + ....: ''' ....: class Bar: pass ....: cdef class Foo: pass ....: ''') - sage: sage_getfile(Bar) + sage: sage_getfile(Bar) # optional - sage.misc.cython '...pyx' - sage: sage_getfile(Foo) + sage: sage_getfile(Foo) # optional - sage.misc.cython '...pyx' By :trac:`18249`, we return an empty string for Python builtins. In that diff --git a/src/sage/misc/superseded.py b/src/sage/misc/superseded.py index 017b2ec2883..c158317ca5a 100644 --- a/src/sage/misc/superseded.py +++ b/src/sage/misc/superseded.py @@ -107,16 +107,17 @@ def deprecation_cython(issue_number, message, stacklevel=3): with the same callsite reference as `deprecation` in a python function, whereas `deprecation` in a cython function does not:: - sage: cython(''' # optional - sage.misc.cython + sage: cython( # optional - sage.misc.cython + ....: ''' ....: from sage.misc.superseded import deprecation_cython, deprecation ....: def foo1(): - ....: deprecation_cython(100,"boo") + ....: deprecation_cython(100, "boo") ....: def foo2(): - ....: deprecation(100,"boo") + ....: deprecation(100, "boo") ....: ''') sage: def foo3(): - ....: deprecation(100,"boo") - sage: if True: # Execute the three "with" blocks as one doctest + ....: deprecation(100, "boo") + sage: if True: # Execute the three "with" blocks as one doctest # optional - sage.misc.cython ....: with warnings.catch_warnings(record=True) as w1: ....: warnings.simplefilter("always") ....: foo1() @@ -126,9 +127,9 @@ def deprecation_cython(issue_number, message, stacklevel=3): ....: with warnings.catch_warnings(record=True) as w3: ....: warnings.simplefilter("always") ....: foo3() - sage: w1[0].filename == w3[0].filename + sage: w1[0].filename == w3[0].filename # optional - sage.misc.cython True - sage: w2[0].filename == w3[0].filename + sage: w2[0].filename == w3[0].filename # optional - sage.misc.cython False """ warning(issue_number, message, DeprecationWarning, stacklevel) diff --git a/src/sage/modular/quasimodform/element.py b/src/sage/modular/quasimodform/element.py index 6821f3e97bf..24a6b7ebfad 100644 --- a/src/sage/modular/quasimodform/element.py +++ b/src/sage/modular/quasimodform/element.py @@ -24,7 +24,9 @@ from sage.structure.element import ModuleElement from sage.structure.richcmp import richcmp, op_NE, op_EQ +from sage.rings.integer import Integer from sage.rings.polynomial.polynomial_element import Polynomial +from sage.rings.integer_ring import ZZ class QuasiModularFormsElement(ModuleElement): r""" @@ -463,7 +465,7 @@ def weights_list(self): sage: (QM.0 + QM.1 + QM.2*QM.1 + QM.3*QM.4).weights_list() [2, 5, 7] """ - return sorted(list(self.to_polynomial().homogeneous_components())) + return sorted(self.homogeneous_components().keys()) def is_homogeneous(self): r""" @@ -474,34 +476,39 @@ def is_homogeneous(self): EXAMPLES:: sage: QM = QuasiModularForms(1) - sage: (QM.0).is_homogeneous() + sage: E2, E4, E6 = QM.gens() + sage: (E2).is_homogeneous() True - sage: (QM.0 + QM.1).is_homogeneous() + sage: (E2 + E4).is_homogeneous() False - sage: (QM.0 * QM.1 + QM.2).is_homogeneous() + sage: (E2 * E4 + E6).is_homogeneous() True sage: QM(1).is_homogeneous() True - sage: (1 + QM.0).is_homogeneous() + sage: (1 + E2).is_homogeneous() False - sage: QM = QuasiModularForms(Gamma0(4)) - sage: (QM.0).is_homogeneous() - True - sage: (QM.0 + QM.1).is_homogeneous() - True - sage: (QM.0 + QM.1 + QM.2).is_homogeneous() + sage: F = E6^3 + E4^4*E2 + (E4^2*E6)*E2^2 + (E4^3 + E6^2)*E2^3 + sage: F.is_homogeneous() True - sage: (QM.0 + QM.1^3).is_homogeneous() - False - """ - return len(self.weights_list()) == 1 + k = None + for i, c in enumerate(self._polynomial.coefficients(sparse=False)): + if c: + if not c.is_homogeneous(): + return False + if k is None: + k = c.weight() + 2*i + continue + if c.weight() + 2*i != k: + return False + return True def weight(self): r""" Return the weight of the given quasimodular form. - Note that the given form must be homogeneous. + Note that the given form must be homogeneous. An alias of this method is + ``degree``. EXAMPLES:: @@ -512,15 +519,21 @@ def weight(self): 6 sage: QM(1/2).weight() 0 + sage: (QM.0).degree() + 2 sage: (QM.0 + QM.1).weight() Traceback (most recent call last): ... ValueError: the given graded quasiform is not an homogeneous element """ if self.is_homogeneous(): - return self.to_polynomial().degree() + return (self._polynomial.leading_coefficient().weight() + + 2*self._polynomial.degree()) else: - raise ValueError("the given graded quasiform is not an homogeneous element") + raise ValueError("the given graded quasiform is not an homogeneous \ + element") + + degree = weight # alias def homogeneous_components(self): r""" @@ -538,17 +551,77 @@ def homogeneous_components(self): 6: 1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6)} sage: (1 + QM.0).homogeneous_components() {0: 1, 2: 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6)} - sage: QM = QuasiModularForms(Gamma0(5)) - sage: F = QM.0 + QM.1 * QM.0 + QM.3^2*QM.0 + sage: QM5 = QuasiModularForms(Gamma1(3)) + sage: F = QM.1 + QM.1*QM.2 + QM.1*QM.0 + (QM.1 + QM.2^2)*QM.0^3 sage: F.homogeneous_components() - {2: 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6), - 4: 1 - 18*q - 198*q^2 - 936*q^3 - 2574*q^4 - 5610*q^5 + O(q^6), - 10: q^2 - 24*q^3 - 52*q^4 - 520*q^5 + O(q^6)} + {4: 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6), + 6: 1 + 216*q - 3672*q^2 - 62496*q^3 - 322488*q^4 - 1121904*q^5 + O(q^6), + 10: 2 - 96*q - 149040*q^2 - 4986240*q^3 - 67535952*q^4 - 538187328*q^5 + O(q^6), + 18: 1 - 1080*q + 294840*q^2 - 902880*q^3 - 452402280*q^4 + 105456816*q^5 + O(q^6)} + sage: F = QM.zero() + sage: F.homogeneous_components() + {0: 0} + sage: F = QM(42/13) + sage: F.homogeneous_components() + {0: 42/13} """ QM = self.parent() - poly_self = self.to_polynomial() - pol_hom_comp = poly_self.homogeneous_components() - return {k: QM.from_polynomial(pol) for k, pol in pol_hom_comp.items()} + if self.is_zero(): + return {ZZ(0): self} + components = {} + E2 = self.parent().weight_2_eisenstein_series() + for i, c in enumerate(self._polynomial.coefficients(sparse=False)): + if c: + forms = c._forms_dictionary + for k in forms.keys(): + try: + components[ZZ(k + 2*i)] += QM(forms[k]*(E2**i)) + except KeyError: + components[ZZ(k + 2*i)] = QM(forms[k]*(E2**i)) + return components + + def __getitem__(self, weight): + r""" + Return the homogeneous component of the given quasimodular form ring + element. + + An alias of this method is ``homogeneous_component``. + + EXAMPLES:: + + sage: QM = QuasiModularForms(1) + sage: E2, E4, E6 = QM.gens() + sage: F = E2 + E4*E6 + E2^3*E6 + sage: F[2] + 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6) + sage: F[10] + 1 - 264*q - 135432*q^2 - 5196576*q^3 - 69341448*q^4 - 515625264*q^5 + O(q^6) + sage: F[12] + 1 - 576*q + 21168*q^2 + 308736*q^3 - 15034608*q^4 - 39208320*q^5 + O(q^6) + sage: F[4] + 0 + sage: F.homogeneous_component(2) + 1 - 24*q - 72*q^2 - 96*q^3 - 168*q^4 - 144*q^5 + O(q^6) + + TESTS:: + + sage: F[x] + Traceback (most recent call last): + ... + KeyError: 'the weight must be an integer' + sage: F[-1] + Traceback (most recent call last): + ... + ValueError: the weight must be nonnegative + """ + if not isinstance(weight, (int, Integer)): + raise KeyError("the weight must be an integer") + if weight < 0: + raise ValueError("the weight must be nonnegative") + return self.homogeneous_components().get(weight, self.parent().zero()) + + homogeneous_component = __getitem__ # alias + def serre_derivative(self): r""" diff --git a/src/sage/modules/vector_rational_dense.pyx b/src/sage/modules/vector_rational_dense.pyx index ff1b4914295..1987e881151 100644 --- a/src/sage/modules/vector_rational_dense.pyx +++ b/src/sage/modules/vector_rational_dense.pyx @@ -326,7 +326,7 @@ cdef class Vector_rational_dense(free_module_element.FreeModuleElement): mpq_set_z(a.value, (left).value) else: # should not happen - raise TypeError("Cannot convert %s to %s" % (type(left).__name__, Rational.__name__)) + raise TypeError("cannot convert %s to %s" % (type(left).__name__, Rational.__name__)) z = self._new_c() cdef Py_ssize_t i for i in range(self._degree): @@ -343,7 +343,7 @@ cdef class Vector_rational_dense(free_module_element.FreeModuleElement): mpq_set_z(a.value, (right).value) else: # should not happen - raise TypeError("Cannot convert %s to %s" % (type(right).__name__, Rational.__name__)) + raise TypeError("cannot convert %s to %s" % (type(right).__name__, Rational.__name__)) z = self._new_c() cdef Py_ssize_t i for i in range(self._degree): diff --git a/src/sage/plot/complex_plot.pyx b/src/sage/plot/complex_plot.pyx index 6f0aeab87ae..b77c69b2f77 100644 --- a/src/sage/plot/complex_plot.pyx +++ b/src/sage/plot/complex_plot.pyx @@ -461,6 +461,8 @@ def complex_to_rgb(z_values, contoured=False, tiled=False, rgb[i, j, 2] = b sig_off() + nan_indices = np.isnan(rgb).any(-1) # Mask for undefined points + rgb[nan_indices] = 1 # Make nan_indices white return rgb diff --git a/src/sage/plot/histogram.py b/src/sage/plot/histogram.py index 295f3036eba..388c2d1391d 100644 --- a/src/sage/plot/histogram.py +++ b/src/sage/plot/histogram.py @@ -87,13 +87,8 @@ def get_minmax_data(self): TESTS:: - sage: h = histogram([10,3,5], normed=True)[0] - doctest:warning...: - DeprecationWarning: the 'normed' option is deprecated. Use 'density' instead. - See https://github.com/sagemath/sage/issues/25260 for details. + sage: h = histogram([10,3,5], density=True)[0] sage: h.get_minmax_data() - doctest:warning ... - ...VisibleDeprecationWarning: Passing `normed=True` on non-uniform bins has always been broken, and computes neither the probability density function nor the probability mass function. The result is only correct if the bins are uniform, when density=True will produce the same result anyway. The argument will be removed in a future version of numpy. {'xmax': 10.0, 'xmin': 3.0, 'ymax': 0.476190476190..., 'ymin': 0} """ import numpy diff --git a/src/sage/quadratic_forms/quadratic_form.py b/src/sage/quadratic_forms/quadratic_form.py index c4e97d97c50..f53602f49f3 100644 --- a/src/sage/quadratic_forms/quadratic_form.py +++ b/src/sage/quadratic_forms/quadratic_form.py @@ -30,13 +30,15 @@ from sage.arith.all import GCD, LCM from sage.rings.all import Ideal, QQ from sage.rings.ring import is_Ring, PrincipalIdealDomain -from sage.structure.sage_object import SageObject from sage.structure.element import is_Vector from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing +from sage.rings.polynomial.polynomial_element import is_Polynomial +from sage.rings.polynomial.multi_polynomial_element import is_MPolynomial from sage.modules.free_module_element import vector from sage.quadratic_forms.genera.genus import genera from sage.quadratic_forms.quadratic_form__evaluate import QFEvaluateVector, QFEvaluateMatrix - +from sage.structure.sage_object import SageObject +from sage.combinat.integer_lists.invlex import IntegerListsLex def QuadraticForm__constructor(R, n=None, entries=None): """ @@ -206,6 +208,10 @@ class QuadraticForm(SageObject): in `R` (given lexicographically, or equivalently, by rows of the matrix) + #. ``QuadraticForm(p)``, where + + - `p` -- a homogeneous polynomial of degree `2` + #. ``QuadraticForm(R, n)``, where - `R` -- a ring @@ -284,6 +290,16 @@ class QuadraticForm(SageObject): [ 1 5 ] [ * 4 ] + :: + + sage: P. = QQ[] + sage: p = x^2 + 2*x*y + x*z/2 + y^2 + y*z/3 + sage: QuadraticForm(p) + Quadratic form in 3 variables over Rational Field with coefficients: + [ 1 2 1/2 ] + [ * 1 1/3 ] + [ * * 0 ] + :: sage: QuadraticForm(ZZ, m + m.transpose()) @@ -499,6 +515,25 @@ def __init__(self, R, n=None, entries=None, unsafe_initialization=False, number_ sage: s.dim() 4 + sage: P. = QQ[] + sage: p = x^2 + y^2 + 2*x*z + sage: QuadraticForm(p) + Quadratic form in 3 variables over Rational Field with coefficients: + [ 1 0 2 ] + [ * 1 0 ] + [ * * 0 ] + sage: z = P.zero() + sage: QuadraticForm(z) + Quadratic form in 3 variables over Rational Field with coefficients: + [ 0 0 0 ] + [ * 0 0 ] + [ * * 0 ] + sage: q = x^2 + 3*y - z + sage: QuadraticForm(q) + Traceback (most recent call last): + ... + ValueError: polynomial is neither zero nor homogeneous of degree 2 + TESTS:: sage: s == loads(dumps(s)) @@ -510,6 +545,10 @@ def __init__(self, R, n=None, entries=None, unsafe_initialization=False, number_ sage: x = polygen(ZZ, 'x') sage: QuadraticForm(x**2) + Quadratic form in 1 variables over Integer Ring with coefficients: + [ 1 ] + + sage: QuadraticForm(1) Traceback (most recent call last): .... TypeError: wrong input for QuadraticForm @@ -527,20 +566,39 @@ def __init__(self, R, n=None, entries=None, unsafe_initialization=False, number_ M_ring = R matrix_init_flag = True - elif not is_Matrix(R): - # first argument, if not a ring, must be a matrix - raise TypeError('wrong input for QuadraticForm') - else: - # Deal with: QuadraticForm(matrix) + elif is_Matrix(R): + M = R + # Test if R is symmetric and has even diagonal - if not self._is_even_symmetric_matrix_(R): + if not self._is_even_symmetric_matrix_(M): raise TypeError("the matrix is not a symmetric with even diagonal") - # Rename the matrix and ring - M = R - M_ring = R.base_ring() + M_ring = M.base_ring() matrix_init_flag = True + elif is_Polynomial(R) or is_MPolynomial(R): + p = R + + if not p.is_zero() and not (p.is_homogeneous() and p.degree() == 2): + raise ValueError("polynomial is neither zero nor homogeneous of degree 2") + + P = p.parent() + R, n = P.base_ring(), P.ngens() + + # Extract quadratic form coefficients + entries = [] + if n == 0: + exponents = [] + elif n == 1: + exponents = [2] + else: + exponents = IntegerListsLex(2, length=n) + for alpha in exponents: + entries.append(p[alpha]) + + else: + raise TypeError('wrong input for QuadraticForm') + # Perform the quadratic form initialization if matrix_init_flag: self.__n = ZZ(M.nrows()) diff --git a/src/sage/repl/ipython_extension.py b/src/sage/repl/ipython_extension.py index 798671aab42..cad6a47ca8b 100644 --- a/src/sage/repl/ipython_extension.py +++ b/src/sage/repl/ipython_extension.py @@ -405,7 +405,7 @@ def fortran(self, line, cell): ....: C END FILE FIB1.F ....: ''') sage: fib - + sage: from numpy import array sage: a = array(range(10), dtype=float) sage: fib(a, 10) diff --git a/src/sage/rings/asymptotic/asymptotic_ring.py b/src/sage/rings/asymptotic/asymptotic_ring.py index 1423513a993..ff419b69df5 100644 --- a/src/sage/rings/asymptotic/asymptotic_ring.py +++ b/src/sage/rings/asymptotic/asymptotic_ring.py @@ -4158,9 +4158,9 @@ def _element_constructor_(self, data, simplify=True, convert=True): elif is_PowerSeriesRing(P): raise NotImplementedError( - 'Cannot convert %s from the %s to an asymptotic expansion ' + 'cannot convert %s from the %s to an asymptotic expansion ' 'in %s, since growths at other points than +oo are not yet ' - 'supported.' % (data, P, self)) + 'supported' % (data, P, self)) # Delete lines above as soon as we can deal with growths # other than the that at going to +oo. from sage.rings.infinity import PlusInfinity diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index e98b973b592..67a30c01001 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -571,7 +571,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): sage: ZZ(pari(Qp(11)(11^-7))) Traceback (most recent call last): ... - TypeError: Cannot convert p-adic with negative valuation to an integer + TypeError: cannot convert p-adic with negative valuation to an integer Test converting a list with a very large base:: @@ -640,7 +640,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): if n == x: mpz_set_pylong(self.value, n) else: - raise TypeError("Cannot convert non-integral float to integer") + raise TypeError("cannot convert non-integral float to integer") elif isinstance(x, pari_gen): global set_integer_from_gen @@ -2951,13 +2951,21 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): return n - def prime_divisors(self): + def prime_divisors(self, *args, **kwds): """ Return the prime divisors of this integer, sorted in increasing order. If this integer is negative, we do *not* include -1 among its prime divisors, since -1 is not a prime number. + INPUT: + + - ``limit`` -- (integer, optional keyword argument) + Return only prime divisors up to this bound, and the factorization + is done by checking primes up to ``limit`` using trial division. + + Any additional arguments are passed on to the :meth:`factor` method. + EXAMPLES:: sage: a = 1; a.prime_divisors() @@ -2968,8 +2976,23 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): [2, 5] sage: a = 2004; a.prime_divisors() [2, 3, 167] + + Setting the optional ``limit`` argument works as expected:: + + sage: a = 10^100 + 1 + sage: a.prime_divisors() + [73, 137, 401, 1201, 1601, 1676321, 5964848081, + 129694419029057750551385771184564274499075700947656757821537291527196801] + sage: a.prime_divisors(limit=10^3) + [73, 137, 401] + sage: a.prime_divisors(limit=10^7) + [73, 137, 401, 1201, 1601, 1676321] """ - return [r[0] for r in self.factor()] + res = [r[0] for r in self.factor(*args, **kwds)] + limit = kwds.get('limit') + if limit is not None: + res = [r for r in res if r <= limit] + return res prime_factors = prime_divisors diff --git a/src/sage/rings/integer_fake.pxd b/src/sage/rings/integer_fake.pxd index de7672fa22e..d900190f74d 100644 --- a/src/sage/rings/integer_fake.pxd +++ b/src/sage/rings/integer_fake.pxd @@ -17,7 +17,8 @@ This provides two functions: TESTS:: - sage: cython(''' # optional - sage.misc.cython + sage: cython( # optional - sage.misc.cython + ....: ''' ....: from sage.rings.integer_fake cimport Integer_AS_MPZ, is_Integer ....: from sage.rings.integer cimport Integer ....: cdef Integer x = Integer(123456789) diff --git a/src/sage/rings/number_field/number_field.py b/src/sage/rings/number_field/number_field.py index e10d4eeeb33..0d2271844ca 100644 --- a/src/sage/rings/number_field/number_field.py +++ b/src/sage/rings/number_field/number_field.py @@ -8063,7 +8063,7 @@ def _coerce_from_other_number_field(self, x): sage: L(a) Traceback (most recent call last): ... - ValueError: Cannot convert a to Number Field in b with defining polynomial x^3 - 4*x + 1 with b = 1.860805853111704? (using the specified embeddings) + ValueError: cannot convert a to Number Field in b with defining polynomial x^3 - 4*x + 1 with b = 1.860805853111704? (using the specified embeddings) Subfields automatically come with an embedding:: @@ -8156,7 +8156,7 @@ def _coerce_from_other_number_field(self, x): f = x.minpoly() ys = f.roots(ring=K, multiplicities=False) if not ys: - raise ValueError("Cannot convert %s to %s (regardless of embeddings)" % (x, K)) + raise ValueError("cannot convert %s to %s (regardless of embeddings)" % (x, K)) # Define a function are_roots_equal to determine whether two # roots of f are equal. A simple a == b does not suffice for @@ -8213,7 +8213,7 @@ def _coerce_from_other_number_field(self, x): emb_y = y.polynomial()(Kgen) if are_roots_equal(emb_x, emb_y): return y - raise ValueError("Cannot convert %s to %s (using the specified embeddings)" % (x, K)) + raise ValueError("cannot convert %s to %s (using the specified embeddings)" % (x, K)) def _coerce_map_from_(self, R): """ @@ -11220,7 +11220,7 @@ def _coerce_from_other_cyclotomic_field(self, x, only_canonical=False): if z == x: return self.zeta(m)**(r+1) z *= y - raise TypeError("Cannot coerce %s into %s" % (x, self)) + raise TypeError("cannot coerce %s into %s" % (x, self)) return self._element_class(self, x) def _coerce_from_gap(self, x): diff --git a/src/sage/rings/polynomial/multi_polynomial.pyx b/src/sage/rings/polynomial/multi_polynomial.pyx index 7bb03631661..4f8e47049a2 100644 --- a/src/sage/rings/polynomial/multi_polynomial.pyx +++ b/src/sage/rings/polynomial/multi_polynomial.pyx @@ -14,6 +14,8 @@ from sage.rings.integer cimport Integer from sage.rings.integer_ring import ZZ from sage.structure.coerce cimport coercion_model from sage.misc.derivative import multi_derivative +from sage.combinat.integer_lists.invlex import IntegerListsLex +from itertools import chain, islice from sage.misc.misc_c import prod @@ -25,7 +27,7 @@ from sage.categories.map cimport Map from sage.modules.free_module_element import vector from sage.rings.rational_field import QQ from sage.rings.complex_interval_field import ComplexIntervalField -from sage.rings.real_mpfr import RealField_class,RealField +from sage.rings.real_mpfr import RealField_class, RealField from sage.rings.polynomial.polydict cimport ETuple from sage.rings.polynomial.polynomial_element cimport Polynomial @@ -2613,6 +2615,236 @@ cdef class MPolynomial(CommutativeRingElement): with tester.assertRaises((ValueError, TypeError)): self.subs(**d) + def is_lorentzian(self, explain=False): + r""" + Return whether this is a Lorentzian polynomial. + + INPUT: + + - ``explain`` -- boolean (default: ``False``); if ``True`` + return a tuple whose first element is the boolean result of the test, + and the second element is a string describing the reason the test failed, + or ``None`` if the test succeeded. + + Lorentzian polynomials are a class of polynomials connected with the area + of discrete convex analysis. A polynomial `f` with positive real coefficients + is Lorentzian if: + + - `f` is homogeneous; + + - the support of `f` is `M`-convex + + - `f` has degree less than `2`, or if its degree is at least two, + the collection of sequential partial derivatives of `f` which are + quadratic forms have Gram matrices with at most one positive eigenvalue. + + Note in particular that the zero polynomial is Lorentzian. Examples of + Lorentzian polynomials include homogeneous stable polynomials, volume + polynomials of convex bodies and projective varieties, and Schur polynomials + after renormalizing the coefficient of each monomial `x^\alpha` by `1/\alpha!`. + + EXAMPLES: + + Renormalized Schur polynomials are Lorentzian, but not in general if the + renormalization is skipped:: + + sage: P. = QQ[] + sage: p = (x^2 / 2) + x*y + (y^2 / 2) + sage: p.is_lorentzian() + True + sage: p = x^2 + x*y + y^2 + sage: p.is_lorentzian() + False + + Homogeneous linear forms and constant polynomials with positive + coefficients are Lorentzian, as well as the zero polynomial:: + + sage: p = x + 2*y + sage: p.is_lorentzian() + True + sage: p = P(5) + sage: p.is_lorentzian() + True + sage: P.zero().is_lorentzian() + True + + Inhomogeneous polynomials and polynomials with negative coefficients + are not Lorentzian:: + + sage: p = x^2 + 2*x + y^2 + sage: p.is_lorentzian() + False + sage: p = 2*x^2 - y^2 + sage: p.is_lorentzian() + False + + It is an error to check if a polynomial is Lorentzian if its base ring + is not a subring of the real numbers, as the notion is not defined in + this case:: + + sage: Q. = CC[] + sage: q = z^2 + w^2 + sage: q.is_lorentzian() + Traceback (most recent call last): + ... + NotImplementedError: is_lorentzian only implemented for real polynomials + + The method can give a reason for a polynomial failing to be Lorentzian:: + + sage: p = x^2 + 2*x + y^2 + sage: p.is_lorentzian(explain=True) + (False, 'inhomogeneous') + + REFERENCES: + + For full definitions and related discussion, see [BrHu2019]_ and + [HMMS2019]_. The second reference gives the characterization of + Lorentzian polynomials applied in this implementation explicitly. + """ + from sage.rings.imaginary_unit import I + + # function to handle return value when reason requested + def result(val, explanation=None): + return (val, explanation) if explain else val + + try: + # this would better be handled by a category of RealFields() + self.base_ring()(I) + except (ValueError, TypeError): + pass + else: + raise NotImplementedError("is_lorentzian only implemented for real polynomials") + + if self.is_zero(): + return result(True) + + if not self.is_homogeneous(): + return result(False, "inhomogeneous") + + if any(coeff < 0 for coeff in self.coefficients()): + return result(False, "negative coefficient") + + # for degree <= 1, homogeneous with positive coefficients is sufficient + if self.degree() <= 1: + return result(True) + + # check support is M-convex + if not _is_M_convex_(self.exponents()): + return result(False, "not M-convex") + + # compute quadratic forms coming from a sequence of partial derivatives + if self.degree() == 2: + quadratic_derivs = set([self]) + else: + gens = self.parent().gens() + quadratic_derivs = set() + multi_exponents = IntegerListsLex(self.degree() - 2, length=len(gens)) + for alpha in multi_exponents: + # construct list [gen_1, exp_1, ..., gen_n, exp_n] for derivative function + d_list = chain(*zip(gens, alpha)) + d = self.derivative(*d_list) + quadratic_derivs.add(d) + + # check derivative quadratic forms have at most one positive eigenvalue + for deriv in quadratic_derivs: + from sage.quadratic_forms.quadratic_form import QuadraticForm + G = QuadraticForm(deriv).Gram_matrix() + spectrum = sorted(G.eigenvalues(), reverse=True) + if len(spectrum) > 1 and spectrum[1] > 0: + return result(False, "multiple positive eigenvalues") + + return result(True) + + +def _is_M_convex_(points): + r""" + Return whether ``points`` represents a set of integer lattice points + which are M-convex. + + Utility function for method ``is_lorentzian``, which would more properly + fit with code related to discrete convex geometry, generalized permutahedra, + or polymatroids, which are not currently implemented in Sage. + + INPUT: + + - ``points`` -- iterable for a list of integer lattice points of the + same dimension + + Examples of M-convex sets include the vertices of a matroid polytope, and the + support sets of Schur polynomials. + + EXAMPLES: + + The following points represent the vertices of a matroid polytope (indicator + vectors of the bases) of rank `2` on five elements:: + + sage: from sage.rings.polynomial.multi_polynomial import _is_M_convex_ + sage: P = [[1,1,0,0], [1,0,1,0], [0,1,1,0], [0,1,0,1], [0,0,1,1]] + sage: _is_M_convex_(P) + True + + These points are the support of the Schur polynomial in three variables for + the partition `(2,2)`:: + + sage: P = [[2,2,0], [2,0,2], [0,2,2], [2,1,1], [1,2,1], [1,1,2]] + sage: _is_M_convex_(P) + True + + The following are not examples of `M`-convex sets of points:: + + sage: P = [[1, 0, 0], [1, 1, 0], [1, 1, 1]] + sage: _is_M_convex_(P) + False + + sage: P = [[0, 1, 2], [2, 1]] + sage: _is_M_convex_(P) + Traceback (most recent call last): + ... + ValueError: input points are not the same dimension + + sage: P = [[0, 0.5, 1], [1, 1.5, 2]] + sage: _is_M_convex_(P) + Traceback (most recent call last): + ... + ValueError: input points are not integer lattice points + + REFERENCES: + + See [BrHu2019]_ for a definition of M-convexity. + """ + points_set = set(map(tuple, points)) + if not points_set: + return True + dim = len(next(iter(points_set))) + if any(len(p) != dim for p in points_set): + raise ValueError("input points are not the same dimension") + if any(entry not in ZZ for p in points_set for entry in p): + raise ValueError("input points are not integer lattice points") + for p1 in points_set: + list_p1 = list(p1) + for p2 in points_set: + if p2 == p1: + continue + delta = list(x2 - x1 for x1, x2 in zip(p1, p2)) + for i in xrange(dim): + if p2[i] > p1[i]: + # modify list_p1 to represent point p1 + e_i - e_j for various i, j + list_p1[i] += 1 # add e_i + # check exchange condition is satisfied by some index j + for j in xrange(dim): + if p2[j] < p1[j]: + list_p1[j] -= 1 # subtract e_j + exch = tuple(list_p1) # p1 + e_i - e_j + list_p1[j] += 1 # add e_j again + if tuple(exch) in points_set: + break + else: + return False + list_p1[i] -= 1 # subtract e_i + # list_p1 should now have same entries as p1 again + return True + + cdef remove_from_tuple(e, int ind): w = list(e) del w[ind] diff --git a/src/sage/rings/polynomial/multi_polynomial_ideal.py b/src/sage/rings/polynomial/multi_polynomial_ideal.py index 71494eddbc0..aaee4cbeddf 100644 --- a/src/sage/rings/polynomial/multi_polynomial_ideal.py +++ b/src/sage/rings/polynomial/multi_polynomial_ideal.py @@ -2187,7 +2187,7 @@ def transformed_basis(self, algorithm="gwalk", other_ring=None, singular=singula return PolynomialSequence(nR, sorted([nR(f) for f in nIs],reverse=True), immutable=True) else: - raise TypeError("Cannot convert basis with given algorithm") + raise TypeError("cannot convert basis with given algorithm") @handle_AA_and_QQbar def elimination_ideal(self, variables, algorithm=None, *args, **kwds): diff --git a/src/sage/rings/polynomial/ore_polynomial_element.pyx b/src/sage/rings/polynomial/ore_polynomial_element.pyx index 820c758496c..4db1a1652ff 100644 --- a/src/sage/rings/polynomial/ore_polynomial_element.pyx +++ b/src/sage/rings/polynomial/ore_polynomial_element.pyx @@ -1301,7 +1301,8 @@ cdef class OrePolynomial(AlgebraElement): TESTS:: - sage: cython(''' # optional - sage.misc.cython + sage: cython( # optional - sage.misc.cython + ....: ''' ....: from sage.rings.polynomial.ore_polynomial_element cimport OrePolynomial ....: def left_lcm_cofactor(OrePolynomial P, OrePolynomial Q): ....: return P._left_lcm_cofactor(Q) @@ -1315,8 +1316,8 @@ cdef class OrePolynomial(AlgebraElement): sage: P = S.random_element(degree=2) * D sage: Q = S.random_element(degree=2) * D sage: L = P.left_lcm(Q) - sage: U = left_lcm_cofactor(P, Q) - sage: (U*P).right_monic() == L + sage: U = left_lcm_cofactor(P, Q) # optional - sage.misc.cython + sage: (U*P).right_monic() == L # optional - sage.misc.cython True """ cdef OrePolynomial Q, R, T @@ -1378,7 +1379,8 @@ cdef class OrePolynomial(AlgebraElement): TESTS:: - sage: cython(''' # optional - sage.misc.cython + sage: cython( # optional - sage.misc.cython + ....: ''' ....: from sage.rings.polynomial.ore_polynomial_element cimport OrePolynomial ....: def right_lcm_cofactor(OrePolynomial P, OrePolynomial Q): ....: return P._right_lcm_cofactor(Q) @@ -1392,8 +1394,8 @@ cdef class OrePolynomial(AlgebraElement): sage: P = D * S.random_element(degree=2) sage: Q = D * S.random_element(degree=2) sage: L = P.right_lcm(Q) - sage: U = right_lcm_cofactor(P, Q) - sage: (P*U).left_monic() == L + sage: U = right_lcm_cofactor(P, Q) # optional - sage.misc.cython + sage: (P*U).left_monic() == L # optional - sage.misc.cython True """ cdef OrePolynomial Q, R, T diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index a522af5457c..ceb36976126 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -8027,11 +8027,11 @@ cdef class Polynomial(CommutativeAlgebraElement): sage: f.roots(RR) Traceback (most recent call last): ... - TypeError: Cannot evaluate symbolic expression to a numeric value. + TypeError: cannot evaluate symbolic expression to a numeric value sage: f.roots(CC) Traceback (most recent call last): ... - TypeError: Cannot evaluate symbolic expression to a numeric value. + TypeError: cannot evaluate symbolic expression to a numeric value We can find roots of polynomials defined over `\ZZ` or `\QQ` over the `p`-adics, see :trac:`15422`:: @@ -8856,6 +8856,61 @@ cdef class Polynomial(CommutativeAlgebraElement): else: return b + def is_lorentzian(self, explain=False): + r""" + Return ``True`` if this is a Lorentzian polynomial. + + A univariate real polynomial is Lorentzian if and only if it is a + monomial with positive coefficient, or zero. The definition is more + involved for multivariate real polynomials. + + INPUT: + + - ``explain`` -- boolean (default: ``False``); if ``True`` + return a tuple whose first element is the boolean result of the test, + and the second element is a string describing the reason the test failed, + or ``None`` if the test succeeded + + EXAMPLES:: + + sage: P. = QQ[] + sage: p1 = x^2 + sage: p1.is_lorentzian() + True + sage: p2 = 1 + x^2 + sage: p2.is_lorentzian() + False + sage: p3 = P.zero() + sage: p3.is_lorentzian() + True + sage: p4 = -2*x^3 + sage: p4.is_lorentzian() + False + + It is an error to check if a polynomial is Lorentzian if its base ring + is not a subring of the real numbers, as the notion is not defined in + this case:: + + sage: Q. = CC[] + sage: q = y^2 + sage: q.is_lorentzian() + Traceback (most recent call last): + ... + NotImplementedError: is_lorentzian only implemented for real polynomials + + The method can give a reason for a polynomial failing to be Lorentzian:: + + sage: p = x^2 + 2*x + sage: p.is_lorentzian(explain=True) + (False, 'inhomogeneous') + + REFERENCES: + + For full definitions and related discussion, see [BrHu2019]_ and + [HMMS2019]_. + """ + R = PolynomialRing(self.base_ring(), 1, [self.variable_name()]) + return R(self).is_lorentzian(explain=explain) def variable_name(self): """ diff --git a/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx b/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx index 2b55a681a32..1b1d37f9d2a 100644 --- a/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx +++ b/src/sage/rings/polynomial/polynomial_modn_dense_ntl.pyx @@ -383,6 +383,41 @@ cdef class Polynomial_dense_mod_n(Polynomial): self.__singular = singular(str(self)) return self.__singular + @coerce_binop + def minpoly_mod(self, other): + r""" + Compute the minimal polynomial of this polynomial modulo another + polynomial in the same ring. + + ALGORITHM: + + NTL's ``MinPolyMod()``, which uses Shoup's algorithm [Sho1999]_. + + EXAMPLES:: + + sage: R. = PolynomialRing(GF(101), implementation='NTL') + sage: f = x^17 + x^2 - 1 + sage: (x^2).minpoly_mod(f) + x^17 + 100*x^2 + 2*x + 100 + + TESTS: + + Random testing:: + + sage: p = random_prime(2^99) + sage: R. = PolynomialRing(GF(p), implementation='NTL') + sage: d = randrange(1,50) + sage: f = R.random_element(d) + sage: g = R.random_element((-1,5*d)) + sage: poly = g.minpoly_mod(f) + sage: poly(R.quotient(f)(g)) + 0 + """ + mod = other.ntl_ZZ_pX() + elt = self.ntl_ZZ_pX() % mod + res = elt.minpoly_mod(mod) + return self.parent()(res, construct=True) + def small_roots(self, *args, **kwds): r""" See :func:`sage.rings.polynomial.polynomial_modn_dense_ntl.small_roots` diff --git a/src/sage/rings/polynomial/polynomial_real_mpfr_dense.pyx b/src/sage/rings/polynomial/polynomial_real_mpfr_dense.pyx index 8fa744ff668..c13372dcd25 100644 --- a/src/sage/rings/polynomial/polynomial_real_mpfr_dense.pyx +++ b/src/sage/rings/polynomial/polynomial_real_mpfr_dense.pyx @@ -85,12 +85,12 @@ cdef class PolynomialRealDense(Polynomial): sage: PolynomialRealDense(RR['x'], [1,a]) Traceback (most recent call last): ... - TypeError: Cannot evaluate symbolic expression to a numeric value. + TypeError: cannot evaluate symbolic expression to a numeric value sage: R. = SR[] sage: (x-a).change_ring(RR) Traceback (most recent call last): ... - TypeError: Cannot evaluate symbolic expression to a numeric value. + TypeError: cannot evaluate symbolic expression to a numeric value sage: sig_on_count() 0 diff --git a/src/sage/rings/polynomial/polynomial_zmod_flint.pyx b/src/sage/rings/polynomial/polynomial_zmod_flint.pyx index 15958758d18..04c523d9788 100644 --- a/src/sage/rings/polynomial/polynomial_zmod_flint.pyx +++ b/src/sage/rings/polynomial/polynomial_zmod_flint.pyx @@ -850,3 +850,23 @@ cdef class Polynomial_zmod_flint(Polynomial_template): sig_off() return res + + @coerce_binop + def minpoly_mod(self, other): + r""" + Thin wrapper for + :meth:`sage.rings.polynomial.polynomial_modn_dense_ntl.Polynomial_dense_mod_n.minpoly_mod`. + + EXAMPLES:: + + sage: R. = GF(127)[] + sage: type(x) + + sage: (x^5-3).minpoly_mod(x^3+5*x-1) + x^3 + 34*x^2 + 125*x + 95 + """ + parent = self.parent() + name, = parent.variable_names() + from sage.rings.polynomial.polynomial_ring_constructor import _single_variate + R = _single_variate(parent.base_ring(), name=name, implementation='NTL') + return parent(R(self % other).minpoly_mod(R(other))) diff --git a/src/sage/rings/qqbar.py b/src/sage/rings/qqbar.py index d9eee8fd318..1e21659d504 100644 --- a/src/sage/rings/qqbar.py +++ b/src/sage/rings/qqbar.py @@ -2230,30 +2230,76 @@ def clear_denominators(poly): (2, x + 3) sage: clear_denominators(x^2 + x/2 + 1/4) (2, x^2 + x + 1) - """ - # This algorithm factors the polynomial denominators. - # We should check the size of the denominators and switch to - # an alternate, less precise algorithm if we decide factoring - # would be too slow. + TESTS:: + + sage: R. = QQ[] + sage: coefficients_as_integer_ratios = [ + ....: (-2774600080567517563395913264491323241652779066919616441429094563840, + ....: 4143301981494946291120265789013000494010735992517219217956448435626412078440663802209333), + ....: (-24216324060414384566983400245979288839929814383090701293489050615808, + ....: 4143301981494946291120265789013000494010735992517219217956448435626412078440663802209333), + ....: (325579773864372490083706670433410006284520887405882567940047555526656, + ....: 180143564412823751787837643000565238870031999674661705128541236331583133845246252269971), + ....: (-86736048492777879473586471630941922517134071457946320753641122078523392, + ....: 4143301981494946291120265789013000494010735992517219217956448435626412078440663802209333), + ....: (-2338058278498910195688689352766977573607428722429118859280880481590329344, + ....: 4143301981494946291120265789013000494010735992517219217956448435626412078440663802209333), + ....: (105830270645785996318880019945503938356315302592627229453391693256551317504, + ....: 1381100660498315430373421929671000164670245330839073072652149478542137359480221267403111), + ....: (1110926147990548796149597141538460730252912439930561079348611699181798425600, + ....: 4143301981494946291120265789013000494010735992517219217956448435626412078440663802209333), + ....: (-89705438380888704653335165590083767769953879654958783855317882966200828559360, + ....: 4143301981494946291120265789013000494010735992517219217956448435626412078440663802209333), + ....: (1151092895747371986483047191334923516591005329489629755485810229546333821625856, + ....: 1381100660498315430373421929671000164670245330839073072652149478542137359480221267403111), + ....: (24725641793859400310483886670136079788266826658111372723121573233077840328938576, + ....: 4143301981494946291120265789013000494010735992517219217956448435626412078440663802209333), + ....: (-31051495080139473677925068000403254349133134904365702868216464107777210775457136, + ....: 153455628944257270041491325519000018296693925648785896961349942060237484386691251933679), + ....: (9431591461895130351865642769482226964622378075329823505708119342634182162193000560, + ....: 4143301981494946291120265789013000494010735992517219217956448435626412078440663802209333), + ....: (1721694880863483428337378731387732043714427651970488363462560317808769716807148992, + ....: 153455628944257270041491325519000018296693925648785896961349942060237484386691251933679), + ....: (255327752077837584624694974814916395144764296822788813014081161094149724325120096, + ....: 27080405107810106477910233915117650287651869232138687699061754481218379597651397400061), + ....: (238105337335596176836773151768694069523377650990453522899627157538495252117232992338, + ....: 27080405107810106477910233915117650287651869232138687699061754481218379597651397400061), + ....: (1255826892296350234297164500548658984205287902407560187136301197703464130999349114638, + ....: 14336685057075938723599535602121108975815695475838128781856222960645024492874269211797), + ....: (1, 1)] + sage: p = R(coefficients_as_integer_ratios) + sage: a = QQbar.polynomial_root( + ....: AA.common_polynomial(p), + ....: CIF(RIF(-RR(0.036151142425748496), -RR(0.036151142425748489)), + ....: RIF(-RR(0.011298617187916445), -RR(0.011298617187916443)))) + sage: a.exactify() + sage: a + -0.03615114242574849? - 0.011298617187916444?*I + """ d = poly.denominator() if d == 1: return d, poly deg = poly.degree() - factors = {} - for i in range(deg): - d = poly[i].denominator() - df = factor(d) - for f, e in df: - oe = 0 - if f in factors: - oe = factors[f] - min_e = (e + (deg - i) - 1) // (deg - i) - factors[f] = max(oe, min_e) - change = 1 - for f, e in factors.items(): - change = change * f**e + denoms = [c.denominator() for c in poly] + if all(d.nbits() < 128 for d in denoms): + # Factor the polynomial denominators. + factors = {} + for i, d in enumerate(denoms): + df = factor(d) + for f, e in df: + oe = 0 + if f in factors: + oe = factors[f] + min_e = (e + (deg - i) - 1) // (deg - i) + factors[f] = max(oe, min_e) + change = 1 + for f, e in factors.items(): + change = change * f**e + else: + # Factoring would be too slow. + change = poly.monic().denominator() poly = poly * (change**deg) poly = poly(poly.parent().gen() / change) return change, poly diff --git a/src/sage/rings/real_double.pyx b/src/sage/rings/real_double.pyx index 1341d2f65ff..d5760fd69e2 100644 --- a/src/sage/rings/real_double.pyx +++ b/src/sage/rings/real_double.pyx @@ -947,7 +947,7 @@ cdef class RealDoubleElement(FieldElement): sage: ZZ(RDF(-2345.67)) Traceback (most recent call last): ... - TypeError: Cannot convert non-integral float to integer + TypeError: cannot convert non-integral float to integer """ return Integer(self._value) diff --git a/src/sage/rings/real_mpfi.pyx b/src/sage/rings/real_mpfi.pyx index 1f7d7d7f4f8..c6573448a93 100644 --- a/src/sage/rings/real_mpfi.pyx +++ b/src/sage/rings/real_mpfi.pyx @@ -5356,7 +5356,8 @@ def __create__RealIntervalField_version0(prec, sci_not): """ return RealIntervalField(prec, sci_not) -## Keep all old versions!!! + +# Keep all old versions!!! def __create__RealIntervalFieldElement_version0(parent, x, base=10): """ For pickling. @@ -5368,6 +5369,7 @@ def __create__RealIntervalFieldElement_version0(parent, x, base=10): """ return RealIntervalFieldElement(parent, x, base=base) + def __create__RealIntervalFieldElement_version1(parent, lower, upper): """ For pickling. diff --git a/src/sage/rings/real_mpfr.pyx b/src/sage/rings/real_mpfr.pyx index 421f489a559..32a3e0494f8 100644 --- a/src/sage/rings/real_mpfr.pyx +++ b/src/sage/rings/real_mpfr.pyx @@ -2247,7 +2247,7 @@ cdef class RealNumber(sage.structure.element.RingElement): 100000000000000000 """ if not mpfr_number_p(self.value): - raise ValueError('Cannot convert infinity or NaN to Sage Integer') + raise ValueError('cannot convert infinity or NaN to Sage Integer') cdef Integer z = Integer() mpfr_get_z(z.value, self.value, MPFR_RNDZ) @@ -3236,7 +3236,7 @@ cdef class RealNumber(sage.structure.element.RingElement): <... 'int'> """ if not mpfr_number_p(self.value): - raise ValueError('Cannot convert infinity or NaN to Python int') + raise ValueError('cannot convert infinity or NaN to Python int') cdef Integer z = Integer() mpfr_get_z(z.value, self.value, MPFR_RNDZ) @@ -3352,7 +3352,7 @@ cdef class RealNumber(sage.structure.element.RingElement): # as subject-to-change. if mpfr_nan_p(self.value) or mpfr_inf_p(self.value): - raise ValueError('Cannot convert NaN or infinity to Pari float') + raise ValueError('cannot convert NaN or infinity to Pari float') # wordsize for PARI cdef unsigned long wordsize = sizeof(long)*8 @@ -3678,14 +3678,14 @@ cdef class RealNumber(sage.structure.element.RingElement): sage: RR('nan').simplest_rational() Traceback (most recent call last): ... - ValueError: Cannot convert NaN or infinity to rational number + ValueError: cannot convert NaN or infinity to rational number sage: RR('-infinity').simplest_rational() Traceback (most recent call last): ... - ValueError: Cannot convert NaN or infinity to rational number + ValueError: cannot convert NaN or infinity to rational number """ if not mpfr_number_p(self.value): - raise ValueError('Cannot convert NaN or infinity to rational number') + raise ValueError('cannot convert NaN or infinity to rational number') if mpfr_zero_p(self.value): return Rational(0) @@ -3784,23 +3784,23 @@ cdef class RealNumber(sage.structure.element.RingElement): sage: RR('nan').nearby_rational(max_denominator=1000) Traceback (most recent call last): ... - ValueError: Cannot convert NaN or infinity to rational number + ValueError: cannot convert NaN or infinity to rational number sage: RR('nan').nearby_rational(max_error=0.01) Traceback (most recent call last): ... - ValueError: Cannot convert NaN or infinity to rational number + ValueError: cannot convert NaN or infinity to rational number sage: RR(oo).nearby_rational(max_denominator=1000) Traceback (most recent call last): ... - ValueError: Cannot convert NaN or infinity to rational number + ValueError: cannot convert NaN or infinity to rational number sage: RR(oo).nearby_rational(max_error=0.01) Traceback (most recent call last): ... - ValueError: Cannot convert NaN or infinity to rational number + ValueError: cannot convert NaN or infinity to rational number """ if not mpfr_number_p(self.value): - raise ValueError('Cannot convert NaN or infinity to rational number') + raise ValueError('cannot convert NaN or infinity to rational number') if ((max_error is None and max_denominator is None) or (max_error is not None and max_denominator is not None)): @@ -6105,7 +6105,7 @@ def create_RealField(*args, **kwds): See https://github.com/sagemath/sage/issues/24511 for details. Real Field with 53 bits of precision """ - #deprecation has already been imported in this file + # deprecation has already been imported in this file deprecation(24511, "Please import create_RealField from sage.rings.real_field") from sage.rings.real_field import create_RealField as cr return cr(*args, **kwds) diff --git a/src/sage/rings/tate_algebra_ideal.pyx b/src/sage/rings/tate_algebra_ideal.pyx index 17031adcec2..84d1b05b3db 100644 --- a/src/sage/rings/tate_algebra_ideal.pyx +++ b/src/sage/rings/tate_algebra_ideal.pyx @@ -625,7 +625,8 @@ cdef TateAlgebraElement regular_reduce(sgb, TateAlgebraTerm s, TateAlgebraElemen TESTS:: - sage: cython(''' # optional - sage.misc.cython + sage: cython( # optional - sage.misc.cython + ....: ''' ....: from sage.rings.tate_algebra_ideal cimport regular_reduce ....: def python_regular_reduce(gb, s, v, stopval): ....: return regular_reduce(gb, s, v, stopval) diff --git a/src/sage/rings/universal_cyclotomic_field.py b/src/sage/rings/universal_cyclotomic_field.py index d238bce3450..0ef56bfd2d0 100644 --- a/src/sage/rings/universal_cyclotomic_field.py +++ b/src/sage/rings/universal_cyclotomic_field.py @@ -561,7 +561,7 @@ def to_cyclotomic_field(self, R=None): sage: CF(E(5)) # indirect doctest Traceback (most recent call last): ... - TypeError: Cannot coerce zeta5 into Cyclotomic Field of order 7 and + TypeError: cannot coerce zeta5 into Cyclotomic Field of order 7 and degree 6 sage: CF = CyclotomicField(10) diff --git a/src/sage/schemes/affine/affine_morphism.py b/src/sage/schemes/affine/affine_morphism.py index 32c2e47e494..9efef46cda3 100644 --- a/src/sage/schemes/affine/affine_morphism.py +++ b/src/sage/schemes/affine/affine_morphism.py @@ -59,7 +59,7 @@ from sage.misc.cachefunc import cached_method from sage.misc.lazy_attribute import lazy_attribute -from sage.arith.all import gcd +from sage.arith.misc import GCD as gcd from sage.rings.integer import Integer from sage.rings.finite_rings.finite_field_constructor import is_PrimeFiniteField diff --git a/src/sage/schemes/elliptic_curves/BSD.py b/src/sage/schemes/elliptic_curves/BSD.py index a9a42ebd84b..b44ef5d9c16 100644 --- a/src/sage/schemes/elliptic_curves/BSD.py +++ b/src/sage/schemes/elliptic_curves/BSD.py @@ -2,7 +2,9 @@ "Birch and Swinnerton-Dyer formulas" from sage.arith.misc import prime_divisors -from sage.rings.all import ZZ, Infinity, QuadraticField +from sage.rings.integer_ring import ZZ +from sage.rings.infinity import Infinity +from sage.rings.number_field.number_field import QuadraticField from sage.functions.other import ceil @@ -480,7 +482,7 @@ def prove_BSD(E, verbosity=0, two_desc='mwrank', proof=None, secs_hi=5, # We do not know BSD(E,p) for even a single p, since it's # an open problem to show that L^r(E,1)/(Reg*Omega) is # rational for any curve with r >= 2. - from sage.sets.all import Primes + from sage.sets.primes import Primes BSD.primes = Primes() if return_BSD: BSD.rank = rank_lower_bd diff --git a/src/sage/schemes/elliptic_curves/cardinality.py b/src/sage/schemes/elliptic_curves/cardinality.py index cc93b9ecf74..345b0e761d4 100644 --- a/src/sage/schemes/elliptic_curves/cardinality.py +++ b/src/sage/schemes/elliptic_curves/cardinality.py @@ -21,7 +21,10 @@ # **************************************************************************** from .constructor import EllipticCurve, EllipticCurve_from_j from sage.schemes.curves.projective_curve import Hasse_bounds -from sage.rings.all import Integer, ZZ, GF, polygen +from sage.rings.integer import Integer +from sage.rings.integer_ring import ZZ +from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF +from sage.rings.polynomial.polynomial_ring import polygen from sage.groups.generic import order_from_bounds diff --git a/src/sage/schemes/elliptic_curves/cm.py b/src/sage/schemes/elliptic_curves/cm.py index 6d56371ce93..9bb1552b68e 100644 --- a/src/sage/schemes/elliptic_curves/cm.py +++ b/src/sage/schemes/elliptic_curves/cm.py @@ -34,12 +34,12 @@ # **************************************************************************** from sage.interfaces.magma import magma -from sage.rings.all import (Integer, - QQ, - ZZ, - IntegerRing, - is_fundamental_discriminant, - PolynomialRing) +from sage.rings.integer import Integer +from sage.rings.rational_field import QQ +from sage.rings.integer_ring import ZZ +from sage.rings.integer_ring import IntegerRing +from sage.rings.number_field.number_field import is_fundamental_discriminant +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.misc.cachefunc import cached_function @@ -124,7 +124,8 @@ def hilbert_class_polynomial(D, algorithm=None): raise ValueError("%s is not a valid algorithm" % algorithm) from sage.quadratic_forms.binary_qf import BinaryQF_reduced_representatives - from sage.rings.all import RR, ComplexField + from sage.rings.real_mpfr import RR + from sage.rings.complex_mpfr import ComplexField from sage.functions.all import elliptic_j # get all primitive reduced quadratic forms, (necessary to exclude @@ -623,7 +624,8 @@ def is_cm_j_invariant(j, method='new'): True """ # First we check that j is an algebraic number: - from sage.rings.all import NumberFieldElement, NumberField + from sage.rings.number_field.number_field_element import NumberFieldElement + from sage.rings.number_field.number_field import NumberField if not isinstance(j, NumberFieldElement) and j not in QQ: raise NotImplementedError("is_cm_j_invariant() is only implemented for number field elements") diff --git a/src/sage/schemes/elliptic_curves/descent_two_isogeny.pyx b/src/sage/schemes/elliptic_curves/descent_two_isogeny.pyx index 5a265b40c85..4550db78cbd 100644 --- a/src/sage/schemes/elliptic_curves/descent_two_isogeny.pyx +++ b/src/sage/schemes/elliptic_curves/descent_two_isogeny.pyx @@ -19,8 +19,8 @@ from sage.rings.integer_ring import ZZ from sage.rings.polynomial.polynomial_ring import polygen cdef object x_ZZ = polygen(ZZ) from sage.rings.polynomial.real_roots import real_roots -from sage.arith.all import prime_divisors -from sage.all import ntl +from sage.arith.misc import prime_divisors +import sage.libs.ntl.all as ntl from sage.rings.integer cimport Integer from sage.libs.gmp.mpz cimport * diff --git a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py index 68194f600c2..441f45c2e12 100644 --- a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py +++ b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py @@ -2486,7 +2486,7 @@ def __compute_omega_general(self, E, psi, psi_pr, phi, phi_pr): # thesis are wrong, the correct formulas # are coded below - from sage.arith.all import binomial + from sage.arith.misc import binomial for j in range(n - 1): psi_prpr += binomial(j+2, 2) * psi[j+2] * cur_x_pow diff --git a/src/sage/schemes/elliptic_curves/ell_field.py b/src/sage/schemes/elliptic_curves/ell_field.py index 9d342607c7b..107e0669da2 100644 --- a/src/sage/schemes/elliptic_curves/ell_field.py +++ b/src/sage/schemes/elliptic_curves/ell_field.py @@ -232,7 +232,7 @@ def quartic_twist(self, D): INPUT: - - ``D`` (must be nonzero) -- the twisting parameter.. + - ``D`` (must be nonzero) -- the twisting parameter .. NOTE:: @@ -271,11 +271,11 @@ def quartic_twist(self, D): def sextic_twist(self, D): r""" - Return the quartic twist of this curve by `D`. + Return the sextic twist of this curve by `D`. INPUT: - - ``D`` (must be nonzero) -- the twisting parameter.. + - ``D`` (must be nonzero) -- the twisting parameter .. NOTE:: @@ -1434,7 +1434,7 @@ def isogenies_prime_degree(self, l=None, max_l=31): raise NotImplementedError("This code could be implemented for QQbar, but has not been yet.") if l is None: - from sage.rings.all import prime_range + from sage.rings.fast_arith import prime_range L = prime_range(max_l + 1) else: try: diff --git a/src/sage/schemes/elliptic_curves/ell_finite_field.py b/src/sage/schemes/elliptic_curves/ell_finite_field.py index 2ab127bcb92..a379bc469e8 100644 --- a/src/sage/schemes/elliptic_curves/ell_finite_field.py +++ b/src/sage/schemes/elliptic_curves/ell_finite_field.py @@ -10,7 +10,9 @@ - John Cremona (2008-02): Point counting and group structure for non-prime fields, Frobenius endomorphism and order, elliptic logs -- Mariah Lenox (2011-03): Added set_order method +- Mariah Lenox (2011-03): Added ``set_order`` method + +- Lorenz Panny, John Cremona (2023-02): ``.twists()`` """ # **************************************************************************** @@ -23,18 +25,24 @@ # https://www.gnu.org/licenses/ # **************************************************************************** +import sage.groups.generic as generic +from sage.arith.functions import lcm +from sage.arith.misc import binomial, GCD as gcd +from sage.groups.additive_abelian.additive_abelian_wrapper import AdditiveAbelianGroupWrapper +from sage.misc.cachefunc import cached_method +from sage.rings.finite_rings.element_base import is_FiniteFieldElement +from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF +from sage.rings.integer import Integer +from sage.rings.integer_ring import ZZ +from sage.rings.polynomial.polynomial_ring import polygen +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.schemes.curves.projective_curve import Hasse_bounds -from .ell_field import EllipticCurve_field -from .constructor import EllipticCurve from sage.schemes.hyperelliptic_curves.hyperelliptic_finite_field import HyperellipticCurve_finite_field -from sage.rings.all import Integer, ZZ, PolynomialRing, GF, polygen -from sage.rings.finite_rings.element_base import is_FiniteFieldElement -import sage.groups.generic as generic + from . import ell_point -from sage.arith.all import gcd, lcm, binomial -from sage.misc.cachefunc import cached_method -from sage.groups.additive_abelian.additive_abelian_wrapper import AdditiveAbelianGroupWrapper +from .constructor import EllipticCurve +from .ell_field import EllipticCurve_field class EllipticCurve_finite_field(EllipticCurve_field, HyperellipticCurve_finite_field): @@ -1414,6 +1422,482 @@ def _fetch_cached_order(self, other): if n is not None: self._order = n + def twists(self): + r""" + Return a list of `k`-isomorphism representatives of all + twists of this elliptic curve, where `k` is the base field. + + The input curve appears as the first entry of the result. + + .. NOTE:: + + A *twist* of `E/k` is an elliptic curve `E'` defined over + `k` that is isomorphic to `E` over the algebraic closure + `\bar k`. + + Most elliptic curves over a finite field only admit a + single nontrivial twist (the quadratic twist); the only + exceptions are curves with `j`-invariant `0` or `1728`. + + In all cases the sum over all the twists `E'` of `1/|Aut(E')|` is 1. + + .. SEEALSO:: + + - :meth:`~sage.schemes.elliptic_curves.ell_field.EllipticCurve_field.quadratic_twist` + - :meth:`~sage.schemes.elliptic_curves.ell_field.EllipticCurve_field.quartic_twist` + - :meth:`~sage.schemes.elliptic_curves.ell_field.EllipticCurve_field.sextic_twist` + + EXAMPLES:: + + sage: E = EllipticCurve(GF(97), [1,1]) + sage: E.j_invariant() + 54 + sage: E.twists() + [Elliptic Curve defined by y^2 = x^3 + x + 1 over Finite Field of size 97, + Elliptic Curve defined by y^2 = x^3 + ... over Finite Field of size 97] + + :: + + sage: E = EllipticCurve(GF(97), [1,0]) + sage: E.j_invariant() + 79 + sage: E.twists() + [Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 97, + Elliptic Curve defined by y^2 = x^3 + ... over Finite Field of size 97, + Elliptic Curve defined by y^2 = x^3 + ... over Finite Field of size 97, + Elliptic Curve defined by y^2 = x^3 + ... over Finite Field of size 97] + + :: + + sage: E = EllipticCurve(GF(97), [0,1]) + sage: E.j_invariant() + 0 + sage: E.twists() + [Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 97, + Elliptic Curve defined by y^2 = x^3 + ... over Finite Field of size 97, + Elliptic Curve defined by y^2 = x^3 + ... over Finite Field of size 97, + Elliptic Curve defined by y^2 = x^3 + ... over Finite Field of size 97, + Elliptic Curve defined by y^2 = x^3 + ... over Finite Field of size 97, + Elliptic Curve defined by y^2 = x^3 + ... over Finite Field of size 97] + + This can be useful to quickly compute a list of all elliptic curves + over a finite field `k` up to `k`-isomorphism:: + + sage: Es = [E for j in GF(13) for E in EllipticCurve(j=j).twists()] + sage: len(Es) + 32 + sage: Es + [Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 13, + ... + Elliptic Curve defined by y^2 = x^3 + ... over Finite Field of size 13] + + In characteristic 3, the number of twists is 2 except for + `j=0=1728`, when there are either 4 or 6 depending on whether the + field has odd or even degree over `\GF{3}`:: + + sage: K = GF(3**5) + sage: [E.ainvs() for E in EllipticCurve(j=K(1)).twists()] + [(0, 1, 0, 0, 2), (0, z5, 0, 0, 2*z5^3)] + + sage: K = GF(3**5) + sage: [E.ainvs() for E in EllipticCurve(j=K(0)).twists()] # random + [(0, 0, 0, 1, 0), + (0, 0, 0, 2, 0), + (0, 0, 0, 2, z5^4 + z5^3 + z5^2), + (0, 0, 0, 2, 2*z5^4 + 2*z5^3 + 2*z5^2)] + + sage: K = GF(3**4) + sage: [E.ainvs() for E in EllipticCurve(j=K(1)).twists()] + [(0, 1, 0, 0, 2), (0, z4, 0, 0, 2*z4^3)] + + sage: K = GF(3**4) + sage: [E.ainvs() for E in EllipticCurve(j=K(0)).twists()] # random + [(0, 0, 0, 1, 0), + (0, 0, 0, 2, 2*z4^3 + 2*z4^2 + 2*z4 + 2), + (0, 0, 0, 1, 0), + (0, 0, 0, 1, 2*z4^3 + 2*z4^2 + 2*z4 + 2), + (0, 0, 0, z4, 0), + (0, 0, 0, z4^3, 0)] + + In characteristic 2, the number of twists is 2 except for + `j=0=1728`, when there are either 3 or 7 depending on whether the + field has odd or even degree over `\GF{2}`:: + + sage: K = GF(2**7) + sage: [E.ainvs() for E in EllipticCurve(j=K(1)).twists()] + [(1, 0, 0, 0, 1), (1, 1, 0, 0, 1)] + + sage: K = GF(2**7) + sage: [E.ainvs() for E in EllipticCurve(j=K(0)).twists()] + [(0, 0, 1, 0, 0), (0, 0, 1, 1, 0), (0, 0, 1, 1, 1)] + + sage: K = GF(2**8) + sage: [E.ainvs() for E in EllipticCurve(j=K(1)).twists()] # random + [(1, 0, 0, 0, 1), (1, z8^7 + z8^6 + z8^5 + z8^4 + z8^2 + z8, 0, 0, 1)] + + sage: K = GF(2**8) + sage: [E.ainvs() for E in EllipticCurve(j=K(0)).twists()] # random + [(0, 0, 1, 0, 0), + (0, 0, 1, 0, z8^5 + z8^4 + z8^3), + (0, 0, 1, z8^6 + z8^5 + z8^2 + 1, 0), + (0, 0, z8^4 + z8^3 + z8^2 + 1, 0, 0), + (0, 0, z8^4 + z8^3 + z8^2 + 1, 0, z8^3 + z8^2 + 1), + (0, 0, z8^6 + z8^3 + z8^2, 0, 0), + (0, 0, z8^6 + z8^3 + z8^2, 0, z8^3 + z8^2)] + + TESTS: + + Randomized check that we find all twists and there are no duplicates:: + + sage: p = next_prime(randrange(2,100)) + sage: e = randrange(1,10) + sage: F. = GF((p,e)) + sage: while True: + ....: try: + ....: E = EllipticCurve([F.random_element() for _ in range(5)]) + ....: except ArithmeticError: + ....: pass + ....: else: + ....: break + sage: twists1 = E.twists() + sage: {sum(E1.is_isomorphic(E2) for E2 in twists1) == 1 for E1 in twists1} + {True} + sage: j = E.j_invariant() + sage: A,B = polygens(F, 'A,B') + sage: eq = 1728*4*A**3 - j * (4*A**3 + 27*B**2) + sage: twists2 = [] + sage: for _ in range(10): + ....: V = Ideal([eq, A + B - F.random_element()]).variety() + ....: if not V: + ....: continue + ....: sol = choice(V) + ....: a, b = sol[A], sol[B] + ....: try: + ....: twists2.append(EllipticCurve([a, b])) + ....: except ArithmeticError: + ....: pass + sage: all(any(E2.is_isomorphic(E1) for E1 in twists1) for E2 in twists2) + True + """ + K = self.base_field() + j = self.j_invariant() + twists = None + if not j: + twists = curves_with_j_0(K) + elif j==1728: + twists = curves_with_j_1728(K) + if twists: # i.e. if j=0 or 1728 + # replace the one isomorphic to self with self and move to front + for i,t in enumerate(twists): + if self.is_isomorphic(t): + twists[i] = twists[0] + twists[0] = self + break + return twists + + # Now j is not 0 or 1728, and we only have a quadratic twist + + if K.characteristic() == 2: # find D with trace 1 for the additive twist + D = K.one() # will work if degree is odd + while D.trace() == 0: + D = K.random_element() + else: # find a nonsquare D + D = K.gen() + q2 = (K.cardinality()-1)//2 + while not D or D**q2 == 1: + D = K.random_element() + return [self, self.quadratic_twist(D)] + +def curves_with_j_0(K): + r""" + Return a complete list of pairwise nonisomorphic elliptic curves with `j`-invariant 0 over the finite field `K`. + + .. NOTE:: + + In characteristics 2 and 3 this function simply calls ``curves_with_j_0_char2`` or + ``curves_with_j_0_char3``. Otherwise there are either 2 or 6 curves, parametrised by + `K^*/(K^*)^6`. + + Examples: + + For `K=\GF{q}` where `q\equiv1\mod{6}` there are six curves, the sextic twists of `y^2=x^3+1`:: + + sage: from sage.schemes.elliptic_curves.ell_finite_field import curves_with_j_0 + sage: sorted(curves_with_j_0(GF(7)), key = lambda E: E.a_invariants()) + [Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7, + Elliptic Curve defined by y^2 = x^3 + 2 over Finite Field of size 7, + Elliptic Curve defined by y^2 = x^3 + 3 over Finite Field of size 7, + Elliptic Curve defined by y^2 = x^3 + 4 over Finite Field of size 7, + Elliptic Curve defined by y^2 = x^3 + 5 over Finite Field of size 7, + Elliptic Curve defined by y^2 = x^3 + 6 over Finite Field of size 7] + sage: curves_with_j_0(GF(25)) + [Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field in z2 of size 5^2, + Elliptic Curve defined by y^2 = x^3 + z2 over Finite Field in z2 of size 5^2, + Elliptic Curve defined by y^2 = x^3 + (z2+3) over Finite Field in z2 of size 5^2, + Elliptic Curve defined by y^2 = x^3 + (4*z2+3) over Finite Field in z2 of size 5^2, + Elliptic Curve defined by y^2 = x^3 + (2*z2+2) over Finite Field in z2 of size 5^2, + Elliptic Curve defined by y^2 = x^3 + (4*z2+1) over Finite Field in z2 of size 5^2] + + For `K=\GF{q}` where `q\equiv5\mod{6}` there are two curves, + quadratic twists of each other by `-3`: `y^2=x^3+1` and + `y^2=x^3-27`:: + + sage: from sage.schemes.elliptic_curves.ell_finite_field import curves_with_j_0 + sage: curves_with_j_0(GF(5)) + [Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 5, + Elliptic Curve defined by y^2 = x^3 + 3 over Finite Field of size 5] + sage: curves_with_j_0(GF(11)) + [Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 11, + Elliptic Curve defined by y^2 = x^3 + 6 over Finite Field of size 11] + """ + if not K.is_finite(): + raise ValueError("field must be finite") + p = K.characteristic() + if p==2: + return curves_with_j_0_char2(K) + if p==3: + return curves_with_j_0_char3(K) + q = K.cardinality() + if q%3==2: + # Then we only have two quadratic twists (and -3 is non-square) + return [EllipticCurve(K, [0,a]) for a in [1,-27]] + # Now we have genuine sextic twists, find D generating K* mod 6th powers + q2 = (q-1)//2 + q3 = (q-1)//3 + D = K.gen() + while not D or D**q2 == 1 or D**q3==1: + D = K.random_element() + return [EllipticCurve(K, [0,D**i]) for i in range(6)] + +def curves_with_j_1728(K): + r""" + Return a complete list of pairwise nonisomorphic elliptic curves with `j`-invariant 1728 over the finite field `K`. + + .. NOTE:: + + In characteristics 2 and 3 (so 0=1728) this function simply calls ``curves_with_j_0_char2`` or + ``curves_with_j_0_char3``. Otherwise there are either 2 or 4 curves, parametrised by + `K^*/(K^*)^4`. + + Examples: + + For `K=\GF{q}` where `q\equiv1\mod{4} there are four curves, the quartic twists of `y^2=x^3+x`:: + + sage: from sage.schemes.elliptic_curves.ell_finite_field import curves_with_j_1728 + sage: sorted(curves_with_j_1728(GF(5)), key = lambda E: E.a_invariants()) + [Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 5, + Elliptic Curve defined by y^2 = x^3 + 2*x over Finite Field of size 5, + Elliptic Curve defined by y^2 = x^3 + 3*x over Finite Field of size 5, + Elliptic Curve defined by y^2 = x^3 + 4*x over Finite Field of size 5] + sage: curves_with_j_1728(GF(49)) + [Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 7^2, + Elliptic Curve defined by y^2 = x^3 + z2*x over Finite Field in z2 of size 7^2, + Elliptic Curve defined by y^2 = x^3 + (z2+4)*x over Finite Field in z2 of size 7^2, + Elliptic Curve defined by y^2 = x^3 + (5*z2+4)*x over Finite Field in z2 of size 7^2] + + For `K=\GF{q}` where `q\equiv3\mod{4} there are two curves, + quadratic twists of each other by `-1`: `y^2=x^3+x` and + `y^2=x^3-x`:: + + sage: from sage.schemes.elliptic_curves.ell_finite_field import curves_with_j_1728 + sage: curves_with_j_1728(GF(7)) + [Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 7, + Elliptic Curve defined by y^2 = x^3 + 6*x over Finite Field of size 7] + sage: curves_with_j_1728(GF(11)) + [Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 11, + Elliptic Curve defined by y^2 = x^3 + 10*x over Finite Field of size 11] + """ + if not K.is_finite(): + raise ValueError("field must be finite") + p = K.characteristic() + if p==2: + return curves_with_j_0_char2(K) + if p==3: + return curves_with_j_0_char3(K) + q = K.cardinality() + if q%4==3: + return [EllipticCurve(K, [a,0]) for a in [1,-1]] + # Now we have genuine quartic twists, find D generating K* mod 4th powers + q2 = (q-1)//2 + D = K.gen() + while not D or D**q2 == 1: + D = K.random_element() + return [EllipticCurve(K, [D**i,0]) for i in range(4)] + +def curves_with_j_0_char2(K): + r""" + Return a complete list of pairwise nonisomorphic elliptic curves with `j`-invariant 0 over the finite field `K` of characteristic 2. + + .. NOTE:: + + The number of twists is either 3 or 7 depending on whether + the field has odd or even degree over `\GF{2}`. See + [Connell1999]_, pages 429-431. + + Examples: + + In odd degree, there are three isomorphism classes all with representatives defined over `\GF{2}`:: + + sage: from sage.schemes.elliptic_curves.ell_finite_field import curves_with_j_0_char2 + sage: K = GF(2**7) + sage: curves = curves_with_j_0_char2(K) + sage: len(curves) + 3 + sage: [E.ainvs() for E in curves] + [(0, 0, 1, 0, 0), (0, 0, 1, 1, 0), (0, 0, 1, 1, 1)] + + Check that the curves are mutually non-isomorphic:: + + sage: all((e1 == e2 or not e1.is_isomorphic(e2)) for e1 in curves for e2 in curves) + True + + Check that the weight formula holds:: + + sage: sum(1/len(E.automorphisms()) for E in curves) == 1 + True + + In even degree there are seven isomorphism classes:: + + sage: from sage.schemes.elliptic_curves.ell_finite_field import curves_with_j_0_char2 + sage: K = GF(2**8) + sage: curves = EllipticCurve(j=K(0)).twists() + sage: len(curves) + 7 + sage: [E.ainvs() for E in curves] # random + [(0, 0, 1, 0, 0), + (0, 0, 1, 0, z8^5 + z8^4 + z8^3), + (0, 0, 1, z8^6 + z8^5 + z8^2 + 1, 0), + (0, 0, z8^4 + z8^3 + z8^2 + 1, 0, 0), + (0, 0, z8^4 + z8^3 + z8^2 + 1, 0, z8^3 + z8^2 + 1), + (0, 0, z8^6 + z8^3 + z8^2, 0, 0), + (0, 0, z8^6 + z8^3 + z8^2, 0, z8^3 + z8^2)] + + Check that the twists are mutually non-isomorphic:: + + sage: all((e1 == e2 or not e1.is_isomorphic(e2)) for e1 in curves for e2 in curves) + True + + Check that the weight formula holds:: + + sage: sum(1/len(E.automorphisms()) for E in curves) == 1 + True + """ + if not K.is_finite() or K.characteristic() != 2: + raise ValueError("field must be finite of characteristic 2") + if K.degree()%2: + return [EllipticCurve(K,[0,0,1,0,0]), EllipticCurve(K,[0,0,1,1,0]), EllipticCurve(K,[0,0,1,1,1])] + # find a,b,c,d,e such that + # a is not a cube, i.e. a**((q-1)//3)!=1 + # Tr(b)=1 + # X^4+X+c irreducible + # X^2+a*X+d irreducible + # X^2+a^2*X+e irreducible + a = b = c = d = e = None + x = polygen(K) + q3 = (K.cardinality()-1)//3 + while not a or a**q3==1: + a = K.random_element() + asq = a*a + while not b or not b.trace(): + b = K.random_element() + c = K.one() # OK if degree is 2 mod 4 + if K.degree()%4 == 0: + while (x**4+x+c).roots(): + c = K.random_element() + while not d or (x**2+a*x+d).roots(): + d = K.random_element() + while not e or (x**2+asq*x+e).roots(): + e = K.random_element() + return [EllipticCurve(K, ai) for ai in + [[0,0,1,0,0], [0,0,1,0,b], [0,0,1,c,0], [0,0,a,0,0], [0,0,a,0,d], [0,0,asq,0,0], [0,0,asq,0,e]]] + +def curves_with_j_0_char3(K): + r""" + Return a complete list of pairwise nonisomorphic elliptic curves with `j`-invariant 0 over the finite field `K` of characteristic 3. + + .. NOTE:: + + The number of twists is either 4 or 6 depending on whether + the field has odd or even degree over `\GF{3}`. See + [Connell1999]_, pages 429-431. + + Examples: + + In odd degree, there are four isomorphism classes:: + + sage: from sage.schemes.elliptic_curves.ell_finite_field import curves_with_j_0_char3 + sage: K = GF(3**5) + sage: curves = curves_with_j_0_char3(K) + sage: len(curves) + 4 + sage: [E.ainvs() for E in curves] # random + [(0, 0, 0, 1, 0), + (0, 0, 0, 2, 0), + (0, 0, 0, 2, z5^4 + z5^3 + z5^2), + (0, 0, 0, 2, 2*z5^4 + 2*z5^3 + 2*z5^2)] + + Check that the twists are mutually non-isomorphic:: + + sage: all((e1 == e2 or not e1.is_isomorphic(e2)) for e1 in curves for e2 in curves) + True + + Check that the weight formula holds:: + + sage: sum(1/len(E.automorphisms()) for E in curves) == 1 + True + + In even degree, there are six isomorphism classes:: + + sage: from sage.schemes.elliptic_curves.ell_finite_field import curves_with_j_0_char3 + sage: K = GF(3**4) + sage: curves = EllipticCurve(j=K(0)).twists() + sage: len(curves) + 6 + sage: [E.ainvs() for E in curves] # random + [(0, 0, 0, 1, 0), + (0, 0, 0, 2, 2*z4^3 + 2*z4^2 + 2*z4 + 2), + (0, 0, 0, 1, 0), + (0, 0, 0, 1, 2*z4^3 + 2*z4^2 + 2*z4 + 2), + (0, 0, 0, z4, 0), + (0, 0, 0, z4^3, 0)] + + Check that the twists are mutually non-isomorphic:: + + sage: all((e1 == e2 or not e1.is_isomorphic(e2)) for e1 in curves for e2 in curves) + True + + Check that the weight formula holds:: + + sage: sum(1/len(E.automorphisms()) for E in curves) == 1 + True + """ + if not K.is_finite() or K.characteristic() != 3: + raise ValueError("field must be finite of characteristic 3") + # find b with nonzero trace + b = None + while not b or not b.trace(): + b = K.random_element() + + if K.degree()%2: + return [EllipticCurve(K, a4a6) for a4a6 in + [[1,0], [-1,0], [-1,b], [-1,-b]]] + + # find a, i, c where: + # a generates K* mod 4th powers, i.e. non-square, + # i^2=-1 + # c with x^3+a^2*x+c irreducible + a = K.gen() + q2 = (K.cardinality()-1)//2 + while not a or a**q2 == 1: + a = K.random_element() + x = polygen(K) + i = (x**2+1).roots()[0][0] + c = None + while not c or (x**3 + a**2*x + c).roots(): + c = K.random_element() + return [EllipticCurve(K, a4a6) for a4a6 in + [[1,0], [1,i*b], [a,0], [a**2,0], [a**2,c], [a**3,0]]] + # dict to hold precomputed coefficient vectors of supersingular j values (excluding 0, 1728): diff --git a/src/sage/schemes/elliptic_curves/ell_generic.py b/src/sage/schemes/elliptic_curves/ell_generic.py index d3ca4896b01..e9d42c7e487 100644 --- a/src/sage/schemes/elliptic_curves/ell_generic.py +++ b/src/sage/schemes/elliptic_curves/ell_generic.py @@ -62,7 +62,7 @@ import sage.groups.additive_abelian.additive_abelian_group as groups import sage.groups.generic as generic -from sage.arith.all import lcm +from sage.arith.functions import lcm import sage.rings.all as rings from sage.misc.cachefunc import cached_method from sage.misc.fast_methods import WithEqualityById @@ -1991,6 +1991,14 @@ def _multiple_x_numerator(self, n, x=None): EXAMPLES:: + sage: E = EllipticCurve([1,2]) + sage: E._multiple_x_numerator(3) + x^9 - 12*x^7 - 192*x^6 + 30*x^5 - 48*x^4 + 228*x^3 + 96*x^2 + 393*x + 528 + sage: E._multiple_x_numerator(-3) + x^9 - 12*x^7 - 192*x^6 + 30*x^5 - 48*x^4 + 228*x^3 + 96*x^2 + 393*x + 528 + + :: + sage: E = EllipticCurve("37a") sage: P = E.gens()[0] sage: x = P[0] @@ -2043,9 +2051,9 @@ def _multiple_x_numerator(self, n, x=None): sage: E._multiple_x_numerator(5) x^25 + 65037*x^23 + 55137*x^22 + ... + 813*x^2 + 10220*x + 42539 """ - n = rings.Integer(n) - if n < 2: - raise ValueError("n must be at least 2") + n = rings.Integer(n).abs() + if not n: + raise ValueError("n must be nonzero") if x is None: try: @@ -2061,6 +2069,9 @@ def _multiple_x_numerator(self, n, x=None): cache = None xx = x + if n == 1: + return xx + polys = self.division_polynomial_0([-2,-1,n-1,n,n+1], x) if n % 2 == 0: @@ -2101,6 +2112,14 @@ def _multiple_x_denominator(self, n, x=None): EXAMPLES:: + sage: E = EllipticCurve([1,2]) + sage: E._multiple_x_denominator(3) + 9*x^8 + 36*x^6 + 144*x^5 + 30*x^4 + 288*x^3 + 564*x^2 - 48*x + 1 + sage: E._multiple_x_denominator(-3) + 9*x^8 + 36*x^6 + 144*x^5 + 30*x^4 + 288*x^3 + 564*x^2 - 48*x + 1 + + :: + sage: E = EllipticCurve("43a") sage: P = E.gens()[0] sage: x = P[0] @@ -2128,9 +2147,9 @@ def _multiple_x_denominator(self, n, x=None): sage: E._multiple_x_denominator(5) 25*x^24 + 3100*x^22 + 19000*x^21 + ... + 24111*x^2 + 52039*x + 56726 """ - n = rings.Integer(n) - if n < 2: - raise ValueError("n must be at least 2") + n = rings.Integer(n).abs() + if not n: + raise ValueError("n must be nonzero") if x is None: try: diff --git a/src/sage/schemes/elliptic_curves/ell_modular_symbols.py b/src/sage/schemes/elliptic_curves/ell_modular_symbols.py index c91a54fdc27..b31f7dfe46c 100644 --- a/src/sage/schemes/elliptic_curves/ell_modular_symbols.py +++ b/src/sage/schemes/elliptic_curves/ell_modular_symbols.py @@ -87,19 +87,22 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from sage.structure.sage_object import SageObject -from sage.modular.modsym.all import ModularSymbols +from sage.arith.misc import (kronecker as kronecker_symbol, + next_prime, + prime_divisors, + valuation) from sage.databases.cremona import parse_cremona_label - -from sage.arith.all import next_prime, kronecker_symbol, prime_divisors, valuation +from sage.misc.verbose import verbose +from sage.modular.cusps import Cusps +from sage.modular.modsym.all import ModularSymbols from sage.rings.infinity import unsigned_infinity as infinity from sage.rings.integer import Integer -from sage.modular.cusps import Cusps from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ -from sage.misc.verbose import verbose +from sage.structure.sage_object import SageObject + +from .constructor import EllipticCurve -from sage.schemes.elliptic_curves.constructor import EllipticCurve oo = Cusps(infinity) zero = Integer(0) diff --git a/src/sage/schemes/elliptic_curves/ell_number_field.py b/src/sage/schemes/elliptic_curves/ell_number_field.py index 3b31f9cf43f..acb392a0773 100644 --- a/src/sage/schemes/elliptic_curves/ell_number_field.py +++ b/src/sage/schemes/elliptic_curves/ell_number_field.py @@ -388,7 +388,7 @@ def height_pairing_matrix(self, points=None, precision=None, normalised=True): RR = RealField() else: RR = RealField(precision) - from sage.matrix.all import MatrixSpace + from sage.matrix.matrix_space import MatrixSpace M = MatrixSpace(RR, r) mat = M() for j in range(r): @@ -3897,7 +3897,7 @@ def saturation(self, points, verbose=False, raise ValueError("points not linearly independent in saturation()") sat_reg = reg - from sage.rings.all import prime_range + from sage.rings.fast_arith import prime_range if full_saturation: if lower_ht_bound is None: # TODO (robertwb): verify this for rank > 1 diff --git a/src/sage/schemes/elliptic_curves/ell_point.py b/src/sage/schemes/elliptic_curves/ell_point.py index 9f0c3799f36..d49bcccd279 100644 --- a/src/sage/schemes/elliptic_curves/ell_point.py +++ b/src/sage/schemes/elliptic_curves/ell_point.py @@ -2833,7 +2833,9 @@ def archimedean_local_height(self, v=None, prec=None, weighted=False): 4.0000000000000000000000000000000000000000000000000000000000 """ from sage.rings.number_field.number_field import refine_embedding - from sage.all import RealField, ComplexField, Infinity + from sage.rings.real_mpfr import RealField + from sage.rings.complex_mpfr import ComplexField + from sage.rings.infinity import Infinity E = self.curve() K = E.base_ring() @@ -3254,7 +3256,9 @@ def elliptic_logarithm(self, embedding=None, precision=100, 0.70448375537782208460499649302 - 0.79246725643650979858266018068*I """ from sage.rings.number_field.number_field import refine_embedding - from sage.rings.all import RealField, ComplexField, QQ + from sage.rings.real_mpfr import RealField + from sage.rings.complex_mpfr import ComplexField + from sage.rings.rational_field import QQ # Check the trivial case: diff --git a/src/sage/schemes/elliptic_curves/ell_rational_field.py b/src/sage/schemes/elliptic_curves/ell_rational_field.py index c2b8436f2a1..f1b7d937748 100644 --- a/src/sage/schemes/elliptic_curves/ell_rational_field.py +++ b/src/sage/schemes/elliptic_curves/ell_rational_field.py @@ -74,13 +74,14 @@ import sage.arith.all as arith import sage.rings.all as rings -from sage.rings.all import ( - PowerSeriesRing, - infinity as oo, - ZZ, QQ, - Integer, - IntegerRing, RealField, - ComplexField, RationalField) +from sage.rings.power_series_ring import PowerSeriesRing +from sage.rings.infinity import Infinity as oo +from sage.rings.integer_ring import ZZ, IntegerRing +from sage.rings.rational_field import QQ +from sage.rings.integer import Integer +from sage.rings.real_mpfr import RealField +from sage.rings.complex_mpfr import ComplexField +from sage.rings.rational_field import RationalField from sage.structure.coerce import py_scalar_to_element from sage.structure.element import Element @@ -3436,7 +3437,7 @@ def Lambda(self, s, prec): sage: E.Lambda(1.4+0.5*I, 50) -0.354172680517... + 0.874518681720...*I """ - from sage.all import pi + from sage.symbolic.constants import pi s = C(s) N = self.conductor() @@ -6013,7 +6014,7 @@ def point_preprocessing(free,tor): roots.remove(e3) e1,e2 = roots - from sage.all import pi + from sage.symbolic.constants import pi e = R(1).exp() pi = R(pi) @@ -7054,7 +7055,7 @@ def elliptic_curve_congruence_graph(curves): Graph on 12 vertices """ from sage.graphs.graph import Graph - from sage.arith.all import lcm + from sage.arith.functions import lcm from sage.rings.fast_arith import prime_range from sage.misc.misc_c import prod G = Graph() diff --git a/src/sage/schemes/elliptic_curves/ell_tate_curve.py b/src/sage/schemes/elliptic_curves/ell_tate_curve.py index 22a4f0a29d0..4b7cd3e82c5 100644 --- a/src/sage/schemes/elliptic_curves/ell_tate_curve.py +++ b/src/sage/schemes/elliptic_curves/ell_tate_curve.py @@ -44,7 +44,7 @@ from sage.rings.padics.factory import Qp from sage.structure.sage_object import SageObject from sage.structure.richcmp import richcmp, richcmp_method -from sage.arith.all import LCM +from sage.arith.functions import lcm as LCM from sage.modular.modform.constructor import EisensteinForms, CuspForms from sage.schemes.elliptic_curves.constructor import EllipticCurve from sage.functions.log import log diff --git a/src/sage/schemes/elliptic_curves/ell_torsion.py b/src/sage/schemes/elliptic_curves/ell_torsion.py index 8a1208569f2..7bfda81486a 100644 --- a/src/sage/schemes/elliptic_curves/ell_torsion.py +++ b/src/sage/schemes/elliptic_curves/ell_torsion.py @@ -26,7 +26,7 @@ # **************************************************************************** from sage.misc.cachefunc import cached_method -from sage.rings.all import RationalField +from sage.rings.rational_field import RationalField import sage.groups.additive_abelian.additive_abelian_wrapper as groups from sage.structure.richcmp import richcmp_method, richcmp diff --git a/src/sage/schemes/elliptic_curves/formal_group.py b/src/sage/schemes/elliptic_curves/formal_group.py index 17019a5794e..591ce2d6f29 100644 --- a/src/sage/schemes/elliptic_curves/formal_group.py +++ b/src/sage/schemes/elliptic_curves/formal_group.py @@ -16,7 +16,7 @@ import sage.misc.misc as misc import sage.rings.all as rings -from sage.rings.all import O +from sage.rings.big_oh import O class EllipticCurveFormalGroup(SageObject): diff --git a/src/sage/schemes/elliptic_curves/gal_reps.py b/src/sage/schemes/elliptic_curves/gal_reps.py index 55d0ac2d352..056268eb230 100644 --- a/src/sage/schemes/elliptic_curves/gal_reps.py +++ b/src/sage/schemes/elliptic_curves/gal_reps.py @@ -121,7 +121,8 @@ import sage.misc.all as misc from sage.misc.verbose import verbose import sage.rings.all as rings -from sage.rings.all import RealField, GF +from sage.rings.real_mpfr import RealField +from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF from math import sqrt from sage.libs.pari.all import pari @@ -916,14 +917,14 @@ def image_type(self, p): a_ell = self._E.ap(ell) u = k(a_ell)**2 * k(ell)**(-1) if u == 3: - verbose("found an element of order 6",2) + verbose("found an element of order 6", level=2) # found an element of order 6: self.__image_type[p] = non_split_str return self.__image_type[p] if u == 2 and not has_an_el_order_4: # found an element of order 4 - verbose("found an element of order 4",2) + verbose("found an element of order 4", level=2) has_an_el_order_4 = True if has_an_el_order_3: self.__image_type[p] = s4_str @@ -931,13 +932,13 @@ def image_type(self, p): if u == 1 and not has_an_el_order_3: # found an element of order 3 - verbose("found an element of order 3",2) + verbose("found an element of order 3", level=2) has_an_el_order_3 = True if has_an_el_order_4: self.__image_type[p] = s4_str return self.__image_type[p] - verbose("p=5 and we could not determine the image, yet", 2) + verbose("p=5 and we could not determine the image, yet", level=2) # we have not yet determined the image, there are only the following possible subgroups of PGL_2 # (unless we were unlucky and none of the elements of order 6 showed up above, for instance) # A_4 of order 12 with elements of order 2 and 3 @@ -995,15 +996,15 @@ def image_type(self, p): u = k(a_ell)**2 * k(ell)**(-1) if (u not in ex_setp) and could_be_exc == 1: # it can not be in the exceptional - verbose("the image cannot be exceptional, found u=%s"%u,2) + verbose("the image cannot be exceptional, found u=%s"%u, level=2) could_be_exc = 0 if a_ell != 0 and arith.kronecker(a_ell**2 - 4*ell,p) == 1 and could_be_non_split == 1: # it can not be in the normalizer of the non-split Cartan - verbose("the image cannot be non-split, found u=%s"%u,2) + verbose("the image cannot be non-split, found u=%s"%u, level=2) could_be_non_split = 0 if a_ell != 0 and arith.kronecker(a_ell**2 - 4*ell,p) == -1 and could_be_split == 1: # it can not be in the normalizer of the split Cartan - verbose("the image cannot be split, found u=%s"%u,2) + verbose("the image cannot be split, found u=%s"%u, level=2) could_be_split = 0 assert could_be_exc + could_be_split + could_be_non_split > 0, "bug in image_type." @@ -1064,7 +1065,7 @@ def image_type(self, p): K = self._E.division_field(p, 'z') d = K.absolute_degree() - verbose("field of degree %s. try to compute Galois group"%(d),2) + verbose("field of degree %s. try to compute Galois group"%(d), level=2) # If the degree is too big, we have no chance at the Galois # group. K.galois_group calls is_galois which used to rely on # pari's Galois group computations, so degree < 12 diff --git a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py index d484a4a18bd..82127860fd3 100644 --- a/src/sage/schemes/elliptic_curves/gal_reps_number_field.py +++ b/src/sage/schemes/elliptic_curves/gal_reps_number_field.py @@ -45,14 +45,17 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.structure.sage_object import SageObject -from sage.rings.number_field.number_field import NumberField +from sage.arith.misc import legendre_symbol, primes +from sage.misc.functional import cyclotomic_polynomial from sage.modules.free_module import VectorSpace from sage.rings.finite_rings.finite_field_constructor import GF -from sage.misc.functional import cyclotomic_polynomial -from sage.arith.all import legendre_symbol, primes +from sage.rings.infinity import Infinity +from sage.rings.integer import Integer +from sage.rings.integer_ring import ZZ +from sage.rings.number_field.number_field import NumberField +from sage.rings.rational_field import QQ from sage.sets.set import Set -from sage.rings.all import Integer, ZZ, QQ, Infinity +from sage.structure.sage_object import SageObject class GaloisRepresentation(SageObject): diff --git a/src/sage/schemes/elliptic_curves/heegner.py b/src/sage/schemes/elliptic_curves/heegner.py index 298f44fedc6..f9b752f9533 100644 --- a/src/sage/schemes/elliptic_curves/heegner.py +++ b/src/sage/schemes/elliptic_curves/heegner.py @@ -92,30 +92,34 @@ # https://www.gnu.org/licenses/ # **************************************************************************** - -from sage.misc.misc_c import prod -from sage.misc.verbose import verbose -from sage.misc.cachefunc import cached_method - -from sage.structure.sage_object import SageObject -from sage.structure.richcmp import (richcmp_method, richcmp, - richcmp_not_equal, rich_to_bool) - import sage.rings.abc import sage.rings.number_field.number_field_element import sage.rings.number_field.number_field as number_field import sage.rings.all as rings -from sage.rings.all import (ZZ, GF, QQ, CDF, - Integers, RealField, ComplexField, QuadraticField) -from sage.arith.all import (gcd, xgcd, lcm, prime_divisors, factorial, - binomial) + +from sage.arith.functions import lcm +from sage.arith.misc import (binomial, factorial, prime_divisors, + GCD as gcd, XGCD as xgcd) +from sage.matrix.constructor import Matrix as matrix +from sage.matrix.matrix_space import MatrixSpace +from sage.misc.cachefunc import cached_method +from sage.misc.misc_c import prod +from sage.misc.verbose import verbose +from sage.modular.modsym.p1list import P1List +from sage.rings.complex_double import CDF +from sage.rings.complex_mpfr import ComplexField from sage.rings.factorint import factor_trial_division +from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF +from sage.rings.finite_rings.integer_mod_ring import IntegerModRing as Integers +from sage.rings.integer_ring import ZZ +from sage.rings.number_field.number_field import QuadraticField +from sage.rings.rational_field import QQ +from sage.rings.real_mpfr import RealField from sage.quadratic_forms.all import (BinaryQF, BinaryQF_reduced_representatives) -from sage.matrix.all import MatrixSpace, matrix - -from sage.modular.modsym.p1list import P1List - +from sage.structure.sage_object import SageObject +from sage.structure.richcmp import (richcmp_method, richcmp, + richcmp_not_equal, rich_to_bool) ############################################################################### # @@ -6822,7 +6826,7 @@ def heegner_index_bound(self, D=0, prec=5, max_height=None): else: H = 4*h p = 3 - from sage.all import next_prime + from sage.arith.misc import next_prime while True: c = H/(2*p**2) + B if c < max_height: diff --git a/src/sage/schemes/elliptic_curves/height.py b/src/sage/schemes/elliptic_curves/height.py index 06d83bc7759..019dd555941 100644 --- a/src/sage/schemes/elliptic_curves/height.py +++ b/src/sage/schemes/elliptic_curves/height.py @@ -42,7 +42,8 @@ from sage.misc.cachefunc import cached_method from sage.misc.mrange import cartesian_product_iterator -from sage.arith.all import lcm, factorial +from sage.arith.functions import lcm +from sage.arith.misc import factorial from sage.ext.fast_callable import fast_callable from sage.functions.log import log, exp from sage.symbolic.ring import SR diff --git a/src/sage/schemes/elliptic_curves/hom_velusqrt.py b/src/sage/schemes/elliptic_curves/hom_velusqrt.py index 22ae56018a3..0f1101e57d2 100644 --- a/src/sage/schemes/elliptic_curves/hom_velusqrt.py +++ b/src/sage/schemes/elliptic_curves/hom_velusqrt.py @@ -122,21 +122,17 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.structure.sequence import Sequence -from sage.structure.all import coercion_model as cm - from sage.misc.cachefunc import cached_method - from sage.misc.misc_c import prod from sage.rings.generic import ProductTree, prod_with_derivative - -from sage.structure.richcmp import op_EQ - from sage.rings.integer import Integer +from sage.structure.all import coercion_model as cm +from sage.structure.richcmp import op_EQ +from sage.structure.sequence import Sequence -from sage.schemes.elliptic_curves.constructor import EllipticCurve -from sage.schemes.elliptic_curves.ell_finite_field import EllipticCurve_finite_field -from sage.schemes.elliptic_curves.hom import EllipticCurveHom, compare_via_evaluation +from .constructor import EllipticCurve +from .ell_finite_field import EllipticCurve_finite_field +from .hom import EllipticCurveHom, compare_via_evaluation def _choose_IJK(n): @@ -1213,7 +1209,12 @@ def _random_example_for_testing(): sage: 5 <= K.order() True """ - from sage.all import prime_range, choice, randrange, GF, lcm, Mod + from sage.rings.fast_arith import prime_range + from sage.misc.prandom import choice, randrange + from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF + from sage.arith.functions import lcm + from sage.rings.finite_rings.integer_mod import Mod + while True: p = choice(prime_range(2, 100)) e = randrange(1,5) diff --git a/src/sage/schemes/elliptic_curves/isogeny_class.py b/src/sage/schemes/elliptic_curves/isogeny_class.py index e635c77a458..0d50a9863ef 100644 --- a/src/sage/schemes/elliptic_curves/isogeny_class.py +++ b/src/sage/schemes/elliptic_curves/isogeny_class.py @@ -770,7 +770,7 @@ def _compute(self, verbose=False): True """ from sage.schemes.elliptic_curves.ell_curve_isogeny import fill_isogeny_matrix - from sage.matrix.all import MatrixSpace + from sage.matrix.matrix_space import MatrixSpace from sage.sets.set import Set self._maps = None @@ -1055,7 +1055,7 @@ def _compute(self): [0 2 0 0 0 0] """ algorithm = self._algorithm - from sage.matrix.all import MatrixSpace + from sage.matrix.matrix_space import MatrixSpace self._maps = None if algorithm == "database": try: @@ -1183,8 +1183,8 @@ def isogeny_degrees_cm(E, verbose=False): print("CM case, discriminant = %s" % d) from sage.libs.pari.all import pari - from sage.sets.all import Set - from sage.arith.all import kronecker_symbol + from sage.sets.set import Set + from sage.arith.misc import kronecker as kronecker_symbol n = E.base_field().absolute_degree() if not E.has_rational_cm(): diff --git a/src/sage/schemes/elliptic_curves/isogeny_small_degree.py b/src/sage/schemes/elliptic_curves/isogeny_small_degree.py index f5657f2cf19..65cbbc29a35 100644 --- a/src/sage/schemes/elliptic_curves/isogeny_small_degree.py +++ b/src/sage/schemes/elliptic_curves/isogeny_small_degree.py @@ -536,7 +536,7 @@ def _sporadic_Q_data(j): ....: g = E.division_polynomial(ell) ....: assert g % f == 0 """ - from sage.rings.all import RealField + from sage.rings.real_mpfr import RealField from sage.misc.misc_c import prod ell = sporadic_j[j] E = EllipticCurve(j=j).short_weierstrass_model() diff --git a/src/sage/schemes/elliptic_curves/lseries_ell.py b/src/sage/schemes/elliptic_curves/lseries_ell.py index 94b381a2f0c..e1506b17910 100644 --- a/src/sage/schemes/elliptic_curves/lseries_ell.py +++ b/src/sage/schemes/elliptic_curves/lseries_ell.py @@ -23,7 +23,8 @@ #***************************************************************************** from sage.structure.sage_object import SageObject -from sage.rings.all import RealField, RationalField +from sage.rings.real_mpfr import RealField +from sage.rings.rational_field import RationalField from math import sqrt, log, ceil import sage.functions.exp_integral as exp_integral from sage.misc.verbose import verbose diff --git a/src/sage/schemes/elliptic_curves/mod_sym_num.pyx b/src/sage/schemes/elliptic_curves/mod_sym_num.pyx index ea646b7fbe3..369cd98a293 100644 --- a/src/sage/schemes/elliptic_curves/mod_sym_num.pyx +++ b/src/sage/schemes/elliptic_curves/mod_sym_num.pyx @@ -164,18 +164,16 @@ AUTHORS: from cysignals.memory cimport sig_malloc, sig_free, sig_realloc from cysignals.signals cimport sig_check +from sage.arith.misc import euler_phi, kronecker as kronecker_symbol from sage.misc.cachefunc import cached_method - +from sage.misc.misc_c import prod +from sage.misc.verbose import verbose from sage.rings.complex_mpfr cimport ComplexNumber from sage.rings.complex_mpfr import ComplexField -from sage.rings.real_mpfr cimport RealNumber, RealField -from sage.rings.rational cimport Rational from sage.rings.integer cimport Integer +from sage.rings.rational cimport Rational +from sage.rings.real_mpfr cimport RealNumber, RealField -from sage.misc.misc_c import prod -from sage.misc.verbose import verbose -from sage.arith.all import kronecker_symbol -from sage.arith.misc import euler_phi cdef extern from "": double log(double) diff --git a/src/sage/schemes/elliptic_curves/modular_parametrization.py b/src/sage/schemes/elliptic_curves/modular_parametrization.py index dca43dcd191..57a90190fe5 100644 --- a/src/sage/schemes/elliptic_curves/modular_parametrization.py +++ b/src/sage/schemes/elliptic_curves/modular_parametrization.py @@ -44,7 +44,10 @@ from . import heegner -from sage.rings.all import (LaurentSeriesRing, RationalField, ComplexField, QQ) +from sage.rings.laurent_series_ring import LaurentSeriesRing +from sage.rings.rational_field import RationalField +from sage.rings.complex_mpfr import ComplexField +from sage.rings.rational_field import QQ class ModularParameterization: diff --git a/src/sage/schemes/elliptic_curves/padic_lseries.py b/src/sage/schemes/elliptic_curves/padic_lseries.py index ccdc0dcc941..875a4113464 100644 --- a/src/sage/schemes/elliptic_curves/padic_lseries.py +++ b/src/sage/schemes/elliptic_curves/padic_lseries.py @@ -61,27 +61,33 @@ # https://www.gnu.org/licenses/ ###################################################################### -from sage.rings.integer_ring import ZZ -from sage.rings.rational_field import QQ -from sage.rings.padics.factory import Qp -from sage.rings.infinity import infinity -from sage.rings.all import LaurentSeriesRing, PowerSeriesRing, PolynomialRing, Integers - -from sage.rings.integer import Integer -from sage.arith.all import valuation, binomial, kronecker_symbol, gcd, prime_divisors, LCM - -from sage.structure.sage_object import SageObject -from sage.structure.richcmp import richcmp_method, richcmp - -from sage.misc.functional import denominator -from sage.misc.verbose import verbose, get_verbose - -from sage.modules.free_module_element import vector import sage.matrix.all as matrix import sage.schemes.hyperelliptic_curves.monsky_washnitzer + +from sage.arith.functions import lcm as LCM +from sage.arith.misc import (binomial, + GCD as gcd, + prime_divisors, + kronecker as kronecker_symbol, + valuation) from sage.functions.log import log from sage.functions.other import floor from sage.misc.cachefunc import cached_method +from sage.misc.functional import denominator +from sage.misc.verbose import get_verbose, verbose +from sage.modules.free_module_element import vector +from sage.rings.finite_rings.integer_mod_ring import IntegerModRing as Integers +from sage.rings.infinity import infinity +from sage.rings.integer import Integer +from sage.rings.integer_ring import ZZ +from sage.rings.laurent_series_ring import LaurentSeriesRing +from sage.rings.padics.factory import Qp +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing +from sage.rings.power_series_ring import PowerSeriesRing +from sage.rings.rational_field import QQ +from sage.structure.richcmp import richcmp_method, richcmp +from sage.structure.sage_object import SageObject + @richcmp_method class pAdicLseries(SageObject): diff --git a/src/sage/schemes/elliptic_curves/padics.py b/src/sage/schemes/elliptic_curves/padics.py index 96fb8510c12..e4d88113716 100644 --- a/src/sage/schemes/elliptic_curves/padics.py +++ b/src/sage/schemes/elliptic_curves/padics.py @@ -21,25 +21,28 @@ # https://www.gnu.org/licenses/ ###################################################################### +import math -import sage.rings.all as rings -from . import padic_lseries as plseries import sage.arith.all as arith -from sage.rings.all import ( - Qp, Zp, - Integers, - Integer, - O, - PowerSeriesRing, - LaurentSeriesRing, - RationalField) -import math -import sage.misc.misc as misc import sage.matrix.all as matrix -sqrt = math.sqrt -import sage.schemes.hyperelliptic_curves.monsky_washnitzer +import sage.misc.misc as misc +import sage.rings.all as rings import sage.schemes.hyperelliptic_curves.hypellfrob +import sage.schemes.hyperelliptic_curves.monsky_washnitzer + from sage.misc.cachefunc import cached_method +from sage.rings.big_oh import O +from sage.rings.finite_rings.integer_mod_ring import IntegerModRing as Integers +from sage.rings.integer import Integer +from sage.rings.laurent_series_ring import LaurentSeriesRing +from sage.rings.padics.factory import Qp, Zp +from sage.rings.power_series_ring import PowerSeriesRing +from sage.rings.rational_field import RationalField + +from . import padic_lseries as plseries + +sqrt = math.sqrt + def __check_padic_hypotheses(self, p): r""" diff --git a/src/sage/schemes/elliptic_curves/period_lattice.py b/src/sage/schemes/elliptic_curves/period_lattice.py index 7206ea74a7a..7224988fc27 100644 --- a/src/sage/schemes/elliptic_curves/period_lattice.py +++ b/src/sage/schemes/elliptic_curves/period_lattice.py @@ -96,17 +96,22 @@ """ -from sage.modules.free_module import FreeModule_generic_pid -from sage.rings.all import ZZ, QQ, RealField, ComplexField, QQbar, AA import sage.rings.abc + +from sage.libs.pari.all import pari +from sage.misc.cachefunc import cached_method +from sage.modules.free_module import FreeModule_generic_pid +from sage.rings.complex_mpfr import ComplexField from sage.rings.complex_mpfr import ComplexNumber -from sage.rings.real_mpfr import RealNumber as RealNumber -from sage.rings.number_field.number_field import refine_embedding from sage.rings.infinity import Infinity +from sage.rings.integer_ring import ZZ +from sage.rings.number_field.number_field import refine_embedding +from sage.rings.qqbar import AA, QQbar +from sage.rings.rational_field import QQ +from sage.rings.real_mpfr import RealField +from sage.rings.real_mpfr import RealNumber as RealNumber from sage.schemes.elliptic_curves.constructor import EllipticCurve -from sage.misc.cachefunc import cached_method from sage.structure.richcmp import richcmp_method, richcmp, richcmp_not_equal -from sage.libs.pari.all import pari class PeriodLattice(FreeModule_generic_pid): diff --git a/src/sage/schemes/elliptic_curves/saturation.py b/src/sage/schemes/elliptic_curves/saturation.py index 9f5b59ac404..57367c515d4 100644 --- a/src/sage/schemes/elliptic_curves/saturation.py +++ b/src/sage/schemes/elliptic_curves/saturation.py @@ -52,7 +52,7 @@ from sage.rings.finite_rings.finite_field_constructor import GF from sage.rings.integer_ring import ZZ -from sage.arith.all import kronecker_symbol as kro +from sage.arith.misc import kronecker as kro from sage.structure.sage_object import SageObject def reduce_mod_q(x,amodq): diff --git a/src/sage/schemes/elliptic_curves/sha_tate.py b/src/sage/schemes/elliptic_curves/sha_tate.py index bf8eb3e060e..1e4fe251ff6 100644 --- a/src/sage/schemes/elliptic_curves/sha_tate.py +++ b/src/sage/schemes/elliptic_curves/sha_tate.py @@ -80,12 +80,11 @@ # **************************************************************************** from sage.structure.sage_object import SageObject -from sage.rings.all import ( - Integer, - RealField, - RationalField, - RIF, - ZZ) +from sage.rings.integer import Integer +from sage.rings.real_mpfr import RealField +from sage.rings.rational_field import RationalField +from sage.rings.real_mpfi import RIF +from sage.rings.integer_ring import ZZ from sage.functions.log import log from math import sqrt from sage.misc.verbose import verbose diff --git a/src/sage/schemes/elliptic_curves/weierstrass_morphism.py b/src/sage/schemes/elliptic_curves/weierstrass_morphism.py index 6b56e94eba8..4db88f1f7f2 100644 --- a/src/sage/schemes/elliptic_curves/weierstrass_morphism.py +++ b/src/sage/schemes/elliptic_curves/weierstrass_morphism.py @@ -29,7 +29,8 @@ from sage.schemes.elliptic_curves.hom import EllipticCurveHom from sage.structure.richcmp import (richcmp, richcmp_not_equal, op_EQ, op_NE) from sage.structure.sequence import Sequence -from sage.rings.all import Integer, PolynomialRing +from sage.rings.integer import Integer +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing class baseWI(): r""" diff --git a/src/sage/schemes/generic/ambient_space.py b/src/sage/schemes/generic/ambient_space.py index aa4645d4e88..0f9b9b55240 100644 --- a/src/sage/schemes/generic/ambient_space.py +++ b/src/sage/schemes/generic/ambient_space.py @@ -379,7 +379,7 @@ def dimension_absolute(self): base = self.base_scheme() if base.is_noetherian(): return self.dimension_relative() + base.dimension() - raise NotImplementedError("Cannot compute the dimension of this scheme.") + raise NotImplementedError("cannot compute the dimension of this scheme") dimension = dimension_absolute diff --git a/src/sage/schemes/generic/spec.py b/src/sage/schemes/generic/spec.py index 261bb899d68..fcbda338c59 100644 --- a/src/sage/schemes/generic/spec.py +++ b/src/sage/schemes/generic/spec.py @@ -98,7 +98,8 @@ def __init__(self, base_ring=None): Spec functor from Category of commutative rings to Category of schemes over Rational Field """ - from sage.categories.all import CommutativeRings, Schemes + from sage.categories.commutative_rings import CommutativeRings + from sage.categories.schemes import Schemes if base_ring is None: domain = CommutativeRings() diff --git a/src/sage/schemes/hyperelliptic_curves/hypellfrob.pyx b/src/sage/schemes/hyperelliptic_curves/hypellfrob.pyx index c08bb3cfb53..50730d1081f 100644 --- a/src/sage/schemes/hyperelliptic_curves/hypellfrob.pyx +++ b/src/sage/schemes/hyperelliptic_curves/hypellfrob.pyx @@ -38,8 +38,9 @@ from libcpp.vector cimport vector from sage.libs.ntl.ntl_ZZ_pContext import ZZ_pContext_factory from sage.libs.ntl.all import ZZ, ZZX from sage.matrix.constructor import Matrix -from sage.rings.all import Qp, O as big_oh -from sage.arith.all import is_prime +from sage.rings.padics.factory import Qp +from sage.rings.big_oh import O as big_oh +from sage.arith.misc import is_prime from sage.libs.ntl.ntl_ZZ_p cimport ntl_ZZ_p from sage.libs.ntl.ntl_ZZ cimport ntl_ZZ diff --git a/src/sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py b/src/sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py index 9f9227cbcf3..ab883076d33 100644 --- a/src/sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +++ b/src/sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py @@ -48,8 +48,11 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.rings.all import ZZ, RR, QQ, GF -from sage.arith.all import binomial +from sage.rings.integer_ring import ZZ +from sage.rings.real_mpfr import RR +from sage.rings.rational_field import QQ +from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF +from sage.arith.misc import binomial from sage.rings.power_series_ring import PowerSeriesRing from . import hyperelliptic_generic from sage.schemes.hyperelliptic_curves.hypellfrob import hypellfrob diff --git a/src/sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py b/src/sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py index a79843c0e99..030d8dab2e7 100644 --- a/src/sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +++ b/src/sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py @@ -12,8 +12,15 @@ # **************************************************************************** -from sage.rings.all import (PowerSeriesRing, PolynomialRing, ZZ, QQ, - pAdicField, GF, RR, RationalField, Infinity) +from sage.rings.power_series_ring import PowerSeriesRing +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ +from sage.rings.padics.factory import Qp as pAdicField +from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF +from sage.rings.real_mpfr import RR +from sage.rings.rational_field import RationalField +from sage.rings.infinity import Infinity from sage.functions.log import log from sage.modules.free_module import VectorSpace from sage.matrix.constructor import matrix diff --git a/src/sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py b/src/sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py index e75a071657f..5c7c4b22c5c 100644 --- a/src/sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +++ b/src/sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py @@ -90,10 +90,14 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.rings.all import QQ, ZZ, PolynomialRing, FiniteField, NumberField +from sage.rings.rational_field import QQ +from sage.rings.integer_ring import ZZ +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing +from sage.rings.finite_rings.finite_field_constructor import FiniteField +from sage.rings.number_field.number_field import NumberField from sage.misc.lazy_import import lazy_import from sage.rings.fast_arith import prime_range -from sage.arith.all import gcd +from sage.arith.misc import GCD as gcd lazy_import('sage.interfaces.genus2reduction', ['genus2reduction', 'Genus2reduction']) diff --git a/src/sage/schemes/hyperelliptic_curves/jacobian_generic.py b/src/sage/schemes/hyperelliptic_curves/jacobian_generic.py index c7cdf99a83f..21de152a878 100644 --- a/src/sage/schemes/hyperelliptic_curves/jacobian_generic.py +++ b/src/sage/schemes/hyperelliptic_curves/jacobian_generic.py @@ -8,7 +8,8 @@ # http://www.gnu.org/licenses/ # **************************************************************************** -from sage.rings.all import Integer, QQ +from sage.rings.integer import Integer +from sage.rings.rational_field import QQ from sage.misc.lazy_attribute import lazy_attribute from sage.schemes.jacobians.abstract_jacobian import Jacobian_generic from . import jacobian_homset diff --git a/src/sage/schemes/hyperelliptic_curves/kummer_surface.py b/src/sage/schemes/hyperelliptic_curves/kummer_surface.py index 987099f8d4b..dadf1200f01 100644 --- a/src/sage/schemes/hyperelliptic_curves/kummer_surface.py +++ b/src/sage/schemes/hyperelliptic_curves/kummer_surface.py @@ -12,7 +12,7 @@ from sage.schemes.projective.projective_subscheme\ import AlgebraicScheme_subscheme_projective from sage.categories.homset import Hom -from sage.categories.all import Schemes +from sage.categories.schemes import Schemes # The generic genus 2 curve in Weierstrass form: # diff --git a/src/sage/schemes/hyperelliptic_curves/monsky_washnitzer.py b/src/sage/schemes/hyperelliptic_curves/monsky_washnitzer.py index 8118089acdb..6d0d2403ba8 100644 --- a/src/sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +++ b/src/sage/schemes/hyperelliptic_curves/monsky_washnitzer.py @@ -46,7 +46,7 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.arith.all import integer_ceil as ceil +from sage.arith.misc import integer_ceil as ceil from sage.arith.misc import binomial from sage.functions.log import log from sage.matrix.constructor import matrix @@ -58,9 +58,16 @@ from sage.modules.free_module import FreeModule from sage.modules.free_module_element import is_FreeModuleElement from sage.modules.module import Module -from sage.rings.all import (Integers, Integer, PolynomialRing, PowerSeriesRing, - Rationals, Rational, LaurentSeriesRing, QQ, ZZ, - IntegralDomain) +from sage.rings.finite_rings.integer_mod_ring import IntegerModRing as Integers +from sage.rings.integer import Integer +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing +from sage.rings.power_series_ring import PowerSeriesRing +from sage.rings.rational_field import RationalField as Rationals +from sage.rings.rational import Rational +from sage.rings.laurent_series_ring import LaurentSeriesRing +from sage.rings.rational_field import QQ +from sage.rings.integer_ring import ZZ +from sage.rings.ring import IntegralDomain from sage.rings.infinity import Infinity from sage.rings.laurent_series_ring import is_LaurentSeriesRing from sage.rings.padics.all import pAdicField diff --git a/src/sage/schemes/plane_conics/con_rational_field.py b/src/sage/schemes/plane_conics/con_rational_field.py index 9a75336901f..8e14d1e2ba7 100644 --- a/src/sage/schemes/plane_conics/con_rational_field.py +++ b/src/sage/schemes/plane_conics/con_rational_field.py @@ -24,7 +24,9 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.rings.all import (PolynomialRing, ZZ, QQ) +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ import sage.rings.abc @@ -38,7 +40,8 @@ from sage.structure.element import InfinityElement -from sage.arith.all import lcm, hilbert_symbol +from sage.arith.functions import lcm +from sage.arith.misc import hilbert_symbol class ProjectiveConic_rational_field(ProjectiveConic_number_field): diff --git a/src/sage/schemes/plane_conics/con_rational_function_field.py b/src/sage/schemes/plane_conics/con_rational_function_field.py index 0d1d457f085..d90909145e3 100644 --- a/src/sage/schemes/plane_conics/con_rational_function_field.py +++ b/src/sage/schemes/plane_conics/con_rational_function_field.py @@ -42,7 +42,8 @@ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.matrix.constructor import diagonal_matrix, matrix, block_matrix from sage.schemes.plane_conics.con_field import ProjectiveConic_field -from sage.arith.all import lcm, gcd +from sage.arith.functions import lcm +from sage.arith.misc import GCD as gcd from sage.modules.free_module_element import vector from sage.rings.fraction_field import is_FractionField diff --git a/src/sage/schemes/projective/proj_bdd_height.py b/src/sage/schemes/projective/proj_bdd_height.py index 9034f2d5352..2f90e1cc1f9 100644 --- a/src/sage/schemes/projective/proj_bdd_height.py +++ b/src/sage/schemes/projective/proj_bdd_height.py @@ -23,9 +23,9 @@ from sage.schemes.projective.projective_space import ProjectiveSpace from sage.rings.rational_field import QQ -from sage.rings.all import RealField +from sage.rings.real_mpfr import RealField from sage.rings.number_field.unit_group import UnitGroup -from sage.arith.all import gcd +from sage.arith.misc import GCD as gcd from sage.matrix.constructor import matrix, column_matrix from sage.libs.pari.all import pari from sage.modules.free_module_element import vector diff --git a/src/sage/schemes/projective/projective_morphism.py b/src/sage/schemes/projective/projective_morphism.py index 87ad986bb06..facc90bb53d 100644 --- a/src/sage/schemes/projective/projective_morphism.py +++ b/src/sage/schemes/projective/projective_morphism.py @@ -62,7 +62,8 @@ # **************************************************************************** import sys -from sage.arith.all import gcd, lcm +from sage.arith.misc import GCD as gcd +from sage.arith.functions import lcm from sage.interfaces.singular import singular from sage.misc.misc_c import prod from sage.misc.cachefunc import cached_method diff --git a/src/sage/schemes/projective/projective_point.py b/src/sage/schemes/projective/projective_point.py index d94d108e5d6..84e8741f739 100644 --- a/src/sage/schemes/projective/projective_point.py +++ b/src/sage/schemes/projective/projective_point.py @@ -40,7 +40,8 @@ from sage.rings.qqbar import number_field_elements_from_algebraics from sage.rings.quotient_ring import QuotientRing_generic from sage.rings.rational_field import QQ -from sage.arith.all import gcd, lcm +from sage.arith.misc import GCD as gcd +from sage.arith.functions import lcm from sage.misc.misc_c import prod from copy import copy diff --git a/src/sage/schemes/toric/library.py b/src/sage/schemes/toric/library.py index c8ecbf6a587..6f3617f22b6 100644 --- a/src/sage/schemes/toric/library.py +++ b/src/sage/schemes/toric/library.py @@ -40,11 +40,12 @@ from sage.structure.sage_object import SageObject -from sage.matrix.all import matrix, identity_matrix +from sage.matrix.constructor import Matrix as matrix +from sage.matrix.special import identity_matrix from sage.geometry.all import Fan, LatticePolytope, ToricLattice from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ -from sage.arith.all import gcd +from sage.arith.misc import GCD as gcd from sage.schemes.toric.variety import (DEFAULT_PREFIX, ToricVariety, normalize_names) diff --git a/src/sage/schemes/toric/morphism.py b/src/sage/schemes/toric/morphism.py index c86503bd699..d41c35c5a7b 100644 --- a/src/sage/schemes/toric/morphism.py +++ b/src/sage/schemes/toric/morphism.py @@ -370,7 +370,7 @@ from sage.structure.sequence import Sequence from sage.rings.integer_ring import ZZ -from sage.arith.all import gcd +from sage.arith.misc import GCD as gcd from sage.misc.cachefunc import cached_method from sage.matrix.constructor import matrix, identity_matrix from sage.modules.free_module_element import vector diff --git a/src/sage/schemes/toric/points.py b/src/sage/schemes/toric/points.py index 5da8f26a9c5..1815c4fa6f0 100644 --- a/src/sage/schemes/toric/points.py +++ b/src/sage/schemes/toric/points.py @@ -39,7 +39,7 @@ from sage.misc.misc_c import prod from sage.misc.cachefunc import cached_method -from sage.arith.all import gcd +from sage.arith.misc import GCD as gcd from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.parallel.decorate import Parallel diff --git a/src/sage/structure/coerce_maps.pyx b/src/sage/structure/coerce_maps.pyx index 6675fc84019..3537c24e678 100644 --- a/src/sage/structure/coerce_maps.pyx +++ b/src/sage/structure/coerce_maps.pyx @@ -282,7 +282,7 @@ cdef class NamedConvertMap(Map): print(type(x), x) print(type(C), C) print(self.method_name) - raise TypeError("Cannot coerce {} to {}".format(x, C)) + raise TypeError(f"cannot coerce {x} to {C}") cdef Map m cdef Element e = method(C) if e is None: diff --git a/src/sage/structure/element.pyx b/src/sage/structure/element.pyx index 6ad3075c5f4..ad84ab939ac 100644 --- a/src/sage/structure/element.pyx +++ b/src/sage/structure/element.pyx @@ -1137,7 +1137,8 @@ cdef class Element(SageObject): We now create an ``Element`` class where we define ``_richcmp_`` and check that comparison works:: - sage: cython(''' # optional - sage.misc.cython + sage: cython( # optional - sage.misc.cython + ....: ''' ....: from sage.structure.richcmp cimport rich_to_bool ....: from sage.structure.element cimport Element ....: cdef class FloatCmp(Element): @@ -2226,7 +2227,10 @@ cdef class ElementWithCachedMethod(Element): ....: "cdef class MyParent(Parent):", ....: " Element = MyElement"] sage: cython('\n'.join(cython_code)) # optional - sage.misc.cython - sage: cython_code = ["from sage.all import cached_method, cached_in_parent_method, Category, Objects", + sage: cython_code = ["from sage.misc.cachefunc import cached_method", + ....: "from sage.misc.cachefunc import cached_in_parent_method", + ....: "from sage.categories.category import Category", + ....: "from sage.categories.objects import Objects", ....: "class MyCategory(Category):", ....: " @cached_method", ....: " def super_categories(self):", @@ -2313,7 +2317,8 @@ cdef class ElementWithCachedMethod(Element): EXAMPLES:: - sage: cython(''' # optional - sage.misc.cython + sage: cython( # optional - sage.misc.cython + ....: ''' ....: from sage.structure.element cimport ElementWithCachedMethod ....: cdef class MyElement(ElementWithCachedMethod): ....: cdef public object x @@ -2325,7 +2330,10 @@ cdef class ElementWithCachedMethod(Element): ....: from sage.structure.parent cimport Parent ....: cdef class MyParent(Parent): ....: Element = MyElement - ....: from sage.all import cached_method, lazy_attribute, Category, Objects + ....: from sage.misc.cachefunc import cached_method + ....: from sage.misc.lazy_attribute import lazy_attribute + ....: from sage.categories.category import Category + ....: from sage.categories.objects import Objects ....: class MyCategory(Category): ....: @cached_method ....: def super_categories(self): @@ -4048,7 +4056,7 @@ cdef class PrincipalIdealDomainElement(DedekindDomainElement): if not isinstance(right, Element): right = right.sage() if not ((right)._parent is self._parent): - from sage.arith.all import gcd + from sage.arith.misc import GCD as gcd return coercion_model.bin_op(self, right, gcd) return self._gcd(right) @@ -4082,7 +4090,7 @@ cdef class PrincipalIdealDomainElement(DedekindDomainElement): if not isinstance(right, Element): right = right.sage() if not ((right)._parent is self._parent): - from sage.arith.all import lcm + from sage.arith.functions import lcm return coercion_model.bin_op(self, right, lcm) return self._lcm(right) @@ -4117,7 +4125,8 @@ cdef class EuclideanDomainElement(PrincipalIdealDomainElement): EXAMPLES:: - sage: cython(''' # optional - sage.misc.cython + sage: cython( # optional - sage.misc.cython + ....: ''' ....: from sage.structure.element cimport EuclideanDomainElement ....: cdef class MyElt(EuclideanDomainElement): ....: def quo_rem(self, other): @@ -4147,7 +4156,8 @@ cdef class EuclideanDomainElement(PrincipalIdealDomainElement): :: - sage: cython(''' # optional - sage.misc.cython + sage: cython( # optional - sage.misc.cython + ....: ''' ....: from sage.structure.element cimport EuclideanDomainElement ....: cdef class MyElt(EuclideanDomainElement): ....: def quo_rem(self, other): @@ -4432,11 +4442,11 @@ def coerce_binop(method): Another real example:: - sage: R1=QQ['x,y'] - sage: R2=QQ['x,y,z'] - sage: f=R1(1) - sage: g=R1(2) - sage: h=R2(1) + sage: R1 = QQ['x,y'] + sage: R2 = QQ['x,y,z'] + sage: f = R1(1) + sage: g = R1(2) + sage: h = R2(1) sage: f.gcd(g) 1 sage: f.gcd(g,algorithm='modular') diff --git a/src/sage/structure/factory.pyx b/src/sage/structure/factory.pyx index a4a13186973..a1a28a0da7a 100644 --- a/src/sage/structure/factory.pyx +++ b/src/sage/structure/factory.pyx @@ -222,7 +222,9 @@ cdef class UniqueFactory(SageObject): Let us try again, with a Cython class that does allow weak references. Now, creation of an instance using the factory works:: - sage: cython('''cdef class C: # optional - sage.misc.cython + sage: cython( # optional - sage.misc.cython + ....: ''' + ....: cdef class C: ....: cdef __weakref__ ....: ''') ....: diff --git a/src/sage/structure/set_factories_example.py b/src/sage/structure/set_factories_example.py index 44763fda11b..5414edea03d 100644 --- a/src/sage/structure/set_factories_example.py +++ b/src/sage/structure/set_factories_example.py @@ -37,7 +37,7 @@ from sage.structure.element_wrapper import ElementWrapper from sage.structure.set_factories import ( SetFactory, ParentWithSetFactory, TopMostParentPolicy) -from sage.sets.all import DisjointUnionEnumeratedSets +from sage.sets.disjoint_union_enumerated_sets import DisjointUnionEnumeratedSets from sage.sets.family import LazyFamily from sage.categories.enumerated_sets import EnumeratedSets from sage.rings.integer import Integer diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 23bed6330b7..54bfd3465ec 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -1603,7 +1603,7 @@ cdef class Expression(Expression_abc): sage: x._eval_self(CC) Traceback (most recent call last): ... - TypeError: Cannot evaluate symbolic expression to a numeric value. + TypeError: cannot evaluate symbolic expression to a numeric value Check if we can compute a real evaluation even if the expression contains complex coefficients:: @@ -1644,7 +1644,7 @@ cdef class Expression(Expression_abc): ans = ans.real return R(ans) else: - raise TypeError("Cannot evaluate symbolic expression to a numeric value.") + raise TypeError("cannot evaluate symbolic expression to a numeric value") cpdef _convert(self, kwds): """ @@ -3464,6 +3464,12 @@ cdef class Expression(Expression_abc): sage: bool(x^2 + 2*x + 1 != (x + 1)^2) False + + Check that :trac:`16031` is fixed:: + + sage: expr = reduce(lambda u, v: 1/u -v, [1/pi] + list(continued_fraction(pi)[:20])) + sage: expr.is_zero() + False """ if self.is_relational(): # constants are wrappers around Sage objects, compare directly @@ -7064,7 +7070,7 @@ cdef class Expression(Expression_abc): sage: p.coefficients(x, sparse=False) Traceback (most recent call last): ... - ValueError: Cannot return dense coefficient list with noninteger exponents. + ValueError: cannot return dense coefficient list with noninteger exponents Series coefficients are now handled correctly (:trac:`17399`):: @@ -7126,12 +7132,12 @@ cdef class Expression(Expression_abc): else: from sage.rings.integer_ring import ZZ if any(not c[1] in ZZ for c in l): - raise ValueError("Cannot return dense coefficient list with noninteger exponents.") + raise ValueError("cannot return dense coefficient list with noninteger exponents") if not l: l = [[0, 0]] val = l[0][1] if val < 0: - raise ValueError("Cannot return dense coefficient list with negative valuation.") + raise ValueError("cannot return dense coefficient list with negative valuation") deg = l[-1][1] ret = [ZZ(0)] * int(deg+1) for c in l: @@ -8258,7 +8264,7 @@ cdef class Expression(Expression_abc): sage: (x^(1/3)).horner(x) Traceback (most recent call last): ... - ValueError: Cannot return dense coefficient list with noninteger exponents. + ValueError: cannot return dense coefficient list with noninteger exponents """ coef = self.coefficients(x, sparse=False) res = coef[-1] @@ -10702,6 +10708,10 @@ cdef class Expression(Expression_abc): sage: f.simplify_full() sin(x)/cos(x) + Check that :trac:`20846` is fixed:: + + sage: ((1/6*pi^2).series(x)).simplify_full() + 1/6*pi^2 """ x = self x = x.simplify_factorial() @@ -12092,7 +12102,7 @@ cdef class Expression(Expression_abc): sage: wrong.convert() Traceback (most recent call last): ... - ValueError: Cannot convert + ValueError: cannot convert """ from . import units return units.convert(self, target) diff --git a/src/sage/symbolic/pynac.pxi b/src/sage/symbolic/pynac.pxi index e6ab54f4e0b..4015657b951 100644 --- a/src/sage/symbolic/pynac.pxi +++ b/src/sage/symbolic/pynac.pxi @@ -3,7 +3,8 @@ Declarations for pynac, a Python frontend for ginac Check that we can externally cimport this (:trac:`18825`):: - sage: cython(''' # long time; random compiler warnings # optional - sage.misc.cython + sage: cython( # long time; random compiler warnings # optional - sage.misc.cython + ....: ''' ....: from sage.symbolic cimport expression ....: ''') """ diff --git a/src/sage/symbolic/ring.pyx b/src/sage/symbolic/ring.pyx index 20a576a3b5a..2bfb28f249e 100644 --- a/src/sage/symbolic/ring.pyx +++ b/src/sage/symbolic/ring.pyx @@ -1140,7 +1140,7 @@ cdef class SymbolicRing(sage.rings.abc.SymbolicRing): :doc:`subring` """ if self is not SR: - raise NotImplementedError('Cannot create subring of %s.' % (self,)) + raise NotImplementedError('cannot create subring of %s' % (self,)) from .subring import SymbolicSubring return SymbolicSubring(*args, **kwds) diff --git a/src/sage/symbolic/series_impl.pxi b/src/sage/symbolic/series_impl.pxi index 18c017066f6..4ddea0ffc6f 100644 --- a/src/sage/symbolic/series_impl.pxi +++ b/src/sage/symbolic/series_impl.pxi @@ -246,10 +246,10 @@ cdef class SymbolicSeries(Expression): else: from sage.rings.integer_ring import ZZ if any(not c[1] in ZZ for c in l): - raise ValueError("Cannot return dense coefficient list with noninteger exponents.") + raise ValueError("cannot return dense coefficient list with noninteger exponents") val = l[0][1] if val < 0: - raise ValueError("Cannot return dense coefficient list with negative valuation.") + raise ValueError("cannot return dense coefficient list with negative valuation") deg = l[-1][1] ret = [ZZ(0)] * int(deg+1) for c in l: diff --git a/src/sage/symbolic/subring.py b/src/sage/symbolic/subring.py index e30e29a16cf..05ec90861fd 100644 --- a/src/sage/symbolic/subring.py +++ b/src/sage/symbolic/subring.py @@ -181,33 +181,33 @@ def create_key_and_extra_args( sage: SymbolicSubring.create_key_and_extra_args() Traceback (most recent call last): ... - ValueError: Cannot create a symbolic subring since nothing is specified. + ValueError: cannot create a symbolic subring since nothing is specified sage: SymbolicSubring.create_key_and_extra_args( ....: accepting_variables=('a',), rejecting_variables=('r',)) Traceback (most recent call last): ... - ValueError: Cannot create a symbolic subring since input is ambiguous. + ValueError: cannot create a symbolic subring since input is ambiguous sage: SymbolicSubring.create_key_and_extra_args( ....: accepting_variables=('a',), no_variables=True) Traceback (most recent call last): ... - ValueError: Cannot create a symbolic subring since input is ambiguous. + ValueError: cannot create a symbolic subring since input is ambiguous sage: SymbolicSubring.create_key_and_extra_args( ....: rejecting_variables=('r',), no_variables=True) Traceback (most recent call last): ... - ValueError: Cannot create a symbolic subring since input is ambiguous. + ValueError: cannot create a symbolic subring since input is ambiguous """ if accepting_variables is None and \ rejecting_variables is None and \ not no_variables: - raise ValueError('Cannot create a symbolic subring ' - 'since nothing is specified.') + raise ValueError('cannot create a symbolic subring ' + 'since nothing is specified') if accepting_variables is not None and rejecting_variables is not None or \ rejecting_variables is not None and no_variables or \ no_variables and accepting_variables is not None: - raise ValueError('Cannot create a symbolic subring ' - 'since input is ambiguous.') + raise ValueError('cannot create a symbolic subring ' + 'since input is ambiguous') if accepting_variables is not None: vars = tuple(accepting_variables) diff --git a/src/sage/symbolic/units.py b/src/sage/symbolic/units.py index 9b5407786e1..5732f11ded3 100644 --- a/src/sage/symbolic/units.py +++ b/src/sage/symbolic/units.py @@ -61,7 +61,7 @@ sage: wrong.convert() Traceback (most recent call last): ... - ValueError: Cannot convert + ValueError: cannot convert TESTS: @@ -1434,12 +1434,12 @@ def convert_temperature(expr, target): sage: t.convert(units.length.foot) Traceback (most recent call last): ... - ValueError: Cannot convert + ValueError: cannot convert sage: wrong = units.length.meter*units.temperature.fahrenheit sage: wrong.convert() Traceback (most recent call last): ... - ValueError: Cannot convert + ValueError: cannot convert We directly call the convert_temperature function:: @@ -1449,7 +1449,7 @@ def convert_temperature(expr, target): 98.6000000000000 """ if len(expr.variables()) != 1: - raise ValueError("Cannot convert") + raise ValueError("cannot convert") elif target is None or unit_to_type[str(target)] == 'temperature': from sage.misc.sage_eval import sage_eval expr_temp = expr.variables()[0] @@ -1467,4 +1467,4 @@ def convert_temperature(expr, target): elif target_temp == units.temperature.rankine: return a[3]*target_temp else: - raise ValueError("Cannot convert") + raise ValueError("cannot convert") diff --git a/src/sage/version.py b/src/sage/version.py index 962b5cea054..6c86cab5b29 100644 --- a/src/sage/version.py +++ b/src/sage/version.py @@ -1,5 +1,5 @@ # Sage version information for Python scripts # This file is auto-generated by the sage-update-version script, do not edit! -version = '10.0.beta1' -date = '2023-02-19' -banner = 'SageMath version 10.0.beta1, Release Date: 2023-02-19' +version = '10.0.beta3' +date = '2023-03-02' +banner = 'SageMath version 10.0.beta3, Release Date: 2023-03-02'