diff --git a/.upstream.d/20-github.com-sagemath-sage-releases b/.upstream.d/20-github.com-sagemath-sage-releases index 0176fddf829..1ab20a34a06 100644 --- a/.upstream.d/20-github.com-sagemath-sage-releases +++ b/.upstream.d/20-github.com-sagemath-sage-releases @@ -1,4 +1,5 @@ # Upstream packages as uploaded as GitHub release assets. # This file is automatically updated by the sage-update-version script. +https://github.com/sagemath/sage/releases/download/10.3/ https://github.com/sagemath/sage/releases/download/10.2/ https://github.com/sagemath/sage/releases/download/10.1/ diff --git a/CITATION.cff b/CITATION.cff index 0a73d8da64e..33dda263384 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -4,8 +4,8 @@ title: SageMath abstract: SageMath is a free open-source mathematics software system. authors: - name: "The SageMath Developers" -version: 10.2.rc5 +version: 10.3.beta0 doi: 10.5281/zenodo.593563 -date-released: 2023-11-30 +date-released: 2023-12-05 repository-code: "https://github.com/sagemath/sage" url: "https://www.sagemath.org/" diff --git a/VERSION.txt b/VERSION.txt index 9fb07a54404..75f3e554fbb 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -SageMath version 10.2.rc5, Release Date: 2023-11-30 +SageMath version 10.3.beta0, Release Date: 2023-12-05 diff --git a/build/pkgs/antic/SPKG.rst b/build/pkgs/antic/SPKG.rst deleted file mode 100644 index d6c32377957..00000000000 --- a/build/pkgs/antic/SPKG.rst +++ /dev/null @@ -1,18 +0,0 @@ -antic: Algebraic Number Theory In C -=================================== - -Description ------------ - -Algebraic Number Theory In C - -License -------- - -LGPL 2.1 - -Upstream Contact ----------------- - -https://github.com/wbhart/antic - diff --git a/build/pkgs/antic/checksums.ini b/build/pkgs/antic/checksums.ini deleted file mode 100644 index fc8711ecd13..00000000000 --- a/build/pkgs/antic/checksums.ini +++ /dev/null @@ -1,5 +0,0 @@ -tarball=antic-VERSION.tar.gz -sha1=940d8ea2c3512b9d49ee3101cf043f777764bd8f -md5=4e896420dd6344b53b307871efb2cbb4 -cksum=1938565125 -upstream_url=https://github.com/wbhart/antic/archive/refs/tags/vVERSION.tar.gz diff --git a/build/pkgs/antic/distros/arch.txt b/build/pkgs/antic/distros/arch.txt deleted file mode 100644 index 83c7cab14e4..00000000000 --- a/build/pkgs/antic/distros/arch.txt +++ /dev/null @@ -1 +0,0 @@ -antic diff --git a/build/pkgs/antic/distros/conda.txt b/build/pkgs/antic/distros/conda.txt deleted file mode 100644 index 83c7cab14e4..00000000000 --- a/build/pkgs/antic/distros/conda.txt +++ /dev/null @@ -1 +0,0 @@ -antic diff --git a/build/pkgs/antic/distros/debian.txt b/build/pkgs/antic/distros/debian.txt deleted file mode 100644 index 8fdcd3e5721..00000000000 --- a/build/pkgs/antic/distros/debian.txt +++ /dev/null @@ -1 +0,0 @@ -libantic-dev diff --git a/build/pkgs/antic/distros/fedora.txt b/build/pkgs/antic/distros/fedora.txt deleted file mode 100644 index 1b16da9f64b..00000000000 --- a/build/pkgs/antic/distros/fedora.txt +++ /dev/null @@ -1 +0,0 @@ -antic-devel diff --git a/build/pkgs/antic/distros/freebsd.txt b/build/pkgs/antic/distros/freebsd.txt deleted file mode 100644 index 116ff3a26f3..00000000000 --- a/build/pkgs/antic/distros/freebsd.txt +++ /dev/null @@ -1 +0,0 @@ -math/antic diff --git a/build/pkgs/antic/distros/opensuse.txt b/build/pkgs/antic/distros/opensuse.txt deleted file mode 100644 index 1b16da9f64b..00000000000 --- a/build/pkgs/antic/distros/opensuse.txt +++ /dev/null @@ -1 +0,0 @@ -antic-devel diff --git a/build/pkgs/antic/distros/repology.txt b/build/pkgs/antic/distros/repology.txt deleted file mode 100644 index 83c7cab14e4..00000000000 --- a/build/pkgs/antic/distros/repology.txt +++ /dev/null @@ -1 +0,0 @@ -antic diff --git a/build/pkgs/antic/package-version.txt b/build/pkgs/antic/package-version.txt deleted file mode 100644 index 3a4036fb450..00000000000 --- a/build/pkgs/antic/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -0.2.5 diff --git a/build/pkgs/antic/spkg-install.in b/build/pkgs/antic/spkg-install.in deleted file mode 100644 index c57fa884a20..00000000000 --- a/build/pkgs/antic/spkg-install.in +++ /dev/null @@ -1,19 +0,0 @@ -cd src - -# Copied from build/pkgs/flint/spkg-install.in: -# Trac #29607: We must always supply --with-gmp, --with-mpfr, -# --with-ntl because otherwise FLINT's configure script uses -# /usr/local, which is always wrong. -# This is why we do not use $SAGE_CONFIGURE_GMP etc. here. -# The value $SAGE_LOCAL is always a safe choice even if the library -# is coming from the system and is found using what is in -# LIBRARY_PATH or LDFLAGS etc. -./configure \ - --disable-static \ - --prefix="$SAGE_LOCAL" \ - --with-gmp="$SAGE_LOCAL" \ - --with-mpfr="$SAGE_LOCAL" \ - --with-flint="$SAGE_LOCAL" || sdh_die "Error: Failed to configure antic." - -sdh_make verbose -sdh_make_install diff --git a/build/pkgs/antic/type b/build/pkgs/antic/type deleted file mode 100644 index 134d9bc32d5..00000000000 --- a/build/pkgs/antic/type +++ /dev/null @@ -1 +0,0 @@ -optional diff --git a/build/pkgs/anyio/SPKG.rst b/build/pkgs/anyio/SPKG.rst new file mode 100644 index 00000000000..bf455f06bdb --- /dev/null +++ b/build/pkgs/anyio/SPKG.rst @@ -0,0 +1,18 @@ +anyio: High level compatibility layer for multiple asynchronous event loop implementations +========================================================================================== + +Description +----------- + +High level compatibility layer for multiple asynchronous event loop implementations + +License +------- + +MIT + +Upstream Contact +---------------- + +https://pypi.org/project/anyio/ + diff --git a/build/pkgs/anyio/checksums.ini b/build/pkgs/anyio/checksums.ini new file mode 100644 index 00000000000..4dcafcb69da --- /dev/null +++ b/build/pkgs/anyio/checksums.ini @@ -0,0 +1,5 @@ +tarball=anyio-VERSION-py3-none-any.whl +sha1=bb08368bb19e1aff2f4190e39300e43fee52103e +md5=420d85e19168705cdf0223621b18831a +cksum=627181302 +upstream_url=https://pypi.io/packages/py3/a/anyio/anyio-VERSION-py3-none-any.whl diff --git a/build/pkgs/hatch_nodejs_version/dependencies b/build/pkgs/anyio/dependencies similarity index 59% rename from build/pkgs/hatch_nodejs_version/dependencies rename to build/pkgs/anyio/dependencies index 85e8893f785..5be99073470 100644 --- a/build/pkgs/hatch_nodejs_version/dependencies +++ b/build/pkgs/anyio/dependencies @@ -1,4 +1,4 @@ - hatchling | $(PYTHON_TOOLCHAIN) $(PYTHON) +idna sniffio | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/anyio/install-requires.txt b/build/pkgs/anyio/install-requires.txt new file mode 100644 index 00000000000..c77c069ecc9 --- /dev/null +++ b/build/pkgs/anyio/install-requires.txt @@ -0,0 +1 @@ +anyio diff --git a/build/pkgs/anyio/package-version.txt b/build/pkgs/anyio/package-version.txt new file mode 100644 index 00000000000..fcdb2e109f6 --- /dev/null +++ b/build/pkgs/anyio/package-version.txt @@ -0,0 +1 @@ +4.0.0 diff --git a/build/pkgs/arb/type b/build/pkgs/anyio/type similarity index 100% rename from build/pkgs/arb/type rename to build/pkgs/anyio/type diff --git a/build/pkgs/arb/SPKG.rst b/build/pkgs/arb/SPKG.rst deleted file mode 100644 index cff49ddb95b..00000000000 --- a/build/pkgs/arb/SPKG.rst +++ /dev/null @@ -1,27 +0,0 @@ -arb: Arbitrary-precision floating-point ball arithmetic -======================================================= - -Description ------------ - -Arb is a C library for arbitrary-precision floating-point ball -arithmetic, developed by Fredrik Johansson -(fredrik.johansson@gmail.com). It supports efficient high-precision -computation with polynomials, power series, matrices and special -functions over the real and complex numbers, with automatic, rigorous -error control. - -License -------- - -GNU General Public License v2+ - - -Upstream Contact ----------------- - - - Fredrik Johansson: fredrik.johansson@gmail.com - - - https://arblib.org/ - - - http://github.com/fredrik-johansson/arb/ diff --git a/build/pkgs/arb/checksums.ini b/build/pkgs/arb/checksums.ini deleted file mode 100644 index 80ef43dad5d..00000000000 --- a/build/pkgs/arb/checksums.ini +++ /dev/null @@ -1,5 +0,0 @@ -tarball=arb-VERSION.tar.gz -sha1=a1efe035dd3af3613dd685971a156f652b86ff63 -md5=9b369e29f93cdf2d4f90b57a92526cce -cksum=64252121 -upstream_url=https://github.com/fredrik-johansson/arb/archive/VERSION.tar.gz diff --git a/build/pkgs/arb/distros/arch.txt b/build/pkgs/arb/distros/arch.txt deleted file mode 100644 index 86c41dbaa5f..00000000000 --- a/build/pkgs/arb/distros/arch.txt +++ /dev/null @@ -1 +0,0 @@ -arb diff --git a/build/pkgs/arb/distros/conda.txt b/build/pkgs/arb/distros/conda.txt deleted file mode 100644 index 86c41dbaa5f..00000000000 --- a/build/pkgs/arb/distros/conda.txt +++ /dev/null @@ -1 +0,0 @@ -arb diff --git a/build/pkgs/arb/distros/debian.txt b/build/pkgs/arb/distros/debian.txt deleted file mode 100644 index 9fe71110712..00000000000 --- a/build/pkgs/arb/distros/debian.txt +++ /dev/null @@ -1 +0,0 @@ -libflint-arb-dev diff --git a/build/pkgs/arb/distros/fedora.txt b/build/pkgs/arb/distros/fedora.txt deleted file mode 100644 index 76794404627..00000000000 --- a/build/pkgs/arb/distros/fedora.txt +++ /dev/null @@ -1 +0,0 @@ -arb arb-devel diff --git a/build/pkgs/arb/distros/freebsd.txt b/build/pkgs/arb/distros/freebsd.txt deleted file mode 100644 index 2ef8c7cec0f..00000000000 --- a/build/pkgs/arb/distros/freebsd.txt +++ /dev/null @@ -1 +0,0 @@ -math/arb diff --git a/build/pkgs/arb/distros/gentoo.txt b/build/pkgs/arb/distros/gentoo.txt deleted file mode 100644 index 58e3d4f8008..00000000000 --- a/build/pkgs/arb/distros/gentoo.txt +++ /dev/null @@ -1 +0,0 @@ -sci-mathematics/arb diff --git a/build/pkgs/arb/distros/homebrew.txt b/build/pkgs/arb/distros/homebrew.txt deleted file mode 100644 index 86c41dbaa5f..00000000000 --- a/build/pkgs/arb/distros/homebrew.txt +++ /dev/null @@ -1 +0,0 @@ -arb diff --git a/build/pkgs/arb/distros/nix.txt b/build/pkgs/arb/distros/nix.txt deleted file mode 100644 index 86c41dbaa5f..00000000000 --- a/build/pkgs/arb/distros/nix.txt +++ /dev/null @@ -1 +0,0 @@ -arb diff --git a/build/pkgs/arb/distros/opensuse.txt b/build/pkgs/arb/distros/opensuse.txt deleted file mode 100644 index 3319855150c..00000000000 --- a/build/pkgs/arb/distros/opensuse.txt +++ /dev/null @@ -1 +0,0 @@ -arb-devel diff --git a/build/pkgs/arb/distros/repology.txt b/build/pkgs/arb/distros/repology.txt deleted file mode 100644 index 179c9d507e1..00000000000 --- a/build/pkgs/arb/distros/repology.txt +++ /dev/null @@ -1 +0,0 @@ -arb-fp diff --git a/build/pkgs/arb/distros/void.txt b/build/pkgs/arb/distros/void.txt deleted file mode 100644 index 3319855150c..00000000000 --- a/build/pkgs/arb/distros/void.txt +++ /dev/null @@ -1 +0,0 @@ -arb-devel diff --git a/build/pkgs/arb/package-version.txt b/build/pkgs/arb/package-version.txt deleted file mode 100644 index e9763f6bfed..00000000000 --- a/build/pkgs/arb/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -2.23.0 diff --git a/build/pkgs/arb/spkg-check.in b/build/pkgs/arb/spkg-check.in deleted file mode 100644 index 27cd9419538..00000000000 --- a/build/pkgs/arb/spkg-check.in +++ /dev/null @@ -1,2 +0,0 @@ -cd src -$MAKE check diff --git a/build/pkgs/arb/spkg-configure.m4 b/build/pkgs/arb/spkg-configure.m4 deleted file mode 100644 index ef2dd0aac4a..00000000000 --- a/build/pkgs/arb/spkg-configure.m4 +++ /dev/null @@ -1,23 +0,0 @@ -SAGE_SPKG_CONFIGURE([arb], [ - AC_REQUIRE([SAGE_SPKG_CONFIGURE_FLINT]) - SAGE_ARB_LIBRARY="arb" - AC_MSG_CHECKING([installing flint? ]) - if test x$sage_spkg_install_flint = xyes; then - AC_MSG_RESULT([yes; install arb as well]) - sage_spkg_install_arb=yes - else - AC_CHECK_HEADER(arb.h, [ - dnl below function added in version 2.16 of arb - AC_CHECK_LIB([arb], [acb_mat_eig_simple], [], - [dnl in Debian the name of dylib is different. - AC_CHECK_LIB([flint-arb], [acb_mat_eig_simple], - [SAGE_ARB_LIBRARY="flint-arb"], [sage_spkg_install_arb=yes])]) - ], [sage_spkg_install_arb=yes]) - fi -], [], [], [ - if test x$sage_spkg_install_arb = xyes; then - AC_SUBST(SAGE_ARB_LIBRARY,["arb"]) - else - AC_SUBST(SAGE_ARB_LIBRARY,[$SAGE_ARB_LIBRARY]) - fi -]) diff --git a/build/pkgs/arb/spkg-install.in b/build/pkgs/arb/spkg-install.in deleted file mode 100644 index 9322f04c912..00000000000 --- a/build/pkgs/arb/spkg-install.in +++ /dev/null @@ -1,17 +0,0 @@ -cd src - -# Trac #29607: We must always supply --with-gmp, --with-mpfr, -# --with-flint because otherwise ARB's configure script uses -# /usr/local, which is always wrong. -# This is why we do not use $SAGE_CONFIGURE_GMP etc. here. -# The value $SAGE_LOCAL is always a safe choice even if the library -# is coming from the system and is found using what is in -# LIBRARY_PATH or LDFLAGS etc. -./configure --disable-static --prefix="$SAGE_LOCAL" \ - --with-gmp="$SAGE_LOCAL" \ - --with-mpfr="$SAGE_LOCAL" \ - --with-flint="$SAGE_LOCAL" || \ - sdh_die "Error configuring arb." - -sdh_make verbose -sdh_make_install diff --git a/build/pkgs/arrow/SPKG.rst b/build/pkgs/arrow/SPKG.rst new file mode 100644 index 00000000000..0b4f6eea8b0 --- /dev/null +++ b/build/pkgs/arrow/SPKG.rst @@ -0,0 +1,18 @@ +arrow: Better dates & times for Python +====================================== + +Description +----------- + +Better dates & times for Python + +License +------- + +Apache 2.0 + +Upstream Contact +---------------- + +https://pypi.org/project/arrow/ + diff --git a/build/pkgs/arrow/checksums.ini b/build/pkgs/arrow/checksums.ini new file mode 100644 index 00000000000..8823edda27e --- /dev/null +++ b/build/pkgs/arrow/checksums.ini @@ -0,0 +1,5 @@ +tarball=arrow-VERSION-py3-none-any.whl +sha1=fd9376ef4788dc2b1c981e6b5beb9048e046c556 +md5=71d18bb3d882ae242b5b1a397313bb12 +cksum=244356435 +upstream_url=https://pypi.io/packages/py3/a/arrow/arrow-VERSION-py3-none-any.whl diff --git a/build/pkgs/arrow/dependencies b/build/pkgs/arrow/dependencies new file mode 100644 index 00000000000..585a06aa604 --- /dev/null +++ b/build/pkgs/arrow/dependencies @@ -0,0 +1,4 @@ +dateutil types_python_dateutil | $(PYTHON_TOOLCHAIN) $(PYTHON) + +---------- +All lines of this file are ignored except the first. diff --git a/build/pkgs/arrow/install-requires.txt b/build/pkgs/arrow/install-requires.txt new file mode 100644 index 00000000000..e2dc7471c20 --- /dev/null +++ b/build/pkgs/arrow/install-requires.txt @@ -0,0 +1 @@ +arrow diff --git a/build/pkgs/arrow/package-version.txt b/build/pkgs/arrow/package-version.txt new file mode 100644 index 00000000000..f0bb29e7638 --- /dev/null +++ b/build/pkgs/arrow/package-version.txt @@ -0,0 +1 @@ +1.3.0 diff --git a/build/pkgs/hatch_nodejs_version/type b/build/pkgs/arrow/type similarity index 100% rename from build/pkgs/hatch_nodejs_version/type rename to build/pkgs/arrow/type diff --git a/build/pkgs/asttokens/checksums.ini b/build/pkgs/asttokens/checksums.ini index e69f1ecdfb3..44d0ca1b500 100644 --- a/build/pkgs/asttokens/checksums.ini +++ b/build/pkgs/asttokens/checksums.ini @@ -1,5 +1,5 @@ tarball=asttokens-VERSION.tar.gz -sha1=cca6058c6c23195148be93bfa32c0a0ca9b2f873 -md5=67b269e359fcb404cd8626985f3676ae -cksum=3749309047 +sha1=d522a139240293953c99d32ca62c41542babb963 +md5=c353679585a40f43c24ca60fca33bbf6 +cksum=1117135252 upstream_url=https://pypi.io/packages/source/a/asttokens/asttokens-VERSION.tar.gz diff --git a/build/pkgs/asttokens/package-version.txt b/build/pkgs/asttokens/package-version.txt index 7ec1d6db408..005119baaa0 100644 --- a/build/pkgs/asttokens/package-version.txt +++ b/build/pkgs/asttokens/package-version.txt @@ -1 +1 @@ -2.1.0 +2.4.1 diff --git a/build/pkgs/async_lru/SPKG.rst b/build/pkgs/async_lru/SPKG.rst new file mode 100644 index 00000000000..069608d47c6 --- /dev/null +++ b/build/pkgs/async_lru/SPKG.rst @@ -0,0 +1,18 @@ +async_lru: Simple LRU cache for asyncio +======================================= + +Description +----------- + +Simple LRU cache for asyncio + +License +------- + +MIT License + +Upstream Contact +---------------- + +https://pypi.org/project/async-lru/ + diff --git a/build/pkgs/async_lru/checksums.ini b/build/pkgs/async_lru/checksums.ini new file mode 100644 index 00000000000..1a289cb63c3 --- /dev/null +++ b/build/pkgs/async_lru/checksums.ini @@ -0,0 +1,5 @@ +tarball=async_lru-VERSION-py3-none-any.whl +sha1=99b2ea5d551cbad28e08e45f0d0b00827f9ff73d +md5=de1e9e7559810690de8b7084b372d9a2 +cksum=3326301475 +upstream_url=https://pypi.io/packages/py3/a/async_lru/async_lru-VERSION-py3-none-any.whl diff --git a/build/pkgs/vcversioner/dependencies b/build/pkgs/async_lru/dependencies similarity index 100% rename from build/pkgs/vcversioner/dependencies rename to build/pkgs/async_lru/dependencies diff --git a/build/pkgs/async_lru/install-requires.txt b/build/pkgs/async_lru/install-requires.txt new file mode 100644 index 00000000000..c289e49b9fa --- /dev/null +++ b/build/pkgs/async_lru/install-requires.txt @@ -0,0 +1 @@ +async-lru diff --git a/build/pkgs/async_lru/package-version.txt b/build/pkgs/async_lru/package-version.txt new file mode 100644 index 00000000000..2165f8f9b6a --- /dev/null +++ b/build/pkgs/async_lru/package-version.txt @@ -0,0 +1 @@ +2.0.4 diff --git a/build/pkgs/vcversioner/type b/build/pkgs/async_lru/type similarity index 100% rename from build/pkgs/vcversioner/type rename to build/pkgs/async_lru/type diff --git a/build/pkgs/beautifulsoup4/checksums.ini b/build/pkgs/beautifulsoup4/checksums.ini index aa0baa2216c..0fd063dd71c 100644 --- a/build/pkgs/beautifulsoup4/checksums.ini +++ b/build/pkgs/beautifulsoup4/checksums.ini @@ -1,5 +1,5 @@ tarball=beautifulsoup4-VERSION.tar.gz -sha1=fbb73ba4221122b56cd4eac2d9e5d3ad2e383ae0 -md5=22f22f89cf9da41b22e1ece9639c66a3 -cksum=2807377018 +sha1=d9cd72f81e7710692b8ff0a42e69bf93375b5fd3 +md5=b49a6696a762e946c2be97c36a5adaa8 +cksum=839566236 upstream_url=https://pypi.io/packages/source/b/beautifulsoup4/beautifulsoup4-VERSION.tar.gz diff --git a/build/pkgs/beautifulsoup4/package-version.txt b/build/pkgs/beautifulsoup4/package-version.txt index d782fca8f64..f1cd7de1de5 100644 --- a/build/pkgs/beautifulsoup4/package-version.txt +++ b/build/pkgs/beautifulsoup4/package-version.txt @@ -1 +1 @@ -4.11.1 +4.12.2 diff --git a/build/pkgs/bleach/checksums.ini b/build/pkgs/bleach/checksums.ini index 4d4855aab72..33843727cd9 100644 --- a/build/pkgs/bleach/checksums.ini +++ b/build/pkgs/bleach/checksums.ini @@ -1,5 +1,5 @@ -tarball=bleach-VERSION.tar.gz -sha1=73c6b8fad993b318859ca65c365ac2191edd35fc -md5=03b5faa43c0d771a86a2c4cb2575d070 -cksum=4204308806 -upstream_url=https://pypi.io/packages/source/b/bleach/bleach-VERSION.tar.gz +tarball=bleach-VERSION-py3-none-any.whl +sha1=7ba81a446171fb840d3083afadd0c87f0b599305 +md5=ec9e860103ffbc3e6e9963485464bfbc +cksum=1174632300 +upstream_url=https://pypi.io/packages/py3/b/bleach/bleach-VERSION-py3-none-any.whl diff --git a/build/pkgs/bleach/dependencies b/build/pkgs/bleach/dependencies index c7ac2e8b3e7..b597779be66 100644 --- a/build/pkgs/bleach/dependencies +++ b/build/pkgs/bleach/dependencies @@ -1,4 +1,4 @@ - packaging six webencodings | $(PYTHON_TOOLCHAIN) $(PYTHON) + six webencodings | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/bleach/install-requires.txt b/build/pkgs/bleach/install-requires.txt index 49c810a0dcb..7f7581bd261 100644 --- a/build/pkgs/bleach/install-requires.txt +++ b/build/pkgs/bleach/install-requires.txt @@ -1 +1 @@ -bleach >=3.1.5 +bleach >= 5 diff --git a/build/pkgs/bleach/package-version.txt b/build/pkgs/bleach/package-version.txt index 6b244dcd696..dfda3e0b4f0 100644 --- a/build/pkgs/bleach/package-version.txt +++ b/build/pkgs/bleach/package-version.txt @@ -1 +1 @@ -5.0.1 +6.1.0 diff --git a/build/pkgs/bleach/spkg-install.in b/build/pkgs/bleach/spkg-install.in deleted file mode 100644 index deba1bb42bb..00000000000 --- a/build/pkgs/bleach/spkg-install.in +++ /dev/null @@ -1 +0,0 @@ -cd src && sdh_pip_install . diff --git a/build/pkgs/bliss/SPKG.rst b/build/pkgs/bliss/SPKG.rst index 77407f16ac7..8abc6975ddf 100644 --- a/build/pkgs/bliss/SPKG.rst +++ b/build/pkgs/bliss/SPKG.rst @@ -23,8 +23,3 @@ https://users.aalto.fi/~tjunttil/bliss/index.html Bliss used to be maintained by Tommi Junttila and Petteri Kaski up to version 0.73 at http://www.tcs.tkk.fi/Software/bliss/index.html - -Dependencies ------------- - -None diff --git a/build/pkgs/bliss/distros/alpine.txt b/build/pkgs/bliss/distros/alpine.txt new file mode 100644 index 00000000000..d90d94bbcc3 --- /dev/null +++ b/build/pkgs/bliss/distros/alpine.txt @@ -0,0 +1 @@ +bliss diff --git a/build/pkgs/bliss/distros/fedora.txt b/build/pkgs/bliss/distros/fedora.txt new file mode 100644 index 00000000000..681ebb3f402 --- /dev/null +++ b/build/pkgs/bliss/distros/fedora.txt @@ -0,0 +1,2 @@ +bliss +bliss-devel diff --git a/build/pkgs/bliss/spkg-configure.m4 b/build/pkgs/bliss/spkg-configure.m4 new file mode 100644 index 00000000000..052d6d1e5e3 --- /dev/null +++ b/build/pkgs/bliss/spkg-configure.m4 @@ -0,0 +1,27 @@ +SAGE_SPKG_CONFIGURE([bliss], [ + m4_pushdef([SAGE_BLISS_MINVER],[0.77]) + m4_pushdef([SAGE_BLISS_MAJOR],[0]) + m4_pushdef([SAGE_BLISS_MINOR],[77]) + AC_CHECK_HEADER([bliss/bliss_C.h], [ + AC_SEARCH_LIBS([bliss_new], [bliss], [ + AC_MSG_CHECKING([checking bliss version directly]) + AC_RUN_IFELSE([AC_LANG_PROGRAM([ + [#include + ]],[[ + if (BLISS_VERSION_MAJOR > ]] SAGE_BLISS_MAJOR [[ ) return 0; + if (BLISS_VERSION_MAJOR == ]] SAGE_BLISS_MAJOR [[ && + BLISS_VERSION_MINOR >= ]] SAGE_BLISS_MINOR [[ ) return 0; + else return 1; + ]])], + [AC_MSG_RESULT([Good.])], + [AC_MSG_RESULT([Too old.]) + sage_spkg_install_bliss=yes], + []) dnl cross-compilation - noop + ], + [sage_spkg_install_bliss=yes]) + ], [sage_spkg_install_bliss=yes]) + m4_popdef([SAGE_BLISS_MINVER]) + m4_popdef([SAGE_BLISS_MAJOR]) + m4_popdef([SAGE_BLISS_MINOR]) +]) + diff --git a/build/pkgs/calver/dependencies b/build/pkgs/calver/dependencies index 0738c2d7777..47296a7bace 100644 --- a/build/pkgs/calver/dependencies +++ b/build/pkgs/calver/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/comm/SPKG.rst b/build/pkgs/comm/SPKG.rst new file mode 100644 index 00000000000..6f0ec348582 --- /dev/null +++ b/build/pkgs/comm/SPKG.rst @@ -0,0 +1,18 @@ +comm: Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc. +================================================================================== + +Description +----------- + +Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc. + +License +------- + +BSD 3-Clause License + +Upstream Contact +---------------- + +https://pypi.org/project/comm/ + diff --git a/build/pkgs/comm/checksums.ini b/build/pkgs/comm/checksums.ini new file mode 100644 index 00000000000..a3c7481f090 --- /dev/null +++ b/build/pkgs/comm/checksums.ini @@ -0,0 +1,5 @@ +tarball=comm-VERSION-py3-none-any.whl +sha1=e7e20f9c1524a9fe059c0b6df90a68e1cd2115a9 +md5=165e29c257c70498b61c7a31916727f2 +cksum=2011044045 +upstream_url=https://pypi.io/packages/py3/c/comm/comm-VERSION-py3-none-any.whl diff --git a/build/pkgs/comm/dependencies b/build/pkgs/comm/dependencies new file mode 100644 index 00000000000..73ec1534907 --- /dev/null +++ b/build/pkgs/comm/dependencies @@ -0,0 +1,4 @@ +traitlets | $(PYTHON_TOOLCHAIN) $(PYTHON) + +---------- +All lines of this file are ignored except the first. diff --git a/build/pkgs/comm/install-requires.txt b/build/pkgs/comm/install-requires.txt new file mode 100644 index 00000000000..9ba1f1eecf4 --- /dev/null +++ b/build/pkgs/comm/install-requires.txt @@ -0,0 +1 @@ +comm diff --git a/build/pkgs/comm/package-version.txt b/build/pkgs/comm/package-version.txt new file mode 100644 index 00000000000..845639eef26 --- /dev/null +++ b/build/pkgs/comm/package-version.txt @@ -0,0 +1 @@ +0.1.4 diff --git a/build/pkgs/comm/type b/build/pkgs/comm/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/comm/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index 98b8d9e6ad5..6fab326e890 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,4 +1,4 @@ tarball=configure-VERSION.tar.gz -sha1=615fc6a4d0eeb9b3dd4bb915c151a631d1979eff -md5=d59860c6efb7274cc16c5cbf2dfc0e3c -cksum=3537541662 +sha1=cba1a107f45084e1884ca8a873504c70eec9c16c +md5=b61e77023581c8994c73313e867a6c26 +cksum=615928275 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index adc514205e8..d124c289596 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -6a5b6c0f934acefeadcdfcfb937092a124c0a09a +9b1e18ffc022a8ed0e7451ccf190a009ceb2d81c diff --git a/build/pkgs/debugpy/checksums.ini b/build/pkgs/debugpy/checksums.ini index 94e60c8de63..43f1c2c84a5 100644 --- a/build/pkgs/debugpy/checksums.ini +++ b/build/pkgs/debugpy/checksums.ini @@ -1,5 +1,5 @@ tarball=debugpy-VERSION.zip -sha1=44ae7bfe2d355990604f83ee4c24eb81631b4433 -md5=a999f81d29db030bfacab544d5fb0976 -cksum=3944616380 +sha1=af611dc5c401424196c27363379fc483814efe26 +md5=b4a6173035b58a0ad61561a4c5017885 +cksum=57995549 upstream_url=https://pypi.io/packages/source/d/debugpy/debugpy-VERSION.zip diff --git a/build/pkgs/debugpy/package-version.txt b/build/pkgs/debugpy/package-version.txt index 266146b87cb..27f9cd322bb 100644 --- a/build/pkgs/debugpy/package-version.txt +++ b/build/pkgs/debugpy/package-version.txt @@ -1 +1 @@ -1.6.3 +1.8.0 diff --git a/build/pkgs/debugpy/type b/build/pkgs/debugpy/type index 134d9bc32d5..a6a7b9cd726 100644 --- a/build/pkgs/debugpy/type +++ b/build/pkgs/debugpy/type @@ -1 +1 @@ -optional +standard diff --git a/build/pkgs/e_antic/dependencies b/build/pkgs/e_antic/dependencies index fea1ffbda45..8e977a55c13 100644 --- a/build/pkgs/e_antic/dependencies +++ b/build/pkgs/e_antic/dependencies @@ -1,4 +1,4 @@ -$(MP_LIBRARY) flint arb antic boost_cropped +$(MP_LIBRARY) flint boost_cropped ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/exceptiongroup/SPKG.rst b/build/pkgs/exceptiongroup/SPKG.rst new file mode 100644 index 00000000000..4fe6e94f57e --- /dev/null +++ b/build/pkgs/exceptiongroup/SPKG.rst @@ -0,0 +1,16 @@ +exceptiongroup: Backport of PEP 654 (exception groups) +====================================================== + +Description +----------- + +Backport of PEP 654 (exception groups) + +License +------- + +Upstream Contact +---------------- + +https://pypi.org/project/exceptiongroup/ + diff --git a/build/pkgs/exceptiongroup/checksums.ini b/build/pkgs/exceptiongroup/checksums.ini new file mode 100644 index 00000000000..1ca0c50d46d --- /dev/null +++ b/build/pkgs/exceptiongroup/checksums.ini @@ -0,0 +1,5 @@ +tarball=exceptiongroup-VERSION-py3-none-any.whl +sha1=e69c438e6d15111c4f7cc18224b31a42a58663da +md5=d252c64173c449dc34654e7be8211744 +cksum=527795480 +upstream_url=https://pypi.io/packages/py3/e/exceptiongroup/exceptiongroup-VERSION-py3-none-any.whl diff --git a/build/pkgs/arb/dependencies b/build/pkgs/exceptiongroup/dependencies similarity index 66% rename from build/pkgs/arb/dependencies rename to build/pkgs/exceptiongroup/dependencies index c95d2836ce5..47296a7bace 100644 --- a/build/pkgs/arb/dependencies +++ b/build/pkgs/exceptiongroup/dependencies @@ -1,4 +1,4 @@ -$(MP_LIBRARY) mpfr flint + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/exceptiongroup/install-requires.txt b/build/pkgs/exceptiongroup/install-requires.txt new file mode 100644 index 00000000000..341183a94c9 --- /dev/null +++ b/build/pkgs/exceptiongroup/install-requires.txt @@ -0,0 +1 @@ +exceptiongroup diff --git a/build/pkgs/exceptiongroup/package-version.txt b/build/pkgs/exceptiongroup/package-version.txt new file mode 100644 index 00000000000..26aaba0e866 --- /dev/null +++ b/build/pkgs/exceptiongroup/package-version.txt @@ -0,0 +1 @@ +1.2.0 diff --git a/build/pkgs/exceptiongroup/type b/build/pkgs/exceptiongroup/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/exceptiongroup/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/flint/SPKG.rst b/build/pkgs/flint/SPKG.rst index f91de70d1ff..d9dcea0903b 100644 --- a/build/pkgs/flint/SPKG.rst +++ b/build/pkgs/flint/SPKG.rst @@ -4,8 +4,8 @@ flint: Fast Library for Number Theory Description ----------- -FLINT is a C library for doing number theory, maintained by William -Hart. +FLINT is a C library for doing number theory, maintained by +Fredrik Johansson. Website: http://www.flintlib.org @@ -20,4 +20,4 @@ Upstream Contact - flint-devel Gougle Group (http://groups.google.co.uk/group/flint-devel) -- William Hart +- Fredrik Johansson diff --git a/build/pkgs/flint/checksums.ini b/build/pkgs/flint/checksums.ini index 3d449d98064..ab836606657 100644 --- a/build/pkgs/flint/checksums.ini +++ b/build/pkgs/flint/checksums.ini @@ -1,5 +1,5 @@ tarball=flint-VERSION.tar.gz -sha1=63d90f8242c8f8ab4011fbcfb44b86c154f43abd -md5=c2d3cec326438f159a530c66eb07fafe -cksum=4244948341 -upstream_url=http://flintlib.org/flint-VERSION.tar.gz +sha1=65be9297c06edd7e24f20874b7bd6130cee56723 +md5=5189f67b0ec12e4a54d6782851642b81 +cksum=172350473 +upstream_url=https://github.com/flintlib/flint/releases/download/vVERSION/flint-VERSION.tar.gz diff --git a/build/pkgs/flint/dependencies b/build/pkgs/flint/dependencies index 385df4faa7d..1108dc4fb21 100644 --- a/build/pkgs/flint/dependencies +++ b/build/pkgs/flint/dependencies @@ -1,4 +1,4 @@ -$(MP_LIBRARY) mpfr ntl +$(MP_LIBRARY) mpfr ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/flint/package-version.txt b/build/pkgs/flint/package-version.txt index c8e38b61405..cb2b00e4f7a 100644 --- a/build/pkgs/flint/package-version.txt +++ b/build/pkgs/flint/package-version.txt @@ -1 +1 @@ -2.9.0 +3.0.1 diff --git a/build/pkgs/flint/patches/0001-Makefile.in-fix-handling-of-DESTDIR.patch b/build/pkgs/flint/patches/0001-Makefile.in-fix-handling-of-DESTDIR.patch new file mode 100644 index 00000000000..48a32f5d894 --- /dev/null +++ b/build/pkgs/flint/patches/0001-Makefile.in-fix-handling-of-DESTDIR.patch @@ -0,0 +1,106 @@ +From 54277f054f13254898c9a57c2c7eb869877e1252 Mon Sep 17 00:00:00 2001 +From: Marc Mezzarobba +Date: Mon, 13 Nov 2023 10:23:54 +0100 +Subject: [PATCH] Makefile.in: fix handling of $DESTDIR + +--- + Makefile.in | 54 ++++++++++++++++++++++++++--------------------------- + 1 file changed, 27 insertions(+), 27 deletions(-) + +diff --git a/Makefile.in b/Makefile.in +index 08db6837c..2827b9da1 100644 +--- a/Makefile.in ++++ b/Makefile.in +@@ -34,9 +34,9 @@ FLINT_SOLIB:=@FLINT_SOLIB@ + prefix:=@prefix@ + exec_prefix:=@exec_prefix@ + +-INCLUDEDIR:=$(DESTDIR)@includedir@ +-LIBDIR:=$(DESTDIR)@libdir@ +-BINDIR:=$(DESTDIR)@bindir@ ++INCLUDEDIR:=@includedir@ ++LIBDIR:=@libdir@ ++BINDIR:=@bindir@ + PKGCONFIGDIR:=$(LIBDIR)/pkgconfig + + HOST_OS:=@host_os@ +@@ -202,10 +202,10 @@ BUILD_DIRS += \ + endif + + INSTALL_DIRS := \ +- $(LIBDIR) $(INCLUDEDIR)/flint \ +- $(PKGCONFIGDIR) ++ $(DESTDIR)$(LIBDIR) $(DESTDIR)$(INCLUDEDIR)/flint \ ++ $(DESTDIR)$(PKGCONFIGDIR) + ifneq ($(FLINT_DLLLIB),0) +-INSTALL_DIRS += $(BINDIR) ++INSTALL_DIRS += $(DESTDIR)$(BINDIR) + endif + + ################################################################################ +@@ -722,41 +722,41 @@ distclean: clean + ################################################################################ + + install: library | $(INSTALL_DIRS) +- $(CP) flint.pc $(PKGCONFIGDIR)/flint.pc ++ $(CP) flint.pc $(DESTDIR)$(PKGCONFIGDIR)/flint.pc + ifneq ($(SHARED), 0) + ifneq ($(FLINT_DLLLIB),0) +- $(CP_A) $(FLINT_DIR)/$(FLINT_LIB) $(BINDIR) +- $(CP_A) $(FLINT_DIR)/$(FLINT_LIB_MAJOR) $(BINDIR) +- $(CP_A) $(FLINT_DIR)/$(FLINT_LIB_FULL) $(BINDIR) +- $(CP) $(FLINT_DIR)/$(FLINT_IMPLIB) $(LIBDIR) ++ $(CP_A) $(FLINT_DIR)/$(FLINT_LIB) $(DESTDIR)$(BINDIR) ++ $(CP_A) $(FLINT_DIR)/$(FLINT_LIB_MAJOR) $(DESTDIR)$(BINDIR) ++ $(CP_A) $(FLINT_DIR)/$(FLINT_LIB_FULL) $(DESTDIR)$(BINDIR) ++ $(CP) $(FLINT_DIR)/$(FLINT_IMPLIB) $(DESTDIR)$(LIBDIR) + else +- $(CP_A) $(FLINT_DIR)/$(FLINT_LIB) $(LIBDIR) +- $(CP_A) $(FLINT_DIR)/$(FLINT_LIB_MAJOR) $(LIBDIR) +- $(CP_A) $(FLINT_DIR)/$(FLINT_LIB_FULL) $(LIBDIR) ++ $(CP_A) $(FLINT_DIR)/$(FLINT_LIB) $(DESTDIR)$(LIBDIR) ++ $(CP_A) $(FLINT_DIR)/$(FLINT_LIB_MAJOR) $(DESTDIR)$(LIBDIR) ++ $(CP_A) $(FLINT_DIR)/$(FLINT_LIB_FULL) $(DESTDIR)$(LIBDIR) + endif + ifneq ($(FLINT_DYLIB),0) +- install_name_tool -id $(LIBDIR)/$(FLINT_LIB_FULL) $(LIBDIR)/$(FLINT_LIB) ++ install_name_tool -id $(LIBDIR)/$(FLINT_LIB_FULL) $(DESTDIR)$(LIBDIR)/$(FLINT_LIB) + endif + endif + ifneq ($(STATIC), 0) +- $(CP) $(FLINT_DIR)/$(FLINT_LIB_STATIC) $(LIBDIR) ++ $(CP) $(FLINT_DIR)/$(FLINT_LIB_STATIC) $(DESTDIR)$(LIBDIR) + endif +- $(CP) $(HEADERS) $(INCLUDEDIR)/flint ++ $(CP) $(HEADERS) $(DESTDIR)$(INCLUDEDIR)/flint + + uninstall: +- $(RM_F) $(PKGCONFIGDIR)/flint.pc ++ $(RM_F) $(DESTDIR)$(PKGCONFIGDIR)/flint.pc + ifneq ($(FLINT_DLLLIB),0) +- $(RM_F) $(BINDIR)/$(FLINT_LIB) +- $(RM_F) $(BINDIR)/$(FLINT_LIB_MAJOR) +- $(RM_F) $(BINDIR)/$(FLINT_LIB_FULL) +- $(RM_F) $(LIBDIR)/$(FLINT_IMPLIB) ++ $(RM_F) $(DESTDIR)$(BINDIR)/$(FLINT_LIB) ++ $(RM_F) $(DESTDIR)$(BINDIR)/$(FLINT_LIB_MAJOR) ++ $(RM_F) $(DESTDIR)$(BINDIR)/$(FLINT_LIB_FULL) ++ $(RM_F) $(DESTDIR)$(LIBDIR)/$(FLINT_IMPLIB) + else +- $(RM_F) $(LIBDIR)/$(FLINT_LIB) +- $(RM_F) $(LIBDIR)/$(FLINT_LIB_MAJOR) +- $(RM_F) $(LIBDIR)/$(FLINT_LIB_FULL) ++ $(RM_F) $(DESTDIR)$(LIBDIR)/$(FLINT_LIB) ++ $(RM_F) $(DESTDIR)$(LIBDIR)/$(FLINT_LIB_MAJOR) ++ $(RM_F) $(DESTDIR)$(LIBDIR)/$(FLINT_LIB_FULL) + endif +- $(RM_F) $(LIBDIR)/$(FLINT_LIB_STATIC) +- $(RM_RF) $(INCLUDEDIR)/flint ++ $(RM_F) $(DESTDIR)$(LIBDIR)/$(FLINT_LIB_STATIC) ++ $(RM_RF) $(DESTDIR)$(INCLUDEDIR)/flint + + ################################################################################ + # maintainer stuff +-- +2.42.0 + diff --git a/build/pkgs/flint/spkg-build.in b/build/pkgs/flint/spkg-build.in new file mode 100644 index 00000000000..ffb822c8a97 --- /dev/null +++ b/build/pkgs/flint/spkg-build.in @@ -0,0 +1,3 @@ +cd src +sdh_configure +sdh_make diff --git a/build/pkgs/flint/spkg-configure.m4 b/build/pkgs/flint/spkg-configure.m4 index a58108c9d6e..9576e4cc1e9 100644 --- a/build/pkgs/flint/spkg-configure.m4 +++ b/build/pkgs/flint/spkg-configure.m4 @@ -1,25 +1,8 @@ SAGE_SPKG_CONFIGURE([flint], [ - SAGE_SPKG_DEPCHECK([mpfr ntl], [ + SAGE_SPKG_DEPCHECK([mpfr], [ AC_CHECK_HEADER(flint/flint.h, [ - dnl flint_parallel_binary_splitting appears in Flint 2.9.0, needed by arb 2.23 - AC_SEARCH_LIBS([flint_parallel_binary_splitting], [flint], [ - dnl check that NTL is linked in - AC_SEARCH_LIBS([fmpz_poly_get_ZZX], [flint], [ - - AC_MSG_CHECKING([that GC is not enabled in Flint... ]) - AC_RUN_IFELSE([ - AC_LANG_PROGRAM([[#include ]], [ - [#ifdef HAVE_GC] - [return HAVE_GC;] - [#else] - [return 0;] - [#endif]])], - [AC_MSG_RESULT([GC not enabled. Good.])], - [AC_MSG_RESULT([GC enabled. Incompatible with Sage.]) - sage_spkg_install_flint=yes], - [AC_MSG_RESULT(["cross compiling. assuming GC is not enabled"])]) - ], [sage_spkg_install_flint=yes]) - ], [sage_spkg_install_flint=yes]) + dnl gr_get_fexpr appears in Flint 3.0 + AC_SEARCH_LIBS([gr_get_fexpr], [flint], [], [sage_spkg_install_flint=yes]) ], [sage_spkg_install_flint=yes]) ]) ], [], [], [ diff --git a/build/pkgs/flint/spkg-install.in b/build/pkgs/flint/spkg-install.in index eacd7b6e491..3ea8c053669 100644 --- a/build/pkgs/flint/spkg-install.in +++ b/build/pkgs/flint/spkg-install.in @@ -1,36 +1,2 @@ -############################################################################### -# -# FLINT Sage install script -# -############################################################################### -if [ "$SAGE_DEBUG" = "yes" ]; then - echo "Building a debug version of FLINT." - FLINT_TUNE=" $FLINT_TUNE"; export FLINT_TUNE - FLINT_CONFIGURE="--enable-assert $FLINT_CONFIGURE" -fi - cd src - -echo "Configuring FLINT." -# Trac #29607: We must always supply --with-gmp, --with-mpfr, -# --with-ntl because otherwise FLINT's configure script uses -# /usr/local, which is always wrong. -# This is why we do not use $SAGE_CONFIGURE_GMP etc. here. -# The value $SAGE_LOCAL is always a safe choice even if the library -# is coming from the system and is found using what is in -# LIBRARY_PATH or LDFLAGS etc. -./configure \ - --disable-static \ - --prefix="$SAGE_LOCAL" \ - --with-gmp="$SAGE_LOCAL" \ - --with-mpfr="$SAGE_LOCAL" \ - --with-ntl="$SAGE_LOCAL" \ - $FLINT_CONFIGURE || sdh_die "Error: Failed to configure FLINT." - -sdh_make verbose - -echo "Deleting old FLINT files." -rm -f $SAGE_LOCAL/lib/libflint* -rm -rf $SAGE_LOCAL/include/flint - sdh_make_install diff --git a/build/pkgs/fqdn/SPKG.rst b/build/pkgs/fqdn/SPKG.rst new file mode 100644 index 00000000000..7b94349b48e --- /dev/null +++ b/build/pkgs/fqdn/SPKG.rst @@ -0,0 +1,18 @@ +fqdn: Validates fully-qualified domain names against RFC 1123, so that they are acceptable to modern bowsers +============================================================================================================ + +Description +----------- + +Validates fully-qualified domain names against RFC 1123, so that they are acceptable to modern bowsers + +License +------- + +MPL 2.0 + +Upstream Contact +---------------- + +https://pypi.org/project/fqdn/ + diff --git a/build/pkgs/fqdn/checksums.ini b/build/pkgs/fqdn/checksums.ini new file mode 100644 index 00000000000..423dc55e68f --- /dev/null +++ b/build/pkgs/fqdn/checksums.ini @@ -0,0 +1,5 @@ +tarball=fqdn-VERSION-py3-none-any.whl +sha1=85a7ac7d7f45d2e0b64c4b7653ab277ceec91ecf +md5=376c19af0cd5029cd8b36d1042a1490e +cksum=4276482151 +upstream_url=https://pypi.io/packages/py3/f/fqdn/fqdn-VERSION-py3-none-any.whl diff --git a/build/pkgs/nodejs/dependencies b/build/pkgs/fqdn/dependencies similarity index 66% rename from build/pkgs/nodejs/dependencies rename to build/pkgs/fqdn/dependencies index a8de0ed1559..47296a7bace 100644 --- a/build/pkgs/nodejs/dependencies +++ b/build/pkgs/fqdn/dependencies @@ -1,4 +1,4 @@ -nodeenv + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/fqdn/install-requires.txt b/build/pkgs/fqdn/install-requires.txt new file mode 100644 index 00000000000..ade5cc3798f --- /dev/null +++ b/build/pkgs/fqdn/install-requires.txt @@ -0,0 +1 @@ +fqdn diff --git a/build/pkgs/fqdn/package-version.txt b/build/pkgs/fqdn/package-version.txt new file mode 100644 index 00000000000..26ca594609a --- /dev/null +++ b/build/pkgs/fqdn/package-version.txt @@ -0,0 +1 @@ +1.5.1 diff --git a/build/pkgs/fqdn/type b/build/pkgs/fqdn/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/fqdn/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/fricas/distros/debian.txt b/build/pkgs/fricas/distros/debian.txt new file mode 100644 index 00000000000..ab59e032f00 --- /dev/null +++ b/build/pkgs/fricas/distros/debian.txt @@ -0,0 +1 @@ +fricas diff --git a/build/pkgs/fricas/distros/freebsd.txt b/build/pkgs/fricas/distros/freebsd.txt new file mode 100644 index 00000000000..75e565427a2 --- /dev/null +++ b/build/pkgs/fricas/distros/freebsd.txt @@ -0,0 +1 @@ +math/fricas diff --git a/build/pkgs/fricas/distros/gentoo.txt b/build/pkgs/fricas/distros/gentoo.txt new file mode 100644 index 00000000000..e6cab7611fc --- /dev/null +++ b/build/pkgs/fricas/distros/gentoo.txt @@ -0,0 +1 @@ +sci-mathematics/fricas diff --git a/build/pkgs/fricas/distros/opensuse.txt b/build/pkgs/fricas/distros/opensuse.txt new file mode 100644 index 00000000000..ab59e032f00 --- /dev/null +++ b/build/pkgs/fricas/distros/opensuse.txt @@ -0,0 +1 @@ +fricas diff --git a/build/pkgs/fricas/spkg-configure.m4 b/build/pkgs/fricas/spkg-configure.m4 new file mode 100644 index 00000000000..905859f6a95 --- /dev/null +++ b/build/pkgs/fricas/spkg-configure.m4 @@ -0,0 +1,16 @@ +SAGE_SPKG_CONFIGURE( + [fricas], [ + AC_CACHE_CHECK([for FriCAS >= 1.3.8], [ac_cv_path_FRICAS], [ + AC_PATH_PROGS_FEATURE_CHECK([FRICAS], [fricas], [ + fricas_version=`echo ")quit" | $ac_path_FRICAS -nox -noclef | grep Version | tail -1 2>&1 \ + | $SED -n -e 's/.* Version: FriCAS //p'` + AS_IF([test -n "$fricas_version"], [ + AX_COMPARE_VERSION([$fricas_version], [ge], [1.3.8], [ + ac_cv_path_FRICAS="$ac_path_FRICAS" + ac_path_FRICAS_found=: + ]) + ]) + ]) + ]) + AS_IF([test -z "$ac_cv_path_FRICAS"], [sage_spkg_install_fricas=yes]) +]) diff --git a/build/pkgs/gmp/spkg-configure.m4 b/build/pkgs/gmp/spkg-configure.m4 index 61d7c5f3b2f..4000200db2c 100644 --- a/build/pkgs/gmp/spkg-configure.m4 +++ b/build/pkgs/gmp/spkg-configure.m4 @@ -2,8 +2,10 @@ SAGE_SPKG_CONFIGURE([gmp], [ sage_spkg_install_gmp=no AC_CHECK_HEADER(gmp.h, [], [sage_spkg_install_gmp=yes]) AC_CHECK_HEADER(gmpxx.h, [], [sage_spkg_install_gmp=yes]) - dnl mpq_cmp_z appeared in GMP 6.1.0 and is used by pynac - AC_SEARCH_LIBS([__gmpq_cmp_z], [gmp], [], + dnl mpn_gcd_11 appeared in GMP 6.2.1 + dnl It is undocumented but is used by Flint when built with default + dnl flags. + AC_SEARCH_LIBS([__gmpn_gcd_11], [gmp], [], [sage_spkg_install_gmp=yes]) ], [], [], [ if test x$sage_spkg_install_gmp = xyes; then diff --git a/build/pkgs/hatch_nodejs_version/SPKG.rst b/build/pkgs/hatch_nodejs_version/SPKG.rst deleted file mode 100644 index 6a1cd5f991c..00000000000 --- a/build/pkgs/hatch_nodejs_version/SPKG.rst +++ /dev/null @@ -1,18 +0,0 @@ -hatch_nodejs_version: Hatch plugin for versioning from a package.json file -========================================================================== - -Description ------------ - -Hatch plugin for versioning from a package.json file - -License -------- - -MIT - -Upstream Contact ----------------- - -https://pypi.org/project/hatch-nodejs-version/ - diff --git a/build/pkgs/hatch_nodejs_version/checksums.ini b/build/pkgs/hatch_nodejs_version/checksums.ini deleted file mode 100644 index bb5f28d0e24..00000000000 --- a/build/pkgs/hatch_nodejs_version/checksums.ini +++ /dev/null @@ -1,5 +0,0 @@ -tarball=hatch_nodejs_version-VERSION.tar.gz -sha1=ce77992d461d5108c481e985250cfb401b4ee5df -md5=6e5f9d5cfa442572637478cacaa8ea81 -cksum=1271494344 -upstream_url=https://pypi.io/packages/source/h/hatch_nodejs_version/hatch_nodejs_version-VERSION.tar.gz diff --git a/build/pkgs/hatch_nodejs_version/install-requires.txt b/build/pkgs/hatch_nodejs_version/install-requires.txt deleted file mode 100644 index 5c606fe80f5..00000000000 --- a/build/pkgs/hatch_nodejs_version/install-requires.txt +++ /dev/null @@ -1 +0,0 @@ -hatch-nodejs-version diff --git a/build/pkgs/hatch_nodejs_version/package-version.txt b/build/pkgs/hatch_nodejs_version/package-version.txt deleted file mode 100644 index 9e11b32fcaa..00000000000 --- a/build/pkgs/hatch_nodejs_version/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -0.3.1 diff --git a/build/pkgs/idna/checksums.ini b/build/pkgs/idna/checksums.ini index 47b585b69cd..d87a004eb57 100644 --- a/build/pkgs/idna/checksums.ini +++ b/build/pkgs/idna/checksums.ini @@ -1,5 +1,5 @@ -tarball=idna-VERSION.tar.gz -sha1=c01a061b5ace87f662049d205d5d15e7f8a3a533 -md5=13ea24e076212b6baae1135a116d1e0e -cksum=1497605198 -upstream_url=https://pypi.io/packages/source/i/idna/idna-VERSION.tar.gz +tarball=idna-VERSION-py3-none-any.whl +sha1=4460f34853efc88e4b14ea5e0e3fa7959b3f0c29 +md5=7ab9782a3a1180cfa1fef20a1c9c166c +cksum=3196216420 +upstream_url=https://pypi.io/packages/py3/i/idna/idna-VERSION-py3-none-any.whl diff --git a/build/pkgs/importlib_resources/checksums.ini b/build/pkgs/importlib_resources/checksums.ini index 5f8bc23a6fd..39040fbf296 100644 --- a/build/pkgs/importlib_resources/checksums.ini +++ b/build/pkgs/importlib_resources/checksums.ini @@ -1,5 +1,5 @@ tarball=importlib_resources-VERSION.tar.gz -sha1=dc5322c0a6414fa823f54ef7fe938210abecd6a8 -md5=ebb549867902e44c9314ac3998e0d31f -cksum=3214105952 +sha1=4af82ed75a1672a45157bfa7d09c4dfd0605802a +md5=525d238db212bdec2df06c0d4b479e73 +cksum=1494471486 upstream_url=https://pypi.io/packages/source/i/importlib_resources/importlib_resources-VERSION.tar.gz diff --git a/build/pkgs/importlib_resources/package-version.txt b/build/pkgs/importlib_resources/package-version.txt index 5fe60723048..dfda3e0b4f0 100644 --- a/build/pkgs/importlib_resources/package-version.txt +++ b/build/pkgs/importlib_resources/package-version.txt @@ -1 +1 @@ -6.0.1 +6.1.0 diff --git a/build/pkgs/ipykernel/checksums.ini b/build/pkgs/ipykernel/checksums.ini index bf5d60330a7..3eaa681a507 100644 --- a/build/pkgs/ipykernel/checksums.ini +++ b/build/pkgs/ipykernel/checksums.ini @@ -1,5 +1,5 @@ tarball=ipykernel-VERSION.tar.gz -sha1=5a5cf7f8c0c02d0c0cc5fe3e0fe7481a86de6552 -md5=f940975eb00de793695c386ad3a8800c -cksum=597841676 -upstream_url=https://files.pythonhosted.org/packages/60/30/cf3867ce0dee0a7230ec5eb85232136c3875688816ad355a7b65f4f4e8ef/ipykernel-6.6.0.tar.gz +sha1=88c5159bb5caba780383f00fceebb4cce80f96b5 +md5=9a5a3ded6795afecfe55c74f9f77307d +cksum=3205929883 +upstream_url=https://pypi.io/packages/source/i/ipykernel/ipykernel-VERSION.tar.gz diff --git a/build/pkgs/ipykernel/dependencies b/build/pkgs/ipykernel/dependencies index 7e153a0cb46..000e4aafb66 100644 --- a/build/pkgs/ipykernel/dependencies +++ b/build/pkgs/ipykernel/dependencies @@ -1,4 +1,4 @@ - ipython_genutils importlib_metadata matplotlib_inline ipython jupyter_client tornado appnope traitlets executing | $(PYTHON_TOOLCHAIN) $(PYTHON) +debugpy ipython comm traitlets jupyter_client jupyter_core nest_asyncio tornado matplotlib_inline appnope pyzmq psutil packaging | $(PYTHON_TOOLCHAIN) hatchling $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/ipykernel/package-version.txt b/build/pkgs/ipykernel/package-version.txt index 826f5ce030e..9cd1a39f656 100644 --- a/build/pkgs/ipykernel/package-version.txt +++ b/build/pkgs/ipykernel/package-version.txt @@ -1 +1 @@ -6.6.0 +6.27.0 diff --git a/build/pkgs/ipykernel/patches/debugpy-make-optional.patch b/build/pkgs/ipykernel/patches/debugpy-make-optional.patch deleted file mode 100644 index 308e4dd26f9..00000000000 --- a/build/pkgs/ipykernel/patches/debugpy-make-optional.patch +++ /dev/null @@ -1,21 +0,0 @@ ---- a/pyproject.toml 2021-12-01 10:23:30.000000000 -0300 -+++ b/pyproject.toml 2021-12-13 18:01:36.239921204 -0300 -@@ -3,7 +3,6 @@ - requires=[ - "setuptools", - "wheel", -- "debugpy", - "ipython>=5", - "jupyter_core>=4.2", - "jupyter_client", -diff -ruN a/setup.py b/setup.py ---- a/setup.py 2021-12-01 10:23:09.000000000 -0300 -+++ b/setup.py 2021-12-13 18:01:40.112873823 -0300 -@@ -63,7 +63,6 @@ - install_requires=[ - 'importlib-metadata<5;python_version<"3.8.0"', - 'argcomplete>=1.12.3;python_version<"3.8.0"', -- 'debugpy>=1.0.0,<2.0', - 'ipython>=7.23.1', - 'traitlets>=5.1.0,<6.0', - 'jupyter_client<8.0', diff --git a/build/pkgs/ipympl/type b/build/pkgs/ipympl/type index 134d9bc32d5..a6a7b9cd726 100644 --- a/build/pkgs/ipympl/type +++ b/build/pkgs/ipympl/type @@ -1 +1 @@ -optional +standard diff --git a/build/pkgs/ipython/checksums.ini b/build/pkgs/ipython/checksums.ini index a539eb830b4..3b0a8df72dd 100644 --- a/build/pkgs/ipython/checksums.ini +++ b/build/pkgs/ipython/checksums.ini @@ -1,5 +1,5 @@ tarball=ipython-VERSION.tar.gz -sha1=e0dd247f29befed1159d9bdca987d90c2ee0d34a -md5=8c98f6def0622ea32975cb779247c3d7 -cksum=2860792697 +sha1=62afbe2e62e713ee89bfe5303809bdcd2affb2a3 +md5=ac2ff5bad97aa09befdf7f0f27323699 +cksum=413345511 upstream_url=https://pypi.io/packages/source/i/ipython/ipython-VERSION.tar.gz diff --git a/build/pkgs/ipython/dependencies b/build/pkgs/ipython/dependencies index cc719ef4ea5..b00056b1a63 100644 --- a/build/pkgs/ipython/dependencies +++ b/build/pkgs/ipython/dependencies @@ -1,4 +1,4 @@ -tornado pyzmq pickleshare traitlets decorator wcwidth prompt_toolkit pygments pexpect appnope backcall jedi stack_data | $(PYTHON_TOOLCHAIN) $(PYTHON) +tornado pyzmq pickleshare traitlets decorator wcwidth prompt_toolkit pygments pexpect appnope backcall jedi stack_data exceptiongroup | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/ipython/install-requires.txt b/build/pkgs/ipython/install-requires.txt index 03d4a4f3413..a52df49c421 100644 --- a/build/pkgs/ipython/install-requires.txt +++ b/build/pkgs/ipython/install-requires.txt @@ -1,2 +1 @@ -ipython >=7.13.0, <8.9.0 -# ipython >= 8.9.0 requires prompt_toolkit too new for Sage +ipython >=7.13.0 diff --git a/build/pkgs/ipython/package-version.txt b/build/pkgs/ipython/package-version.txt index acd405b1d62..86487fdd0f7 100644 --- a/build/pkgs/ipython/package-version.txt +++ b/build/pkgs/ipython/package-version.txt @@ -1 +1 @@ -8.6.0 +8.17.2 diff --git a/build/pkgs/ipywidgets/checksums.ini b/build/pkgs/ipywidgets/checksums.ini index 63a890dcf81..a04080bb509 100644 --- a/build/pkgs/ipywidgets/checksums.ini +++ b/build/pkgs/ipywidgets/checksums.ini @@ -1,5 +1,5 @@ tarball=ipywidgets-VERSION.tar.gz -sha1=b2c8adf4fefc012adfb61e03a2e957bddbbb7597 -md5=c976de164b782eac9e5dfc933e8da295 -cksum=305610881 +sha1=95f7ec13e8ce75e2da40c1789b4af291946a6d99 +md5=2809d1668037606caac588cab329bece +cksum=1839869422 upstream_url=https://pypi.io/packages/source/i/ipywidgets/ipywidgets-VERSION.tar.gz diff --git a/build/pkgs/ipywidgets/dependencies b/build/pkgs/ipywidgets/dependencies index bcb4e030b7d..75467c6fdb0 100644 --- a/build/pkgs/ipywidgets/dependencies +++ b/build/pkgs/ipywidgets/dependencies @@ -1,4 +1,4 @@ - widgetsnbextension jupyterlab_widgets | $(PYTHON_TOOLCHAIN) ipykernel ipython traitlets $(PYTHON) +widgetsnbextension jupyterlab_widgets comm ipykernel ipython traitlets | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/ipywidgets/package-version.txt b/build/pkgs/ipywidgets/package-version.txt index 8b22a322d0f..0e79152459e 100644 --- a/build/pkgs/ipywidgets/package-version.txt +++ b/build/pkgs/ipywidgets/package-version.txt @@ -1 +1 @@ -8.0.2 +8.1.1 diff --git a/build/pkgs/isoduration/SPKG.rst b/build/pkgs/isoduration/SPKG.rst new file mode 100644 index 00000000000..413f8239948 --- /dev/null +++ b/build/pkgs/isoduration/SPKG.rst @@ -0,0 +1,16 @@ +isoduration: Operations with ISO 8601 durations +=============================================== + +Description +----------- + +Operations with ISO 8601 durations + +License +------- + +Upstream Contact +---------------- + +https://pypi.org/project/isoduration/ + diff --git a/build/pkgs/isoduration/checksums.ini b/build/pkgs/isoduration/checksums.ini new file mode 100644 index 00000000000..490fd21be52 --- /dev/null +++ b/build/pkgs/isoduration/checksums.ini @@ -0,0 +1,5 @@ +tarball=isoduration-VERSION-py3-none-any.whl +sha1=a113878d368fee6881efcfd12421b12f8e6ae11c +md5=c5f76c264bf80cca84b99c48d8af5afb +cksum=3373220361 +upstream_url=https://pypi.io/packages/py3/i/isoduration/isoduration-VERSION-py3-none-any.whl diff --git a/build/pkgs/nodeenv/dependencies b/build/pkgs/isoduration/dependencies similarity index 61% rename from build/pkgs/nodeenv/dependencies rename to build/pkgs/isoduration/dependencies index 04eff0c842c..e928cdc6089 100644 --- a/build/pkgs/nodeenv/dependencies +++ b/build/pkgs/isoduration/dependencies @@ -1,4 +1,4 @@ - | $(PYTHON_TOOLCHAIN) certifi $(PYTHON) +$(PYTHON) arrow | $(PYTHON_TOOLCHAIN) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/isoduration/install-requires.txt b/build/pkgs/isoduration/install-requires.txt new file mode 100644 index 00000000000..05836d3c935 --- /dev/null +++ b/build/pkgs/isoduration/install-requires.txt @@ -0,0 +1 @@ +isoduration diff --git a/build/pkgs/isoduration/package-version.txt b/build/pkgs/isoduration/package-version.txt new file mode 100644 index 00000000000..8b0beab16a5 --- /dev/null +++ b/build/pkgs/isoduration/package-version.txt @@ -0,0 +1 @@ +20.11.0 diff --git a/build/pkgs/isoduration/type b/build/pkgs/isoduration/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/isoduration/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/jedi/checksums.ini b/build/pkgs/jedi/checksums.ini index 2db629c8d82..291cf130faf 100644 --- a/build/pkgs/jedi/checksums.ini +++ b/build/pkgs/jedi/checksums.ini @@ -1,5 +1,5 @@ tarball=jedi-VERSION.tar.gz -sha1=e94444bd83b55247fd1f3d27d47cc0b148560134 -md5=d8dba4a98a35530f7f5b461c20aff180 -cksum=4093067035 +sha1=07d1e04c24cecf1b7f38f8905ce81c006f76cc20 +md5=0951191b506b660bfdb90c3dcd5b3254 +cksum=8256815 upstream_url=https://pypi.io/packages/source/j/jedi/jedi-VERSION.tar.gz diff --git a/build/pkgs/jedi/package-version.txt b/build/pkgs/jedi/package-version.txt index 249afd517d9..41915c79947 100644 --- a/build/pkgs/jedi/package-version.txt +++ b/build/pkgs/jedi/package-version.txt @@ -1 +1 @@ -0.18.1 +0.19.1 diff --git a/build/pkgs/json5/SPKG.rst b/build/pkgs/json5/SPKG.rst new file mode 100644 index 00000000000..5f85e534785 --- /dev/null +++ b/build/pkgs/json5/SPKG.rst @@ -0,0 +1,18 @@ +json5: A Python implementation of the JSON5 data format. +======================================================== + +Description +----------- + +A Python implementation of the JSON5 data format. + +License +------- + +Apache + +Upstream Contact +---------------- + +https://pypi.org/project/json5/ + diff --git a/build/pkgs/json5/checksums.ini b/build/pkgs/json5/checksums.ini new file mode 100644 index 00000000000..5e05994b435 --- /dev/null +++ b/build/pkgs/json5/checksums.ini @@ -0,0 +1,5 @@ +tarball=json5-VERSION-py2.py3-none-any.whl +sha1=54bf91b9c2812e82ccd212cefca5bc5607a538b4 +md5=aede9af2a42cc0cd928e4dc99e9a6a45 +cksum=134804175 +upstream_url=https://pypi.io/packages/py2.py3/j/json5/json5-VERSION-py2.py3-none-any.whl diff --git a/build/pkgs/antic/dependencies b/build/pkgs/json5/dependencies similarity index 66% rename from build/pkgs/antic/dependencies rename to build/pkgs/json5/dependencies index c95d2836ce5..47296a7bace 100644 --- a/build/pkgs/antic/dependencies +++ b/build/pkgs/json5/dependencies @@ -1,4 +1,4 @@ -$(MP_LIBRARY) mpfr flint + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/json5/install-requires.txt b/build/pkgs/json5/install-requires.txt new file mode 100644 index 00000000000..8c1150297b3 --- /dev/null +++ b/build/pkgs/json5/install-requires.txt @@ -0,0 +1 @@ +json5 diff --git a/build/pkgs/json5/package-version.txt b/build/pkgs/json5/package-version.txt new file mode 100644 index 00000000000..6d44d227cf9 --- /dev/null +++ b/build/pkgs/json5/package-version.txt @@ -0,0 +1 @@ +0.9.14 diff --git a/build/pkgs/json5/type b/build/pkgs/json5/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/json5/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/jsonpointer/SPKG.rst b/build/pkgs/jsonpointer/SPKG.rst new file mode 100644 index 00000000000..60a89995b2a --- /dev/null +++ b/build/pkgs/jsonpointer/SPKG.rst @@ -0,0 +1,18 @@ +jsonpointer: Identify specific nodes in a JSON document (RFC 6901) +================================================================== + +Description +----------- + +Identify specific nodes in a JSON document (RFC 6901) + +License +------- + +Modified BSD License + +Upstream Contact +---------------- + +https://pypi.org/project/jsonpointer/ + diff --git a/build/pkgs/jsonpointer/checksums.ini b/build/pkgs/jsonpointer/checksums.ini new file mode 100644 index 00000000000..67173595af5 --- /dev/null +++ b/build/pkgs/jsonpointer/checksums.ini @@ -0,0 +1,5 @@ +tarball=jsonpointer-VERSION-py2.py3-none-any.whl +sha1=de1b07c2d014f5b8e672cf0fb1225b2232d0b414 +md5=eb9dcb8c4ccf5d97cea88a7d13510032 +cksum=1224177904 +upstream_url=https://pypi.io/packages/py2.py3/j/jsonpointer/jsonpointer-VERSION-py2.py3-none-any.whl diff --git a/build/pkgs/jsonpointer/dependencies b/build/pkgs/jsonpointer/dependencies new file mode 100644 index 00000000000..47296a7bace --- /dev/null +++ b/build/pkgs/jsonpointer/dependencies @@ -0,0 +1,4 @@ + | $(PYTHON_TOOLCHAIN) $(PYTHON) + +---------- +All lines of this file are ignored except the first. diff --git a/build/pkgs/jsonpointer/install-requires.txt b/build/pkgs/jsonpointer/install-requires.txt new file mode 100644 index 00000000000..5d437553666 --- /dev/null +++ b/build/pkgs/jsonpointer/install-requires.txt @@ -0,0 +1 @@ +jsonpointer diff --git a/build/pkgs/jsonpointer/package-version.txt b/build/pkgs/jsonpointer/package-version.txt new file mode 100644 index 00000000000..6b4950e3de2 --- /dev/null +++ b/build/pkgs/jsonpointer/package-version.txt @@ -0,0 +1 @@ +2.4 diff --git a/build/pkgs/jsonpointer/type b/build/pkgs/jsonpointer/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/jsonpointer/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/jsonschema/checksums.ini b/build/pkgs/jsonschema/checksums.ini index 5a214ae38fc..e2b4c0ecb27 100644 --- a/build/pkgs/jsonschema/checksums.ini +++ b/build/pkgs/jsonschema/checksums.ini @@ -1,5 +1,5 @@ tarball=jsonschema-VERSION.tar.gz -sha1=ccea159a8a0c453e6fbbcfd7bb681b1bc766500e -md5=527bc4d51d31e8d0b8a0d833b6a50002 -cksum=1885537635 +sha1=9f762c6c2b92defddf1c441cce8132d021252b2c +md5=7c65ceb8923c83cb1f22c2b5a86d99b0 +cksum=2329321415 upstream_url=https://pypi.io/packages/source/j/jsonschema/jsonschema-VERSION.tar.gz diff --git a/build/pkgs/jsonschema/dependencies b/build/pkgs/jsonschema/dependencies index d0211604157..1a62386aa97 100644 --- a/build/pkgs/jsonschema/dependencies +++ b/build/pkgs/jsonschema/dependencies @@ -1,4 +1,4 @@ - vcversioner attrs importlib_metadata pyrsistent | $(PYTHON_TOOLCHAIN) hatchling hatch_vcs hatch_fancy_pypi_readme $(PYTHON) +jsonschema_specifications pyrsistent attrs importlib_metadata fqdn isoduration jsonpointer uri_template webcolors | $(PYTHON_TOOLCHAIN) hatchling hatch_vcs hatch_fancy_pypi_readme $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/jsonschema/package-version.txt b/build/pkgs/jsonschema/package-version.txt index 1b0a87fdfc9..ab268c2099f 100644 --- a/build/pkgs/jsonschema/package-version.txt +++ b/build/pkgs/jsonschema/package-version.txt @@ -1 +1 @@ -4.17.1 +4.17.3 diff --git a/build/pkgs/jsonschema_specifications/SPKG.rst b/build/pkgs/jsonschema_specifications/SPKG.rst new file mode 100644 index 00000000000..0765571207d --- /dev/null +++ b/build/pkgs/jsonschema_specifications/SPKG.rst @@ -0,0 +1,18 @@ +jsonschema_specifications: The JSON Schema meta-schemas and vocabularies, exposed as a Registry +=============================================================================================== + +Description +----------- + +The JSON Schema meta-schemas and vocabularies, exposed as a Registry + +License +------- + +MIT + +Upstream Contact +---------------- + +https://pypi.org/project/jsonschema-specifications/ + diff --git a/build/pkgs/jsonschema_specifications/checksums.ini b/build/pkgs/jsonschema_specifications/checksums.ini new file mode 100644 index 00000000000..b0a51d9b7b4 --- /dev/null +++ b/build/pkgs/jsonschema_specifications/checksums.ini @@ -0,0 +1,5 @@ +tarball=jsonschema_specifications-VERSION-py3-none-any.whl +sha1=4132bed31478bc96960099e58ae4c083c514c551 +md5=dbd17550f666e0f9aa74270d0d4e97a3 +cksum=135654159 +upstream_url=https://pypi.io/packages/py3/j/jsonschema_specifications/jsonschema_specifications-VERSION-py3-none-any.whl diff --git a/build/pkgs/jsonschema_specifications/dependencies b/build/pkgs/jsonschema_specifications/dependencies new file mode 100644 index 00000000000..19f2b856671 --- /dev/null +++ b/build/pkgs/jsonschema_specifications/dependencies @@ -0,0 +1,4 @@ + referencing | $(PYTHON_TOOLCHAIN) $(PYTHON) + +---------- +All lines of this file are ignored except the first. diff --git a/build/pkgs/jsonschema_specifications/install-requires.txt b/build/pkgs/jsonschema_specifications/install-requires.txt new file mode 100644 index 00000000000..db1f1fad885 --- /dev/null +++ b/build/pkgs/jsonschema_specifications/install-requires.txt @@ -0,0 +1 @@ +jsonschema-specifications diff --git a/build/pkgs/jsonschema_specifications/package-version.txt b/build/pkgs/jsonschema_specifications/package-version.txt new file mode 100644 index 00000000000..5fe615f731b --- /dev/null +++ b/build/pkgs/jsonschema_specifications/package-version.txt @@ -0,0 +1 @@ +2023.3.3 diff --git a/build/pkgs/jsonschema_specifications/type b/build/pkgs/jsonschema_specifications/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/jsonschema_specifications/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/jupyter_client/SPKG.rst b/build/pkgs/jupyter_client/SPKG.rst index 3c25d65afff..9b1bb3b235a 100644 --- a/build/pkgs/jupyter_client/SPKG.rst +++ b/build/pkgs/jupyter_client/SPKG.rst @@ -4,9 +4,15 @@ jupyter_client: Jupyter protocol implementation and client libraries Description ----------- -jupyter_client contains the reference implementation of the Jupyter -protocol. It also provides client and kernel management APIs for working -with kernels. +Jupyter protocol implementation and client libraries + +License +------- + +BSD 3-Clause License + +Upstream Contact +---------------- + +https://pypi.org/project/jupyter-client/ -It also provides the jupyter kernelspec entrypoint for installing -kernelspecs for use with Jupyter frontends. diff --git a/build/pkgs/jupyter_client/checksums.ini b/build/pkgs/jupyter_client/checksums.ini index 7e31fb35fc6..b91837ba332 100644 --- a/build/pkgs/jupyter_client/checksums.ini +++ b/build/pkgs/jupyter_client/checksums.ini @@ -1,5 +1,5 @@ -tarball=jupyter_client-VERSION.tar.gz -sha1=0a9446eda476e3614d4509db0646ae5a89f6b492 -md5=481db492a8a0d16022c49481438e6285 -cksum=3316985535 -upstream_url=https://pypi.io/packages/source/j/jupyter_client/jupyter_client-VERSION.tar.gz +tarball=jupyter_client-VERSION-py3-none-any.whl +sha1=341f822626b55b53f03a21a44d78dc203472406b +md5=cca418dacc69d69f3e3c71704f1fd259 +cksum=753481733 +upstream_url=https://pypi.io/packages/py3/j/jupyter_client/jupyter_client-VERSION-py3-none-any.whl diff --git a/build/pkgs/jupyter_client/dependencies b/build/pkgs/jupyter_client/dependencies index dcc8c256fad..3818d456c82 100644 --- a/build/pkgs/jupyter_client/dependencies +++ b/build/pkgs/jupyter_client/dependencies @@ -1,4 +1,4 @@ - jupyter_core | $(PYTHON_TOOLCHAIN) pyzmq dateutil nest_asyncio tornado traitlets entrypoints hatchling $(PYTHON) + jupyter_core pyzmq dateutil tornado traitlets importlib_metadata | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/jupyter_client/install-requires.txt b/build/pkgs/jupyter_client/install-requires.txt index db02ea315bb..d1eb6b530b3 100644 --- a/build/pkgs/jupyter_client/install-requires.txt +++ b/build/pkgs/jupyter_client/install-requires.txt @@ -1 +1 @@ -jupyter_client >=6.1.6 +jupyter-client diff --git a/build/pkgs/jupyter_client/package-version.txt b/build/pkgs/jupyter_client/package-version.txt index 4e61aeef901..56b6be4ebb2 100644 --- a/build/pkgs/jupyter_client/package-version.txt +++ b/build/pkgs/jupyter_client/package-version.txt @@ -1 +1 @@ -7.4.4 +8.3.1 diff --git a/build/pkgs/jupyter_client/spkg-install.in b/build/pkgs/jupyter_client/spkg-install.in deleted file mode 100644 index deba1bb42bb..00000000000 --- a/build/pkgs/jupyter_client/spkg-install.in +++ /dev/null @@ -1 +0,0 @@ -cd src && sdh_pip_install . diff --git a/build/pkgs/jupyter_core/checksums.ini b/build/pkgs/jupyter_core/checksums.ini index 3e45d122068..0c807beeff7 100644 --- a/build/pkgs/jupyter_core/checksums.ini +++ b/build/pkgs/jupyter_core/checksums.ini @@ -1,5 +1,5 @@ tarball=jupyter_core-VERSION.tar.gz -sha1=2a0a14c4c1624826100d59169636bb588465deb9 -md5=7586526dd4ca9d1bc820a4a5429df48b -cksum=1776144013 +sha1=0fe33e3247e595cdb83e2220f02c566ea9397e6a +md5=1d61b3c16f6781d8f44e1bd95cd8e73f +cksum=523684111 upstream_url=https://pypi.io/packages/source/j/jupyter_core/jupyter_core-VERSION.tar.gz diff --git a/build/pkgs/jupyter_core/dependencies b/build/pkgs/jupyter_core/dependencies index a312196cbed..7099b915818 100644 --- a/build/pkgs/jupyter_core/dependencies +++ b/build/pkgs/jupyter_core/dependencies @@ -1,4 +1,4 @@ - traitlets | $(PYTHON_TOOLCHAIN) hatchling $(PYTHON) +platformdirs traitlets | $(PYTHON_TOOLCHAIN) hatchling $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/jupyter_core/package-version.txt b/build/pkgs/jupyter_core/package-version.txt index 815588ef140..84197c89467 100644 --- a/build/pkgs/jupyter_core/package-version.txt +++ b/build/pkgs/jupyter_core/package-version.txt @@ -1 +1 @@ -4.12.0 +5.3.2 diff --git a/build/pkgs/jupyter_events/SPKG.rst b/build/pkgs/jupyter_events/SPKG.rst new file mode 100644 index 00000000000..760f6035e04 --- /dev/null +++ b/build/pkgs/jupyter_events/SPKG.rst @@ -0,0 +1,18 @@ +jupyter_events: Jupyter Event System library +============================================ + +Description +----------- + +Jupyter Event System library + +License +------- + +BSD 3-Clause License + +Upstream Contact +---------------- + +https://pypi.org/project/jupyter-events/ + diff --git a/build/pkgs/jupyter_events/checksums.ini b/build/pkgs/jupyter_events/checksums.ini new file mode 100644 index 00000000000..b0721f150a1 --- /dev/null +++ b/build/pkgs/jupyter_events/checksums.ini @@ -0,0 +1,5 @@ +tarball=jupyter_events-VERSION-py3-none-any.whl +sha1=1b3fd8c003ea9e51b0f2d38daa89fded161767f7 +md5=c29e5cb7f9f1b3916b2d9d416b470294 +cksum=2851951719 +upstream_url=https://pypi.io/packages/py3/j/jupyter_events/jupyter_events-VERSION-py3-none-any.whl diff --git a/build/pkgs/jupyter_events/dependencies b/build/pkgs/jupyter_events/dependencies new file mode 100644 index 00000000000..f82f8a9adba --- /dev/null +++ b/build/pkgs/jupyter_events/dependencies @@ -0,0 +1,4 @@ +jsonschema python_json_logger pyyaml referencing rfc3339_validator rfc3986_validator | $(PYTHON_TOOLCHAIN) $(PYTHON) + +---------- +All lines of this file are ignored except the first. diff --git a/build/pkgs/jupyter_events/install-requires.txt b/build/pkgs/jupyter_events/install-requires.txt new file mode 100644 index 00000000000..e31af18cf10 --- /dev/null +++ b/build/pkgs/jupyter_events/install-requires.txt @@ -0,0 +1 @@ +jupyter-events diff --git a/build/pkgs/jupyter_events/package-version.txt b/build/pkgs/jupyter_events/package-version.txt new file mode 100644 index 00000000000..844f6a91acb --- /dev/null +++ b/build/pkgs/jupyter_events/package-version.txt @@ -0,0 +1 @@ +0.6.3 diff --git a/build/pkgs/jupyter_events/type b/build/pkgs/jupyter_events/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/jupyter_events/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/jupyter_lsp/SPKG.rst b/build/pkgs/jupyter_lsp/SPKG.rst new file mode 100644 index 00000000000..ec6e3bf4e03 --- /dev/null +++ b/build/pkgs/jupyter_lsp/SPKG.rst @@ -0,0 +1,18 @@ +jupyter_lsp: Multi-Language Server WebSocket proxy for Jupyter Notebook/Lab server +================================================================================== + +Description +----------- + +Multi-Language Server WebSocket proxy for Jupyter Notebook/Lab server + +License +------- + +BSD-3-Clause + +Upstream Contact +---------------- + +https://pypi.org/project/jupyter-lsp/ + diff --git a/build/pkgs/jupyter_lsp/checksums.ini b/build/pkgs/jupyter_lsp/checksums.ini new file mode 100644 index 00000000000..0e0a2cbf90e --- /dev/null +++ b/build/pkgs/jupyter_lsp/checksums.ini @@ -0,0 +1,5 @@ +tarball=jupyter_lsp-VERSION-py3-none-any.whl +sha1=0f7a63d99c5cf624315583099f00eafc4b996b59 +md5=9c17daaa4372bffca936c1b6977e713b +cksum=1933820697 +upstream_url=https://pypi.io/packages/py3/j/jupyter_lsp/jupyter_lsp-VERSION-py3-none-any.whl diff --git a/build/pkgs/jupyter_lsp/dependencies b/build/pkgs/jupyter_lsp/dependencies new file mode 100644 index 00000000000..97d97af24c5 --- /dev/null +++ b/build/pkgs/jupyter_lsp/dependencies @@ -0,0 +1,4 @@ +jupyter_server | $(PYTHON_TOOLCHAIN) $(PYTHON) + +---------- +All lines of this file are ignored except the first. diff --git a/build/pkgs/jupyter_lsp/install-requires.txt b/build/pkgs/jupyter_lsp/install-requires.txt new file mode 100644 index 00000000000..367c01e01a1 --- /dev/null +++ b/build/pkgs/jupyter_lsp/install-requires.txt @@ -0,0 +1 @@ +jupyter-lsp diff --git a/build/pkgs/jupyter_lsp/package-version.txt b/build/pkgs/jupyter_lsp/package-version.txt new file mode 100644 index 00000000000..ccbccc3dc62 --- /dev/null +++ b/build/pkgs/jupyter_lsp/package-version.txt @@ -0,0 +1 @@ +2.2.0 diff --git a/build/pkgs/jupyter_lsp/type b/build/pkgs/jupyter_lsp/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/jupyter_lsp/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/jupyter_server/SPKG.rst b/build/pkgs/jupyter_server/SPKG.rst new file mode 100644 index 00000000000..19c144f9a8e --- /dev/null +++ b/build/pkgs/jupyter_server/SPKG.rst @@ -0,0 +1,18 @@ +jupyter_server: The backend (core services, APIs, REST endpoints) to Jupyter web applications +============================================================================================= + +Description +----------- + +The backend, i.e., core services, APIs, and REST endpoints, to Jupyter web applications. + +License +------- + +BSD 3-Clause License + +Upstream Contact +---------------- + +https://pypi.org/project/jupyter-server/ + diff --git a/build/pkgs/jupyter_server/checksums.ini b/build/pkgs/jupyter_server/checksums.ini new file mode 100644 index 00000000000..e81f1110be3 --- /dev/null +++ b/build/pkgs/jupyter_server/checksums.ini @@ -0,0 +1,5 @@ +tarball=jupyter_server-VERSION-py3-none-any.whl +sha1=a54aa7f6f1657a55cae9ecc4a6654b6e3ca5fb73 +md5=b028711b35fa80f6c7b01a54bd70718a +cksum=1159424906 +upstream_url=https://pypi.io/packages/py3/j/jupyter_server/jupyter_server-VERSION-py3-none-any.whl diff --git a/build/pkgs/jupyter_server/dependencies b/build/pkgs/jupyter_server/dependencies new file mode 100644 index 00000000000..2b81efb7a64 --- /dev/null +++ b/build/pkgs/jupyter_server/dependencies @@ -0,0 +1,4 @@ +anyio argon2_cffi jinja2 jupyter_client jupyter_core jupyter_events jupyter_server_terminals nbconvert nbformat overrides platformdirs prometheus_client pyzmq send2trash terminado tornado traitlets websocket_client | $(PYTHON_TOOLCHAIN) $(PYTHON) + +---------- +All lines of this file are ignored except the first. diff --git a/build/pkgs/jupyter_server/install-requires.txt b/build/pkgs/jupyter_server/install-requires.txt new file mode 100644 index 00000000000..72a770c947c --- /dev/null +++ b/build/pkgs/jupyter_server/install-requires.txt @@ -0,0 +1 @@ +jupyter-server diff --git a/build/pkgs/jupyter_server/package-version.txt b/build/pkgs/jupyter_server/package-version.txt new file mode 100644 index 00000000000..2c9b4ef42ec --- /dev/null +++ b/build/pkgs/jupyter_server/package-version.txt @@ -0,0 +1 @@ +2.7.3 diff --git a/build/pkgs/jupyter_server/type b/build/pkgs/jupyter_server/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/jupyter_server/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/jupyter_server_terminals/SPKG.rst b/build/pkgs/jupyter_server_terminals/SPKG.rst new file mode 100644 index 00000000000..6624c35d243 --- /dev/null +++ b/build/pkgs/jupyter_server_terminals/SPKG.rst @@ -0,0 +1,18 @@ +jupyter_server_terminals: A Jupyter Server Extension Providing Terminals +======================================================================== + +Description +----------- + +A Jupyter Server Extension Providing Terminals. + +License +------- + +Modified BSD License (also known as New or Revised or 3-Clause BSD) + +Upstream Contact +---------------- + +https://pypi.org/project/jupyter-server-terminals/ + diff --git a/build/pkgs/jupyter_server_terminals/checksums.ini b/build/pkgs/jupyter_server_terminals/checksums.ini new file mode 100644 index 00000000000..99f9ede51e0 --- /dev/null +++ b/build/pkgs/jupyter_server_terminals/checksums.ini @@ -0,0 +1,5 @@ +tarball=jupyter_server_terminals-VERSION-py3-none-any.whl +sha1=fd1201e9f0064b2a5a05ed7346dfe52546f13b0b +md5=6312ef2342aa944aaa59619249d7248b +cksum=2312769383 +upstream_url=https://pypi.io/packages/py3/j/jupyter_server_terminals/jupyter_server_terminals-VERSION-py3-none-any.whl diff --git a/build/pkgs/jupyter_server_terminals/dependencies b/build/pkgs/jupyter_server_terminals/dependencies new file mode 100644 index 00000000000..6aedae84479 --- /dev/null +++ b/build/pkgs/jupyter_server_terminals/dependencies @@ -0,0 +1,4 @@ +terminado | $(PYTHON_TOOLCHAIN) $(PYTHON) + +---------- +All lines of this file are ignored except the first. diff --git a/build/pkgs/jupyter_server_terminals/install-requires.txt b/build/pkgs/jupyter_server_terminals/install-requires.txt new file mode 100644 index 00000000000..7841d7c9a9b --- /dev/null +++ b/build/pkgs/jupyter_server_terminals/install-requires.txt @@ -0,0 +1 @@ +jupyter-server-terminals diff --git a/build/pkgs/jupyter_server_terminals/package-version.txt b/build/pkgs/jupyter_server_terminals/package-version.txt new file mode 100644 index 00000000000..6f2743d65dc --- /dev/null +++ b/build/pkgs/jupyter_server_terminals/package-version.txt @@ -0,0 +1 @@ +0.4.4 diff --git a/build/pkgs/jupyter_server_terminals/type b/build/pkgs/jupyter_server_terminals/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/jupyter_server_terminals/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/jupyterlab/SPKG.rst b/build/pkgs/jupyterlab/SPKG.rst index f728314ffae..00c89cb7aa0 100644 --- a/build/pkgs/jupyterlab/SPKG.rst +++ b/build/pkgs/jupyterlab/SPKG.rst @@ -1,19 +1,20 @@ -jupyterlab: An extensible environment for interactive and reproducible computing -================================================================================ +jupyterlab: JupyterLab computational environment +================================================ Description ----------- -An extensible environment for interactive and reproducible computing, -based on the Jupyter Notebook and Architecture. +JupyterLab computational environment License ------- -BSD License +Copyright (c) 2015-2022 Project Jupyter Contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Semver File License: The semver.py file is from https://github.com/podhmo/python-semver which is licensed under the "MIT" license. See the semver.py file for details. Upstream Contact ---------------- -Home page: https://jupyter.org/ +https://pypi.org/project/jupyterlab/ diff --git a/build/pkgs/jupyterlab/checksums.ini b/build/pkgs/jupyterlab/checksums.ini new file mode 100644 index 00000000000..8ce07466089 --- /dev/null +++ b/build/pkgs/jupyterlab/checksums.ini @@ -0,0 +1,5 @@ +tarball=jupyterlab-VERSION-py3-none-any.whl +sha1=06ca895226e055d4bf92f3971eab23035d9c18c7 +md5=a608fbbd9a4616afcc8b0f2e9e0c76ef +cksum=1688505838 +upstream_url=https://pypi.io/packages/py3/j/jupyterlab/jupyterlab-VERSION-py3-none-any.whl diff --git a/build/pkgs/jupyterlab/dependencies b/build/pkgs/jupyterlab/dependencies index 059006650e1..5d2f8f03d6a 100644 --- a/build/pkgs/jupyterlab/dependencies +++ b/build/pkgs/jupyterlab/dependencies @@ -1,4 +1,4 @@ - vcversioner jupyter_core jupyter_client jinja2 tornado ipython packaging terminado traitlets nbconvert send2trash nbformat prometheus_client ipython_genutils argon2_cffi pyzmq idna requests jsonschema babel notebook | $(PYTHON_TOOLCHAIN) $(PYTHON) +async_lru importlib_metadata ipykernel jinja2 jupyter_core jupyter_lsp jupyter_server jupyterlab_server notebook_shim packaging traitlets tornado tomli | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/jupyterlab/install-requires.txt b/build/pkgs/jupyterlab/install-requires.txt new file mode 100644 index 00000000000..c9356a72837 --- /dev/null +++ b/build/pkgs/jupyterlab/install-requires.txt @@ -0,0 +1 @@ +jupyterlab diff --git a/build/pkgs/jupyterlab/package-version.txt b/build/pkgs/jupyterlab/package-version.txt new file mode 100644 index 00000000000..d13e837c8ec --- /dev/null +++ b/build/pkgs/jupyterlab/package-version.txt @@ -0,0 +1 @@ +4.0.6 diff --git a/build/pkgs/jupyterlab/requirements.txt b/build/pkgs/jupyterlab/requirements.txt deleted file mode 100644 index f03a26674fd..00000000000 --- a/build/pkgs/jupyterlab/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -jupyterlab ~= 3.3 -# See https://github.com/sagemath/sage/issues/33607 -jupyterlab-server < 2.11 diff --git a/build/pkgs/jupyterlab/type b/build/pkgs/jupyterlab/type index 134d9bc32d5..a6a7b9cd726 100644 --- a/build/pkgs/jupyterlab/type +++ b/build/pkgs/jupyterlab/type @@ -1 +1 @@ -optional +standard diff --git a/build/pkgs/jupyterlab_mathjax2/SPKG.rst b/build/pkgs/jupyterlab_mathjax2/SPKG.rst new file mode 100644 index 00000000000..521fef10085 --- /dev/null +++ b/build/pkgs/jupyterlab_mathjax2/SPKG.rst @@ -0,0 +1,18 @@ +jupyterlab_mathjax2: A MathJax Typesetting provider for JupyterLab 4 and above +============================================================================== + +Description +----------- + +A MathJax Typesetting provider for JupyterLab 4 and above + +License +------- + +BSD 3-Clause License Copyright (c) 2023, Project Jupyter All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Upstream Contact +---------------- + +https://pypi.org/project/jupyterlab-mathjax2/ + diff --git a/build/pkgs/jupyterlab_mathjax2/checksums.ini b/build/pkgs/jupyterlab_mathjax2/checksums.ini new file mode 100644 index 00000000000..6a428bd21dc --- /dev/null +++ b/build/pkgs/jupyterlab_mathjax2/checksums.ini @@ -0,0 +1,5 @@ +tarball=jupyterlab_mathjax2-VERSION-py3-none-any.whl +sha1=4e2bb182594a6c4f5d4edfb4f6e33597f09de402 +md5=4172e36b068af6a3f36c26a3f1946dc9 +cksum=387386440 +upstream_url=https://pypi.io/packages/py3/j/jupyterlab_mathjax2/jupyterlab_mathjax2-VERSION-py3-none-any.whl diff --git a/build/pkgs/jupyterlab_mathjax2/dependencies b/build/pkgs/jupyterlab_mathjax2/dependencies new file mode 100644 index 00000000000..47296a7bace --- /dev/null +++ b/build/pkgs/jupyterlab_mathjax2/dependencies @@ -0,0 +1,4 @@ + | $(PYTHON_TOOLCHAIN) $(PYTHON) + +---------- +All lines of this file are ignored except the first. diff --git a/build/pkgs/jupyterlab_mathjax2/install-requires.txt b/build/pkgs/jupyterlab_mathjax2/install-requires.txt new file mode 100644 index 00000000000..d0db4b4ac19 --- /dev/null +++ b/build/pkgs/jupyterlab_mathjax2/install-requires.txt @@ -0,0 +1 @@ +jupyterlab-mathjax2 diff --git a/build/pkgs/jupyterlab_mathjax2/package-version.txt b/build/pkgs/jupyterlab_mathjax2/package-version.txt new file mode 100644 index 00000000000..fcdb2e109f6 --- /dev/null +++ b/build/pkgs/jupyterlab_mathjax2/package-version.txt @@ -0,0 +1 @@ +4.0.0 diff --git a/build/pkgs/jupyterlab_mathjax2/type b/build/pkgs/jupyterlab_mathjax2/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/jupyterlab_mathjax2/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/jupyterlab_pygments/checksums.ini b/build/pkgs/jupyterlab_pygments/checksums.ini index dbcf15bf6fd..6f5af4d8afd 100644 --- a/build/pkgs/jupyterlab_pygments/checksums.ini +++ b/build/pkgs/jupyterlab_pygments/checksums.ini @@ -1,5 +1,5 @@ -tarball=jupyterlab_pygments-VERSION.tar.gz -sha1=1c2b2ffc2d4a5fa2a7b5143f68b742758de39bd2 -md5=beb54b1cf0bd25b53549efc4824f7fea -cksum=3472265164 -upstream_url=https://pypi.io/packages/source/j/jupyterlab_pygments/jupyterlab_pygments-VERSION.tar.gz +tarball=jupyterlab_pygments-VERSION-py2.py3-none-any.whl +sha1=601f547767fa867494ff0764891807904b8ebbd2 +md5=44194b8e643cf025ec3a91f0c751c7d7 +cksum=4169885263 +upstream_url=https://pypi.io/packages/py2.py3/j/jupyterlab_pygments/jupyterlab_pygments-VERSION-py2.py3-none-any.whl diff --git a/build/pkgs/jupyterlab_pygments/package-version.txt b/build/pkgs/jupyterlab_pygments/package-version.txt index d917d3e26ad..ee1372d33a2 100644 --- a/build/pkgs/jupyterlab_pygments/package-version.txt +++ b/build/pkgs/jupyterlab_pygments/package-version.txt @@ -1 +1 @@ -0.1.2 +0.2.2 diff --git a/build/pkgs/jupyterlab_pygments/spkg-install.in b/build/pkgs/jupyterlab_pygments/spkg-install.in deleted file mode 100644 index 37ac1a53437..00000000000 --- a/build/pkgs/jupyterlab_pygments/spkg-install.in +++ /dev/null @@ -1,2 +0,0 @@ -cd src -sdh_pip_install . diff --git a/build/pkgs/jupyterlab_server/SPKG.rst b/build/pkgs/jupyterlab_server/SPKG.rst new file mode 100644 index 00000000000..aca71f627ec --- /dev/null +++ b/build/pkgs/jupyterlab_server/SPKG.rst @@ -0,0 +1,18 @@ +jupyterlab_server: A set of server components for JupyterLab and JupyterLab like applications. +============================================================================================== + +Description +----------- + +A set of server components for JupyterLab and JupyterLab like applications. + +License +------- + +Copyright (c) 2015-2017, Project Jupyter Contributors All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Upstream Contact +---------------- + +https://pypi.org/project/jupyterlab-server/ + diff --git a/build/pkgs/jupyterlab_server/checksums.ini b/build/pkgs/jupyterlab_server/checksums.ini new file mode 100644 index 00000000000..3bd8926fd7b --- /dev/null +++ b/build/pkgs/jupyterlab_server/checksums.ini @@ -0,0 +1,5 @@ +tarball=jupyterlab_server-VERSION-py3-none-any.whl +sha1=1fff8c8bc4c81b006cb83d4524dc8a6f3364e57c +md5=795bbf343ae17b75a31a50ef574d4b77 +cksum=696988100 +upstream_url=https://pypi.io/packages/py3/j/jupyterlab_server/jupyterlab_server-VERSION-py3-none-any.whl diff --git a/build/pkgs/jupyterlab_server/dependencies b/build/pkgs/jupyterlab_server/dependencies new file mode 100644 index 00000000000..8a1817a0d0d --- /dev/null +++ b/build/pkgs/jupyterlab_server/dependencies @@ -0,0 +1,4 @@ +babel jupyter_events jupyter_server json5 jsonschema requests | $(PYTHON_TOOLCHAIN) $(PYTHON) + +---------- +All lines of this file are ignored except the first. diff --git a/build/pkgs/jupyterlab_server/install-requires.txt b/build/pkgs/jupyterlab_server/install-requires.txt new file mode 100644 index 00000000000..06b850a61cc --- /dev/null +++ b/build/pkgs/jupyterlab_server/install-requires.txt @@ -0,0 +1 @@ +jupyterlab-server diff --git a/build/pkgs/jupyterlab_server/package-version.txt b/build/pkgs/jupyterlab_server/package-version.txt new file mode 100644 index 00000000000..ad2261920c0 --- /dev/null +++ b/build/pkgs/jupyterlab_server/package-version.txt @@ -0,0 +1 @@ +2.24.0 diff --git a/build/pkgs/jupyterlab_server/type b/build/pkgs/jupyterlab_server/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/jupyterlab_server/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/jupyterlab_widgets/checksums.ini b/build/pkgs/jupyterlab_widgets/checksums.ini index 5d021049263..7da29e7849e 100644 --- a/build/pkgs/jupyterlab_widgets/checksums.ini +++ b/build/pkgs/jupyterlab_widgets/checksums.ini @@ -1,5 +1,5 @@ tarball=jupyterlab_widgets-VERSION-py3-none-any.whl -sha1=584e25e221b38c3ca7139667621a3eaf23260ffc -md5=d7b643a04ef1bb9012c58e6833d277c9 -cksum=202463248 +sha1=b10775bb3966af627bb44fbda4efb553b24a5b93 +md5=fc3c9f41000461dbdca2b965fcee37db +cksum=441194289 upstream_url=https://pypi.io/packages/py3/j/jupyterlab_widgets/jupyterlab_widgets-VERSION-py3-none-any.whl diff --git a/build/pkgs/jupyterlab_widgets/package-version.txt b/build/pkgs/jupyterlab_widgets/package-version.txt index 75a22a26ac4..747457c6d22 100644 --- a/build/pkgs/jupyterlab_widgets/package-version.txt +++ b/build/pkgs/jupyterlab_widgets/package-version.txt @@ -1 +1 @@ -3.0.3 +3.0.9 diff --git a/build/pkgs/msolve/patches/0001-Make-msolve-build-with-flint3.patch b/build/pkgs/msolve/patches/0001-Make-msolve-build-with-flint3.patch new file mode 100644 index 00000000000..27a642a13b0 --- /dev/null +++ b/build/pkgs/msolve/patches/0001-Make-msolve-build-with-flint3.patch @@ -0,0 +1,53 @@ +From fe730579476de0b2d4181a38efa7f63dff9c81d7 Mon Sep 17 00:00:00 2001 +From: Marc Mezzarobba +Date: Tue, 12 Sep 2023 08:23:08 +0200 +Subject: [PATCH] Make msolve build with flint3 + +--- + src/fglm/berlekamp_massey.c | 3 +++ + src/fglm/data_fglm.c | 7 +++++-- + 2 files changed, 8 insertions(+), 2 deletions(-) + +diff --git a/src/fglm/berlekamp_massey.c b/src/fglm/berlekamp_massey.c +index b0f2052..998af1c 100644 +--- a/src/fglm/berlekamp_massey.c ++++ b/src/fglm/berlekamp_massey.c +@@ -30,6 +30,9 @@ + */ + + #include ++#if __FLINT_VERSION >= 3 ++# include ++#endif + //#include "nmod_poly.h" + //#include "mpn_extras.h" + +diff --git a/src/fglm/data_fglm.c b/src/fglm/data_fglm.c +index 0726760..0e1da6f 100644 +--- a/src/fglm/data_fglm.c ++++ b/src/fglm/data_fglm.c +@@ -24,6 +24,7 @@ + #include + #include + #include ++#include + + + typedef uint32_t szmat_t; +@@ -299,9 +300,11 @@ static inline void nmod_poly_set_prime(nmod_poly_t poly, + mp_limb_t ninv = n_preinvert_limb(prime); + poly->mod.n = prime; + poly->mod.ninv = ninv; ++#if __FLINT_VERSION < 3 + count_leading_zeros(poly->mod.norm, prime); +- /* poly->mod.norm = flint_clz(prime); */ +- ++#else ++ poly->mod.norm = flint_clz(prime); ++#endif + } + + static inline void fglm_param_set_prime(param_t *param, mp_limb_t prime){ +-- +2.40.1 + diff --git a/build/pkgs/nbclient/checksums.ini b/build/pkgs/nbclient/checksums.ini index 459341ff20e..a5f4616ad8b 100644 --- a/build/pkgs/nbclient/checksums.ini +++ b/build/pkgs/nbclient/checksums.ini @@ -1,5 +1,5 @@ -tarball=nbclient-VERSION.tar.gz -sha1=8f6309bc37fb2c5b49fcdfe835b6ef9762fa583c -md5=6a59800791be74079cf2ade421526289 -cksum=1870577652 -upstream_url=https://pypi.io/packages/source/n/nbclient/nbclient-VERSION.tar.gz +tarball=nbclient-VERSION-py3-none-any.whl +sha1=fcb4ad9b3ea1bea4d305076c0a7640a483bd11f3 +md5=db61a38c8b66b5b9c7f6f0c7c7de8f26 +cksum=2793018181 +upstream_url=https://pypi.io/packages/py3/n/nbclient/nbclient-VERSION-py3-none-any.whl diff --git a/build/pkgs/nbclient/package-version.txt b/build/pkgs/nbclient/package-version.txt index faef31a4357..a3df0a6959e 100644 --- a/build/pkgs/nbclient/package-version.txt +++ b/build/pkgs/nbclient/package-version.txt @@ -1 +1 @@ -0.7.0 +0.8.0 diff --git a/build/pkgs/nbclient/spkg-install.in b/build/pkgs/nbclient/spkg-install.in deleted file mode 100644 index 37ac1a53437..00000000000 --- a/build/pkgs/nbclient/spkg-install.in +++ /dev/null @@ -1,2 +0,0 @@ -cd src -sdh_pip_install . diff --git a/build/pkgs/nbconvert/checksums.ini b/build/pkgs/nbconvert/checksums.ini index 1c3926c6ce3..20eb0e3e2df 100644 --- a/build/pkgs/nbconvert/checksums.ini +++ b/build/pkgs/nbconvert/checksums.ini @@ -1,5 +1,5 @@ tarball=nbconvert-VERSION-py3-none-any.whl -sha1=de3dd5e475d84c2d143c03dfc22bfc490c03092f -md5=942dd716bd6976c58fdbcfec97bfbe20 -cksum=610202196 +sha1=5317fa68bbd7f66fc3fcc5b0e6b0d6e2df967ba0 +md5=ad534f2db53d8677b790be0e98992f8e +cksum=2885634129 upstream_url=https://pypi.io/packages/py3/n/nbconvert/nbconvert-VERSION-py3-none-any.whl diff --git a/build/pkgs/nbconvert/package-version.txt b/build/pkgs/nbconvert/package-version.txt index 429dc57af3a..33d00300e4a 100644 --- a/build/pkgs/nbconvert/package-version.txt +++ b/build/pkgs/nbconvert/package-version.txt @@ -1 +1 @@ -7.2.3 +7.9.2 diff --git a/build/pkgs/nbformat/SPKG.rst b/build/pkgs/nbformat/SPKG.rst index 88eebb18a2e..fdb14030fd2 100644 --- a/build/pkgs/nbformat/SPKG.rst +++ b/build/pkgs/nbformat/SPKG.rst @@ -1,8 +1,18 @@ -nbformat: Base implementation of the Jupyter notebook format -============================================================ +nbformat: The Jupyter Notebook format +===================================== Description ----------- -This package contains the base implementation of the Jupyter Notebook -format, and Python APIs for working with notebooks. +The Jupyter Notebook format + +License +------- + +BSD 3-Clause License + +Upstream Contact +---------------- + +https://pypi.org/project/nbformat/ + diff --git a/build/pkgs/nbformat/checksums.ini b/build/pkgs/nbformat/checksums.ini index af04e4f35aa..81f66428e25 100644 --- a/build/pkgs/nbformat/checksums.ini +++ b/build/pkgs/nbformat/checksums.ini @@ -1,5 +1,5 @@ -tarball=nbformat-VERSION.tar.gz -sha1=ecad83c07bdc475f6fd88d28485cf8fe31fbba41 -md5=5e11cc3240d4b1410610786309cc6076 -cksum=767940068 -upstream_url=https://pypi.io/packages/source/n/nbformat/nbformat-VERSION.tar.gz +tarball=nbformat-VERSION-py3-none-any.whl +sha1=e38af74817e9d81101583363d9ffe349f0038eb9 +md5=0821545beba702b7001ad5bd744c89ba +cksum=2633499795 +upstream_url=https://pypi.io/packages/py3/n/nbformat/nbformat-VERSION-py3-none-any.whl diff --git a/build/pkgs/nbformat/dependencies b/build/pkgs/nbformat/dependencies index a6f9cc5f425..4e265a78b6a 100644 --- a/build/pkgs/nbformat/dependencies +++ b/build/pkgs/nbformat/dependencies @@ -1,4 +1,4 @@ - jsonschema fastjsonschema jupyter_core traitlets | $(PYTHON_TOOLCHAIN) hatchling hatch_nodejs_version $(PYTHON) +jsonschema fastjsonschema jupyter_core traitlets | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/nbformat/package-version.txt b/build/pkgs/nbformat/package-version.txt index 42cdd0b540f..da902181863 100644 --- a/build/pkgs/nbformat/package-version.txt +++ b/build/pkgs/nbformat/package-version.txt @@ -1 +1 @@ -5.7.0 +5.9.2 diff --git a/build/pkgs/nbformat/spkg-install.in b/build/pkgs/nbformat/spkg-install.in deleted file mode 100644 index deba1bb42bb..00000000000 --- a/build/pkgs/nbformat/spkg-install.in +++ /dev/null @@ -1 +0,0 @@ -cd src && sdh_pip_install . diff --git a/build/pkgs/nest_asyncio/checksums.ini b/build/pkgs/nest_asyncio/checksums.ini index 1a11eb5178b..9752b8da3bb 100644 --- a/build/pkgs/nest_asyncio/checksums.ini +++ b/build/pkgs/nest_asyncio/checksums.ini @@ -1,5 +1,5 @@ tarball=nest_asyncio-VERSION.tar.gz -sha1=1e862862afe4c2e057065212eefe7203ccee4927 -md5=7c7108921a64e7abbb6993803343819b -cksum=982689987 +sha1=e7d8036f6558011c5ae0c649e0af21eb530044d3 +md5=9f0fe9ca229b1eef6e1ffba266413616 +cksum=3560927178 upstream_url=https://pypi.io/packages/source/n/nest_asyncio/nest_asyncio-VERSION.tar.gz diff --git a/build/pkgs/nest_asyncio/package-version.txt b/build/pkgs/nest_asyncio/package-version.txt index eac1e0ada6d..1cc9c180e26 100644 --- a/build/pkgs/nest_asyncio/package-version.txt +++ b/build/pkgs/nest_asyncio/package-version.txt @@ -1 +1 @@ -1.5.6 +1.5.8 diff --git a/build/pkgs/nodeenv/SPKG.rst b/build/pkgs/nodeenv/SPKG.rst deleted file mode 100644 index 397d909f16d..00000000000 --- a/build/pkgs/nodeenv/SPKG.rst +++ /dev/null @@ -1,21 +0,0 @@ -nodeenv: A tool to create isolated node.js environments -======================================================= - -Description ------------ - -nodeenv (node.js virtual environment) is a tool to create isolated node.js environments. - -It creates an environment that has its own installation directories, that doesn’t share -libraries with other node.js virtual environments. - -License -------- - -BSD License - -Upstream Contact ----------------- - -Home page: https://github.com/ekalinin/nodeenv - diff --git a/build/pkgs/nodeenv/distros/conda.txt b/build/pkgs/nodeenv/distros/conda.txt deleted file mode 100644 index f69a126dec6..00000000000 --- a/build/pkgs/nodeenv/distros/conda.txt +++ /dev/null @@ -1 +0,0 @@ -nodeenv diff --git a/build/pkgs/nodeenv/distros/homebrew.txt b/build/pkgs/nodeenv/distros/homebrew.txt deleted file mode 100644 index f69a126dec6..00000000000 --- a/build/pkgs/nodeenv/distros/homebrew.txt +++ /dev/null @@ -1 +0,0 @@ -nodeenv diff --git a/build/pkgs/nodeenv/distros/repology.txt b/build/pkgs/nodeenv/distros/repology.txt deleted file mode 100644 index a3202e13f17..00000000000 --- a/build/pkgs/nodeenv/distros/repology.txt +++ /dev/null @@ -1,2 +0,0 @@ -nodeenv -python:nodeenv diff --git a/build/pkgs/nodeenv/requirements.txt b/build/pkgs/nodeenv/requirements.txt deleted file mode 100644 index 926d31bf049..00000000000 --- a/build/pkgs/nodeenv/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -nodeenv ~= 1.4.0 diff --git a/build/pkgs/nodeenv/type b/build/pkgs/nodeenv/type deleted file mode 100644 index 134d9bc32d5..00000000000 --- a/build/pkgs/nodeenv/type +++ /dev/null @@ -1 +0,0 @@ -optional diff --git a/build/pkgs/nodejs/SPKG.rst b/build/pkgs/nodejs/SPKG.rst deleted file mode 100644 index 1176f4fea3b..00000000000 --- a/build/pkgs/nodejs/SPKG.rst +++ /dev/null @@ -1,20 +0,0 @@ -nodejs: A JavaScript runtime built on Chrome's V8 JavaScript engine -=================================================================== - -Description ------------ - -Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. - -It is installed into an isolated nodeenv. - -License -------- - -MIT License - -Upstream Contact ----------------- - -Home page: https://nodejs.org/ - diff --git a/build/pkgs/nodejs/distros/conda.txt b/build/pkgs/nodejs/distros/conda.txt deleted file mode 100644 index e36de65c4cc..00000000000 --- a/build/pkgs/nodejs/distros/conda.txt +++ /dev/null @@ -1 +0,0 @@ -nodejs diff --git a/build/pkgs/nodejs/distros/homebrew.txt b/build/pkgs/nodejs/distros/homebrew.txt deleted file mode 100644 index 64f5a0a6813..00000000000 --- a/build/pkgs/nodejs/distros/homebrew.txt +++ /dev/null @@ -1 +0,0 @@ -node diff --git a/build/pkgs/nodejs/distros/opensuse.txt b/build/pkgs/nodejs/distros/opensuse.txt deleted file mode 100644 index e36de65c4cc..00000000000 --- a/build/pkgs/nodejs/distros/opensuse.txt +++ /dev/null @@ -1 +0,0 @@ -nodejs diff --git a/build/pkgs/nodejs/distros/repology.txt b/build/pkgs/nodejs/distros/repology.txt deleted file mode 100644 index e36de65c4cc..00000000000 --- a/build/pkgs/nodejs/distros/repology.txt +++ /dev/null @@ -1 +0,0 @@ -nodejs diff --git a/build/pkgs/nodejs/distros/void.txt b/build/pkgs/nodejs/distros/void.txt deleted file mode 100644 index e36de65c4cc..00000000000 --- a/build/pkgs/nodejs/distros/void.txt +++ /dev/null @@ -1 +0,0 @@ -nodejs diff --git a/build/pkgs/nodejs/package-version.txt b/build/pkgs/nodejs/package-version.txt deleted file mode 100644 index 9cd25a1fec8..00000000000 --- a/build/pkgs/nodejs/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -12.18.3 diff --git a/build/pkgs/nodejs/spkg-install b/build/pkgs/nodejs/spkg-install deleted file mode 100755 index 731d8f3089d..00000000000 --- a/build/pkgs/nodejs/spkg-install +++ /dev/null @@ -1,53 +0,0 @@ -if [ -z "$SAGE_LOCAL" ]; then - echo >&2 "SAGE_LOCAL undefined ... exiting" - echo >&2 "Maybe run 'sage --sh'?" - exit 1 -fi - -nodejs_ver=`grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+" package-version.txt` - -if [ $? -ne 0 ]; then - echo "Error determining which nodejs version to install ... exiting" - exit 1 -fi - -nodeenv_dir="$SAGE_LOCAL/share/nodejs/$nodejs_ver" -nodeenv_activate="$nodeenv_dir/bin/activate" - -echo "Will use/install nodejs in nodeenv located at $nodeenv_dir ..." - -if [ ! -f "$nodeenv_activate" ]; then - # The nodeenv may not exist, or it may exist but installing nodejs into - # it previously failed, so --force to cover both cases. - nodeenv --force --verbose --node="$nodejs_ver" "$nodeenv_dir" - - if [ $? -ne 0 ]; then - echo "Error installing nodejs ... exiting" - exit 1 - fi -fi - -. "$nodeenv_activate" - -if [ $? -ne 0 ]; then - echo "Error activating nodeenv containing nodejs ... exiting" - exit 1 -fi - -active_ver=`node --version | grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+"` - -if [ $? -ne 0 ]; then - echo "Error determining which nodejs version is active ... exiting" - deactivate_node - exit 1 -fi - -deactivate_node - -if [ ! "$nodejs_ver" = "$active_ver" ]; then - echo "Wrong version of nodejs was activated ... exiting" - echo "Expected $nodejs_ver but found $active_ver" - exit 1 -fi - -ln -sf "$nodeenv_activate" "$SAGE_LOCAL/share/nodejs/activate" diff --git a/build/pkgs/nodejs/type b/build/pkgs/nodejs/type deleted file mode 100644 index 134d9bc32d5..00000000000 --- a/build/pkgs/nodejs/type +++ /dev/null @@ -1 +0,0 @@ -optional diff --git a/build/pkgs/notebook/SPKG.rst b/build/pkgs/notebook/SPKG.rst index 7dfdc5ee1c8..9cbb9b2463c 100644 --- a/build/pkgs/notebook/SPKG.rst +++ b/build/pkgs/notebook/SPKG.rst @@ -6,3 +6,13 @@ Description The Jupyter HTML notebook is a web-based notebook environment for interactive computing. + +License +------- + +BSD 3-Clause License + +Upstream Contact +---------------- + +https://pypi.org/project/notebook/ diff --git a/build/pkgs/notebook/checksums.ini b/build/pkgs/notebook/checksums.ini index 16bbe6de420..434646c23c3 100644 --- a/build/pkgs/notebook/checksums.ini +++ b/build/pkgs/notebook/checksums.ini @@ -1,5 +1,5 @@ -tarball=notebook-VERSION.tar.gz -sha1=d715730ac48bca8739ce8faf5329841d147163cd -md5=90a5b998e496ed4c18975d3a42960df0 -cksum=577775576 -upstream_url=https://pypi.io/packages/source/n/notebook/notebook-VERSION.tar.gz +tarball=notebook-VERSION-py3-none-any.whl +sha1=cd0c99c8a267ced6a451f712007665df88c60d71 +md5=e61e0d6c55bf3920c013554c6dd071b9 +cksum=2202937268 +upstream_url=https://pypi.io/packages/py3/n/notebook/notebook-VERSION-py3-none-any.whl diff --git a/build/pkgs/notebook/dependencies b/build/pkgs/notebook/dependencies index 9e6cbf4b36d..876c76eec23 100644 --- a/build/pkgs/notebook/dependencies +++ b/build/pkgs/notebook/dependencies @@ -1,4 +1,4 @@ - | $(PYTHON_TOOLCHAIN) ipython jupyter_client ipykernel nbconvert nbformat jinja2 tornado terminado send2trash prometheus_client argon2_cffi $(PYTHON) +jupyter_server jupyterlab_server jupyterlab notebook_shim | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/notebook/package-version.txt b/build/pkgs/notebook/package-version.txt index d613169e889..024b4b9b53a 100644 --- a/build/pkgs/notebook/package-version.txt +++ b/build/pkgs/notebook/package-version.txt @@ -1 +1 @@ -6.4.12 +7.0.6 diff --git a/build/pkgs/notebook/spkg-install.in b/build/pkgs/notebook/spkg-install.in deleted file mode 100644 index b0979b55cb8..00000000000 --- a/build/pkgs/notebook/spkg-install.in +++ /dev/null @@ -1,10 +0,0 @@ -cd src - -set -e - -sdh_pip_install . - -# Install the Jupyter notebook configuration in the installation tree -ETC_JUPYTER="$SAGE_INST_LOCAL"/etc/jupyter -mkdir -p "$ETC_JUPYTER" -cp ../jupyter_notebook_config.py "$ETC_JUPYTER"/ diff --git a/build/pkgs/notebook_shim/SPKG.rst b/build/pkgs/notebook_shim/SPKG.rst new file mode 100644 index 00000000000..102ffbb5b99 --- /dev/null +++ b/build/pkgs/notebook_shim/SPKG.rst @@ -0,0 +1,18 @@ +notebook_shim: A shim layer for notebook traits and config +========================================================== + +Description +----------- + +A shim layer for notebook traits and config + +License +------- + +BSD 3-Clause License + +Upstream Contact +---------------- + +https://pypi.org/project/notebook-shim/ + diff --git a/build/pkgs/notebook_shim/checksums.ini b/build/pkgs/notebook_shim/checksums.ini new file mode 100644 index 00000000000..c646e5c3ae9 --- /dev/null +++ b/build/pkgs/notebook_shim/checksums.ini @@ -0,0 +1,5 @@ +tarball=notebook_shim-VERSION-py3-none-any.whl +sha1=9bb3dce360ce69aec99f873d8e80c1e9fdf92fde +md5=f2207bef3d00f9b2dc14b0eeec63460d +cksum=2703250856 +upstream_url=https://pypi.io/packages/py3/n/notebook_shim/notebook_shim-VERSION-py3-none-any.whl diff --git a/build/pkgs/notebook_shim/dependencies b/build/pkgs/notebook_shim/dependencies new file mode 100644 index 00000000000..97d97af24c5 --- /dev/null +++ b/build/pkgs/notebook_shim/dependencies @@ -0,0 +1,4 @@ +jupyter_server | $(PYTHON_TOOLCHAIN) $(PYTHON) + +---------- +All lines of this file are ignored except the first. diff --git a/build/pkgs/notebook_shim/install-requires.txt b/build/pkgs/notebook_shim/install-requires.txt new file mode 100644 index 00000000000..73d88bc8706 --- /dev/null +++ b/build/pkgs/notebook_shim/install-requires.txt @@ -0,0 +1 @@ +notebook-shim diff --git a/build/pkgs/notebook_shim/package-version.txt b/build/pkgs/notebook_shim/package-version.txt new file mode 100644 index 00000000000..7179039691c --- /dev/null +++ b/build/pkgs/notebook_shim/package-version.txt @@ -0,0 +1 @@ +0.2.3 diff --git a/build/pkgs/notebook_shim/type b/build/pkgs/notebook_shim/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/notebook_shim/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/notedown/dependencies b/build/pkgs/notedown/dependencies index 3dcb5b1900f..58f0c5d2c56 100644 --- a/build/pkgs/notedown/dependencies +++ b/build/pkgs/notedown/dependencies @@ -1,4 +1,4 @@ - $(PYTHON_TOOLCHAIN) | pip nbformat nbconvert six pandoc_attributes $(PYTHON) +nbformat nbconvert six pandoc_attributes | $(PYTHON) $(PYTHON_TOOLCHAIN) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/overrides/SPKG.rst b/build/pkgs/overrides/SPKG.rst new file mode 100644 index 00000000000..bc6dcdbfdd6 --- /dev/null +++ b/build/pkgs/overrides/SPKG.rst @@ -0,0 +1,18 @@ +overrides: A decorator to automatically detect mismatch when overriding a method. +================================================================================= + +Description +----------- + +A decorator to automatically detect mismatch when overriding a method. + +License +------- + +Apache License, Version 2.0 + +Upstream Contact +---------------- + +https://pypi.org/project/overrides/ + diff --git a/build/pkgs/overrides/checksums.ini b/build/pkgs/overrides/checksums.ini new file mode 100644 index 00000000000..cd313073a39 --- /dev/null +++ b/build/pkgs/overrides/checksums.ini @@ -0,0 +1,5 @@ +tarball=overrides-VERSION-py3-none-any.whl +sha1=740e9e607a9e4f78dea7a1b82bcb27f285bc5f48 +md5=ed4ab0bd43112d05105576f0a50f5aa7 +cksum=3865068538 +upstream_url=https://pypi.io/packages/py3/o/overrides/overrides-VERSION-py3-none-any.whl diff --git a/build/pkgs/overrides/dependencies b/build/pkgs/overrides/dependencies new file mode 100644 index 00000000000..47296a7bace --- /dev/null +++ b/build/pkgs/overrides/dependencies @@ -0,0 +1,4 @@ + | $(PYTHON_TOOLCHAIN) $(PYTHON) + +---------- +All lines of this file are ignored except the first. diff --git a/build/pkgs/overrides/install-requires.txt b/build/pkgs/overrides/install-requires.txt new file mode 100644 index 00000000000..6113455c332 --- /dev/null +++ b/build/pkgs/overrides/install-requires.txt @@ -0,0 +1 @@ +overrides diff --git a/build/pkgs/overrides/package-version.txt b/build/pkgs/overrides/package-version.txt new file mode 100644 index 00000000000..ba7f754d0c3 --- /dev/null +++ b/build/pkgs/overrides/package-version.txt @@ -0,0 +1 @@ +7.4.0 diff --git a/build/pkgs/overrides/type b/build/pkgs/overrides/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/overrides/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/pandoc_attributes/dependencies b/build/pkgs/pandoc_attributes/dependencies index cc9d4970706..4d6a540cf45 100644 --- a/build/pkgs/pandoc_attributes/dependencies +++ b/build/pkgs/pandoc_attributes/dependencies @@ -1,4 +1,4 @@ - $(PYTHON_TOOLCHAIN) | pip pandocfilters $(PYTHON) + | pandocfilters $(PYTHON) $(PYTHON_TOOLCHAIN) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/prompt_toolkit/checksums.ini b/build/pkgs/prompt_toolkit/checksums.ini index ec0df09c5b9..47d7ffa3c1c 100644 --- a/build/pkgs/prompt_toolkit/checksums.ini +++ b/build/pkgs/prompt_toolkit/checksums.ini @@ -1,5 +1,5 @@ tarball=prompt_toolkit-VERSION.tar.gz -sha1=77365bfc17ab577d80708a3395186ec68a7dbb2c -md5=214d36301eb139adba280793040d7755 -cksum=3187933391 +sha1=d36c3286a16c09b9bc02c2733b9fc7a8a9c30ba1 +md5=252a5d200e41d46b65a3076d2bc0a4bd +cksum=361343842 upstream_url=https://pypi.io/packages/source/p/prompt_toolkit/prompt_toolkit-VERSION.tar.gz diff --git a/build/pkgs/prompt_toolkit/distros/conda.txt b/build/pkgs/prompt_toolkit/distros/conda.txt index bfb1ed6a874..b99577146cd 100644 --- a/build/pkgs/prompt_toolkit/distros/conda.txt +++ b/build/pkgs/prompt_toolkit/distros/conda.txt @@ -1 +1 @@ -prompt_toolkit>=3.0.5,<3.0.25 +prompt_toolkit>=3.0.38 diff --git a/build/pkgs/prompt_toolkit/install-requires.txt b/build/pkgs/prompt_toolkit/install-requires.txt index 30d49fc8454..e3e1de9a3ea 100644 --- a/build/pkgs/prompt_toolkit/install-requires.txt +++ b/build/pkgs/prompt_toolkit/install-requires.txt @@ -1,2 +1 @@ -# https://github.com/sagemath/sage/issues/33428 - prompt_toolkit 3.0.25+ breaks Ctrl-C -prompt_toolkit >=3.0.5, <3.0.25 +prompt_toolkit >=3.0.38 diff --git a/build/pkgs/prompt_toolkit/package-version.txt b/build/pkgs/prompt_toolkit/package-version.txt index 03a04fce56f..dad0d9dd27c 100644 --- a/build/pkgs/prompt_toolkit/package-version.txt +++ b/build/pkgs/prompt_toolkit/package-version.txt @@ -1 +1 @@ -3.0.24 +3.0.41 diff --git a/build/pkgs/psutil/SPKG.rst b/build/pkgs/psutil/SPKG.rst new file mode 100644 index 00000000000..90c0ffe4bd9 --- /dev/null +++ b/build/pkgs/psutil/SPKG.rst @@ -0,0 +1,18 @@ +psutil: Cross-platform lib for process and system monitoring in Python. +======================================================================= + +Description +----------- + +Cross-platform lib for process and system monitoring in Python. + +License +------- + +BSD-3-Clause + +Upstream Contact +---------------- + +https://pypi.org/project/psutil/ + diff --git a/build/pkgs/psutil/checksums.ini b/build/pkgs/psutil/checksums.ini new file mode 100644 index 00000000000..f9d3d687f9d --- /dev/null +++ b/build/pkgs/psutil/checksums.ini @@ -0,0 +1,5 @@ +tarball=psutil-VERSION.tar.gz +sha1=24c493ef33d4df44e76a1801e480b4185bd911c5 +md5=eec35090e7474e471a12f0dd16c981f9 +cksum=3278898496 +upstream_url=https://pypi.io/packages/source/p/psutil/psutil-VERSION.tar.gz diff --git a/build/pkgs/psutil/dependencies b/build/pkgs/psutil/dependencies new file mode 100644 index 00000000000..47296a7bace --- /dev/null +++ b/build/pkgs/psutil/dependencies @@ -0,0 +1,4 @@ + | $(PYTHON_TOOLCHAIN) $(PYTHON) + +---------- +All lines of this file are ignored except the first. diff --git a/build/pkgs/psutil/install-requires.txt b/build/pkgs/psutil/install-requires.txt new file mode 100644 index 00000000000..a4d92cc08db --- /dev/null +++ b/build/pkgs/psutil/install-requires.txt @@ -0,0 +1 @@ +psutil diff --git a/build/pkgs/psutil/package-version.txt b/build/pkgs/psutil/package-version.txt new file mode 100644 index 00000000000..9bc6cde81a7 --- /dev/null +++ b/build/pkgs/psutil/package-version.txt @@ -0,0 +1 @@ +5.9.6 diff --git a/build/pkgs/hatch_nodejs_version/spkg-install.in b/build/pkgs/psutil/spkg-install.in similarity index 100% rename from build/pkgs/hatch_nodejs_version/spkg-install.in rename to build/pkgs/psutil/spkg-install.in diff --git a/build/pkgs/psutil/type b/build/pkgs/psutil/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/psutil/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/pygments/checksums.ini b/build/pkgs/pygments/checksums.ini index 14fc1c04cdb..5bd874eaaf6 100644 --- a/build/pkgs/pygments/checksums.ini +++ b/build/pkgs/pygments/checksums.ini @@ -1,5 +1,5 @@ tarball=Pygments-VERSION.tar.gz -sha1=adaf31bf13a7bcc210568537138e0984ecdea626 -md5=6ccae578d28d18968b30a4711652fd9a -cksum=613387624 +sha1=7d9a2dcf63799c011033529b326ba3d1b2900c38 +md5=20cb967029c23389253326cf515dec8a +cksum=601328323 upstream_url=https://pypi.io/packages/source/p/pygments/Pygments-VERSION.tar.gz diff --git a/build/pkgs/pygments/package-version.txt b/build/pkgs/pygments/package-version.txt index fb2c0766b7c..0e7079b6911 100644 --- a/build/pkgs/pygments/package-version.txt +++ b/build/pkgs/pygments/package-version.txt @@ -1 +1 @@ -2.13.0 +2.16.1 diff --git a/build/pkgs/pyrsistent/checksums.ini b/build/pkgs/pyrsistent/checksums.ini index 7d537e43e37..cffce58a92e 100644 --- a/build/pkgs/pyrsistent/checksums.ini +++ b/build/pkgs/pyrsistent/checksums.ini @@ -1,5 +1,5 @@ tarball=pyrsistent-VERSION.tar.gz -sha1=a2c5cc517a33dcfd3918d3eabf4859b8901d3913 -md5=23da81256b8817e123568a858bf78997 -cksum=1165148669 +sha1=79980873658f7634ae25758b9710088b62e0612a +md5=761266eab1f9dc9280cdb0a6d2dedb08 +cksum=2666822194 upstream_url=https://pypi.io/packages/source/p/pyrsistent/pyrsistent-VERSION.tar.gz diff --git a/build/pkgs/pyrsistent/dependencies b/build/pkgs/pyrsistent/dependencies index 9be6b4aab7c..47296a7bace 100644 --- a/build/pkgs/pyrsistent/dependencies +++ b/build/pkgs/pyrsistent/dependencies @@ -1,4 +1,4 @@ - vcversioner | $(PYTHON_TOOLCHAIN) $(PYTHON) + | $(PYTHON_TOOLCHAIN) $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/pyrsistent/package-version.txt b/build/pkgs/pyrsistent/package-version.txt index 61e6e92d914..b72b05ede10 100644 --- a/build/pkgs/pyrsistent/package-version.txt +++ b/build/pkgs/pyrsistent/package-version.txt @@ -1 +1 @@ -0.19.2 +0.19.3 diff --git a/build/pkgs/python_json_logger/SPKG.rst b/build/pkgs/python_json_logger/SPKG.rst new file mode 100644 index 00000000000..8e25e0f8387 --- /dev/null +++ b/build/pkgs/python_json_logger/SPKG.rst @@ -0,0 +1,18 @@ +python_json_logger: A python library adding a json log formatter +================================================================ + +Description +----------- + +A python library adding a json log formatter + +License +------- + +BSD + +Upstream Contact +---------------- + +https://pypi.org/project/python-json-logger/ + diff --git a/build/pkgs/python_json_logger/checksums.ini b/build/pkgs/python_json_logger/checksums.ini new file mode 100644 index 00000000000..b17d08d7100 --- /dev/null +++ b/build/pkgs/python_json_logger/checksums.ini @@ -0,0 +1,5 @@ +tarball=python_json_logger-VERSION-py3-none-any.whl +sha1=c1176f521d95b5452b6169943b2b9b259e024b39 +md5=618fc5f196be90261afa8372eb458f47 +cksum=349551342 +upstream_url=https://pypi.io/packages/py3/p/python_json_logger/python_json_logger-VERSION-py3-none-any.whl diff --git a/build/pkgs/python_json_logger/dependencies b/build/pkgs/python_json_logger/dependencies new file mode 100644 index 00000000000..47296a7bace --- /dev/null +++ b/build/pkgs/python_json_logger/dependencies @@ -0,0 +1,4 @@ + | $(PYTHON_TOOLCHAIN) $(PYTHON) + +---------- +All lines of this file are ignored except the first. diff --git a/build/pkgs/python_json_logger/install-requires.txt b/build/pkgs/python_json_logger/install-requires.txt new file mode 100644 index 00000000000..02a48421600 --- /dev/null +++ b/build/pkgs/python_json_logger/install-requires.txt @@ -0,0 +1 @@ +python-json-logger diff --git a/build/pkgs/python_json_logger/package-version.txt b/build/pkgs/python_json_logger/package-version.txt new file mode 100644 index 00000000000..f1547e6d134 --- /dev/null +++ b/build/pkgs/python_json_logger/package-version.txt @@ -0,0 +1 @@ +2.0.7 diff --git a/build/pkgs/python_json_logger/type b/build/pkgs/python_json_logger/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/python_json_logger/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/pyyaml/SPKG.rst b/build/pkgs/pyyaml/SPKG.rst new file mode 100644 index 00000000000..34b6fdcd32c --- /dev/null +++ b/build/pkgs/pyyaml/SPKG.rst @@ -0,0 +1,18 @@ +pyyaml: YAML parser and emitter for Python +========================================== + +Description +----------- + +YAML parser and emitter for Python + +License +------- + +MIT + +Upstream Contact +---------------- + +https://pypi.org/project/PyYAML/ + diff --git a/build/pkgs/pyyaml/checksums.ini b/build/pkgs/pyyaml/checksums.ini new file mode 100644 index 00000000000..6918d8fda58 --- /dev/null +++ b/build/pkgs/pyyaml/checksums.ini @@ -0,0 +1,5 @@ +tarball=PyYAML-VERSION.tar.gz +sha1=a80d802ad8f693bed34c8fb5ee168a1872663c9a +md5=c9246277af2d9a13b7018af267a0831a +cksum=2585952669 +upstream_url=https://pypi.io/packages/source/p/pyyaml/PyYAML-VERSION.tar.gz diff --git a/build/pkgs/pyyaml/dependencies b/build/pkgs/pyyaml/dependencies new file mode 100644 index 00000000000..909380550a2 --- /dev/null +++ b/build/pkgs/pyyaml/dependencies @@ -0,0 +1,4 @@ + | $(PYTHON_TOOLCHAIN) cython $(PYTHON) + +---------- +All lines of this file are ignored except the first. diff --git a/build/pkgs/pyyaml/install-requires.txt b/build/pkgs/pyyaml/install-requires.txt new file mode 100644 index 00000000000..5500f007d0b --- /dev/null +++ b/build/pkgs/pyyaml/install-requires.txt @@ -0,0 +1 @@ +PyYAML diff --git a/build/pkgs/pyyaml/package-version.txt b/build/pkgs/pyyaml/package-version.txt new file mode 100644 index 00000000000..5fe60723048 --- /dev/null +++ b/build/pkgs/pyyaml/package-version.txt @@ -0,0 +1 @@ +6.0.1 diff --git a/build/pkgs/pyyaml/patches/pyyaml-6.0.1-cython3.patch b/build/pkgs/pyyaml/patches/pyyaml-6.0.1-cython3.patch new file mode 100644 index 00000000000..d55db130977 --- /dev/null +++ b/build/pkgs/pyyaml/patches/pyyaml-6.0.1-cython3.patch @@ -0,0 +1,33 @@ +From 17dc5b6cd96dcfe64fd71789c771ca9b96d260e5 Mon Sep 17 00:00:00 2001 +From: "Andrew J. Hesford" +Date: Fri, 21 Jul 2023 09:50:00 -0400 +Subject: [PATCH] Fix builds with Cython 3 + +This is a *de minimis* fix for building with Cython 3. Recent Cython<3 +releases provided `Cython.Distutils.build_ext` as an alias to +`Cython.Distutils.old_build_ext.old_build_ext`; Cython 3 drops this +alias and instead uses a wholly new `Cython.Distutils.build_ext` that +does not provide the `cython_sources` function used in `setup.py`. + +Explicitly importing `old_build_ext` preserves the existing behavior for +recent Cython<3 and uses the correct behavior for Cython 3. Should the +import fail (*e.g.*, because the version of Cython available predates +the availability of `old_build_ext`), the import falls back to just +`Cython.Distutils.build_ext`. + +Signed-off-by: Andrew J. Hesford +--- a/setup.py ++++ b/setup.py +@@ -82,7 +82,11 @@ + with_cython = True + try: + from Cython.Distutils.extension import Extension as _Extension +- from Cython.Distutils import build_ext as _build_ext ++ try: ++ from Cython.Distutils.old_build_ext import old_build_ext as _build_ext ++ except ImportError: ++ from Cython.Distutils import build_ext as _build_ext ++ + with_cython = True + except ImportError: + if with_cython: diff --git a/build/pkgs/idna/spkg-install.in b/build/pkgs/pyyaml/spkg-install.in similarity index 100% rename from build/pkgs/idna/spkg-install.in rename to build/pkgs/pyyaml/spkg-install.in diff --git a/build/pkgs/pyyaml/type b/build/pkgs/pyyaml/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/pyyaml/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/referencing/SPKG.rst b/build/pkgs/referencing/SPKG.rst new file mode 100644 index 00000000000..5b8c16c5cf5 --- /dev/null +++ b/build/pkgs/referencing/SPKG.rst @@ -0,0 +1,18 @@ +referencing: JSON Referencing + Python +====================================== + +Description +----------- + +JSON Referencing + Python + +License +------- + +MIT + +Upstream Contact +---------------- + +https://pypi.org/project/referencing/ + diff --git a/build/pkgs/referencing/checksums.ini b/build/pkgs/referencing/checksums.ini new file mode 100644 index 00000000000..a121d900f04 --- /dev/null +++ b/build/pkgs/referencing/checksums.ini @@ -0,0 +1,5 @@ +tarball=referencing-VERSION-py3-none-any.whl +sha1=9d710ba3a604d24ffded218a3813b5fd1fe2e495 +md5=d12db197f05a5c560011e40e1852e8fc +cksum=2747749685 +upstream_url=https://pypi.io/packages/py3/r/referencing/referencing-VERSION-py3-none-any.whl diff --git a/build/pkgs/referencing/dependencies b/build/pkgs/referencing/dependencies new file mode 100644 index 00000000000..12067bf5c3e --- /dev/null +++ b/build/pkgs/referencing/dependencies @@ -0,0 +1,4 @@ +attrs | $(PYTHON_TOOLCHAIN) $(PYTHON) + +---------- +All lines of this file are ignored except the first. diff --git a/build/pkgs/referencing/install-requires.txt b/build/pkgs/referencing/install-requires.txt new file mode 100644 index 00000000000..953f1cdb0c7 --- /dev/null +++ b/build/pkgs/referencing/install-requires.txt @@ -0,0 +1 @@ +referencing diff --git a/build/pkgs/referencing/package-version.txt b/build/pkgs/referencing/package-version.txt new file mode 100644 index 00000000000..ca222b7cf39 --- /dev/null +++ b/build/pkgs/referencing/package-version.txt @@ -0,0 +1 @@ +0.23.0 diff --git a/build/pkgs/referencing/type b/build/pkgs/referencing/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/referencing/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/requests/checksums.ini b/build/pkgs/requests/checksums.ini index 5aabe04f278..925be456c02 100644 --- a/build/pkgs/requests/checksums.ini +++ b/build/pkgs/requests/checksums.ini @@ -1,5 +1,5 @@ tarball=requests-VERSION.tar.gz -sha1=53381250a0d114109a9e712dd7ce8e40e63e61e2 -md5=796ea875cdae283529c03b9203d9c454 -cksum=4112189908 +sha1=23ef233afce04d4a1d4856353dc3aaa255cbce3e +md5=941e175c276cd7d39d098092c56679a4 +cksum=2854825644 upstream_url=https://pypi.io/packages/source/r/requests/requests-VERSION.tar.gz diff --git a/build/pkgs/requests/package-version.txt b/build/pkgs/requests/package-version.txt index 9738a24f699..bafceb320ec 100644 --- a/build/pkgs/requests/package-version.txt +++ b/build/pkgs/requests/package-version.txt @@ -1 +1 @@ -2.28.1 +2.31.0 diff --git a/build/pkgs/retrolab/SPKG.rst b/build/pkgs/retrolab/SPKG.rst deleted file mode 100644 index b2d68eac755..00000000000 --- a/build/pkgs/retrolab/SPKG.rst +++ /dev/null @@ -1,16 +0,0 @@ -retrolab: JupyterLab Distribution with a retro look and feel -============================================================ - -Description ------------ - -JupyterLab Distribution with a retro look and feel - -License -------- - -Upstream Contact ----------------- - -https://pypi.org/project/retrolab/ - diff --git a/build/pkgs/retrolab/dependencies b/build/pkgs/retrolab/dependencies deleted file mode 100644 index 58027d3558c..00000000000 --- a/build/pkgs/retrolab/dependencies +++ /dev/null @@ -1,4 +0,0 @@ - jupyterlab | $(PYTHON_TOOLCHAIN) $(PYTHON) - ----------- -All lines of this file are ignored except the first. diff --git a/build/pkgs/retrolab/distros/conda.txt b/build/pkgs/retrolab/distros/conda.txt deleted file mode 100644 index 7f3af99fb78..00000000000 --- a/build/pkgs/retrolab/distros/conda.txt +++ /dev/null @@ -1 +0,0 @@ -retrolab diff --git a/build/pkgs/retrolab/requirements.txt b/build/pkgs/retrolab/requirements.txt deleted file mode 100644 index 059cd874f5d..00000000000 --- a/build/pkgs/retrolab/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -retrolab ~= 0.3 diff --git a/build/pkgs/retrolab/type b/build/pkgs/retrolab/type deleted file mode 100644 index 134d9bc32d5..00000000000 --- a/build/pkgs/retrolab/type +++ /dev/null @@ -1 +0,0 @@ -optional diff --git a/build/pkgs/rfc3339_validator/SPKG.rst b/build/pkgs/rfc3339_validator/SPKG.rst new file mode 100644 index 00000000000..1795adb3fef --- /dev/null +++ b/build/pkgs/rfc3339_validator/SPKG.rst @@ -0,0 +1,18 @@ +rfc3339_validator: A pure python RFC3339 validator +================================================== + +Description +----------- + +A pure python RFC3339 validator + +License +------- + +MIT license + +Upstream Contact +---------------- + +https://pypi.org/project/rfc3339-validator/ + diff --git a/build/pkgs/rfc3339_validator/checksums.ini b/build/pkgs/rfc3339_validator/checksums.ini new file mode 100644 index 00000000000..f91914fd5f7 --- /dev/null +++ b/build/pkgs/rfc3339_validator/checksums.ini @@ -0,0 +1,5 @@ +tarball=rfc3339_validator-VERSION-py2.py3-none-any.whl +sha1=daa86cb641dfd6ebfef4ece6dea1be8fd63dec00 +md5=e16fb743ff1c88d7c7de18890935b647 +cksum=2330309218 +upstream_url=https://pypi.io/packages/py2.py3/r/rfc3339_validator/rfc3339_validator-VERSION-py2.py3-none-any.whl diff --git a/build/pkgs/rfc3339_validator/dependencies b/build/pkgs/rfc3339_validator/dependencies new file mode 100644 index 00000000000..47296a7bace --- /dev/null +++ b/build/pkgs/rfc3339_validator/dependencies @@ -0,0 +1,4 @@ + | $(PYTHON_TOOLCHAIN) $(PYTHON) + +---------- +All lines of this file are ignored except the first. diff --git a/build/pkgs/rfc3339_validator/install-requires.txt b/build/pkgs/rfc3339_validator/install-requires.txt new file mode 100644 index 00000000000..26ed401db35 --- /dev/null +++ b/build/pkgs/rfc3339_validator/install-requires.txt @@ -0,0 +1 @@ +rfc3339-validator diff --git a/build/pkgs/rfc3339_validator/package-version.txt b/build/pkgs/rfc3339_validator/package-version.txt new file mode 100644 index 00000000000..845639eef26 --- /dev/null +++ b/build/pkgs/rfc3339_validator/package-version.txt @@ -0,0 +1 @@ +0.1.4 diff --git a/build/pkgs/rfc3339_validator/type b/build/pkgs/rfc3339_validator/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/rfc3339_validator/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/rfc3986_validator/SPKG.rst b/build/pkgs/rfc3986_validator/SPKG.rst new file mode 100644 index 00000000000..f7abaad9edb --- /dev/null +++ b/build/pkgs/rfc3986_validator/SPKG.rst @@ -0,0 +1,18 @@ +rfc3986_validator: Pure python rfc3986 validator +================================================ + +Description +----------- + +Pure python rfc3986 validator + +License +------- + +MIT license + +Upstream Contact +---------------- + +https://pypi.org/project/rfc3986-validator/ + diff --git a/build/pkgs/rfc3986_validator/checksums.ini b/build/pkgs/rfc3986_validator/checksums.ini new file mode 100644 index 00000000000..c0ad30c07e7 --- /dev/null +++ b/build/pkgs/rfc3986_validator/checksums.ini @@ -0,0 +1,5 @@ +tarball=rfc3986_validator-VERSION-py2.py3-none-any.whl +sha1=c0fabd5c0568cc516f9258f3e5846a04a059dc31 +md5=41aef4395cd3d560c96a3992534dfd53 +cksum=1606077510 +upstream_url=https://pypi.io/packages/py2.py3/r/rfc3986_validator/rfc3986_validator-VERSION-py2.py3-none-any.whl diff --git a/build/pkgs/rfc3986_validator/dependencies b/build/pkgs/rfc3986_validator/dependencies new file mode 100644 index 00000000000..47296a7bace --- /dev/null +++ b/build/pkgs/rfc3986_validator/dependencies @@ -0,0 +1,4 @@ + | $(PYTHON_TOOLCHAIN) $(PYTHON) + +---------- +All lines of this file are ignored except the first. diff --git a/build/pkgs/rfc3986_validator/install-requires.txt b/build/pkgs/rfc3986_validator/install-requires.txt new file mode 100644 index 00000000000..f7a1c754962 --- /dev/null +++ b/build/pkgs/rfc3986_validator/install-requires.txt @@ -0,0 +1 @@ +rfc3986-validator diff --git a/build/pkgs/rfc3986_validator/package-version.txt b/build/pkgs/rfc3986_validator/package-version.txt new file mode 100644 index 00000000000..17e51c385ea --- /dev/null +++ b/build/pkgs/rfc3986_validator/package-version.txt @@ -0,0 +1 @@ +0.1.1 diff --git a/build/pkgs/rfc3986_validator/type b/build/pkgs/rfc3986_validator/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/rfc3986_validator/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/sage_conf/install-requires.txt b/build/pkgs/sage_conf/install-requires.txt index 69ceb96ebeb..38ec7e2cd5d 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.2rc5 +sage-conf ~= 10.3b0 diff --git a/build/pkgs/sage_docbuild/install-requires.txt b/build/pkgs/sage_docbuild/install-requires.txt index 7eb9bc66d31..3769c7054e8 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.2rc5 +sage-docbuild ~= 10.3b0 diff --git a/build/pkgs/sage_setup/install-requires.txt b/build/pkgs/sage_setup/install-requires.txt index 97e120387e6..0913b873634 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.2rc5 +sage-setup ~= 10.3b0 diff --git a/build/pkgs/sage_sws2rst/install-requires.txt b/build/pkgs/sage_sws2rst/install-requires.txt index 2dba653e685..8e3570a99d3 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.2rc5 +sage-sws2rst ~= 10.3b0 diff --git a/build/pkgs/sagelib/dependencies b/build/pkgs/sagelib/dependencies index 5dc2efe1d31..fa6e98df7db 100644 --- a/build/pkgs/sagelib/dependencies +++ b/build/pkgs/sagelib/dependencies @@ -1,4 +1,4 @@ -FORCE $(SCRIPTS) arb boost_cropped $(BLAS) brial cliquer cypari cysignals cython ecl eclib ecm flint libgd gap giac givaro glpk gmpy2 gsl iml importlib_metadata importlib_resources jupyter_core lcalc lrcalc_python libbraiding libhomfly libpng linbox m4ri m4rie memory_allocator mpc mpfi mpfr $(MP_LIBRARY) ntl numpy pari pip pkgconfig planarity ppl pplpy primesieve primecount primecountpy pycygwin $(PYTHON) requests rw sage_conf singular symmetrica typing_extensions $(PCFILES) | $(PYTHON_TOOLCHAIN) sage_setup $(PYTHON) pythran +FORCE $(SCRIPTS) boost_cropped $(BLAS) brial cliquer cypari cysignals cython ecl eclib ecm flint libgd gap giac givaro glpk gmpy2 gsl iml importlib_metadata importlib_resources jupyter_core lcalc lrcalc_python libbraiding libhomfly libpng linbox m4ri m4rie memory_allocator mpc mpfi mpfr $(MP_LIBRARY) ntl numpy pari pip pkgconfig planarity ppl pplpy primesieve primecount primecountpy pycygwin $(PYTHON) requests rw sage_conf singular symmetrica typing_extensions $(PCFILES) | $(PYTHON_TOOLCHAIN) sage_setup $(PYTHON) pythran ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/sagelib/install-requires.txt b/build/pkgs/sagelib/install-requires.txt index 88b37e5b39b..307a02db545 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 -sagemath-standard ~= 10.2rc5 +sagemath-standard ~= 10.3b0 diff --git a/build/pkgs/sagemath_bliss/install-requires.txt b/build/pkgs/sagemath_bliss/install-requires.txt index 802cb5862b5..b340ea27044 100644 --- a/build/pkgs/sagemath_bliss/install-requires.txt +++ b/build/pkgs/sagemath_bliss/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-bliss ~= 10.2rc5 +sagemath-bliss ~= 10.3b0 diff --git a/build/pkgs/sagemath_categories/install-requires.txt b/build/pkgs/sagemath_categories/install-requires.txt index 2b855c948b8..9019a793f10 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.2rc5 +sagemath-categories ~= 10.3b0 diff --git a/build/pkgs/sagemath_coxeter3/install-requires.txt b/build/pkgs/sagemath_coxeter3/install-requires.txt index 53877fef069..e57fd056654 100644 --- a/build/pkgs/sagemath_coxeter3/install-requires.txt +++ b/build/pkgs/sagemath_coxeter3/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-coxeter3 ~= 10.2rc5 +sagemath-coxeter3 ~= 10.3b0 diff --git a/build/pkgs/sagemath_environment/install-requires.txt b/build/pkgs/sagemath_environment/install-requires.txt index baa147acba3..9202789d78a 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.2rc5 +sagemath-environment ~= 10.3b0 diff --git a/build/pkgs/sagemath_mcqd/install-requires.txt b/build/pkgs/sagemath_mcqd/install-requires.txt index d788fa95032..93f176e6fc5 100644 --- a/build/pkgs/sagemath_mcqd/install-requires.txt +++ b/build/pkgs/sagemath_mcqd/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-mcqd ~= 10.2rc5 +sagemath-mcqd ~= 10.3b0 diff --git a/build/pkgs/sagemath_meataxe/install-requires.txt b/build/pkgs/sagemath_meataxe/install-requires.txt index 785e39748d8..ee1e280aad1 100644 --- a/build/pkgs/sagemath_meataxe/install-requires.txt +++ b/build/pkgs/sagemath_meataxe/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-meataxe ~= 10.2rc5 +sagemath-meataxe ~= 10.3b0 diff --git a/build/pkgs/sagemath_objects/install-requires.txt b/build/pkgs/sagemath_objects/install-requires.txt index fc3dc412bcd..07baf32ec81 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.2rc5 +sagemath-objects ~= 10.3b0 diff --git a/build/pkgs/sagemath_repl/install-requires.txt b/build/pkgs/sagemath_repl/install-requires.txt index c8430b9db44..79c7e5a7ed0 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.2rc5 +sagemath-repl ~= 10.3b0 diff --git a/build/pkgs/sagemath_sirocco/install-requires.txt b/build/pkgs/sagemath_sirocco/install-requires.txt index ccb288563b1..44ebb97d788 100644 --- a/build/pkgs/sagemath_sirocco/install-requires.txt +++ b/build/pkgs/sagemath_sirocco/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-sirocco ~= 10.2rc5 +sagemath-sirocco ~= 10.3b0 diff --git a/build/pkgs/sagemath_tdlib/install-requires.txt b/build/pkgs/sagemath_tdlib/install-requires.txt index cb431838e65..ea24439a16a 100644 --- a/build/pkgs/sagemath_tdlib/install-requires.txt +++ b/build/pkgs/sagemath_tdlib/install-requires.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-tdlib ~= 10.2rc5 +sagemath-tdlib ~= 10.3b0 diff --git a/build/pkgs/sniffio/SPKG.rst b/build/pkgs/sniffio/SPKG.rst new file mode 100644 index 00000000000..238aeec12b3 --- /dev/null +++ b/build/pkgs/sniffio/SPKG.rst @@ -0,0 +1,18 @@ +sniffio: Sniff out which async library your code is running under +================================================================= + +Description +----------- + +Sniff out which async library your code is running under + +License +------- + +MIT OR Apache-2.0 + +Upstream Contact +---------------- + +https://pypi.org/project/sniffio/ + diff --git a/build/pkgs/sniffio/checksums.ini b/build/pkgs/sniffio/checksums.ini new file mode 100644 index 00000000000..d8475bc91d3 --- /dev/null +++ b/build/pkgs/sniffio/checksums.ini @@ -0,0 +1,5 @@ +tarball=sniffio-VERSION-py3-none-any.whl +sha1=16f883fd7e31aa383df8901002f9ce5cec7606e5 +md5=7890655ffc549d04087bbc2f93332034 +cksum=2528943486 +upstream_url=https://pypi.io/packages/py3/s/sniffio/sniffio-VERSION-py3-none-any.whl diff --git a/build/pkgs/sniffio/dependencies b/build/pkgs/sniffio/dependencies new file mode 100644 index 00000000000..47296a7bace --- /dev/null +++ b/build/pkgs/sniffio/dependencies @@ -0,0 +1,4 @@ + | $(PYTHON_TOOLCHAIN) $(PYTHON) + +---------- +All lines of this file are ignored except the first. diff --git a/build/pkgs/sniffio/install-requires.txt b/build/pkgs/sniffio/install-requires.txt new file mode 100644 index 00000000000..01c650244d0 --- /dev/null +++ b/build/pkgs/sniffio/install-requires.txt @@ -0,0 +1 @@ +sniffio diff --git a/build/pkgs/sniffio/package-version.txt b/build/pkgs/sniffio/package-version.txt new file mode 100644 index 00000000000..f0bb29e7638 --- /dev/null +++ b/build/pkgs/sniffio/package-version.txt @@ -0,0 +1 @@ +1.3.0 diff --git a/build/pkgs/sniffio/type b/build/pkgs/sniffio/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/sniffio/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/stack_data/checksums.ini b/build/pkgs/stack_data/checksums.ini index 625aaf0578f..f86f44c1587 100644 --- a/build/pkgs/stack_data/checksums.ini +++ b/build/pkgs/stack_data/checksums.ini @@ -1,5 +1,5 @@ tarball=stack_data-VERSION.tar.gz -sha1=58ed9cb32a42e07dbc18356d06f8db96475bc0f2 -md5=05c8c6c58c02280bc87b6851e40d38e6 -cksum=1485401259 +sha1=7f7627afc47570ffb06924c1b2fbb48e21bac724 +md5=d04f7cda6589138e90691aec1edbf0d5 +cksum=4043168585 upstream_url=https://pypi.io/packages/source/s/stack_data/stack_data-VERSION.tar.gz diff --git a/build/pkgs/stack_data/package-version.txt b/build/pkgs/stack_data/package-version.txt index ee6cdce3c29..844f6a91acb 100644 --- a/build/pkgs/stack_data/package-version.txt +++ b/build/pkgs/stack_data/package-version.txt @@ -1 +1 @@ -0.6.1 +0.6.3 diff --git a/build/pkgs/symengine/dependencies b/build/pkgs/symengine/dependencies index 1fc34963eda..7795d486018 100644 --- a/build/pkgs/symengine/dependencies +++ b/build/pkgs/symengine/dependencies @@ -1,4 +1,4 @@ -$(MP_LIBRARY) arb ecm flint mpc mpfr | cmake +$(MP_LIBRARY) ecm flint mpc mpfr | cmake ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/terminado/checksums.ini b/build/pkgs/terminado/checksums.ini index 27333946973..be9b273fa2b 100644 --- a/build/pkgs/terminado/checksums.ini +++ b/build/pkgs/terminado/checksums.ini @@ -1,5 +1,5 @@ tarball=terminado-VERSION.tar.gz -sha1=e2e37fe16c03d5bb6ab035c78e99a89bc742384c -md5=cf5f5f7dd1ece772f16013ad355b75e1 -cksum=2626848318 +sha1=608fcc44b845e1fb783e361d59e79fba83126e14 +md5=aafcc42623986e42469712786edb127c +cksum=3344744872 upstream_url=https://pypi.io/packages/source/t/terminado/terminado-VERSION.tar.gz diff --git a/build/pkgs/terminado/package-version.txt b/build/pkgs/terminado/package-version.txt index c5523bd09b1..7cca7711a0d 100644 --- a/build/pkgs/terminado/package-version.txt +++ b/build/pkgs/terminado/package-version.txt @@ -1 +1 @@ -0.17.0 +0.17.1 diff --git a/build/pkgs/tomlkit/distros/gentoo.txt b/build/pkgs/tomlkit/distros/gentoo.txt deleted file mode 100644 index afe59d9bfe2..00000000000 --- a/build/pkgs/tomlkit/distros/gentoo.txt +++ /dev/null @@ -1 +0,0 @@ -dev-python/tomlkit diff --git a/build/pkgs/tomlkit/spkg-configure.m4 b/build/pkgs/tomlkit/spkg-configure.m4 deleted file mode 100644 index 6da571e5370..00000000000 --- a/build/pkgs/tomlkit/spkg-configure.m4 +++ /dev/null @@ -1,2 +0,0 @@ -SAGE_SPKG_CONFIGURE([tomlkit], [SAGE_PYTHON_PACKAGE_CHECK([tomlkit])]) - diff --git a/build/pkgs/tornado/checksums.ini b/build/pkgs/tornado/checksums.ini index 9f69d85d5dc..46e14d34d98 100644 --- a/build/pkgs/tornado/checksums.ini +++ b/build/pkgs/tornado/checksums.ini @@ -1,5 +1,5 @@ tarball=tornado-VERSION.tar.gz -sha1=2fa6cbd83ebafad83f49e89fbd5bbd20c42bbdc9 -md5=32fbad606b439c3e1bf4e79d4e872741 -cksum=3183867326 +sha1=de0ef2eb77e7ca1ba1210bd02d56d9494b413cd7 +md5=e5fca0b30397bbdfe1f5e8e49e6cacf9 +cksum=327419258 upstream_url=https://pypi.io/packages/source/t/tornado/tornado-VERSION.tar.gz diff --git a/build/pkgs/tornado/package-version.txt b/build/pkgs/tornado/package-version.txt index 0cda48ac61e..7849b73dc74 100644 --- a/build/pkgs/tornado/package-version.txt +++ b/build/pkgs/tornado/package-version.txt @@ -1 +1 @@ -6.2 +6.3.3 diff --git a/build/pkgs/traitlets/checksums.ini b/build/pkgs/traitlets/checksums.ini index 8ca6285b9e3..fb0575fb4db 100644 --- a/build/pkgs/traitlets/checksums.ini +++ b/build/pkgs/traitlets/checksums.ini @@ -1,5 +1,5 @@ tarball=traitlets-VERSION.tar.gz -sha1=694fb48d89f2dcdca0d15957a23e24e340ac1567 -md5=91af43de0a2182735677875b4c8a533a -cksum=1530835442 +sha1=7dffc7781492e43a88dad84c925c0acfbc370943 +md5=58e13c21997e7cc01dda3765c9731f95 +cksum=1487040947 upstream_url=https://pypi.io/packages/source/t/traitlets/traitlets-VERSION.tar.gz diff --git a/build/pkgs/traitlets/package-version.txt b/build/pkgs/traitlets/package-version.txt index b3d91f9cfc0..26f30f79ccc 100644 --- a/build/pkgs/traitlets/package-version.txt +++ b/build/pkgs/traitlets/package-version.txt @@ -1 +1 @@ -5.9.0 +5.13.0 diff --git a/build/pkgs/types_python_dateutil/SPKG.rst b/build/pkgs/types_python_dateutil/SPKG.rst new file mode 100644 index 00000000000..8c8c7929594 --- /dev/null +++ b/build/pkgs/types_python_dateutil/SPKG.rst @@ -0,0 +1,18 @@ +types_python_dateutil: Typing stubs for python-dateutil +======================================================= + +Description +----------- + +Typing stubs for python-dateutil + +License +------- + +Apache-2.0 license + +Upstream Contact +---------------- + +https://pypi.org/project/types-python-dateutil/ + diff --git a/build/pkgs/types_python_dateutil/checksums.ini b/build/pkgs/types_python_dateutil/checksums.ini new file mode 100644 index 00000000000..f0dc860781b --- /dev/null +++ b/build/pkgs/types_python_dateutil/checksums.ini @@ -0,0 +1,5 @@ +tarball=types_python_dateutil-VERSION-py3-none-any.whl +sha1=c039b93ad4b5f3ea1c6aac3d08386995e8c7b19e +md5=6281a2b67e2347366238ef28e3f8a070 +cksum=1399426019 +upstream_url=https://pypi.io/packages/py3/t/types_python_dateutil/types_python_dateutil-VERSION-py3-none-any.whl diff --git a/build/pkgs/types_python_dateutil/dependencies b/build/pkgs/types_python_dateutil/dependencies new file mode 100644 index 00000000000..47296a7bace --- /dev/null +++ b/build/pkgs/types_python_dateutil/dependencies @@ -0,0 +1,4 @@ + | $(PYTHON_TOOLCHAIN) $(PYTHON) + +---------- +All lines of this file are ignored except the first. diff --git a/build/pkgs/types_python_dateutil/install-requires.txt b/build/pkgs/types_python_dateutil/install-requires.txt new file mode 100644 index 00000000000..890ac2f7409 --- /dev/null +++ b/build/pkgs/types_python_dateutil/install-requires.txt @@ -0,0 +1 @@ +types-python-dateutil diff --git a/build/pkgs/types_python_dateutil/package-version.txt b/build/pkgs/types_python_dateutil/package-version.txt new file mode 100644 index 00000000000..b7ec6d6578b --- /dev/null +++ b/build/pkgs/types_python_dateutil/package-version.txt @@ -0,0 +1 @@ +2.8.19.14 diff --git a/build/pkgs/types_python_dateutil/type b/build/pkgs/types_python_dateutil/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/types_python_dateutil/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/uri_template/SPKG.rst b/build/pkgs/uri_template/SPKG.rst new file mode 100644 index 00000000000..e8f6af0ec09 --- /dev/null +++ b/build/pkgs/uri_template/SPKG.rst @@ -0,0 +1,18 @@ +uri_template: RFC 6570 URI Template Processor +============================================= + +Description +----------- + +RFC 6570 URI Template Processor + +License +------- + +MIT License + +Upstream Contact +---------------- + +https://pypi.org/project/uri-template/ + diff --git a/build/pkgs/uri_template/checksums.ini b/build/pkgs/uri_template/checksums.ini new file mode 100644 index 00000000000..cdcfc0caeaa --- /dev/null +++ b/build/pkgs/uri_template/checksums.ini @@ -0,0 +1,5 @@ +tarball=uri_template-VERSION-py3-none-any.whl +sha1=bbc8808bdb7e687f0c099c8120cd901dc90bce69 +md5=7d7f28c2ffd7d4746174ab761f6025e5 +cksum=1943559906 +upstream_url=https://pypi.io/packages/py3/u/uri_template/uri_template-VERSION-py3-none-any.whl diff --git a/build/pkgs/uri_template/dependencies b/build/pkgs/uri_template/dependencies new file mode 100644 index 00000000000..47296a7bace --- /dev/null +++ b/build/pkgs/uri_template/dependencies @@ -0,0 +1,4 @@ + | $(PYTHON_TOOLCHAIN) $(PYTHON) + +---------- +All lines of this file are ignored except the first. diff --git a/build/pkgs/uri_template/install-requires.txt b/build/pkgs/uri_template/install-requires.txt new file mode 100644 index 00000000000..5d10570d87b --- /dev/null +++ b/build/pkgs/uri_template/install-requires.txt @@ -0,0 +1 @@ +uri-template diff --git a/build/pkgs/uri_template/package-version.txt b/build/pkgs/uri_template/package-version.txt new file mode 100644 index 00000000000..f0bb29e7638 --- /dev/null +++ b/build/pkgs/uri_template/package-version.txt @@ -0,0 +1 @@ +1.3.0 diff --git a/build/pkgs/uri_template/type b/build/pkgs/uri_template/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/uri_template/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/urllib3/checksums.ini b/build/pkgs/urllib3/checksums.ini index bfb7c5afa48..758013b041c 100644 --- a/build/pkgs/urllib3/checksums.ini +++ b/build/pkgs/urllib3/checksums.ini @@ -1,5 +1,5 @@ tarball=urllib3-VERSION.tar.gz -sha1=ad6bd811a3f4c3e04d86c2706c9994c3e2236e53 -md5=ba308b52b9092184cf4905bc59a88fc0 -cksum=2776794349 +sha1=b784e5ebe0377d45a406665f3a3fad2616cbed22 +md5=4d824b7bba1976591fc05fad02fb258d +cksum=3511203397 upstream_url=https://pypi.io/packages/source/u/urllib3/urllib3-VERSION.tar.gz diff --git a/build/pkgs/urllib3/dependencies b/build/pkgs/urllib3/dependencies index 47296a7bace..cfb7c484697 100644 --- a/build/pkgs/urllib3/dependencies +++ b/build/pkgs/urllib3/dependencies @@ -1,4 +1,4 @@ - | $(PYTHON_TOOLCHAIN) $(PYTHON) + | $(PYTHON_TOOLCHAIN) hatchling $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/urllib3/package-version.txt b/build/pkgs/urllib3/package-version.txt index b74a856da82..e01025862f7 100644 --- a/build/pkgs/urllib3/package-version.txt +++ b/build/pkgs/urllib3/package-version.txt @@ -1 +1 @@ -1.26.12 +2.0.5 diff --git a/build/pkgs/vcversioner/SPKG.rst b/build/pkgs/vcversioner/SPKG.rst deleted file mode 100644 index 17d7f952f61..00000000000 --- a/build/pkgs/vcversioner/SPKG.rst +++ /dev/null @@ -1,25 +0,0 @@ -vcversioner: Python build system extension to obtain package version from version control -========================================================================================= - -Description ------------ - -Write a setup.py with no version information specified, and vcversioner -will find a recent, properly-formatted VCS tag and extract a version -from it. - -License -------- - -Python Software Foundation License - - -Upstream Contact ----------------- - -Home page: https://pypi.python.org/pypi/vcversioner/ - -Dependencies ------------- - -Python, Setuptools diff --git a/build/pkgs/vcversioner/checksums.ini b/build/pkgs/vcversioner/checksums.ini deleted file mode 100644 index 4d294a20994..00000000000 --- a/build/pkgs/vcversioner/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=vcversioner-VERSION.tar.gz -sha1=ce076b62e8f0772bf79f29762bfc3cf09f6781b5 -md5=aab6ef5e0cf8614a1b1140ed5b7f107d -cksum=1650555311 diff --git a/build/pkgs/vcversioner/distros/conda.txt b/build/pkgs/vcversioner/distros/conda.txt deleted file mode 100644 index 39a323addb3..00000000000 --- a/build/pkgs/vcversioner/distros/conda.txt +++ /dev/null @@ -1 +0,0 @@ -vcversioner diff --git a/build/pkgs/vcversioner/distros/macports.txt b/build/pkgs/vcversioner/distros/macports.txt deleted file mode 100644 index 17f91a4d953..00000000000 --- a/build/pkgs/vcversioner/distros/macports.txt +++ /dev/null @@ -1 +0,0 @@ -py-vcversioner diff --git a/build/pkgs/vcversioner/distros/opensuse.txt b/build/pkgs/vcversioner/distros/opensuse.txt deleted file mode 100644 index a9b307f8509..00000000000 --- a/build/pkgs/vcversioner/distros/opensuse.txt +++ /dev/null @@ -1 +0,0 @@ -python3${PYTHON_MINOR}-vcversioner diff --git a/build/pkgs/vcversioner/distros/repology.txt b/build/pkgs/vcversioner/distros/repology.txt deleted file mode 100644 index 1cf127b4f86..00000000000 --- a/build/pkgs/vcversioner/distros/repology.txt +++ /dev/null @@ -1,2 +0,0 @@ -vcversioner -python:vcversioner diff --git a/build/pkgs/vcversioner/install-requires.txt b/build/pkgs/vcversioner/install-requires.txt deleted file mode 100644 index dbc9d542440..00000000000 --- a/build/pkgs/vcversioner/install-requires.txt +++ /dev/null @@ -1 +0,0 @@ -vcversioner >=2.16.0.0 diff --git a/build/pkgs/vcversioner/package-version.txt b/build/pkgs/vcversioner/package-version.txt deleted file mode 100644 index f66e5d36e77..00000000000 --- a/build/pkgs/vcversioner/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -2.16.0.0.p0 diff --git a/build/pkgs/vcversioner/spkg-install.in b/build/pkgs/vcversioner/spkg-install.in deleted file mode 100644 index 956aeb8c5a7..00000000000 --- a/build/pkgs/vcversioner/spkg-install.in +++ /dev/null @@ -1,14 +0,0 @@ -if [ -z "$SAGE_LOCAL" ]; then - echo >&2 "SAGE_LOCAL undefined ... exiting" - echo >&2 "Maybe run 'sage --sh'?" - exit 1 -fi - -cd src - -sdh_pip_install . - -if [ $? -ne 0 ]; then - echo "Error installing vcversioner ... exiting" - exit 1 -fi diff --git a/build/pkgs/wcwidth/checksums.ini b/build/pkgs/wcwidth/checksums.ini index e81b55d8053..2745366a726 100644 --- a/build/pkgs/wcwidth/checksums.ini +++ b/build/pkgs/wcwidth/checksums.ini @@ -1,5 +1,5 @@ tarball=wcwidth-VERSION.tar.gz -sha1=3822ed26dc70a4055827bc66cdc21126e51efd66 -md5=a07a75f99d316e14838ac760c831ea37 -cksum=497830371 +sha1=49bdbcac346f31be8201c663082331b693264382 +md5=c37cceb9d573adcce0b3e5167ecb1df9 +cksum=68756555 upstream_url=https://pypi.io/packages/source/w/wcwidth/wcwidth-VERSION.tar.gz diff --git a/build/pkgs/wcwidth/package-version.txt b/build/pkgs/wcwidth/package-version.txt index 3a4036fb450..f2722b13396 100644 --- a/build/pkgs/wcwidth/package-version.txt +++ b/build/pkgs/wcwidth/package-version.txt @@ -1 +1 @@ -0.2.5 +0.2.12 diff --git a/build/pkgs/webcolors/SPKG.rst b/build/pkgs/webcolors/SPKG.rst new file mode 100644 index 00000000000..760b53943d2 --- /dev/null +++ b/build/pkgs/webcolors/SPKG.rst @@ -0,0 +1,18 @@ +webcolors: A library for working with the color formats defined by HTML and CSS. +================================================================================ + +Description +----------- + +A library for working with the color formats defined by HTML and CSS. + +License +------- + +BSD-3-Clause + +Upstream Contact +---------------- + +https://pypi.org/project/webcolors/ + diff --git a/build/pkgs/webcolors/checksums.ini b/build/pkgs/webcolors/checksums.ini new file mode 100644 index 00000000000..4a7e6f5de15 --- /dev/null +++ b/build/pkgs/webcolors/checksums.ini @@ -0,0 +1,5 @@ +tarball=webcolors-VERSION-py3-none-any.whl +sha1=e13a9143964b824fc4972b60eddd8115f6839a26 +md5=d9e9ac7c1da7a2b18975265cf0a953ac +cksum=371137261 +upstream_url=https://pypi.io/packages/py3/w/webcolors/webcolors-VERSION-py3-none-any.whl diff --git a/build/pkgs/webcolors/dependencies b/build/pkgs/webcolors/dependencies new file mode 100644 index 00000000000..47296a7bace --- /dev/null +++ b/build/pkgs/webcolors/dependencies @@ -0,0 +1,4 @@ + | $(PYTHON_TOOLCHAIN) $(PYTHON) + +---------- +All lines of this file are ignored except the first. diff --git a/build/pkgs/webcolors/install-requires.txt b/build/pkgs/webcolors/install-requires.txt new file mode 100644 index 00000000000..2ff3d436217 --- /dev/null +++ b/build/pkgs/webcolors/install-requires.txt @@ -0,0 +1 @@ +webcolors diff --git a/build/pkgs/webcolors/package-version.txt b/build/pkgs/webcolors/package-version.txt new file mode 100644 index 00000000000..d3456a90f7d --- /dev/null +++ b/build/pkgs/webcolors/package-version.txt @@ -0,0 +1 @@ +1.13 diff --git a/build/pkgs/webcolors/type b/build/pkgs/webcolors/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/webcolors/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/websocket_client/SPKG.rst b/build/pkgs/websocket_client/SPKG.rst new file mode 100644 index 00000000000..31b54420fd0 --- /dev/null +++ b/build/pkgs/websocket_client/SPKG.rst @@ -0,0 +1,18 @@ +websocket_client: WebSocket client for Python with low level API options +======================================================================== + +Description +----------- + +WebSocket client for Python with low level API options + +License +------- + +Apache-2.0 + +Upstream Contact +---------------- + +https://pypi.org/project/websocket-client/ + diff --git a/build/pkgs/websocket_client/checksums.ini b/build/pkgs/websocket_client/checksums.ini new file mode 100644 index 00000000000..5ebee45e9f9 --- /dev/null +++ b/build/pkgs/websocket_client/checksums.ini @@ -0,0 +1,5 @@ +tarball=websocket_client-VERSION-py3-none-any.whl +sha1=eb78bd39f1ae4d531cc965bd21d121ba3d156f84 +md5=bea7b61d0eda66ffb9071c469d937255 +cksum=21706746 +upstream_url=https://pypi.io/packages/py3/w/websocket_client/websocket_client-VERSION-py3-none-any.whl diff --git a/build/pkgs/websocket_client/dependencies b/build/pkgs/websocket_client/dependencies new file mode 100644 index 00000000000..47296a7bace --- /dev/null +++ b/build/pkgs/websocket_client/dependencies @@ -0,0 +1,4 @@ + | $(PYTHON_TOOLCHAIN) $(PYTHON) + +---------- +All lines of this file are ignored except the first. diff --git a/build/pkgs/websocket_client/install-requires.txt b/build/pkgs/websocket_client/install-requires.txt new file mode 100644 index 00000000000..db0afb87c14 --- /dev/null +++ b/build/pkgs/websocket_client/install-requires.txt @@ -0,0 +1 @@ +websocket-client diff --git a/build/pkgs/websocket_client/package-version.txt b/build/pkgs/websocket_client/package-version.txt new file mode 100644 index 00000000000..9edc58bb1dd --- /dev/null +++ b/build/pkgs/websocket_client/package-version.txt @@ -0,0 +1 @@ +1.6.4 diff --git a/build/pkgs/websocket_client/type b/build/pkgs/websocket_client/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/websocket_client/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/widgetsnbextension/checksums.ini b/build/pkgs/widgetsnbextension/checksums.ini index 30e08312a8f..6c7893d9502 100644 --- a/build/pkgs/widgetsnbextension/checksums.ini +++ b/build/pkgs/widgetsnbextension/checksums.ini @@ -1,5 +1,5 @@ tarball=widgetsnbextension-VERSION-py3-none-any.whl -sha1=1ffb84b17fca00a6e4bbad41f395ed6f37e1c6b9 -md5=38786a4166938b1b4165a76c244c3fc9 -cksum=2255132975 +sha1=067535b5d1738a4de0abb5f1219581a4a66d243c +md5=ac2760673371602f990bb24ac7925c5f +cksum=1509404095 upstream_url=https://pypi.io/packages/py3/w/widgetsnbextension/widgetsnbextension-VERSION-py3-none-any.whl diff --git a/build/pkgs/widgetsnbextension/package-version.txt b/build/pkgs/widgetsnbextension/package-version.txt index a2cec7aff41..7919852fe10 100644 --- a/build/pkgs/widgetsnbextension/package-version.txt +++ b/build/pkgs/widgetsnbextension/package-version.txt @@ -1 +1 @@ -4.0.8 +4.0.9 diff --git a/build/pkgs/zipp/checksums.ini b/build/pkgs/zipp/checksums.ini index 53d559563f8..66cd13339d6 100644 --- a/build/pkgs/zipp/checksums.ini +++ b/build/pkgs/zipp/checksums.ini @@ -1,5 +1,5 @@ tarball=zipp-VERSION.tar.gz -sha1=3f6c57b68f3b9165586ea7cce96fc2540b0078ec -md5=1fbff3bca7294a3a7f09fa3f0652c3da -cksum=1128680850 +sha1=a9f9aebc205b7829c43b34e79c3f87c42b183176 +md5=a4cf8c530da863c27a04251724436681 +cksum=1303269799 upstream_url=https://pypi.io/packages/source/z/zipp/zipp-VERSION.tar.gz diff --git a/build/pkgs/zipp/dependencies b/build/pkgs/zipp/dependencies index 9be6b4aab7c..995ddecb8f4 100644 --- a/build/pkgs/zipp/dependencies +++ b/build/pkgs/zipp/dependencies @@ -1,4 +1,4 @@ - vcversioner | $(PYTHON_TOOLCHAIN) $(PYTHON) + | $(PYTHON_TOOLCHAIN) setuptools_scm $(PYTHON) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/zipp/package-version.txt b/build/pkgs/zipp/package-version.txt index afad818663d..3f67e25cea1 100644 --- a/build/pkgs/zipp/package-version.txt +++ b/build/pkgs/zipp/package-version.txt @@ -1 +1 @@ -3.11.0 +3.17.0 diff --git a/configure.ac b/configure.ac index 62d80bc79ca..d1c2aceb413 100644 --- a/configure.ac +++ b/configure.ac @@ -507,7 +507,7 @@ AC_ARG_ENABLE([cvxopt], AC_ARG_ENABLE([notebook], AS_HELP_STRING([--disable-notebook], [disable build of the Jupyter notebook and related packages]), [ - for pkg in notebook nbconvert beautifulsoup4 sagenb_export nbformat nbclient terminado send2trash prometheus_client mistune pandocfilters bleach defusedxml jsonschema jupyter_jsmol argon2_cffi argon2_cffi_bindings webencodings tinycss2 ipympl soupsieve fastjsonschema; do + for pkg in notebook nbconvert beautifulsoup4 sagenb_export nbformat nbclient terminado send2trash prometheus_client mistune pandocfilters bleach defusedxml jsonschema jupyter_jsmol argon2_cffi argon2_cffi_bindings webencodings tinycss2 ipympl soupsieve fastjsonschema anyio arrow async_lru fqdn isoduration json5 jsonpointer jsonschema_specifications jupyter_events jupyter_lsp jupyter_server jupyter_server_terminals jupyterlab jupyterlab_mathjax2 notebook_shim overrides python_json_logger pyyaml referencing rfc3339_validator rfc3986_validator sniffio types_python_dateutil uri_template webcolors websocket_client; do AS_VAR_SET([SAGE_ENABLE_$pkg], [$enableval]) done ]) @@ -544,7 +544,7 @@ AC_ARG_ENABLE([sagelib], dnl Handle combinations of --disable-foo flags that may enable us to dnl prune even more dependencies. AS_IF([test "$SAGE_ENABLE_notebook" = no -a "$SAGE_ENABLE_sagelib" = no], [ - for pkg in jupyter_client ipykernel ipython zeromq pyzmq; do + for pkg in jupyter_client ipykernel ipython zeromq pyzmq exceptiongroup; do AS_VAR_SET([SAGE_ENABLE_$pkg], [$enableval]) done ]) diff --git a/pkgs/sage-conf/VERSION.txt b/pkgs/sage-conf/VERSION.txt index ea61754a6ef..d1741c9f234 100644 --- a/pkgs/sage-conf/VERSION.txt +++ b/pkgs/sage-conf/VERSION.txt @@ -1 +1 @@ -10.2.rc5 +10.3.beta0 diff --git a/pkgs/sage-conf/_sage_conf/_conf.py.in b/pkgs/sage-conf/_sage_conf/_conf.py.in index 87b27ca05cb..895d6572d1e 100644 --- a/pkgs/sage-conf/_sage_conf/_conf.py.in +++ b/pkgs/sage-conf/_sage_conf/_conf.py.in @@ -19,8 +19,6 @@ MAXIMA_FAS = "@SAGE_MAXIMA_FAS@".replace('${prefix}', SAGE_LOCAL) # Delete this line if your ECL can load Kenzo without further prodding. KENZO_FAS = "@SAGE_KENZO_FAS@".replace('${prefix}', SAGE_LOCAL) -ARB_LIBRARY = "@SAGE_ARB_LIBRARY@" - NTL_INCDIR = "@NTL_INCDIR@" NTL_LIBDIR = "@NTL_LIBDIR@" diff --git a/pkgs/sage-conf_conda/VERSION.txt b/pkgs/sage-conf_conda/VERSION.txt index ea61754a6ef..d1741c9f234 100644 --- a/pkgs/sage-conf_conda/VERSION.txt +++ b/pkgs/sage-conf_conda/VERSION.txt @@ -1 +1 @@ -10.2.rc5 +10.3.beta0 diff --git a/pkgs/sage-conf_pypi/VERSION.txt b/pkgs/sage-conf_pypi/VERSION.txt index ea61754a6ef..d1741c9f234 100644 --- a/pkgs/sage-conf_pypi/VERSION.txt +++ b/pkgs/sage-conf_pypi/VERSION.txt @@ -1 +1 @@ -10.2.rc5 +10.3.beta0 diff --git a/pkgs/sage-docbuild/VERSION.txt b/pkgs/sage-docbuild/VERSION.txt index ea61754a6ef..d1741c9f234 100644 --- a/pkgs/sage-docbuild/VERSION.txt +++ b/pkgs/sage-docbuild/VERSION.txt @@ -1 +1 @@ -10.2.rc5 +10.3.beta0 diff --git a/pkgs/sage-docbuild/pyproject.toml b/pkgs/sage-docbuild/pyproject.toml new file mode 100644 index 00000000000..77840653af0 --- /dev/null +++ b/pkgs/sage-docbuild/pyproject.toml @@ -0,0 +1,40 @@ +[build-system] +requires = ["setuptools>=61.2"] +build-backend = "setuptools.build_meta" + +[project] +name = "sage-docbuild" +description = "Sage: Open Source Mathematics Software: Build system of the Sage documentation" +license = {text = "GNU General Public License (GPL) v2 or later"} +authors = [{name = "The Sage Developers", email = "sage-support@googlegroups.com"}] +classifiers = [ + "Development Status :: 6 - Mature", + "Intended Audience :: Education", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)", + "Operating System :: POSIX", + "Operating System :: MacOS :: MacOS X", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: Implementation :: CPython", + "Topic :: Scientific/Engineering :: Mathematics", +] +urls = {Homepage = "https://www.sagemath.org"} +dependencies = ["sphinx"] +dynamic = ["version"] + +[project.readme] +file = "README.rst" +content-type = "text/x-rst" + +[tool.setuptools] +packages = [ + "sage_docbuild", + "sage_docbuild.ext", +] +include-package-data = false + +[tool.setuptools.dynamic] +version = {file = ["VERSION.txt"]} diff --git a/pkgs/sage-docbuild/setup.cfg b/pkgs/sage-docbuild/setup.cfg deleted file mode 100644 index 596f9b4506e..00000000000 --- a/pkgs/sage-docbuild/setup.cfg +++ /dev/null @@ -1,32 +0,0 @@ -[metadata] -name = sage-docbuild -version = file: VERSION.txt -description = Sage: Open Source Mathematics Software: Build system of the Sage documentation -long_description = file: README.rst -long_description_content_type = text/x-rst -license = GNU General Public License (GPL) v2 or later -author = The Sage Developers -author_email = sage-support@googlegroups.com -url = https://www.sagemath.org - -classifiers = - Development Status :: 6 - Mature - Intended Audience :: Education - Intended Audience :: Science/Research - License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+) - Operating System :: POSIX - Operating System :: MacOS :: MacOS X - Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3.9 - Programming Language :: Python :: 3.10 - Programming Language :: Python :: 3.11 - Programming Language :: Python :: Implementation :: CPython - Topic :: Scientific/Engineering :: Mathematics - -[options] -packages = - sage_docbuild - sage_docbuild.ext - -install_requires = - sphinx diff --git a/pkgs/sage-setup/VERSION.txt b/pkgs/sage-setup/VERSION.txt index ea61754a6ef..d1741c9f234 100644 --- a/pkgs/sage-setup/VERSION.txt +++ b/pkgs/sage-setup/VERSION.txt @@ -1 +1 @@ -10.2.rc5 +10.3.beta0 diff --git a/pkgs/sage-setup/pyproject.toml b/pkgs/sage-setup/pyproject.toml new file mode 100644 index 00000000000..1499fe4c9ba --- /dev/null +++ b/pkgs/sage-setup/pyproject.toml @@ -0,0 +1,47 @@ +[build-system] +requires = ["setuptools>=61.2"] +build-backend = "setuptools.build_meta" + +[project] +name = "sage-setup" +description = "Sage: Open Source Mathematics Software: Build system of the Sage library" +license = {text = "GNU General Public License (GPL) v2 or later"} +authors = [{name = "The Sage Developers", email = "sage-support@googlegroups.com"}] +classifiers = [ + "Development Status :: 6 - Mature", + "Intended Audience :: Education", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+)", + "Operating System :: POSIX", + "Operating System :: MacOS :: MacOS X", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: Implementation :: CPython", + "Topic :: Scientific/Engineering :: Mathematics", +] +urls = {Homepage = "https://www.sagemath.org"} +requires-python = ">=3.9, <3.12" +dependencies = [] +dynamic = ["version"] + +[project.readme] +file = "README.rst" +content-type = "text/x-rst" + +[project.optional-dependencies] +autogen = ["jinja2"] + +[tool.setuptools] +packages = [ + "sage_setup", + "sage_setup.autogen", + "sage_setup.autogen.interpreters", + "sage_setup.autogen.interpreters.specs", + "sage_setup.command", +] +include-package-data = false + +[tool.setuptools.dynamic] +version = {file = ["VERSION.txt"]} diff --git a/pkgs/sage-setup/setup.cfg b/pkgs/sage-setup/setup.cfg deleted file mode 100644 index 2355ef6b301..00000000000 --- a/pkgs/sage-setup/setup.cfg +++ /dev/null @@ -1,39 +0,0 @@ -[metadata] -name = sage-setup -version = file: VERSION.txt -description = Sage: Open Source Mathematics Software: Build system of the Sage library -long_description = file: README.rst -long_description_content_type = text/x-rst -license = GNU General Public License (GPL) v2 or later -author = The Sage Developers -author_email = sage-support@googlegroups.com -url = https://www.sagemath.org - -classifiers = - Development Status :: 6 - Mature - Intended Audience :: Education - Intended Audience :: Science/Research - License :: OSI Approved :: GNU General Public License v2 or later (GPLv2+) - Operating System :: POSIX - Operating System :: MacOS :: MacOS X - Programming Language :: Python :: 3 :: Only - Programming Language :: Python :: 3.8 - Programming Language :: Python :: 3.9 - Programming Language :: Python :: 3.10 - Programming Language :: Python :: 3.11 - Programming Language :: Python :: Implementation :: CPython - Topic :: Scientific/Engineering :: Mathematics - -[options] -packages = - sage_setup - sage_setup.autogen - sage_setup.autogen.interpreters - sage_setup.autogen.interpreters.specs - sage_setup.command - -python_requires = >=3.9, <3.12 - -install_requires = - pkgconfig - jinja2 diff --git a/pkgs/sage-sws2rst/VERSION.txt b/pkgs/sage-sws2rst/VERSION.txt index ea61754a6ef..d1741c9f234 100644 --- a/pkgs/sage-sws2rst/VERSION.txt +++ b/pkgs/sage-sws2rst/VERSION.txt @@ -1 +1 @@ -10.2.rc5 +10.3.beta0 diff --git a/pkgs/sage-sws2rst/pyproject.toml b/pkgs/sage-sws2rst/pyproject.toml new file mode 100644 index 00000000000..1232437fb1e --- /dev/null +++ b/pkgs/sage-sws2rst/pyproject.toml @@ -0,0 +1,25 @@ +[build-system] +requires = ["setuptools>=61.2"] +build-backend = "setuptools.build_meta" + +[project] +name = "sage-sws2rst" +description = "Sage: Open Source Mathematics Software: SageNB worksheet converter" +license = {text = "GNU General Public License (GPL) v3 or later"} +authors = [{name = "The Sage Developers", email = "sage-support@googlegroups.com"}] +urls = {Homepage = "https://www.sagemath.org"} +dynamic = ["version"] + +[project.readme] +file = "README.rst" +content-type = "text/x-rst" + +[tool.setuptools] +script-files = ["bin/sage-sws2rst"] +include-package-data = false + +[tool.setuptools.packages] +find = {namespaces = false} + +[tool.setuptools.dynamic] +version = {file = ["VERSION.txt"]} diff --git a/pkgs/sage-sws2rst/setup.cfg b/pkgs/sage-sws2rst/setup.cfg deleted file mode 100644 index 129f46d55e2..00000000000 --- a/pkgs/sage-sws2rst/setup.cfg +++ /dev/null @@ -1,16 +0,0 @@ -[metadata] -name = sage-sws2rst -version = file: VERSION.txt -description = Sage: Open Source Mathematics Software: SageNB worksheet converter -long_description = file: README.rst -long_description_content_type = text/x-rst -license = GNU General Public License (GPL) v3 or later -author = The Sage Developers -author_email = sage-support@googlegroups.com -url = https://www.sagemath.org - -[options] -packages = find: - -scripts = - bin/sage-sws2rst diff --git a/pkgs/sagemath-bliss/VERSION.txt b/pkgs/sagemath-bliss/VERSION.txt index ea61754a6ef..d1741c9f234 100644 --- a/pkgs/sagemath-bliss/VERSION.txt +++ b/pkgs/sagemath-bliss/VERSION.txt @@ -1 +1 @@ -10.2.rc5 +10.3.beta0 diff --git a/pkgs/sagemath-bliss/pyproject.toml.m4 b/pkgs/sagemath-bliss/pyproject.toml.m4 index 1cbcdf7e162..7783c12c118 100644 --- a/pkgs/sagemath-bliss/pyproject.toml.m4 +++ b/pkgs/sagemath-bliss/pyproject.toml.m4 @@ -8,5 +8,6 @@ requires = [ SPKG_INSTALL_REQUIRES_sagemath_environment SPKG_INSTALL_REQUIRES_cython SPKG_INSTALL_REQUIRES_cysignals + SPKG_INSTALL_REQUIRES_pkgconfig ] build-backend = "setuptools.build_meta" diff --git a/pkgs/sagemath-categories/VERSION.txt b/pkgs/sagemath-categories/VERSION.txt index ea61754a6ef..d1741c9f234 100644 --- a/pkgs/sagemath-categories/VERSION.txt +++ b/pkgs/sagemath-categories/VERSION.txt @@ -1 +1 @@ -10.2.rc5 +10.3.beta0 diff --git a/pkgs/sagemath-categories/pyproject.toml.m4 b/pkgs/sagemath-categories/pyproject.toml.m4 index 94277dccc0e..72c75ccd11e 100644 --- a/pkgs/sagemath-categories/pyproject.toml.m4 +++ b/pkgs/sagemath-categories/pyproject.toml.m4 @@ -10,6 +10,7 @@ requires = [ SPKG_INSTALL_REQUIRES_cython SPKG_INSTALL_REQUIRES_gmpy2 SPKG_INSTALL_REQUIRES_cysignals + SPKG_INSTALL_REQUIRES_pkgconfig ] build-backend = "setuptools.build_meta" diff --git a/pkgs/sagemath-coxeter3/VERSION.txt b/pkgs/sagemath-coxeter3/VERSION.txt index ea61754a6ef..d1741c9f234 100644 --- a/pkgs/sagemath-coxeter3/VERSION.txt +++ b/pkgs/sagemath-coxeter3/VERSION.txt @@ -1 +1 @@ -10.2.rc5 +10.3.beta0 diff --git a/pkgs/sagemath-coxeter3/pyproject.toml.m4 b/pkgs/sagemath-coxeter3/pyproject.toml.m4 index a7d65382b21..69613011371 100644 --- a/pkgs/sagemath-coxeter3/pyproject.toml.m4 +++ b/pkgs/sagemath-coxeter3/pyproject.toml.m4 @@ -7,5 +7,6 @@ requires = [ SPKG_INSTALL_REQUIRES_sagemath_environment SPKG_INSTALL_REQUIRES_cython SPKG_INSTALL_REQUIRES_cysignals + SPKG_INSTALL_REQUIRES_pkgconfig ] build-backend = "setuptools.build_meta" diff --git a/pkgs/sagemath-environment/VERSION.txt b/pkgs/sagemath-environment/VERSION.txt index ea61754a6ef..d1741c9f234 100644 --- a/pkgs/sagemath-environment/VERSION.txt +++ b/pkgs/sagemath-environment/VERSION.txt @@ -1 +1 @@ -10.2.rc5 +10.3.beta0 diff --git a/pkgs/sagemath-mcqd/VERSION.txt b/pkgs/sagemath-mcqd/VERSION.txt index ea61754a6ef..d1741c9f234 100644 --- a/pkgs/sagemath-mcqd/VERSION.txt +++ b/pkgs/sagemath-mcqd/VERSION.txt @@ -1 +1 @@ -10.2.rc5 +10.3.beta0 diff --git a/pkgs/sagemath-mcqd/pyproject.toml.m4 b/pkgs/sagemath-mcqd/pyproject.toml.m4 index 7e651119193..bb34e4c5eb9 100644 --- a/pkgs/sagemath-mcqd/pyproject.toml.m4 +++ b/pkgs/sagemath-mcqd/pyproject.toml.m4 @@ -8,5 +8,6 @@ requires = [ SPKG_INSTALL_REQUIRES_cython SPKG_INSTALL_REQUIRES_memory_allocator SPKG_INSTALL_REQUIRES_cysignals + SPKG_INSTALL_REQUIRES_pkgconfig ] build-backend = "setuptools.build_meta" diff --git a/pkgs/sagemath-meataxe/VERSION.txt b/pkgs/sagemath-meataxe/VERSION.txt index ea61754a6ef..d1741c9f234 100644 --- a/pkgs/sagemath-meataxe/VERSION.txt +++ b/pkgs/sagemath-meataxe/VERSION.txt @@ -1 +1 @@ -10.2.rc5 +10.3.beta0 diff --git a/pkgs/sagemath-meataxe/pyproject.toml.m4 b/pkgs/sagemath-meataxe/pyproject.toml.m4 index a7d65382b21..69613011371 100644 --- a/pkgs/sagemath-meataxe/pyproject.toml.m4 +++ b/pkgs/sagemath-meataxe/pyproject.toml.m4 @@ -7,5 +7,6 @@ requires = [ SPKG_INSTALL_REQUIRES_sagemath_environment SPKG_INSTALL_REQUIRES_cython SPKG_INSTALL_REQUIRES_cysignals + SPKG_INSTALL_REQUIRES_pkgconfig ] build-backend = "setuptools.build_meta" diff --git a/pkgs/sagemath-objects/VERSION.txt b/pkgs/sagemath-objects/VERSION.txt index ea61754a6ef..d1741c9f234 100644 --- a/pkgs/sagemath-objects/VERSION.txt +++ b/pkgs/sagemath-objects/VERSION.txt @@ -1 +1 @@ -10.2.rc5 +10.3.beta0 diff --git a/pkgs/sagemath-objects/pyproject.toml.m4 b/pkgs/sagemath-objects/pyproject.toml.m4 index ce80e0fea5d..9214f1ffb8d 100644 --- a/pkgs/sagemath-objects/pyproject.toml.m4 +++ b/pkgs/sagemath-objects/pyproject.toml.m4 @@ -9,6 +9,7 @@ requires = [ SPKG_INSTALL_REQUIRES_cython SPKG_INSTALL_REQUIRES_gmpy2 SPKG_INSTALL_REQUIRES_cysignals + SPKG_INSTALL_REQUIRES_pkgconfig ] build-backend = "setuptools.build_meta" diff --git a/pkgs/sagemath-repl/VERSION.txt b/pkgs/sagemath-repl/VERSION.txt index ea61754a6ef..d1741c9f234 100644 --- a/pkgs/sagemath-repl/VERSION.txt +++ b/pkgs/sagemath-repl/VERSION.txt @@ -1 +1 @@ -10.2.rc5 +10.3.beta0 diff --git a/pkgs/sagemath-sirocco/VERSION.txt b/pkgs/sagemath-sirocco/VERSION.txt index ea61754a6ef..d1741c9f234 100644 --- a/pkgs/sagemath-sirocco/VERSION.txt +++ b/pkgs/sagemath-sirocco/VERSION.txt @@ -1 +1 @@ -10.2.rc5 +10.3.beta0 diff --git a/pkgs/sagemath-sirocco/pyproject.toml.m4 b/pkgs/sagemath-sirocco/pyproject.toml.m4 index 99894dd5e5e..684ed189d9f 100644 --- a/pkgs/sagemath-sirocco/pyproject.toml.m4 +++ b/pkgs/sagemath-sirocco/pyproject.toml.m4 @@ -8,5 +8,6 @@ requires = [ SPKG_INSTALL_REQUIRES_cython SPKG_INSTALL_REQUIRES_cypari SPKG_INSTALL_REQUIRES_cysignals + SPKG_INSTALL_REQUIRES_pkgconfig ] build-backend = "setuptools.build_meta" diff --git a/pkgs/sagemath-tdlib/VERSION.txt b/pkgs/sagemath-tdlib/VERSION.txt index ea61754a6ef..d1741c9f234 100644 --- a/pkgs/sagemath-tdlib/VERSION.txt +++ b/pkgs/sagemath-tdlib/VERSION.txt @@ -1 +1 @@ -10.2.rc5 +10.3.beta0 diff --git a/pkgs/sagemath-tdlib/pyproject.toml.m4 b/pkgs/sagemath-tdlib/pyproject.toml.m4 index a7d65382b21..69613011371 100644 --- a/pkgs/sagemath-tdlib/pyproject.toml.m4 +++ b/pkgs/sagemath-tdlib/pyproject.toml.m4 @@ -7,5 +7,6 @@ requires = [ SPKG_INSTALL_REQUIRES_sagemath_environment SPKG_INSTALL_REQUIRES_cython SPKG_INSTALL_REQUIRES_cysignals + SPKG_INSTALL_REQUIRES_pkgconfig ] build-backend = "setuptools.build_meta" diff --git a/src/VERSION.txt b/src/VERSION.txt index ea61754a6ef..d1741c9f234 100644 --- a/src/VERSION.txt +++ b/src/VERSION.txt @@ -1 +1 @@ -10.2.rc5 +10.3.beta0 diff --git a/src/bin/sage b/src/bin/sage index 64d7986482b..ba353116e7c 100755 --- a/src/bin/sage +++ b/src/bin/sage @@ -453,8 +453,8 @@ usage_advanced() { if [ -n "$SAGE_SRC" -a -f "$SAGE_SRC/tox.ini" ]; then echo " --tox [options] -- general entry point for testing" echo " and linting of the Sage library" - echo " -e -- run specific test environments" - echo " (default: run all except full pycodestyle)" + echo " -e -- run specific test environments; default:" + echo " $(echo $(tox -c "$SAGE_SRC" --listenvs 2>/dev/null) | sed 's/ /,/g;')" tox -c "$SAGE_SRC" --listenvs-all -v 2>/dev/null | sed -n '/->/s/^/ /;s/(/\ (/;s/->/ --/p;' echo " -p auto -- run test environments in parallel" @@ -482,10 +482,13 @@ usage_advanced() { echo " --fixdoctests file.py" echo " -- Run doctests and replace output of failing doctests" echo " with actual output." - echo " --fiximports " + echo " --fiximports " echo " -- Replace imports from sage.PAC.KAGE.all by specific" echo " imports when sage.PAC.KAGE is an implicit namespace" echo " package" + echo " --fixdistributions " + echo " -- Check or update '# sage_setup: distribution'" + echo " directives in source files" fi echo " --sh [...] -- run a shell with Sage environment variables" echo " as they are set in the runtime of Sage" @@ -986,6 +989,11 @@ if [ "$1" = '-fiximports' -o "$1" = '--fiximports' ]; then exec sage-python -m sage.misc.replace_dot_all "$@" fi +if [ "$1" = '-fixdistributions' -o "$1" = '--fixdistributions' ]; then + shift + exec sage-python -m sage.misc.package_dir "$@" +fi + if [ "$1" = '-tox' -o "$1" = '--tox' ]; then shift if [ -n "$SAGE_SRC" -a -f "$SAGE_SRC/tox.ini" ]; then diff --git a/src/bin/sage-notebook b/src/bin/sage-notebook index 801b0a6a6a3..8f7687adcc5 100755 --- a/src/bin/sage-notebook +++ b/src/bin/sage-notebook @@ -74,52 +74,6 @@ class NotebookJupyterlab(): main(argv) -class NotebookNbclassic(): - def print_banner(self): - banner() - print('Please wait while the Jupyterlab server starts...') - - @classmethod - def print_help(cls): - cls(['help']) - - def __init__(self, argv): - try: - from nbclassic.notebookapp import main - except ImportError: - import traceback - traceback.print_exc() - print("Jupyterlab is not installed (at least not in this Sage installation).") - print("You can install it by running") - print(" sage -i jupyterlab") - raise SystemExit(1) - self.print_banner() - main(argv) - - -class NotebookRetrolab(): - def print_banner(self): - banner() - print('Please wait while the Jupyterlab server starts...') - - @classmethod - def print_help(cls): - cls(['help']) - - def __init__(self, argv): - try: - from retrolab.app import main - except ImportError: - import traceback - traceback.print_exc() - print("Retrolab is not installed (at least not in this Sage installation).") - print("You can install it by running") - print(" sage -i retrolab") - raise SystemExit(1) - self.print_banner() - main(argv) - - class SageNBExport(NotebookJupyter): def print_banner(self): @@ -183,8 +137,6 @@ notebook_launcher = { 'ipython': NotebookJupyter, 'jupyter': NotebookJupyter, 'jupyterlab': NotebookJupyterlab, - 'nbclassic': NotebookNbclassic, - 'retrolab': NotebookRetrolab, 'export': SageNBExport, } diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index 5adb8b5983d..9f4098364dc 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.2.rc5' -SAGE_RELEASE_DATE='2023-11-30' -SAGE_VERSION_BANNER='SageMath version 10.2.rc5, Release Date: 2023-11-30' +SAGE_VERSION='10.3.beta0' +SAGE_RELEASE_DATE='2023-12-05' +SAGE_VERSION_BANNER='SageMath version 10.3.beta0, Release Date: 2023-12-05' diff --git a/src/doc/en/developer/packaging_sage_library.rst b/src/doc/en/developer/packaging_sage_library.rst index 0244d96e5ac..576356a9dff 100644 --- a/src/doc/en/developer/packaging_sage_library.rst +++ b/src/doc/en/developer/packaging_sage_library.rst @@ -146,6 +146,34 @@ The source directory of a distribution package, such as controls which files and directories of the monolithic Sage library source tree are included in the distribution + The manifest should be kept in sync with the directives of the form + ``# sage_setup: distribution = sagemath-polyhedra`` at the top of + source files. Sage provides a tool ``sage --fixdistributions`` + that assists with this task. For example:: + + $ ./sage --fixdistributions --set sagemath-polyhedra \ + src/sage/geometry/polyhedron/base*.py + + adds or updates the directives in the specified files; and:: + + $ ./sage --fixdistributions --add sagemath-polyhedra \ + src/sage/geometry/polyhedron + + adds the directive to all files in the given directory that do not + include a directive yet. + + After a distribution has been built (for example, by the command + ``make pypi-wheels``) or at least an sdist has been built (for + example, by the command ``make sagemath_polyhedra-sdist``), the + distribution directives in all files in the source distribution + can be updated using the switch ``--from--egg-info``:: + + $ ./sage --fixdistributions --set sagemath-polyhedra --from-egg-info + + To take care of all distributions, use:: + + $ ./sage --fixdistributions --set all --from-egg-info + - `pyproject.toml `_, `setup.cfg `_, and `requirements.txt `_ -- diff --git a/src/doc/en/developer/tools.rst b/src/doc/en/developer/tools.rst index fca5d5ef4c1..02be3f91b4b 100644 --- a/src/doc/en/developer/tools.rst +++ b/src/doc/en/developer/tools.rst @@ -48,8 +48,8 @@ available:: ... --tox [options] -- general entry point for testing and linting of the Sage library - -e -- run specific test environments - (default: run all except full pycodestyle) + -e -- run specific test environments; default: + doctest,coverage,startuptime,pycodestyle-minimal,relint,codespell,rst doctest -- run the Sage doctester (same as "sage -t") coverage -- give information about doctest coverage of files @@ -59,11 +59,13 @@ available:: pycodestyle-minimal -- check against Sage's minimal style conventions relint -- check whether some forbidden patterns appear (includes all patchbot pattern-exclusion plugins) - rst -- validate Python docstrings markup as reStructuredText codespell -- check for misspelled words in source code - cython-lint -- Check Cython files for code style + rst -- validate Python docstrings markup as reStructuredText + coverage.py -- run the Sage doctester with Coverage.py + coverage.py-html -- run the Sage doctester with Coverage.py, generate HTML report pyright -- run the static typing checker pyright pycodestyle -- check against the Python style conventions of PEP8 + cython-lint -- check Cython files for code style -p auto -- run test environments in parallel --help -- show tox help @@ -71,22 +73,64 @@ available:: Doctest ======= -The command ``./sage -tox -e doctest`` requires that Sage has been -built already. ``doctest`` is a special tox environment that runs the -Sage doctester in the normal Sage environment. This is equivalent to -using the command ``./sage -t``; see :ref:`chapter-doctesting`. +The command ``./sage -tox -e doctest`` runs the Sage doctester. This is +equivalent to using the command ``./sage -t``; see :ref:`chapter-doctesting`. + +.. NOTE:: + + ``doctest`` is a special tox environment that requires that Sage has + been built already. A virtual environment is created by tox, but + Sage is invoked in the normal Sage environment. + + +.. _section-tools-coverage-py: + +Doctest with Coverage.py +======================== + +The command ``./sage -tox -e coverage.py`` runs the Sage doctester +(:ref:`chapter-doctesting`) in the normal Sage environment, but +under the control of +`Coverage.py `_ +for code coverage analysis. + +If invoked as ``./sage -tox -e coverage.py-html``, additionally a +detailed HTML report is generated. + +*Configuration:* ``[coverage:run]`` block in ``SAGE_ROOT/src/tox.ini`` +*Documentation:* https://coverage.readthedocs.io + +.. NOTE:: + + ``coverage.py`` is a special tox environment that requires that Sage has + been built already. A virtual environment is created by tox, but the + **coverage** package is installed into the normal Sage environment, and + Sage is invoked from there. .. _section-tools-coverage: Coverage ======== -The command ``./sage -tox -e coverage`` requires that Sage has been -built already. ``coverage`` is a special tox environment that is -equivalent to using the command ``./sage --coverageall`` (if no -arguments are provided) or ``./sage --coverage`` (if arguments are -provided). +The command ``./sage -tox -e coverage`` checks that each function has +at least one doctest (typically in an **EXAMPLES** or **TESTS** block, +see :ref:`section-docstring-function`). + +Without additional arguments, this command is equivalent to using the +command ``./sage --coverageall`` and gives a short report with a one-line +summary for each module of the Sage library. + +If invoked with arguments, for example ``./sage -tox -e coverage +-- src/sage/geometry src/sage/combinat/tableau.py``, it is equivalent to +using the command ``./sage --coverage``, which includes details on +the modules in the given files or directories. + +.. NOTE:: + + ``coverage`` is a special tox environment that requires that Sage has been + built already. A virtual environment is created by tox, but + Sage is invoked in the normal Sage environment. .. _section-tools-startuptime: @@ -94,10 +138,24 @@ provided). Startuptime =========== -The command ``./sage -tox -e startuptime`` requires that Sage has been -built already. ``startuptime`` is a special tox environment that is +The command ``./sage -tox -e startuptime`` measures the time for loading +each module that is imported during the start up phase of Sage. It is equivalent to using the command ``./sage --startuptime``. +Without additional arguments, the command gives a short report that lists +the modules with the longest contributions to the overall startup time, +sorted by time. + +If invoked with arguments, for example ``sage -tox -e startuptime -- sage.rings +src/sage/geometry/polyhedron``, it provides details on the given modules, packages, +source files, or directories. + +.. NOTE:: + + ``startuptime`` is a special tox environment that requires that Sage has been + built already. A virtual environment is created by tox, but + Sage is invoked in the normal Sage environment. + .. _section-tools-pycodestyle: diff --git a/src/doc/en/reference/arithmetic_curves/index.rst b/src/doc/en/reference/arithmetic_curves/index.rst index 6ab10dcf1c0..9e249cf27cc 100644 --- a/src/doc/en/reference/arithmetic_curves/index.rst +++ b/src/doc/en/reference/arithmetic_curves/index.rst @@ -18,13 +18,15 @@ Maps between them :maxdepth: 1 sage/schemes/elliptic_curves/hom + sage/schemes/elliptic_curves/hom_composite + sage/schemes/elliptic_curves/hom_sum sage/schemes/elliptic_curves/weierstrass_morphism sage/schemes/elliptic_curves/ell_curve_isogeny sage/schemes/elliptic_curves/hom_velusqrt - sage/schemes/elliptic_curves/hom_composite sage/schemes/elliptic_curves/hom_scalar sage/schemes/elliptic_curves/hom_frobenius sage/schemes/elliptic_curves/isogeny_small_degree + sage/schemes/elliptic_curves/mod_poly Elliptic curves over number fields diff --git a/src/doc/en/reference/quadratic_forms/index.rst b/src/doc/en/reference/quadratic_forms/index.rst index 7169e7ac503..e553ecd1b82 100644 --- a/src/doc/en/reference/quadratic_forms/index.rst +++ b/src/doc/en/reference/quadratic_forms/index.rst @@ -6,6 +6,7 @@ Quadratic Forms sage/quadratic_forms/quadratic_form sage/quadratic_forms/binary_qf + sage/quadratic_forms/bqf_class_group sage/quadratic_forms/constructions sage/quadratic_forms/random_quadraticform sage/quadratic_forms/special_values diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index fa67dade3ab..d39195c34d3 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -1481,6 +1481,11 @@ REFERENCES: .. [CFI1992] Cai, JY., Fürer, M. & Immerman, N. Combinatorica (1992) 12: 389. :doi:`10.1007/BF01305232` +.. [CFKLMPPS15] Marek Cygan, Fedor V. Fomin, Łukasz Kowalik, Daniel Lokshtanov, + Dániel Marx, Marcin Pilipczuk, Michał Pilipczuk, Saket Saurabh. + *Parameterized Algorithms*. Springer International Publishing + Switzerland 2015 + .. [CFKP1997] James W. Cannon, William J. Floyd, Richard Kenyon and Walter R. Parry. *Hyperbolic Geometry*. Flavors of Geometry, MSRI Publications, Volume 31, 1997. diff --git a/src/pyproject.toml.m4 b/src/pyproject.toml.m4 index f707b6f890e..2b61ea041ea 100644 --- a/src/pyproject.toml.m4 +++ b/src/pyproject.toml.m4 @@ -1,6 +1,7 @@ [build-system] # Minimum requirements for the build system to execute. requires = [ + "sage_setup[autogen]", # Some version of sage-conf is required. # Note that PEP517/518 have no notion of optional sage_spkg dependencies: # https://github.com/pypa/pip/issues/6144 diff --git a/src/sage/algebras/affine_nil_temperley_lieb.py b/src/sage/algebras/affine_nil_temperley_lieb.py index 720c5f481cd..1fa213bd4bc 100644 --- a/src/sage/algebras/affine_nil_temperley_lieb.py +++ b/src/sage/algebras/affine_nil_temperley_lieb.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Affine nilTemperley Lieb Algebra of type A """ diff --git a/src/sage/algebras/algebra.py b/src/sage/algebras/algebra.py index 5aac6f22b9a..e69ea7da530 100644 --- a/src/sage/algebras/algebra.py +++ b/src/sage/algebras/algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Abstract base class for algebras """ diff --git a/src/sage/algebras/askey_wilson.py b/src/sage/algebras/askey_wilson.py index 37303e030c3..4943c73b36d 100644 --- a/src/sage/algebras/askey_wilson.py +++ b/src/sage/algebras/askey_wilson.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Askey-Wilson Algebras diff --git a/src/sage/algebras/associated_graded.py b/src/sage/algebras/associated_graded.py index 5e9d7b1f6b9..5dd01321114 100644 --- a/src/sage/algebras/associated_graded.py +++ b/src/sage/algebras/associated_graded.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.modules r""" Associated Graded Algebras To Filtered Algebras diff --git a/src/sage/algebras/catalog.py b/src/sage/algebras/catalog.py index efda74ed00e..ec48a6debed 100644 --- a/src/sage/algebras/catalog.py +++ b/src/sage/algebras/catalog.py @@ -84,17 +84,18 @@ ` """ -from sage.algebras.free_algebra import FreeAlgebra as Free -from sage.algebras.quatalg.quaternion_algebra import QuaternionAlgebra as Quaternion -from sage.algebras.steenrod.steenrod_algebra import SteenrodAlgebra as Steenrod -from sage.algebras.finite_dimensional_algebras.finite_dimensional_algebra import FiniteDimensionalAlgebra as FiniteDimensional -from sage.algebras.group_algebra import GroupAlgebra as Group -from sage.algebras.clifford_algebra import CliffordAlgebra as Clifford -from sage.algebras.clifford_algebra import ExteriorAlgebra as Exterior -from sage.algebras.weyl_algebra import DifferentialWeylAlgebra as DifferentialWeyl -from sage.algebras.lie_algebras.lie_algebra import LieAlgebra as Lie - from sage.misc.lazy_import import lazy_import +lazy_import('sage.algebras.free_algebra', 'FreeAlgebra', as_='Free') +lazy_import('sage.algebras.quatalg.quaternion_algebra', 'QuaternionAlgebra', as_='Quaternion') +lazy_import('sage.algebras.steenrod.steenrod_algebra', 'SteenrodAlgebra', as_='Steenrod') +lazy_import('sage.algebras.finite_dimensional_algebras.finite_dimensional_algebra', + 'FiniteDimensionalAlgebra', as_='FiniteDimensional') +lazy_import('sage.algebras.group_algebra', 'GroupAlgebra', as_='Group') +lazy_import('sage.algebras.clifford_algebra', 'CliffordAlgebra', as_='Clifford') +lazy_import('sage.algebras.clifford_algebra', 'ExteriorAlgebra', as_='Exterior') +lazy_import('sage.algebras.weyl_algebra', 'DifferentialWeylAlgebra', as_='DifferentialWeyl') +lazy_import('sage.algebras.lie_algebras.lie_algebra', 'LieAlgebra', as_='Lie') + lazy_import('sage.algebras.iwahori_hecke_algebra', 'IwahoriHeckeAlgebra', 'IwahoriHecke') lazy_import('sage.algebras.nil_coxeter_algebra', 'NilCoxeterAlgebra', 'NilCoxeter') lazy_import('sage.algebras.free_zinbiel_algebra', 'FreeZinbielAlgebra', 'FreeZinbiel') diff --git a/src/sage/algebras/cellular_basis.py b/src/sage/algebras/cellular_basis.py index 873bd899b3e..e6e7487cba9 100644 --- a/src/sage/algebras/cellular_basis.py +++ b/src/sage/algebras/cellular_basis.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Cellular Basis ============== diff --git a/src/sage/algebras/clifford_algebra.py b/src/sage/algebras/clifford_algebra.py index 220a2eb27a5..ad8bd314c25 100644 --- a/src/sage/algebras/clifford_algebra.py +++ b/src/sage/algebras/clifford_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.modules r""" Clifford Algebras @@ -1770,6 +1771,7 @@ def interior_product_on_basis(self, a, b): Check :trac:`34694`:: + sage: # needs sage.symbolic sage: E = ExteriorAlgebra(SR,'e',3) sage: E.inject_variables() Defining e0, e1, e2 diff --git a/src/sage/algebras/clifford_algebra_element.pyx b/src/sage/algebras/clifford_algebra_element.pyx index 0a1a4adb681..2e6ad0a8547 100644 --- a/src/sage/algebras/clifford_algebra_element.pyx +++ b/src/sage/algebras/clifford_algebra_element.pyx @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.modules """ Clifford algebra elements @@ -944,6 +945,7 @@ cdef class CohomologyRAAGElement(CliffordAlgebraElement): EXAMPLES:: + sage: # needs sage.graphs sage.groups sage: C4 = graphs.CycleGraph(4) sage: A = groups.misc.RightAngledArtin(C4) sage: H = A.cohomology() diff --git a/src/sage/algebras/cluster_algebra.py b/src/sage/algebras/cluster_algebra.py index 880814feba7..6324bc235be 100644 --- a/src/sage/algebras/cluster_algebra.py +++ b/src/sage/algebras/cluster_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.graphs sage.modules r""" Cluster algebras @@ -361,12 +362,11 @@ from sage.categories.rings import Rings from sage.combinat.cluster_algebra_quiver.quiver import ClusterQuiver from sage.combinat.permutation import Permutation -from sage.geometry.cone import Cone -from sage.geometry.fan import Fan from sage.graphs.digraph import DiGraph from sage.matrix.constructor import identity_matrix, matrix from sage.matrix.special import block_matrix from sage.misc.cachefunc import cached_method +from sage.misc.lazy_import import lazy_import from sage.misc.misc_c import prod from sage.modules.free_module_element import vector from sage.rings.infinity import infinity @@ -381,6 +381,8 @@ from sage.structure.sage_object import SageObject from sage.structure.unique_representation import UniqueRepresentation +lazy_import('sage.geometry.cone', 'Cone') +lazy_import('sage.geometry.fan', 'Fan') ############################################################################## # Elements of a cluster algebra @@ -2373,7 +2375,7 @@ def cluster_fan(self, depth=infinity): EXAMPLES:: sage: A = ClusterAlgebra(['A', 2]) - sage: A.cluster_fan() + sage: A.cluster_fan() # needs sage.geometry.polyhedron Rational polyhedral fan in 2-d lattice N """ seeds = self.seeds(depth=depth, mutating_F=False) diff --git a/src/sage/algebras/commutative_dga.py b/src/sage/algebras/commutative_dga.py index 953364d6813..35facfa7866 100644 --- a/src/sage/algebras/commutative_dga.py +++ b/src/sage/algebras/commutative_dga.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Commutative Differential Graded Algebras @@ -42,7 +43,8 @@ sage: A. = GradedCommutativeAlgebra(QQ, degrees=(1,1,2)) sage: B = A.cdg_algebra({x: x*y, y: -x*y}) sage: B - Commutative Differential Graded Algebra with generators ('x', 'y', 'z') in degrees (1, 1, 2) over Rational Field with differential: + Commutative Differential Graded Algebra with generators ('x', 'y', 'z') + in degrees (1, 1, 2) over Rational Field with differential: x --> x*y y --> -x*y z --> 0 @@ -116,7 +118,7 @@ def sorting_keys(element): OUTPUT: - Its coordinates in the corresponding cohomology_raw quotient vector space + Its coordinates in the corresponding ``cohomology_raw`` quotient vector space EXAMPLES:: @@ -155,7 +157,8 @@ class Differential(UniqueRepresentation, Morphism, sage: A. = GradedCommutativeAlgebra(QQ, degrees=(1, 1, 2, 3)) sage: B = A.cdg_algebra({x: x*y, y: -x*y , z: t}) sage: B - Commutative Differential Graded Algebra with generators ('x', 'y', 'z', 't') in degrees (1, 1, 2, 3) over Rational Field with differential: + Commutative Differential Graded Algebra with generators ('x', 'y', 'z', 't') + in degrees (1, 1, 2, 3) over Rational Field with differential: x --> x*y y --> -x*y z --> t @@ -181,7 +184,9 @@ def __classcall__(cls, A, im_gens): sage: A. = GradedCommutativeAlgebra(QQ,degrees=(2,2,3,3)) sage: A = A.quotient(A.ideal([a*u,b*u,x*u])) sage: A.cdg_algebra({x:a*b,a:u}) - Commutative Differential Graded Algebra with generators ('a', 'b', 'x', 'u') in degrees (2, 2, 3, 3) with relations [a*u, b*u, x*u] over Rational Field with differential: + Commutative Differential Graded Algebra with generators ('a', 'b', 'x', 'u') + in degrees (2, 2, 3, 3) with relations [a*u, b*u, x*u] over Rational Field + with differential: a --> u b --> 0 x --> a*b @@ -910,7 +915,8 @@ class GCAlgebra(UniqueRepresentation, QuotientRing_nc): 2 sage: B = A.quotient(A.ideal(a**2*b)) sage: B - Graded Commutative Algebra with generators ('a', 'b') in degrees (2, 3) with relations [a^2*b] over Rational Field + Graded Commutative Algebra with generators ('a', 'b') in degrees (2, 3) + with relations [a^2*b] over Rational Field sage: A.basis(7) [a^2*b] sage: B.basis(7) @@ -1203,9 +1209,10 @@ def quotient(self, I, check=True): sage: A. = GradedCommutativeAlgebra(GF(5), degrees=(2, 2, 3, 4)) sage: I = A.ideal([x*t+z^2, x*y - t]) - sage: B = A.quotient(I) - sage: B - Graded Commutative Algebra with generators ('x', 'y', 'z', 't') in degrees (2, 2, 3, 4) with relations [x*t, x*y - t] over Finite Field of size 5 + sage: B = A.quotient(I); B + Graded Commutative Algebra with generators ('x', 'y', 'z', 't') + in degrees (2, 2, 3, 4) with relations [x*t, x*y - t] + over Finite Field of size 5 sage: B(x*t) 0 sage: B(x*y) @@ -1304,13 +1311,22 @@ def _Hom_(self, B, category): sage: B. = GradedCommutativeAlgebra(QQ, degrees=(1,2,3)) sage: C. = GradedCommutativeAlgebra(GF(17)) sage: Hom(A,A) - Set of Homomorphisms from Graded Commutative Algebra with generators ('x', 'y') in degrees (1, 1) over Rational Field to Graded Commutative Algebra with generators ('x', 'y') in degrees (1, 1) over Rational Field + Set of Homomorphisms + from Graded Commutative Algebra with generators ('x', 'y') + in degrees (1, 1) over Rational Field + to Graded Commutative Algebra with generators ('x', 'y') + in degrees (1, 1) over Rational Field sage: Hom(A,B) - Set of Homomorphisms from Graded Commutative Algebra with generators ('x', 'y') in degrees (1, 1) over Rational Field to Graded Commutative Algebra with generators ('a', 'b', 'c') in degrees (1, 2, 3) over Rational Field + Set of Homomorphisms + from Graded Commutative Algebra with generators ('x', 'y') + in degrees (1, 1) over Rational Field + to Graded Commutative Algebra with generators ('a', 'b', 'c') + in degrees (1, 2, 3) over Rational Field sage: Hom(A,C) Traceback (most recent call last): ... - NotImplementedError: homomorphisms of graded commutative algebras have only been implemented when the base rings are the same + NotImplementedError: homomorphisms of graded commutative algebras + have only been implemented when the base rings are the same """ R = self.base_ring() # The base rings need to be checked before the categories, or @@ -1345,7 +1361,8 @@ def differential(self, diff): sage: A. = GradedCommutativeAlgebra(QQ, degrees=(1, 1, 2)) sage: A.differential({y:x*y, x: x*y}) - Differential of Graded Commutative Algebra with generators ('x', 'y', 'z') in degrees (1, 1, 2) over Rational Field + Differential of Graded Commutative Algebra with generators ('x', 'y', 'z') + in degrees (1, 1, 2) over Rational Field Defn: x --> x*y y --> x*y z --> 0 @@ -1382,7 +1399,8 @@ def cdg_algebra(self, differential): sage: A. = GradedCommutativeAlgebra(QQ, degrees=(1, 1, 1)) sage: B = A.cdg_algebra({a: b*c, b: a*c}) sage: B - Commutative Differential Graded Algebra with generators ('a', 'b', 'c') in degrees (1, 1, 1) over Rational Field with differential: + Commutative Differential Graded Algebra with generators ('a', 'b', 'c') + in degrees (1, 1, 1) over Rational Field with differential: a --> b*c b --> a*c c --> 0 @@ -1391,7 +1409,8 @@ def cdg_algebra(self, differential): sage: d = A.differential({a: b*c, b: a*c}) sage: d - Differential of Graded Commutative Algebra with generators ('a', 'b', 'c') in degrees (1, 1, 1) over Rational Field + Differential of Graded Commutative Algebra with generators ('a', 'b', 'c') + in degrees (1, 1, 1) over Rational Field Defn: a --> b*c b --> a*c c --> 0 @@ -1646,7 +1665,8 @@ class GCAlgebra_multigraded(GCAlgebra): sage: A. = GradedCommutativeAlgebra(QQ, degrees=((1,0), (0,1), (1,1))) sage: A - Graded Commutative Algebra with generators ('a', 'b', 'c') in degrees ((1, 0), (0, 1), (1, 1)) over Rational Field + Graded Commutative Algebra with generators ('a', 'b', 'c') + in degrees ((1, 0), (0, 1), (1, 1)) over Rational Field sage: a**2 0 sage: c.degree(total=True) @@ -1727,7 +1747,9 @@ def quotient(self, I, check=True): sage: I = A.ideal([x*t+z^2, x*y - t]) sage: B = A.quotient(I) sage: B - Graded Commutative Algebra with generators ('x', 'y', 'z', 't') in degrees (2, 2, 3, 4) with relations [x*t, x*y - t] over Finite Field of size 5 + Graded Commutative Algebra with generators ('x', 'y', 'z', 't') + in degrees (2, 2, 3, 4) with relations [x*t, x*y - t] + over Finite Field of size 5 sage: B(x*t) 0 sage: B(x*y) @@ -1823,7 +1845,8 @@ def differential(self, diff): sage: A. = GradedCommutativeAlgebra(QQ, degrees=((1,0), (0, 1), (0,2))) sage: A.differential({a: c}) - Differential of Graded Commutative Algebra with generators ('a', 'b', 'c') in degrees ((1, 0), (0, 1), (0, 2)) over Rational Field + Differential of Graded Commutative Algebra with generators ('a', 'b', 'c') + in degrees ((1, 0), (0, 1), (0, 2)) over Rational Field Defn: a --> c b --> 0 c --> 0 @@ -1855,13 +1878,15 @@ def cdg_algebra(self, differential): sage: A. = GradedCommutativeAlgebra(QQ, degrees=((1,0), (0, 1), (0,2))) sage: A.cdg_algebra({a: c}) - Commutative Differential Graded Algebra with generators ('a', 'b', 'c') in degrees ((1, 0), (0, 1), (0, 2)) over Rational Field with differential: + Commutative Differential Graded Algebra with generators ('a', 'b', 'c') + in degrees ((1, 0), (0, 1), (0, 2)) over Rational Field with differential: a --> c b --> 0 c --> 0 sage: d = A.differential({a: c}) sage: A.cdg_algebra(d) - Commutative Differential Graded Algebra with generators ('a', 'b', 'c') in degrees ((1, 0), (0, 1), (0, 2)) over Rational Field with differential: + Commutative Differential Graded Algebra with generators ('a', 'b', 'c') + in degrees ((1, 0), (0, 1), (0, 2)) over Rational Field with differential: a --> c b --> 0 c --> 0 @@ -1884,7 +1909,8 @@ def degree(self, total=False): EXAMPLES:: - sage: A. = GradedCommutativeAlgebra(GF(2), degrees=((1,0), (0,1), (1,1))) + sage: A. = GradedCommutativeAlgebra(GF(2), + ....: degrees=((1,0), (0,1), (1,1))) sage: (a**2*b).degree() (2, 1) sage: (a**2*b).degree(total=True) @@ -1944,7 +1970,8 @@ class DifferentialGCAlgebra(GCAlgebra): sage: A. = GradedCommutativeAlgebra(QQ, degrees=(2, 2, 3, 3)) sage: A.cdg_algebra({z: x*y}) - Commutative Differential Graded Algebra with generators ('x', 'y', 'z', 't') in degrees (2, 2, 3, 3) over Rational Field with differential: + Commutative Differential Graded Algebra with generators ('x', 'y', 'z', 't') + in degrees (2, 2, 3, 3) over Rational Field with differential: x --> 0 y --> 0 z --> x*y @@ -1954,7 +1981,8 @@ class DifferentialGCAlgebra(GCAlgebra): sage: A. = GradedCommutativeAlgebra(QQ, degrees=(2, 2, 3, 3)) sage: A.cdg_algebra(differential={z: x*y}) - Commutative Differential Graded Algebra with generators ('x', 'y', 'z', 't') in degrees (2, 2, 3, 3) over Rational Field with differential: + Commutative Differential Graded Algebra with generators ('x', 'y', 'z', 't') + in degrees (2, 2, 3, 3) over Rational Field with differential: x --> 0 y --> 0 z --> x*y @@ -2052,13 +2080,17 @@ def cdg_algebra(self, differential): sage: B = A.quotient(A.ideal(x^3-z*t)) sage: C = B.cdg_algebra({y:t}) sage: C - Commutative Differential Graded Algebra with generators ('x', 'y', 'z', 't') in degrees (2, 3, 2, 4) with relations [x^3 - z*t] over Finite Field of size 5 with differential: + Commutative Differential Graded Algebra with generators ('x', 'y', 'z', 't') + in degrees (2, 3, 2, 4) with relations [x^3 - z*t] + over Finite Field of size 5 with differential: x --> 0 y --> t z --> 0 t --> 0 sage: C.cdg_algebra({}) - Commutative Differential Graded Algebra with generators ('x', 'y', 'z', 't') in degrees (2, 3, 2, 4) with relations [x^3 - z*t] over Finite Field of size 5 with differential: + Commutative Differential Graded Algebra with generators ('x', 'y', 'z', 't') + in degrees (2, 3, 2, 4) with relations [x^3 - z*t] + over Finite Field of size 5 with differential: x --> 0 y --> 0 z --> 0 @@ -2168,7 +2200,8 @@ def differential(self, x=None): sage: A. = GradedCommutativeAlgebra(QQ, degrees=(1,1,2)) sage: B = A.cdg_algebra({y:x*y, x: y*x}) sage: d = B.differential(); d - Differential of Commutative Differential Graded Algebra with generators ('x', 'y', 'z') in degrees (1, 1, 2) over Rational Field + Differential of Commutative Differential Graded Algebra + with generators ('x', 'y', 'z') in degrees (1, 1, 2) over Rational Field Defn: x --> -x*y y --> x*y z --> 0 @@ -2281,7 +2314,8 @@ def cohomology(self, n): sage: A. = GradedCommutativeAlgebra(QQ, degrees=(1,1,1,1,1)) sage: B = A.cdg_algebra({d: a*b, e: b*c}) sage: B.cohomology(2) - Free module generated by {[a*c], [a*d], [b*d], [c*d - a*e], [b*e], [c*e]} over Rational Field + Free module generated by {[a*c], [a*d], [b*d], [c*d - a*e], [b*e], [c*e]} + over Rational Field Compare to :meth:`cohomology_raw`:: @@ -2366,7 +2400,9 @@ def cohomology_generators(self, max_degree): sage: Ds.cohomology_generators(10) {2: [a^2], 4: [b^2]} - sage: Cm. = GradedCommutativeAlgebra(GF(2), degrees=((1,0), (1,1), (0,2), (0,3))) + sage: Cm. = GradedCommutativeAlgebra(GF(2), + ....: degrees=((1,0), (1,1), + ....: (0,2), (0,3))) sage: Dm = Cm.cdg_algebra({a:c, b:d}) sage: Dm.cohomology_generators(10) {2: [a^2], 4: [b^2]} @@ -2459,13 +2495,17 @@ def minimal_model(self, i=3, max_iterations=3, partial_result=False): sage: T = p.domain() sage: p Commutative Differential Graded Algebra morphism: - From: Commutative Differential Graded Algebra with generators ('x1_0', 'x2_0') in degrees (1, 2) over Rational Field with differential: - x1_0 --> 0 - x2_0 --> 0 - To: Commutative Differential Graded Algebra with generators ('x', 'y', 'z') in degrees (1, 1, 2) over Rational Field with differential: - x --> x*y - y --> x*y - z --> 0 + From: Commutative Differential Graded Algebra + with generators ('x1_0', 'x2_0') in degrees (1, 2) + over Rational Field with differential: + x1_0 --> 0 + x2_0 --> 0 + To: Commutative Differential Graded Algebra + with generators ('x', 'y', 'z') in degrees (1, 1, 2) + over Rational Field with differential: + x --> x*y + y --> x*y + z --> 0 Defn: (x1_0, x2_0) --> (x - y, z) sage: R.cohomology(1) Free module generated by {[x - y]} over Rational Field @@ -2488,7 +2528,11 @@ def minimal_model(self, i=3, max_iterations=3, partial_result=False): sage: phi = B.minimal_model(i=3) sage: M = phi.domain() sage: M - Commutative Differential Graded Algebra with generators ('x1_0', 'x1_1', 'x1_2', 'x2_0', 'x2_1', 'x2_2', 'x2_3', 'y3_0', 'y3_1', 'y3_2', 'y3_3', 'y3_4', 'y3_5', 'y3_6', 'y3_7', 'y3_8') in degrees (1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3) over Rational Field with differential: + Commutative Differential Graded Algebra with generators + ('x1_0', 'x1_1', 'x1_2', 'x2_0', 'x2_1', 'x2_2', 'x2_3', + 'y3_0', 'y3_1', 'y3_2', 'y3_3', 'y3_4', 'y3_5', 'y3_6', 'y3_7', 'y3_8') + in degrees (1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3) + over Rational Field with differential: x1_0 --> 0 x1_1 --> 0 x1_2 --> 0 @@ -2508,32 +2552,40 @@ def minimal_model(self, i=3, max_iterations=3, partial_result=False): sage: phi Commutative Differential Graded Algebra morphism: - From: Commutative Differential Graded Algebra with generators ('x1_0', 'x1_1', 'x1_2', 'x2_0', 'x2_1', 'x2_2', 'x2_3', 'y3_0', 'y3_1', 'y3_2', 'y3_3', 'y3_4', 'y3_5', 'y3_6', 'y3_7', 'y3_8') in degrees (1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3) over Rational Field with differential: - x1_0 --> 0 - x1_1 --> 0 - x1_2 --> 0 - x2_0 --> 0 - x2_1 --> 0 - x2_2 --> 0 - x2_3 --> 0 - y3_0 --> x2_0^2 - y3_1 --> x2_0*x2_1 - y3_2 --> x2_1^2 - y3_3 --> x2_0*x2_2 - y3_4 --> x2_1*x2_2 + x2_0*x2_3 - y3_5 --> x2_2^2 - y3_6 --> x2_1*x2_3 - y3_7 --> x2_2*x2_3 - y3_8 --> x2_3^2 - To: Commutative Differential Graded Algebra with generators ('e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7') in degrees (1, 1, 1, 1, 1, 1, 1) over Rational Field with differential: - e1 --> e1*e7 - e2 --> e2*e7 - e3 --> -e3*e7 - e4 --> -e4*e7 - e5 --> 0 - e6 --> 0 - e7 --> 0 - Defn: (x1_0, x1_1, x1_2, x2_0, x2_1, x2_2, x2_3, y3_0, y3_1, y3_2, y3_3, y3_4, y3_5, y3_6, y3_7, y3_8) --> (e5, e6, e7, e1*e3, e2*e3, e1*e4, e2*e4, 0, 0, 0, 0, 0, 0, 0, 0, 0) + From: Commutative Differential Graded Algebra with generators + ('x1_0', 'x1_1', 'x1_2', 'x2_0', 'x2_1', 'x2_2', 'x2_3', + 'y3_0', 'y3_1', 'y3_2', 'y3_3', 'y3_4', 'y3_5', 'y3_6', 'y3_7', 'y3_8') + in degrees (1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3, 3) + over Rational Field with differential: + x1_0 --> 0 + x1_1 --> 0 + x1_2 --> 0 + x2_0 --> 0 + x2_1 --> 0 + x2_2 --> 0 + x2_3 --> 0 + y3_0 --> x2_0^2 + y3_1 --> x2_0*x2_1 + y3_2 --> x2_1^2 + y3_3 --> x2_0*x2_2 + y3_4 --> x2_1*x2_2 + x2_0*x2_3 + y3_5 --> x2_2^2 + y3_6 --> x2_1*x2_3 + y3_7 --> x2_2*x2_3 + y3_8 --> x2_3^2 + To: Commutative Differential Graded Algebra with generators + ('e1', 'e2', 'e3', 'e4', 'e5', 'e6', 'e7') + in degrees (1, 1, 1, 1, 1, 1, 1) over Rational Field with differential: + e1 --> e1*e7 + e2 --> e2*e7 + e3 --> -e3*e7 + e4 --> -e4*e7 + e5 --> 0 + e6 --> 0 + e7 --> 0 + Defn: (x1_0, x1_1, x1_2, x2_0, x2_1, x2_2, x2_3, + y3_0, y3_1, y3_2, y3_3, y3_4, y3_5, y3_6, y3_7, y3_8) + --> (e5, e6, e7, e1*e3, e2*e3, e1*e4, e2*e4, 0, 0, 0, 0, 0, 0, 0, 0, 0) sage: [B.cohomology(i).dimension() for i in [1..3]] [3, 7, 13] sage: [M.cohomology(i).dimension() for i in [1..3]] @@ -2772,7 +2824,8 @@ def cohomology_algebra(self, max_degree=3): sage: B = A.cdg_algebra(d) sage: M = B.cohomology_algebra() sage: M - Commutative Differential Graded Algebra with generators ('x0', 'x1', 'x2') in degrees (1, 1, 2) over Rational Field with differential: + Commutative Differential Graded Algebra with generators ('x0', 'x1', 'x2') + in degrees (1, 1, 2) over Rational Field with differential: x0 --> 0 x1 --> 0 x2 --> 0 @@ -2843,14 +2896,18 @@ def numerical_invariants(self, max_degree=3, max_iterations=3): sage: B = A.cdg_algebra({e3 : e1*e2}) sage: B.minimal_model(4) Commutative Differential Graded Algebra morphism: - From: Commutative Differential Graded Algebra with generators ('x1_0', 'x1_1', 'y1_0') in degrees (1, 1, 1) over Rational Field with differential: - x1_0 --> 0 - x1_1 --> 0 - y1_0 --> x1_0*x1_1 - To: Commutative Differential Graded Algebra with generators ('e1', 'e2', 'e3') in degrees (1, 1, 1) over Rational Field with differential: - e1 --> 0 - e2 --> 0 - e3 --> e1*e2 + From: Commutative Differential Graded Algebra with + generators ('x1_0', 'x1_1', 'y1_0') in degrees (1, 1, 1) + over Rational Field with differential: + x1_0 --> 0 + x1_1 --> 0 + y1_0 --> x1_0*x1_1 + To: Commutative Differential Graded Algebra with + generators ('e1', 'e2', 'e3') in degrees (1, 1, 1) + over Rational Field with differential: + e1 --> 0 + e2 --> 0 + e3 --> e1*e2 Defn: (x1_0, x1_1, y1_0) --> (e1, e2, e3) sage: B.numerical_invariants(2) {1: [2, 1, 0], 2: [0, 0]} @@ -2908,7 +2965,7 @@ def is_formal(self, i, max_iterations=3): EXAMPLES:: sage: A. = GradedCommutativeAlgebra(QQ) - sage: B = A.cdg_algebra({e5 : e1*e2 + e3*e4}) + sage: B = A.cdg_algebra({e5: e1*e2 + e3*e4}) sage: B.is_formal(1) True sage: B.is_formal(2) @@ -2946,7 +3003,7 @@ def differential(self): EXAMPLES:: - sage: A. = GradedCommutativeAlgebra(QQ, degrees = (2, 2, 3, 4)) + sage: A. = GradedCommutativeAlgebra(QQ, degrees=(2, 2, 3, 4)) sage: B = A.cdg_algebra({t: x*z, x: z, y: z}) sage: B.inject_variables() Defining x, y, z, t @@ -2973,9 +3030,9 @@ def is_coboundary(self): False sage: (x*z).is_coboundary() True - sage: (x*z+x*y).is_coboundary() + sage: (x*z + x*y).is_coboundary() False - sage: (x*z+y**2).is_coboundary() + sage: (x*z + y**2).is_coboundary() Traceback (most recent call last): ... ValueError: this element is not homogeneous @@ -3000,7 +3057,7 @@ def is_cohomologous_to(self, other): EXAMPLES:: sage: A. = GradedCommutativeAlgebra(QQ, degrees=(1,1,1,1)) - sage: B = A.cdg_algebra(differential={a:b*c-c*d}) + sage: B = A.cdg_algebra(differential={a: b*c-c*d}) sage: w, x, y, z = B.gens() sage: (x*y).is_cohomologous_to(y*z) True @@ -3016,7 +3073,7 @@ def is_cohomologous_to(self, other): False sage: (x*y-y*z).is_cohomologous_to(x*y*z) True - sage: (x*y*z).is_cohomologous_to(0) # make sure 0 works + sage: (x*y*z).is_cohomologous_to(0) # make sure 0 works True """ if other.is_zero(): @@ -3036,17 +3093,17 @@ def cohomology_class(self): EXAMPLES:: sage: A. = GradedCommutativeAlgebra(QQ) - sage: B = A.cdg_algebra({e5:e1*e2+e3*e4}) + sage: B = A.cdg_algebra({e5: e1*e2+e3*e4}) sage: B.inject_variables() Defining e1, e2, e3, e4, e5 - sage: a = e1*e3*e5-3*e2*e3*e5 + sage: a = e1*e3*e5 - 3*e2*e3*e5 sage: a.cohomology_class() B[[e1*e3*e5]] - 3*B[[e2*e3*e5]] TESTS:: sage: A. = GradedCommutativeAlgebra(QQ, degrees=(1, 2, 3)) - sage: B = A.cdg_algebra({a:b}) + sage: B = A.cdg_algebra({a: b}) sage: B.inject_variables() Defining a, b, c sage: b.cohomology_class() @@ -3057,10 +3114,10 @@ def cohomology_class(self): Check that the issue detected in :trac:`28155` is solved:: sage: A. = GradedCommutativeAlgebra(QQ) - sage: B = A.cdg_algebra({e5:e1*e2+e3*e4}) + sage: B = A.cdg_algebra({e5: e1*e2+e3*e4}) sage: B.inject_variables() Defining e1, e2, e3, e4, e5 - sage: a = e1*e3*e5-3*e2*e3*e5 + sage: a = e1*e3*e5 - 3*e2*e3*e5 sage: ca = a.cohomology_class() sage: C = B.cohomology(3) sage: ca in C @@ -3087,7 +3144,7 @@ def _cohomology_class_dict(self): EXAMPLES:: sage: A. = GradedCommutativeAlgebra(QQ) - sage: B = A.cdg_algebra({e5:e1*e2+e3*e4}) + sage: B = A.cdg_algebra({e5: e1*e2+e3*e4}) sage: a = B(e1*e3*e5-3*e2*e3*e5) sage: a._cohomology_class_dict() {(0, 0, 0, 0, 0, 0, 1, 0, 0): -3, (0, 0, 0, 0, 0, 1, 0, 0, 0): 1} @@ -3096,7 +3153,7 @@ def _cohomology_class_dict(self): x5 - 3*x6 sage: B.cohomology_generators(3) {1: [e1, e2, e3, e4], - 3: [e1*e2*e5 - e3*e4*e5, e1*e3*e5, e2*e3*e5, e1*e4*e5, e2*e4*e5]} + 3: [e1*e2*e5 - e3*e4*e5, e1*e3*e5, e2*e3*e5, e1*e4*e5, e2*e4*e5]} sage: [H(g._cohomology_class_dict()) for g in flatten(B.cohomology_generators(3).values())] [x0, x1, x2, x3, x4, x5, x6, x7, x8] """ @@ -3380,9 +3437,11 @@ def GradedCommutativeAlgebra(ring, names=None, degrees=None, max_degree=None, Defining a graded commutative algebra:: sage: GradedCommutativeAlgebra(QQ, 'x, y, z') - Graded Commutative Algebra with generators ('x', 'y', 'z') in degrees (1, 1, 1) over Rational Field + Graded Commutative Algebra with generators ('x', 'y', 'z') + in degrees (1, 1, 1) over Rational Field sage: GradedCommutativeAlgebra(QQ, degrees=(2, 3, 4)) - Graded Commutative Algebra with generators ('x0', 'x1', 'x2') in degrees (2, 3, 4) over Rational Field + Graded Commutative Algebra with generators ('x0', 'x1', 'x2') + in degrees (2, 3, 4) over Rational Field As usual in Sage, the ``A.<...>`` notation defines both the algebra and the generator names:: @@ -3390,21 +3449,21 @@ def GradedCommutativeAlgebra(ring, names=None, degrees=None, max_degree=None, sage: A. = GradedCommutativeAlgebra(QQ, degrees=(1, 1, 2)) sage: x^2 0 - sage: y*x # Odd classes anticommute. + sage: y*x # Odd classes anticommute. -x*y - sage: z*y # z is central since it is in degree 2. + sage: z*y # z is central since it is in degree 2. y*z sage: (x*y*z**3).degree() 8 - sage: A.basis(3) # basis of homogeneous degree 3 elements + sage: A.basis(3) # basis of homogeneous degree 3 elements [x*z, y*z] Defining a quotient:: sage: I = A.ideal(x*z) - sage: AQ = A.quotient(I) - sage: AQ - Graded Commutative Algebra with generators ('x', 'y', 'z') in degrees (1, 1, 2) with relations [x*z] over Rational Field + sage: AQ = A.quotient(I); AQ + Graded Commutative Algebra with generators ('x', 'y', 'z') + in degrees (1, 1, 2) with relations [x*z] over Rational Field sage: AQ.basis(3) [y*z] @@ -3421,14 +3480,15 @@ def GradedCommutativeAlgebra(ring, names=None, degrees=None, max_degree=None, Now we add a differential to ``AQ``:: - sage: B = AQ.cdg_algebra({z:y*z}) - sage: B - Commutative Differential Graded Algebra with generators ('x', 'y', 'z') in degrees (1, 1, 2) with relations [x*z] over Rational Field with differential: + sage: B = AQ.cdg_algebra({z: y*z}); B + Commutative Differential Graded Algebra with generators ('x', 'y', 'z') + in degrees (1, 1, 2) with relations [x*z] over Rational Field with differential: x --> 0 y --> 0 z --> y*z sage: B.differential() - Differential of Commutative Differential Graded Algebra with generators ('x', 'y', 'z') in degrees (1, 1, 2) with relations [x*z] over Rational Field + Differential of Commutative Differential Graded Algebra with generators + ('x', 'y', 'z') in degrees (1, 1, 2) with relations [x*z] over Rational Field Defn: x --> 0 y --> 0 z --> y*z @@ -3447,10 +3507,12 @@ def GradedCommutativeAlgebra(ring, names=None, degrees=None, max_degree=None, We can construct multi-graded rings as well. We work in characteristic 2 for a change, so the algebras here are honestly commutative:: - sage: C. = GradedCommutativeAlgebra(GF(2), degrees=((1,0), (1,1), (0,2), (0,3))) - sage: D = C.cdg_algebra(differential={a:c, b:d}) - sage: D - Commutative Differential Graded Algebra with generators ('a', 'b', 'c', 'd') in degrees ((1, 0), (1, 1), (0, 2), (0, 3)) over Finite Field of size 2 with differential: + sage: C. = GradedCommutativeAlgebra(GF(2), + ....: degrees=((1,0), (1,1), (0,2), (0,3))) + sage: D = C.cdg_algebra(differential={a: c, b: d}); D + Commutative Differential Graded Algebra with generators ('a', 'b', 'c', 'd') + in degrees ((1, 0), (1, 1), (0, 2), (0, 3)) over Finite Field of size 2 + with differential: a --> c b --> d c --> 0 @@ -3460,9 +3522,9 @@ def GradedCommutativeAlgebra(ring, names=None, degrees=None, max_degree=None, Use tuples, lists, vectors, or elements of additive abelian groups to specify degrees:: - sage: D.basis(3) # basis in total degree 3 + sage: D.basis(3) # basis in total degree 3 [a^3, a*b, a*c, d] - sage: D.basis((1,2)) # basis in degree (1,2) + sage: D.basis((1,2)) # basis in degree (1,2) [a*c] sage: D.basis([1,2]) [a*c] @@ -3504,8 +3566,7 @@ def GradedCommutativeAlgebra(ring, names=None, degrees=None, max_degree=None, Graded algebra with maximal degree:: - sage: A. = GradedCommutativeAlgebra(QQ, degrees=(4,2), max_degree=6) - sage: A + sage: A. = GradedCommutativeAlgebra(QQ, degrees=(4,2), max_degree=6); A Graded commutative algebra with generators ('p', 'e') in degrees (4, 2) with maximal degree 6 sage: p^2 @@ -3563,7 +3624,8 @@ class GCAlgebraMorphism(RingHomomorphism_im_gens): sage: H = Hom(A,A) sage: f = H([y,x]) sage: f - Graded Commutative Algebra endomorphism of Graded Commutative Algebra with generators ('x', 'y') in degrees (1, 1) over Rational Field + Graded Commutative Algebra endomorphism of Graded Commutative Algebra + with generators ('x', 'y') in degrees (1, 1) over Rational Field Defn: (x, y) --> (y, x) sage: f(x*y) -x*y @@ -3590,7 +3652,8 @@ def __init__(self, parent, im_gens, check=True): sage: H = Hom(A,A) sage: f = H([x,x]) sage: f - Graded Commutative Algebra endomorphism of Graded Commutative Algebra with generators ('x', 'y') in degrees (1, 2) over Rational Field + Graded Commutative Algebra endomorphism of Graded Commutative Algebra + with generators ('x', 'y') in degrees (1, 2) over Rational Field Defn: (x, y) --> (x, x) sage: f.is_graded() False @@ -3608,7 +3671,8 @@ def __init__(self, parent, im_gens, check=True): sage: A2. = GradedCommutativeAlgebra(GF(2), degrees=(1,2)) sage: H2 = Hom(A2,A2) sage: H2([y,y]) - Graded Commutative Algebra endomorphism of Graded Commutative Algebra with generators ('x', 'y') in degrees (1, 2) over Finite Field of size 2 + Graded Commutative Algebra endomorphism of Graded Commutative Algebra + with generators ('x', 'y') in degrees (1, 2) over Finite Field of size 2 Defn: (x, y) --> (y, y) The "nc-relations" `a*b = -b*a`, for `a` and `b` in odd @@ -3652,7 +3716,8 @@ def __init__(self, parent, im_gens, check=True): sage: A.cover_ring() Multivariate Polynomial Ring in e1 over Rational Field sage: A.hom([2*e1]) - Graded Commutative Algebra endomorphism of Graded Commutative Algebra with generators ('e1',) in degrees (1,) over Rational Field + Graded Commutative Algebra endomorphism of Graded Commutative Algebra + with generators ('e1',) in degrees (1,) over Rational Field Defn: (e1,) --> (2*e1,) """ @@ -3834,13 +3899,17 @@ class GCAlgebraHomset(RingHomset_generic): sage: H = Hom(A,B) sage: H([y,0]) Graded Commutative Algebra morphism: - From: Graded Commutative Algebra with generators ('w', 'x') in degrees (1, 2) over Rational Field - To: Graded Commutative Algebra with generators ('y', 'z') in degrees (1, 1) over Rational Field + From: Graded Commutative Algebra with generators ('w', 'x') + in degrees (1, 2) over Rational Field + To: Graded Commutative Algebra with generators ('y', 'z') + in degrees (1, 1) over Rational Field Defn: (w, x) --> (y, 0) sage: H([y,y*z]) Graded Commutative Algebra morphism: - From: Graded Commutative Algebra with generators ('w', 'x') in degrees (1, 2) over Rational Field - To: Graded Commutative Algebra with generators ('y', 'z') in degrees (1, 1) over Rational Field + From: Graded Commutative Algebra with generators ('w', 'x') + in degrees (1, 2) over Rational Field + To: Graded Commutative Algebra with generators ('y', 'z') + in degrees (1, 1) over Rational Field Defn: (w, x) --> (y, y*z) """ @@ -3925,8 +3994,8 @@ class CohomologyClass(SageObject, CachedRepresentation): sage: from sage.algebras.commutative_dga import CohomologyClass sage: CohomologyClass(3) [3] - sage: A. = GradedCommutativeAlgebra(QQ, degrees = (2,2,3,3)) - sage: CohomologyClass(x^2+2*y*z, A) + sage: A. = GradedCommutativeAlgebra(QQ, degrees=(2,2,3,3)) + sage: CohomologyClass(x^2 + 2*y*z, A) [2*y*z + x^2] TESTS: @@ -3978,7 +4047,7 @@ def __init__(self, x, cdga=None): EXAMPLES:: sage: from sage.algebras.commutative_dga import CohomologyClass - sage: CohomologyClass(x-2) + sage: CohomologyClass(x - 2) # needs sage.symbolic [x - 2] """ self._x = x @@ -3989,7 +4058,7 @@ def __hash__(self): TESTS:: sage: from sage.algebras.commutative_dga import CohomologyClass - sage: hash(CohomologyClass(sin)) == hash(sin) + sage: hash(CohomologyClass(sin)) == hash(sin) # needs sage.symbolic True """ return hash(self._x) @@ -3999,7 +4068,7 @@ def _repr_(self): EXAMPLES:: sage: from sage.algebras.commutative_dga import CohomologyClass - sage: CohomologyClass(sin) + sage: CohomologyClass(sin) # needs sage.symbolic [sin] """ return '[{}]'.format(self._x) @@ -4009,9 +4078,9 @@ def _latex_(self): EXAMPLES:: sage: from sage.algebras.commutative_dga import CohomologyClass - sage: latex(CohomologyClass(sin)) + sage: latex(CohomologyClass(sin)) # needs sage.symbolic \left[ \sin \right] - sage: latex(CohomologyClass(x^2)) + sage: latex(CohomologyClass(x^2)) # needs sage.symbolic \left[ x^{2} \right] """ from sage.misc.latex import latex @@ -4024,8 +4093,8 @@ def representative(self): EXAMPLES:: sage: from sage.algebras.commutative_dga import CohomologyClass - sage: x = CohomologyClass(sin) - sage: x.representative() == sin + sage: x = CohomologyClass(sin) # needs sage.symbolic + sage: x.representative() == sin # needs sage.symbolic True """ return self._x @@ -4085,7 +4154,7 @@ def total_degree(deg): INPUT: - - ``deg`` - an element of a free abelian group. + - ``deg`` -- an element of a free abelian group. In fact, ``deg`` could be an integer, a Python int, a list, a tuple, a vector, etc. This function returns the sum of the diff --git a/src/sage/algebras/down_up_algebra.py b/src/sage/algebras/down_up_algebra.py index 3ee1bcea25f..088e7ac30ad 100644 --- a/src/sage/algebras/down_up_algebra.py +++ b/src/sage/algebras/down_up_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.modules r""" Down-Up Algebras @@ -539,12 +540,13 @@ class VermaModule(CombinatorialFreeModule): construction of the irreducible representation `V(5)` (but they are different as `\mathfrak{gl}_2` weights):: - sage: B = crystals.Tableaux(['A',1], shape=[5]) - sage: [b.weight() for b in B] + sage: B = crystals.Tableaux(['A',1], shape=[5]) # needs sage.graphs + sage: [b.weight() for b in B] # needs sage.graphs [(5, 0), (4, 1), (3, 2), (2, 3), (1, 4), (0, 5)] An example with periodic weights (see Theorem 2.13 of [BR1998]_):: + sage: # needs sage.rings.number_field sage: k. = CyclotomicField(6) sage: al = z6 + 1 sage: (al - 1)^6 == 1 diff --git a/src/sage/algebras/exterior_algebra_groebner.pyx b/src/sage/algebras/exterior_algebra_groebner.pyx index 376eb454082..265e9323536 100644 --- a/src/sage/algebras/exterior_algebra_groebner.pyx +++ b/src/sage/algebras/exterior_algebra_groebner.pyx @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.modules r""" Exterior algebras Gröbner bases diff --git a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py index af2b5e7dd3c..a3b8742b4e0 100644 --- a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py +++ b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra.py @@ -57,22 +57,28 @@ class FiniteDimensionalAlgebra(UniqueRepresentation, Algebra): EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) - sage: A + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]); A Finite-dimensional algebra of degree 2 over Finite Field of size 3 sage: TestSuite(A).run() - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), Matrix([[0,1,0], [0,0,0], [0,0,0]]), Matrix([[0,0,0], [0,0,0], [0,0,1]])]) + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), + ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,0,0], [0,0,0], [0,0,1]])]) sage: B Finite-dimensional algebra of degree 3 over Rational Field TESTS:: sage: A.category() - Category of finite dimensional magmatic algebras with basis over Finite Field of size 3 - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])], assume_associative=True) + Category of finite dimensional magmatic algebras with basis + over Finite Field of size 3 + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])], + ....: assume_associative=True) sage: A.category() - Category of finite dimensional associative algebras with basis over Finite Field of size 3 + Category of finite dimensional associative algebras with basis + over Finite Field of size 3 """ @staticmethod def __classcall_private__(cls, k, table, names='e', assume_associative=False, @@ -93,7 +99,8 @@ def __classcall_private__(cls, k, table, names='e', assume_associative=False, sage: from sage.categories.magmatic_algebras import MagmaticAlgebras sage: cat = MagmaticAlgebras(GF(3)).FiniteDimensional().WithBasis() - sage: A1 = FiniteDimensionalAlgebra(GF(3), table, category=cat.Associative()) + sage: A1 = FiniteDimensionalAlgebra(GF(3), table, + ....: category=cat.Associative()) sage: A2 = FiniteDimensionalAlgebra(GF(3), table, assume_associative=True) sage: A1 is A2 True @@ -197,7 +204,8 @@ def _coerce_map_from_(self, S): """ TESTS:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) sage: A.has_coerce_map_from(ZZ) True sage: A.has_coerce_map_from(GF(3)) @@ -224,7 +232,9 @@ def _element_constructor_(self, x): ... TypeError: algebra is not unitary - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), Matrix([[0,1,0], [0,0,0], [0,0,0]]), Matrix([[0,0,0], [0,0,0], [0,0,1]])]) + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), + ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,0,0], [0,0,0], [0,0,1]])]) sage: B(17) 17*e0 + 17*e2 """ @@ -243,7 +253,9 @@ def _Hom_(self, B, category): sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([1])]) sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) sage: A._Hom_(B, A.category()) - Set of Homomorphisms from Finite-dimensional algebra of degree 1 over Rational Field to Finite-dimensional algebra of degree 2 over Rational Field + Set of Homomorphisms + from Finite-dimensional algebra of degree 1 over Rational Field + to Finite-dimensional algebra of degree 2 over Rational Field """ cat = MagmaticAlgebras(self.base_ring()).FiniteDimensional().WithBasis() if category.is_subcategory(cat): @@ -258,7 +270,8 @@ def ngens(self): EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) sage: A.ngens() 2 """ @@ -273,7 +286,8 @@ def gen(self, i): EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) sage: A.gen(0) e0 """ @@ -286,7 +300,8 @@ def basis(self): EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) sage: A.basis() Family (e0, e1) """ @@ -299,7 +314,8 @@ def __iter__(self): EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) sage: list(A) [0, e0, 2*e0, e1, e0 + e1, 2*e0 + e1, 2*e1, e0 + 2*e1, 2*e0 + 2*e1] @@ -319,7 +335,8 @@ def _ideal_class_(self, n=0): EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) sage: A._ideal_class_() """ @@ -332,7 +349,8 @@ def table(self): EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) sage: A.table() ( [1 0] [0 1] @@ -349,7 +367,8 @@ def left_table(self): EXAMPLES:: - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), Matrix([[0,1],[-1,0]])]) + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), + ....: Matrix([[0,1], [-1,0]])]) sage: T = B.left_table(); T ( [1 0] [ 0 1] @@ -382,8 +401,8 @@ def base_extend(self, F): EXAMPLES:: sage: C = FiniteDimensionalAlgebra(GF(2), [Matrix([1])]) - sage: k. = GF(4) - sage: C.base_extend(k) + sage: k. = GF(4) # needs sage.rings.finite_rings + sage: C.base_extend(k) # needs sage.rings.finite_rings Finite-dimensional algebra of degree 1 over Finite Field in y of size 2^2 """ # Base extension of the multiplication table is done by __classcall_private__. @@ -395,11 +414,13 @@ def cardinality(self): EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(7), [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [2, 3]])]) + sage: A = FiniteDimensionalAlgebra(GF(7), [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [2, 3]])]) sage: A.cardinality() 49 - sage: B = FiniteDimensionalAlgebra(RR, [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [2, 3]])]) + sage: B = FiniteDimensionalAlgebra(RR, [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [2, 3]])]) sage: B.cardinality() +Infinity @@ -431,9 +452,11 @@ def ideal(self, gens=None, given_by_matrix=False, side=None): EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) sage: A.ideal(A([1,1])) - Ideal (e0 + e1) of Finite-dimensional algebra of degree 2 over Finite Field of size 3 + Ideal (e0 + e1) of + Finite-dimensional algebra of degree 2 over Finite Field of size 3 """ return self._ideal_class_()(self, gens=gens, given_by_matrix=given_by_matrix) @@ -445,11 +468,14 @@ def is_associative(self): EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), Matrix([[0,1],[-1,0]])]) + sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), + ....: Matrix([[0,1], [-1,0]])]) sage: A.is_associative() True - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,1]]), Matrix([[0,1,0], [0,0,0], [0,0,0]]), Matrix([[0,0,1], [0,0,0], [1,0,0]])]) + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,1]]), + ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,0,1], [0,0,0], [1,0,0]])]) sage: B.is_associative() False @@ -473,11 +499,15 @@ def is_commutative(self): EXAMPLES:: - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), Matrix([[0,1,0], [0,0,0], [0,0,0]]), Matrix([[0,0,0], [0,0,0], [0,0,1]])]) + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), + ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,0,0], [0,0,0], [0,0,1]])]) sage: B.is_commutative() True - sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,0,0], [0,0,0]]), Matrix([[0,1,0], [0,0,0], [0,0,0]]), Matrix([[0,0,0], [0,1,0], [0,0,1]])]) + sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,0,0], [0,1,0], [0,0,1]])]) sage: C.is_commutative() False """ @@ -495,11 +525,13 @@ def is_finite(self): EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(7), [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [2, 3]])]) + sage: A = FiniteDimensionalAlgebra(GF(7), [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [2, 3]])]) sage: A.is_finite() True - sage: B = FiniteDimensionalAlgebra(RR, [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [2, 3]])]) + sage: B = FiniteDimensionalAlgebra(RR, [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [2, 3]])]) sage: B.is_finite() False @@ -526,27 +558,35 @@ def is_unitary(self): sage: A.is_unitary() True - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), Matrix([[0,1], [-1,0]])]) + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), + ....: Matrix([[0,1], [-1,0]])]) sage: B.is_unitary() True - sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[0,0], [0,0]]), Matrix([[0,0], [0,0]])]) + sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[0,0], [0,0]]), + ....: Matrix([[0,0], [0,0]])]) sage: C.is_unitary() False - sage: D = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), Matrix([[1,0], [0,1]])]) + sage: D = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), + ....: Matrix([[1,0], [0,1]])]) sage: D.is_unitary() False - sage: E = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0],[1,0]]), Matrix([[0,1],[0,1]])]) + sage: E = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0],[1,0]]), + ....: Matrix([[0,1],[0,1]])]) sage: E.is_unitary() False - sage: F = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,1]]), Matrix([[0,1,0], [0,0,0], [0,0,0]]), Matrix([[0,0,1], [0,0,0], [1,0,0]])]) + sage: F = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,1]]), + ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,0,1], [0,0,0], [1,0,0]])]) sage: F.is_unitary() True - sage: G = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,1]]), Matrix([[0,1,0], [0,0,0], [0,0,0]]), Matrix([[0,1,0], [0,0,0], [1,0,0]])]) + sage: G = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,1]]), + ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,1,0], [0,0,0], [1,0,0]])]) sage: G.is_unitary() # Unique right identity, but no left identity. False """ @@ -600,21 +640,27 @@ def one(self): sage: A.one() 0 - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), Matrix([[0,1], [-1,0]])]) + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), + ....: Matrix([[0,1], [-1,0]])]) sage: B.one() e0 - sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[0,0], [0,0]]), Matrix([[0,0], [0,0]])]) + sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[0,0], [0,0]]), + ....: Matrix([[0,0], [0,0]])]) sage: C.one() Traceback (most recent call last): ... TypeError: algebra is not unitary - sage: D = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,1]]), Matrix([[0,1,0], [0,0,0], [0,0,0]]), Matrix([[0,0,1], [0,0,0], [1,0,0]])]) + sage: D = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,1]]), + ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,0,1], [0,0,0], [1,0,0]])]) sage: D.one() e0 - sage: E = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,1]]), Matrix([[0,1,0], [0,0,0], [0,0,0]]), Matrix([[0,1,0], [0,0,0], [1,0,0]])]) + sage: E = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,1]]), + ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,1,0], [0,0,0], [1,0,0]])]) sage: E.one() Traceback (most recent call last): ... @@ -634,11 +680,14 @@ def random_element(self, *args, **kwargs): EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) sage: A.random_element() # random e0 + 2*e1 - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), Matrix([[0,1,0], [0,0,0], [0,0,0]]), Matrix([[0,0,0], [0,0,0], [0,0,1]])]) + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), + ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,0,0], [0,0,0], [0,0,1]])]) sage: B.random_element(num_bound=1000) # random 215/981*e0 + 709/953*e1 + 931/264*e2 """ @@ -648,32 +697,39 @@ def _is_valid_homomorphism_(self, other, im_gens, base_map=None): """ TESTS:: - sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) + sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([1])]) sage: Hom(A, B)(Matrix([[1], [0]])) - Morphism from Finite-dimensional algebra of degree 2 over Rational Field to Finite-dimensional algebra of degree 1 over Rational Field given by matrix + Morphism from Finite-dimensional algebra of degree 2 over Rational Field + to Finite-dimensional algebra of degree 1 over Rational Field given by matrix [1] [0] sage: Hom(B, A)(Matrix([[1, 0]])) - Morphism from Finite-dimensional algebra of degree 1 over Rational Field to Finite-dimensional algebra of degree 2 over Rational Field given by matrix + Morphism from Finite-dimensional algebra of degree 1 over Rational Field + to Finite-dimensional algebra of degree 2 over Rational Field given by matrix [1 0] sage: H = Hom(A, A) sage: H(Matrix.identity(QQ, 2)) - Morphism from Finite-dimensional algebra of degree 2 over Rational Field to Finite-dimensional algebra of degree 2 over Rational Field given by matrix + Morphism from Finite-dimensional algebra of degree 2 over Rational Field + to Finite-dimensional algebra of degree 2 over Rational Field given by matrix [1 0] [0 1] sage: H(Matrix([[1, 0], [0, 0]])) - Morphism from Finite-dimensional algebra of degree 2 over Rational Field to Finite-dimensional algebra of degree 2 over Rational Field given by matrix + Morphism from Finite-dimensional algebra of degree 2 over Rational Field + to Finite-dimensional algebra of degree 2 over Rational Field given by matrix [1 0] [0 0] sage: H(Matrix([[1, 0], [1, 1]])) Traceback (most recent call last): ... - ValueError: relations do not all (canonically) map to 0 under map determined by images of generators + ValueError: relations do not all (canonically) map to 0 + under map determined by images of generators sage: Hom(B, B)(Matrix([[2]])) Traceback (most recent call last): ... - ValueError: relations do not all (canonically) map to 0 under map determined by images of generators + ValueError: relations do not all (canonically) map to 0 + under map determined by images of generators """ assert len(im_gens) == self.degree() @@ -694,7 +750,7 @@ def quotient_map(self, ideal): INPUT: - - ``ideal`` -- a ``FiniteDimensionalAlgebraIdeal`` + - ``ideal`` -- a :class:`FiniteDimensionalAlgebraIdeal` OUTPUT: @@ -703,17 +759,22 @@ def quotient_map(self, ideal): EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) - sage: q0 = A.quotient_map(A.zero_ideal()) - sage: q0 - Morphism from Finite-dimensional algebra of degree 2 over Finite Field of size 3 to Finite-dimensional algebra of degree 2 over Finite Field of size 3 given by matrix - [1 0] - [0 1] - sage: q1 = A.quotient_map(A.ideal(A.gen(1))) - sage: q1 - Morphism from Finite-dimensional algebra of degree 2 over Finite Field of size 3 to Finite-dimensional algebra of degree 1 over Finite Field of size 3 given by matrix - [1] - [0] + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) + sage: q0 = A.quotient_map(A.zero_ideal()); q0 + Morphism + from Finite-dimensional algebra of degree 2 over Finite Field of size 3 + to Finite-dimensional algebra of degree 2 over Finite Field of size 3 + given by matrix + [1 0] + [0 1] + sage: q1 = A.quotient_map(A.ideal(A.gen(1))); q1 + Morphism + from Finite-dimensional algebra of degree 2 over Finite Field of size 3 + to Finite-dimensional algebra of degree 1 over Finite Field of size 3 + given by matrix + [1] + [0] """ k = self.base_ring() f = ideal.basis_matrix().transpose().kernel().basis_matrix().echelon_form().transpose() @@ -744,12 +805,16 @@ def maximal_ideal(self): EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) - sage: A.maximal_ideal() - Ideal (0, e1) of Finite-dimensional algebra of degree 2 over Finite Field of size 3 + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) + sage: A.maximal_ideal() # needs sage.rings.finite_rings + Ideal (0, e1) of + Finite-dimensional algebra of degree 2 over Finite Field of size 3 - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), Matrix([[0,1,0], [0,0,0], [0,0,0]]), Matrix([[0,0,0], [0,0,0], [0,0,1]])]) - sage: B.maximal_ideal() + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), + ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,0,0], [0,0,0], [0,0,1]])]) + sage: B.maximal_ideal() # needs sage.libs.pari Traceback (most recent call last): ... ValueError: algebra is not local @@ -783,18 +848,31 @@ def primary_decomposition(self): EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) - sage: A.primary_decomposition() - [Morphism from Finite-dimensional algebra of degree 2 over Finite Field of size 3 to Finite-dimensional algebra of degree 2 over Finite Field of size 3 given by matrix [1 0] - [0 1]] - - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), Matrix([[0,1,0], [0,0,0], [0,0,0]]), Matrix([[0,0,0], [0,0,0], [0,0,1]])]) - sage: B.primary_decomposition() - [Morphism from Finite-dimensional algebra of degree 3 over Rational Field to Finite-dimensional algebra of degree 1 over Rational Field given by matrix [0] - [0] - [1], Morphism from Finite-dimensional algebra of degree 3 over Rational Field to Finite-dimensional algebra of degree 2 over Rational Field given by matrix [1 0] - [0 1] - [0 0]] + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) + sage: A.primary_decomposition() # needs sage.rings.finite_rings + [Morphism + from Finite-dimensional algebra of degree 2 over Finite Field of size 3 + to Finite-dimensional algebra of degree 2 over Finite Field of size 3 + given by matrix [1 0] + [0 1]] + + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), + ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,0,0], [0,0,0], [0,0,1]])]) + sage: B.primary_decomposition() # needs sage.libs.pari + [Morphism + from Finite-dimensional algebra of degree 3 over Rational Field + to Finite-dimensional algebra of degree 1 over Rational Field + given by matrix [0] + [0] + [1], + Morphism + from Finite-dimensional algebra of degree 3 over Rational Field + to Finite-dimensional algebra of degree 2 over Rational Field + given by matrix [1 0] + [0 1] + [0 0]] """ k = self.base_ring() n = self.degree() @@ -838,8 +916,9 @@ def maximal_ideals(self): EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) - sage: A.maximal_ideals() + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) + sage: A.maximal_ideals() # needs sage.rings.finite_rings [Ideal (e1) of Finite-dimensional algebra of degree 2 over Finite Field of size 3] sage: B = FiniteDimensionalAlgebra(QQ, []) diff --git a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pyx b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pyx index e4901439e19..d58e1ac8647 100644 --- a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pyx +++ b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_element.pyx @@ -26,7 +26,9 @@ cpdef FiniteDimensionalAlgebraElement unpickle_FiniteDimensionalAlgebraElement(A TESTS:: - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), Matrix([[1,1,0], [0,1,1], [0,1,1]]), Matrix([[0,0,1], [0,1,0], [1,0,0]])]) + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), + ....: Matrix([[1,1,0], [0,1,1], [0,1,1]]), + ....: Matrix([[0,0,1], [0,1,0], [1,0,0]])]) sage: x = B([1,2,3]) sage: loads(dumps(x)) == x # indirect doctest True @@ -59,7 +61,8 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1,0], [0,1]]), Matrix([[0,1], [0,0]])]) + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1,0], [0,1]]), + ....: Matrix([[0,1], [0,0]])]) sage: A(17) 2*e0 sage: A([1,1]) @@ -69,13 +72,15 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): """ TESTS:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1,0], [0,1]]), Matrix([[0,1], [0,0]])]) + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1,0], [0,1]]), + ....: Matrix([[0,1], [0,0]])]) sage: A(QQ(4)) Traceback (most recent call last): ... TypeError: elt should be a vector, a matrix, or an element of the base field - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), Matrix([[0,1], [-1,0]])]) + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), + ....: Matrix([[0,1], [-1,0]])]) sage: elt = B(Matrix([[1,1], [-1,1]])); elt e0 + e1 sage: TestSuite(elt).run() @@ -133,7 +138,9 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): """ TESTS:: - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), Matrix([[1,1,0], [0,1,1], [0,1,1]]), Matrix([[0,0,1], [0,1,0], [1,0,0]])]) + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), + ....: Matrix([[1,1,0], [0,1,1], [0,1,1]]), + ....: Matrix([[0,0,1], [0,1,0], [1,0,0]])]) sage: x = B([1,2,3]) sage: loads(dumps(x)) == x # indirect doctest True @@ -149,7 +156,9 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): TESTS:: - sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), Matrix([[0,1,0], [0,0,0], [0,0,0]]), Matrix([[0,0,0], [0,0,0], [0,0,1]])]) + sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), + ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,0,0], [0,0,0], [0,0,1]])]) sage: x = A.element_class.__new__(A.element_class) sage: x.__setstate__((A, {'_vector':vector([1,1,1]), '_matrix':matrix(QQ,3,[1,1,0, 0,1,0, 0,0,1])})) sage: x @@ -183,7 +192,9 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): """ TESTS:: - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), Matrix([[1,1,0], [0,1,1], [0,1,1]]), Matrix([[0,0,1], [0,1,0], [1,0,0]])]) + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), + ....: Matrix([[1,1,0], [0,1,1], [0,1,1]]), + ....: Matrix([[0,0,1], [0,1,0], [1,0,0]])]) sage: x = B([1,2,3]) sage: x._matrix [3 2 3] @@ -205,7 +216,9 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): EXAMPLES:: - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), Matrix([[0,1,0], [0,0,0], [0,0,0]]), Matrix([[0,0,0], [0,0,0], [0,0,1]])]) + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), + ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,0,0], [0,0,0], [0,0,1]])]) sage: B(5).vector() (5, 0, 5) """ @@ -220,7 +233,9 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): EXAMPLES:: - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), Matrix([[0,1,0], [0,0,0], [0,0,0]]), Matrix([[0,0,0], [0,0,0], [0,0,1]])]) + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), + ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,0,0], [0,0,0], [0,0,1]])]) sage: B(5).matrix() [5 0 0] [0 5 0] @@ -240,7 +255,8 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): EXAMPLES:: - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), Matrix([[0,1], [-1,0]])]) + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), + ....: Matrix([[0,1], [-1,0]])]) sage: elt = B(Matrix([[1,1], [-1,1]])) sage: elt.monomial_coefficients() {0: 1, 1: 1} @@ -254,7 +270,9 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): EXAMPLES:: - sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,0,0], [0,0,0]]), Matrix([[0,1,0], [0,0,0], [0,0,0]]), Matrix([[0,0,0], [0,1,0], [0,0,1]])]) + sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,0,0], [0,1,0], [0,0,1]])]) sage: C([1,2,0]).left_matrix() [1 0 0] [0 1 0] @@ -272,7 +290,8 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1,0], [0,1]]), Matrix([[0,1], [0,0]])]) + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1,0], [0,1]]), + ....: Matrix([[0,1], [0,0]])]) sage: A(1) e0 """ @@ -308,7 +327,8 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1,0], [0,1]]), Matrix([[0,1], [0,0]])]) + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1,0], [0,1]]), + ....: Matrix([[0,1], [0,0]])]) sage: latex(A(1)) # indirect doctest \left(\begin{array}{rr} 1 & 0 \\ @@ -324,7 +344,9 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), Matrix([[0,1,0], [0,0,0], [0,0,0]]), Matrix([[0,0,0], [0,0,0], [0,0,1]])]) + sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), + ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,0,0], [0,0,0], [0,0,1]])]) sage: A([2,1/4,3])[2] 3 """ @@ -334,7 +356,9 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): """ EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), Matrix([[0,1,0], [0,0,0], [0,0,0]]), Matrix([[0,0,0], [0,0,0], [0,0,1]])]) + sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), + ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,0,0], [0,0,0], [0,0,1]])]) sage: len(A([2,1/4,3])) 3 """ @@ -345,7 +369,8 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): """ EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1,0], [0,1]]), Matrix([[0,1], [0,0]])]) + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1,0], [0,1]]), + ....: Matrix([[0,1], [0,0]])]) sage: A(2) == 2 True sage: A(2) == 3 @@ -353,7 +378,9 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): sage: A(2) == GF(5)(2) False - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), Matrix([[0,1,0], [0,0,0], [0,0,0]]), Matrix([[0,0,0], [0,0,0], [0,0,1]])]) + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), + ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,0,0], [0,0,0], [0,0,1]])]) sage: B(1) != 0 True @@ -377,7 +404,8 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): """ EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1,0], [0,1]]), Matrix([[0,1], [0,0]])]) + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1,0], [0,1]]), + ....: Matrix([[0,1], [0,0]])]) sage: A.basis()[0] + A.basis()[1] e0 + e1 """ @@ -387,7 +415,8 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): """ EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1,0], [0,1]]), Matrix([[0,1], [0,0]])]) + sage: A = FiniteDimensionalAlgebra(GF(3), [Matrix([[1,0], [0,1]]), + ....: Matrix([[0,1], [0,0]])]) sage: A.basis()[0] - A.basis()[1] e0 + 2*e1 """ @@ -397,7 +426,9 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): """ EXAMPLES:: - sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,0,0], [0,0,0]]), Matrix([[0,1,0], [0,0,0], [0,0,0]]), Matrix([[0,0,0], [0,1,0], [0,0,1]])]) + sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,0,0], [0,1,0], [0,0,1]])]) sage: C.basis()[1] * C.basis()[2] e1 """ @@ -407,7 +438,9 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): """ TESTS:: - sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,0,0], [0,0,0]]), Matrix([[0,1,0], [0,0,0], [0,0,0]]), Matrix([[0,0,0], [0,1,0], [0,0,1]])]) + sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,0,0], [0,1,0], [0,0,1]])]) sage: c = C.random_element() sage: c * 2 == c + c True @@ -421,7 +454,9 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): """ TESTS:: - sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,0,0], [0,0,0]]), Matrix([[0,1,0], [0,0,0], [0,0,0]]), Matrix([[0,0,0], [0,1,0], [0,0,1]])]) + sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,0,0], [0,1,0], [0,0,1]])]) sage: c = C.random_element() sage: 2 * c == c + c True @@ -438,7 +473,9 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): EXAMPLES:: - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), Matrix([[0,1,0], [0,0,0], [0,0,0]]), Matrix([[0,0,0], [0,0,0], [0,0,1]])]) + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), + ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,0,0], [0,0,0], [0,0,1]])]) sage: b = B([2,3,4]) sage: b^6 64*e0 + 576*e1 + 4096*e2 @@ -459,7 +496,8 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): """ TESTS:: - sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), Matrix([[0,1], [-1,0]])]) + sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), + ....: Matrix([[0,1], [-1,0]])]) sage: x = C([1,2]) sage: y = ~x; y # indirect doctest 1/5*e0 - 2/5*e1 @@ -486,7 +524,8 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): EXAMPLES:: - sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), Matrix([[0,1], [-1,0]])]) + sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), + ....: Matrix([[0,1], [-1,0]])]) sage: C([1,2]).is_invertible() True sage: C(0).is_invertible() @@ -505,7 +544,8 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): EXAMPLES:: - sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), Matrix([[0,1], [-1,0]])]) + sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), + ....: Matrix([[0,1], [-1,0]])]) sage: C([1,2])._inverse 1/5*e0 - 2/5*e1 sage: C(0)._inverse is None @@ -543,7 +583,8 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): EXAMPLES:: - sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), Matrix([[0,1], [-1,0]])]) + sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), + ....: Matrix([[0,1], [-1,0]])]) sage: C([1,2]).inverse() 1/5*e0 - 2/5*e1 """ @@ -561,7 +602,8 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): EXAMPLES:: - sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), Matrix([[0,1], [0,0]])]) + sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), + ....: Matrix([[0,1], [0,0]])]) sage: C([1,0]).is_zerodivisor() False sage: C([0,1]).is_zerodivisor() @@ -575,7 +617,8 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): EXAMPLES:: - sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), Matrix([[0,1], [0,0]])]) + sage: C = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0], [0,1]]), + ....: Matrix([[0,1], [0,0]])]) sage: C([1,0]).is_nilpotent() False sage: C([0,1]).is_nilpotent() @@ -596,13 +639,15 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): EXAMPLES:: - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), Matrix([[0,1,0], [0,0,0], [0,0,0]]), Matrix([[0,0,0], [0,0,0], [0,0,1]])]) - sage: B(0).minimal_polynomial() + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), + ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,0,0], [0,0,0], [0,0,1]])]) + sage: B(0).minimal_polynomial() # needs sage.libs.pari x sage: b = B.random_element() - sage: f = b.minimal_polynomial(); f # random + sage: f = b.minimal_polynomial(); f # random # needs sage.libs.pari x^3 + 1/2*x^2 - 7/16*x + 1/16 - sage: f(b) == 0 + sage: f(b) == 0 # needs sage.libs.pari True """ A = self.parent() @@ -625,13 +670,15 @@ cdef class FiniteDimensionalAlgebraElement(AlgebraElement): EXAMPLES:: - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), Matrix([[0,1,0], [0,0,0], [0,0,0]]), Matrix([[0,0,0], [0,0,0], [0,0,1]])]) - sage: B(0).characteristic_polynomial() + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1,0,0], [0,1,0], [0,0,0]]), + ....: Matrix([[0,1,0], [0,0,0], [0,0,0]]), + ....: Matrix([[0,0,0], [0,0,0], [0,0,1]])]) + sage: B(0).characteristic_polynomial() # needs sage.libs.pari x^3 sage: b = B.random_element() - sage: f = b.characteristic_polynomial(); f # random + sage: f = b.characteristic_polynomial(); f # random # needs sage.libs.pari x^3 - 8*x^2 + 16*x - sage: f(b) == 0 + sage: f(b) == 0 # needs sage.libs.pari True """ return self.matrix().characteristic_polynomial() diff --git a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py index 54f137e1966..15f0881bb8b 100644 --- a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py +++ b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_ideal.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.rings.finite_rings (because all doctests use GF) """ Ideals of Finite Algebras """ diff --git a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py index 22f12ce6bb5..d2114511ae6 100644 --- a/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py +++ b/src/sage/algebras/finite_dimensional_algebras/finite_dimensional_algebra_morphism.py @@ -41,7 +41,8 @@ class FiniteDimensionalAlgebraMorphism(RingHomomorphism_im_gens): EXAMPLES:: sage: from sage.algebras.finite_dimensional_algebras.finite_dimensional_algebra_morphism import FiniteDimensionalAlgebraMorphism - sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) + sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([1])]) sage: H = Hom(A, B) sage: f = H(Matrix([[1], [0]])) @@ -62,7 +63,8 @@ def __init__(self, parent, f, check=True, unitary=True): sage: from sage.algebras.finite_dimensional_algebras.finite_dimensional_algebra_morphism import FiniteDimensionalAlgebraMorphism sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([1])]) - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) sage: H = Hom(A, B) sage: phi = FiniteDimensionalAlgebraMorphism(H, Matrix([[1, 0]])) sage: TestSuite(phi).run(skip="_test_category") @@ -82,10 +84,11 @@ def _repr_(self): r""" TESTS:: - sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) - sage: I = A.maximal_ideal() - sage: q = A.quotient_map(I) - sage: q._repr_() + sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) + sage: I = A.maximal_ideal() # needs sage.libs.pari + sage: q = A.quotient_map(I) # needs sage.libs.pari + sage: q._repr_() # needs sage.libs.pari 'Morphism from Finite-dimensional algebra of degree 2 over Rational Field to Finite-dimensional algebra of degree 1 over Rational Field given by matrix\n[1]\n[0]' """ return "Morphism from {} to {} given by matrix\n{}".format( @@ -95,10 +98,11 @@ def __call__(self, x): """ TESTS:: - sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) - sage: I = A.maximal_ideal() - sage: q = A.quotient_map(I) - sage: q(0) == 0 and q(1) == 1 + sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) + sage: I = A.maximal_ideal() # needs sage.libs.pari + sage: q = A.quotient_map(I) # needs sage.libs.pari + sage: q(0) == 0 and q(1) == 1 # needs sage.libs.pari True """ x = self.domain()(x) @@ -112,7 +116,8 @@ def __eq__(self, other): TESTS:: sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([1])]) - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) sage: H = Hom(A, B) sage: phi = H(Matrix([[1, 0]])) sage: psi = H(Matrix([[1, 0]])) @@ -132,7 +137,8 @@ def __ne__(self, other): TESTS:: sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([1])]) - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) sage: H = Hom(A, B) sage: phi = H(Matrix([[1, 0]])) sage: psi = H(Matrix([[1, 0]])) @@ -149,7 +155,8 @@ def matrix(self): EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) + sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([1])]) sage: M = Matrix([[1], [0]]) sage: H = Hom(A, B) @@ -169,15 +176,16 @@ def inverse_image(self, I): OUTPUT: - -- ``FiniteDimensionalAlgebraIdeal``, the inverse image of `I` under ``self``. + :class:`FiniteDimensionalAlgebraIdeal`, the inverse image of `I` under ``self``. EXAMPLES:: - sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) - sage: I = A.maximal_ideal() - sage: q = A.quotient_map(I) - sage: B = q.codomain() - sage: q.inverse_image(B.zero_ideal()) == I + sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) + sage: I = A.maximal_ideal() # needs sage.libs.pari + sage: q = A.quotient_map(I) # needs sage.libs.pari + sage: B = q.codomain() # needs sage.libs.pari + sage: q.inverse_image(B.zero_ideal()) == I # needs sage.libs.pari True """ coker_I = I.basis_matrix().transpose().kernel().basis_matrix().transpose() @@ -195,7 +203,8 @@ def zero(self): EXAMPLES:: sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([1])]) - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) sage: H = Hom(A, B) sage: H.zero() Morphism from Finite-dimensional algebra of degree 1 over Rational Field to @@ -218,7 +227,8 @@ def __call__(self, f, check=True, unitary=True): EXAMPLES:: sage: A = FiniteDimensionalAlgebra(QQ, [Matrix([1])]) - sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), Matrix([[0, 1], [0, 0]])]) + sage: B = FiniteDimensionalAlgebra(QQ, [Matrix([[1, 0], [0, 1]]), + ....: Matrix([[0, 1], [0, 0]])]) sage: H = Hom(A, B) sage: H(Matrix([[1, 0]])) Morphism from Finite-dimensional algebra of degree 1 over Rational Field to diff --git a/src/sage/algebras/finite_gca.py b/src/sage/algebras/finite_gca.py index 5f21cdc8290..cb6c29e358d 100644 --- a/src/sage/algebras/finite_gca.py +++ b/src/sage/algebras/finite_gca.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.modules r""" Finite dimensional graded commutative algebras @@ -89,14 +90,15 @@ class FiniteGCAlgebra(CombinatorialFreeModule, Algebra): sage: A. = GradedCommutativeAlgebra(QQ, degrees=(1,2,2,3), max_degree=6) sage: A - Graded commutative algebra with generators ('x', 'y', 'z', 't') in degrees (1, 2, 2, 3) with maximal degree 6 + Graded commutative algebra with generators ('x', 'y', 'z', 't') + in degrees (1, 2, 2, 3) with maximal degree 6 sage: t*x + x*t 0 sage: x^2 0 sage: x*t^2 0 - sage: x*y^2+z*t + sage: x*y^2 + z*t x*y^2 + z*t The generators can be returned with :meth:`algebra_generators`:: @@ -114,7 +116,9 @@ class FiniteGCAlgebra(CombinatorialFreeModule, Algebra): Depending on the context, the multiplication can be given a different symbol:: - sage: A. = GradedCommutativeAlgebra(QQ, degrees=(1,2,6,6), max_degree=10, mul_symbol='⌣', mul_latex_symbol=r'\smile') + sage: A. = GradedCommutativeAlgebra(QQ, degrees=(1,2,6,6), max_degree=10, + ....: mul_symbol='⌣', + ....: mul_latex_symbol=r'\smile') sage: x*y^2 + x*t x⌣y^2 + x⌣t sage: latex(x*y^2 - z*x) diff --git a/src/sage/algebras/free_algebra.py b/src/sage/algebras/free_algebra.py index 50793075532..d375a68c0ae 100644 --- a/src/sage/algebras/free_algebra.py +++ b/src/sage/algebras/free_algebra.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules """ Free algebras @@ -17,11 +17,12 @@ EXAMPLES:: - sage: F = FreeAlgebra(ZZ,3,'x,y,z') + sage: F = FreeAlgebra(ZZ, 3, 'x,y,z') sage: F.base_ring() Integer Ring sage: G = FreeAlgebra(F, 2, 'm,n'); G - Free Algebra on 2 generators (m, n) over Free Algebra on 3 generators (x, y, z) over Integer Ring + Free Algebra on 2 generators (m, n) over + Free Algebra on 3 generators (x, y, z) over Integer Ring sage: G.base_ring() Free Algebra on 3 generators (x, y, z) over Integer Ring @@ -34,8 +35,8 @@ Moreover, we can compute Groebner bases with degree bound for its two-sided ideals, and thus provide ideal containment tests:: - sage: F. = FreeAlgebra(QQ, implementation='letterplace') - sage: F + sage: # needs sage.libs.singular + sage: F. = FreeAlgebra(QQ, implementation='letterplace'); F Free Associative Unital Algebra on 3 generators (x, y, z) over Rational Field sage: I = F*[x*y+y*z,x^2+x*y-y*x-y^2]*F sage: I.groebner_basis(degbound=4) @@ -54,6 +55,7 @@ Positive integral degree weights for the letterplace implementation was introduced in :trac:`7797`:: + sage: # needs sage.libs.singular sage: F. = FreeAlgebra(QQ, implementation='letterplace', degrees=[2,1,3]) sage: x.degree() 2 @@ -73,6 +75,8 @@ sage: TestSuite(F).run() sage: F is loads(dumps(F)) True + + sage: # needs sage.libs.singular sage: F = FreeAlgebra(GF(5),3,'x', implementation='letterplace') sage: TestSuite(F).run() sage: F is loads(dumps(F)) @@ -84,6 +88,8 @@ sage: TestSuite(F).run() sage: F is loads(dumps(F)) True + + sage: # needs sage.libs.singular sage: F. = FreeAlgebra(GF(5),3, implementation='letterplace') sage: TestSuite(F).run() sage: F is loads(dumps(F)) @@ -95,6 +101,8 @@ sage: TestSuite(F).run() sage: F is loads(dumps(F)) True + + sage: # needs sage.libs.singular sage: F = FreeAlgebra(GF(5),3, ['xx', 'zba', 'Y'], implementation='letterplace') sage: TestSuite(F).run() sage: F is loads(dumps(F)) @@ -106,6 +114,8 @@ sage: TestSuite(F).run() sage: F is loads(dumps(F)) True + + sage: # needs sage.libs.singular sage: F = FreeAlgebra(GF(5),3, 'abc', implementation='letterplace') sage: TestSuite(F).run() sage: F is loads(dumps(F)) @@ -121,10 +131,11 @@ Note that the letterplace implementation can only be used if the corresponding (multivariate) polynomial ring has an implementation in Singular:: - sage: FreeAlgebra(FreeAlgebra(ZZ,2,'ab'), 2, 'x', implementation='letterplace') + sage: FreeAlgebra(FreeAlgebra(ZZ,2,'ab'), 2, 'x', implementation='letterplace') # needs sage.libs.singular Traceback (most recent call last): ... - NotImplementedError: polynomials over Free Algebra on 2 generators (a, b) over Integer Ring are not supported in Singular + NotImplementedError: polynomials over Free Algebra on 2 generators (a, b) + over Integer Ring are not supported in Singular """ # *************************************************************************** @@ -149,6 +160,7 @@ from sage.structure.factory import UniqueFactory from sage.misc.cachefunc import cached_method +from sage.misc.lazy_import import lazy_import from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.ring import Algebra from sage.categories.algebras_with_basis import AlgebrasWithBasis @@ -156,6 +168,8 @@ from sage.combinat.words.word import Word from sage.structure.category_object import normalize_names +lazy_import('sage.algebras.letterplace.free_algebra_letterplace', 'FreeAlgebra_letterplace') + class FreeAlgebraFactory(UniqueFactory): """ @@ -179,7 +193,8 @@ class FreeAlgebraFactory(UniqueFactory): sage: FreeAlgebra(GF(5),1, ['alpha']) Free Algebra on 1 generators (alpha,) over Finite Field of size 5 sage: FreeAlgebra(FreeAlgebra(ZZ,1,'a'), 2, 'x') - Free Algebra on 2 generators (x0, x1) over Free Algebra on 1 generators (a,) over Integer Ring + Free Algebra on 2 generators (x0, x1) over + Free Algebra on 1 generators (a,) over Integer Ring Free algebras are globally unique:: @@ -203,6 +218,7 @@ class FreeAlgebraFactory(UniqueFactory): elements are supported. Of course, isomorphic algebras in different implementations are not identical:: + sage: # needs sage.libs.singular sage: G = FreeAlgebra(GF(5),['x','y','z'], implementation='letterplace') sage: F == G False @@ -214,10 +230,13 @@ class FreeAlgebraFactory(UniqueFactory): :: - sage: H = FreeAlgebra(GF(5),['x','y','z'], implementation='letterplace', degrees=[1,2,3]) + sage: # needs sage.libs.singular + sage: H = FreeAlgebra(GF(5), ['x','y','z'], implementation='letterplace', + ....: degrees=[1,2,3]) sage: F != H != G True - sage: H is FreeAlgebra(GF(5),['x','y','z'], implementation='letterplace', degrees=[1,2,3]) + sage: H is FreeAlgebra(GF(5),['x','y','z'], implementation='letterplace', + ....: degrees=[1,2,3]) True sage: copy(H) is H is loads(dumps(H)) True @@ -235,7 +254,8 @@ class FreeAlgebraFactory(UniqueFactory): sage: s = a*b^2 * c^3; s a*b^2*c^3 sage: parent(s) - Free Algebra on 1 generators (c,) over Free Algebra on 2 generators (a, b) over Rational Field + Free Algebra on 1 generators (c,) over + Free Algebra on 2 generators (a, b) over Rational Field sage: c^3 * a * b^2 a*b^2*c^3 """ @@ -254,13 +274,19 @@ def create_key(self, base_ring, arg1=None, arg2=None, (Finite Field of size 5, ('x', 'y', 'z')) sage: FreeAlgebra.create_key(GF(5),3,'xyz') (Finite Field of size 5, ('x', 'y', 'z')) - sage: FreeAlgebra.create_key(GF(5),['x','y','z'], implementation='letterplace') + + sage: # needs sage.libs.singular + sage: FreeAlgebra.create_key(GF(5),['x','y','z'], + ....: implementation='letterplace') (Multivariate Polynomial Ring in x, y, z over Finite Field of size 5,) - sage: FreeAlgebra.create_key(GF(5),['x','y','z'],3, implementation='letterplace') + sage: FreeAlgebra.create_key(GF(5),['x','y','z'],3, + ....: implementation='letterplace') (Multivariate Polynomial Ring in x, y, z over Finite Field of size 5,) - sage: FreeAlgebra.create_key(GF(5),3,'xyz', implementation='letterplace') + sage: FreeAlgebra.create_key(GF(5),3,'xyz', + ....: implementation='letterplace') (Multivariate Polynomial Ring in x, y, z over Finite Field of size 5,) - sage: FreeAlgebra.create_key(GF(5),3,'xyz', implementation='letterplace', degrees=[1,2,3]) + sage: FreeAlgebra.create_key(GF(5),3,'xyz', + ....: implementation='letterplace', degrees=[1,2,3]) ((1, 2, 3), Multivariate Polynomial Ring in x, y, z, x_ over Finite Field of size 5) """ @@ -349,10 +375,10 @@ def is_FreeAlgebra(x) -> bool: True sage: is_FreeAlgebra(FreeAlgebra(ZZ,10,'x',implementation='letterplace')) True - sage: is_FreeAlgebra(FreeAlgebra(ZZ,10,'x',implementation='letterplace', degrees=list(range(1,11)))) + sage: is_FreeAlgebra(FreeAlgebra(ZZ,10,'x',implementation='letterplace', + ....: degrees=list(range(1,11)))) True """ - from sage.algebras.letterplace.free_algebra_letterplace import FreeAlgebra_letterplace return isinstance(x, (FreeAlgebra_generic, FreeAlgebra_letterplace)) @@ -542,6 +568,7 @@ def _element_constructor_(self, x): TESTS:: + sage: # needs sage.libs.singular sage: F. = FreeAlgebra(GF(5),3) sage: L. = FreeAlgebra(ZZ,3,implementation='letterplace') sage: F(x) # indirect doctest @@ -553,10 +580,11 @@ def _element_constructor_(self, x): :: + sage: # needs sage.libs.singular sage.rings.finite_rings sage: K. = GF(25) sage: F. = FreeAlgebra(K,3) sage: L. = FreeAlgebra(K,3, implementation='letterplace') - sage: F.1+(z+1)*L.2 + sage: F.1 + (z+1)*L.2 b + (z+1)*c Check that :trac:`15169` is fixed:: @@ -667,6 +695,7 @@ def _coerce_map_from_(self, R): sage: F.has_coerce_map_from(PolynomialRing(ZZ, 3, 'x,y,z')) False + sage: # needs sage.rings.finite_rings sage: K. = GF(25) sage: F. = FreeAlgebra(K,3) sage: F._coerce_map_from_(ZZ) @@ -682,8 +711,8 @@ def _coerce_map_from_(self, R): True sage: G._coerce_map_from_(F) False - sage: L. = FreeAlgebra(K,3, implementation='letterplace') - sage: F.1 + (z+1) * L.2 + sage: L. = FreeAlgebra(K,3, implementation='letterplace') # needs sage.libs.singular + sage: F.1 + (z+1) * L.2 # needs sage.libs.singular b + (z+1)*c """ if self._indices.has_coerce_map_from(R): @@ -780,9 +809,12 @@ def quotient(self, mons, mats=None, names=None, **args): sage: i, j, k = F.gens() sage: mons = [ F(1), i, j, k ] sage: M = MatrixSpace(QQ,4) - sage: mats = [M([0,1,0,0, -1,0,0,0, 0,0,0,-1, 0,0,1,0]), M([0,0,1,0, 0,0,0,1, -1,0,0,0, 0,-1,0,0]), M([0,0,0,1, 0,0,-1,0, 0,1,0,0, -1,0,0,0]) ] + sage: mats = [M([0,1,0,0, -1,0,0,0, 0,0,0,-1, 0,0,1,0]), + ....: M([0,0,1,0, 0,0,0,1, -1,0,0,0, 0,-1,0,0]), + ....: M([0,0,0,1, 0,0,-1,0, 0,1,0,0, -1,0,0,0]) ] sage: H. = A.quotient(mons, mats); H - Free algebra quotient on 3 generators ('i', 'j', 'k') and dimension 4 over Rational Field + Free algebra quotient on 3 generators ('i', 'j', 'k') and dimension 4 + over Rational Field """ if mats is None: return super().quotient(mons, names) @@ -830,6 +862,7 @@ def g_algebra(self, relations, names=None, order='degrevlex', check=True): EXAMPLES:: + sage: # needs sage.libs.singular sage: A. = FreeAlgebra(QQ,3) sage: G = A.g_algebra({y*x: -x*y}) sage: (x,y,z) = G.gens() @@ -840,12 +873,12 @@ def g_algebra(self, relations, names=None, order='degrevlex', check=True): sage: z*x x*z sage: (x,y,z) = A.gens() - sage: G = A.g_algebra({y*x: -x*y+1}) + sage: G = A.g_algebra({y*x: -x*y + 1}) sage: (x,y,z) = G.gens() sage: y*x -x*y + 1 sage: (x,y,z) = A.gens() - sage: G = A.g_algebra({y*x: -x*y+z}) + sage: G = A.g_algebra({y*x: -x*y + z}) sage: (x,y,z) = G.gens() sage: y*x -x*y + z diff --git a/src/sage/algebras/free_algebra_element.py b/src/sage/algebras/free_algebra_element.py index 559df673fbf..1854414e2d0 100644 --- a/src/sage/algebras/free_algebra_element.py +++ b/src/sage/algebras/free_algebra_element.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules """ Free algebra elements diff --git a/src/sage/algebras/free_algebra_quotient.py b/src/sage/algebras/free_algebra_quotient.py index b19884335c4..e41e9c877c5 100644 --- a/src/sage/algebras/free_algebra_quotient.py +++ b/src/sage/algebras/free_algebra_quotient.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Finite dimensional free algebra quotients @@ -21,11 +22,12 @@ sage: A = FreeAlgebra(QQ,n,'x') sage: F = A.monoid() sage: i, j = F.gens() - sage: mons = [ F(1), i, j, i*j ] + sage: mons = [F(1), i, j, i*j] sage: r = len(mons) sage: M = MatrixSpace(QQ,r) - sage: mats = [M([0,1,0,0, -1,0,0,0, 0,0,0,-1, 0,0,1,0]), M([0,0,1,0, 0,0,0,1, -1,0,0,0, 0,-1,0,0]) ] - sage: H2. = A.quotient(mons,mats) + sage: mats = [M([0,1,0,0, -1,0,0,0, 0,0,0,-1, 0,0,1,0]), + ....: M([0,0,1,0, 0,0,0,1, -1,0,0,0, 0,-1,0,0]) ] + sage: H2. = A.quotient(mons, mats) sage: H2 == loads(dumps(H2)) True sage: i == loads(dumps(i)) @@ -106,15 +108,20 @@ def __init__(self, A, mons, mats, names): sage: A = FreeAlgebra(QQ,n,'i') sage: F = A.monoid() sage: i, j, k = F.gens() - sage: mons = [ F(1), i, j, k ] + sage: mons = [F(1), i, j, k] sage: M = MatrixSpace(QQ,4) - sage: mats = [M([0,1,0,0, -1,0,0,0, 0,0,0,-1, 0,0,1,0]), M([0,0,1,0, 0,0,0,1, -1,0,0,0, 0,-1,0,0]), M([0,0,0,1, 0,0,-1,0, 0,1,0,0, -1,0,0,0]) ] + sage: mats = [M([0,1,0,0, -1,0,0,0, 0,0,0,-1, 0,0,1,0]), + ....: M([0,0,1,0, 0,0,0,1, -1,0,0,0, 0,-1,0,0]), + ....: M([0,0,0,1, 0,0,-1,0, 0,1,0,0, -1,0,0,0]) ] sage: H3. = FreeAlgebraQuotient(A,mons,mats) sage: x = 1 + i + j + k sage: x 1 + i + j + k sage: x**128 - -170141183460469231731687303715884105728 + 170141183460469231731687303715884105728*i + 170141183460469231731687303715884105728*j + 170141183460469231731687303715884105728*k + -170141183460469231731687303715884105728 + + 170141183460469231731687303715884105728*i + + 170141183460469231731687303715884105728*j + + 170141183460469231731687303715884105728*k Same algebra defined in terms of two generators, with some penalty on already slow arithmetic. @@ -128,14 +135,18 @@ def __init__(self, A, mons, mats, names): sage: mons = [ F(1), i, j, i*j ] sage: r = len(mons) sage: M = MatrixSpace(QQ,r) - sage: mats = [M([0,1,0,0, -1,0,0,0, 0,0,0,-1, 0,0,1,0]), M([0,0,1,0, 0,0,0,1, -1,0,0,0, 0,-1,0,0]) ] + sage: mats = [M([0,1,0,0, -1,0,0,0, 0,0,0,-1, 0,0,1,0]), + ....: M([0,0,1,0, 0,0,0,1, -1,0,0,0, 0,-1,0,0]) ] sage: H2. = A.quotient(mons,mats) sage: k = i*j sage: x = 1 + i + j + k sage: x 1 + i + j + i*j sage: x**128 - -170141183460469231731687303715884105728 + 170141183460469231731687303715884105728*i + 170141183460469231731687303715884105728*j + 170141183460469231731687303715884105728*i*j + -170141183460469231731687303715884105728 + + 170141183460469231731687303715884105728*i + + 170141183460469231731687303715884105728*j + + 170141183460469231731687303715884105728*i*j TESTS:: @@ -345,7 +356,8 @@ def hamilton_quatalg(R): sage: H, (i,j,k) = sage.algebras.free_algebra_quotient.hamilton_quatalg(ZZ) sage: H - Free algebra quotient on 3 generators ('i', 'j', 'k') and dimension 4 over Integer Ring + Free algebra quotient on 3 generators ('i', 'j', 'k') and dimension 4 + over Integer Ring sage: i^2 -1 sage: i in H diff --git a/src/sage/algebras/free_algebra_quotient_element.py b/src/sage/algebras/free_algebra_quotient_element.py index c841a9210cf..559d4246ac0 100644 --- a/src/sage/algebras/free_algebra_quotient_element.py +++ b/src/sage/algebras/free_algebra_quotient_element.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Free algebra quotient elements diff --git a/src/sage/algebras/free_zinbiel_algebra.py b/src/sage/algebras/free_zinbiel_algebra.py index 39ac9091618..d421b2d7aee 100644 --- a/src/sage/algebras/free_zinbiel_algebra.py +++ b/src/sage/algebras/free_zinbiel_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Free Zinbiel Algebras diff --git a/src/sage/algebras/group_algebra.py b/src/sage/algebras/group_algebra.py index e16b0c08a21..eaffe7538b7 100644 --- a/src/sage/algebras/group_algebra.py +++ b/src/sage/algebras/group_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.groups sage.modules r""" Group algebras diff --git a/src/sage/algebras/hall_algebra.py b/src/sage/algebras/hall_algebra.py index 3492ba5e073..83442eabc94 100644 --- a/src/sage/algebras/hall_algebra.py +++ b/src/sage/algebras/hall_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Hall Algebras diff --git a/src/sage/algebras/hecke_algebras/ariki_koike_algebra.py b/src/sage/algebras/hecke_algebras/ariki_koike_algebra.py index cf1c7a04c39..f34beb5a1f8 100644 --- a/src/sage/algebras/hecke_algebras/ariki_koike_algebra.py +++ b/src/sage/algebras/hecke_algebras/ariki_koike_algebra.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Ariki-Koike Algebras @@ -234,6 +234,7 @@ class ArikiKoikeAlgebra(Parent, UniqueRepresentation): We construct an Ariki-Koike algebra with `u = (1, \zeta_3, \zeta_3^2)`, where `\zeta_3` is a primitive third root of unity:: + sage: # needs sage.rings.number_field sage: F = CyclotomicField(3) sage: zeta3 = F.gen() sage: R. = LaurentPolynomialRing(F) @@ -248,6 +249,7 @@ class ArikiKoikeAlgebra(Parent, UniqueRepresentation): Next, we additionally take `q = 1` to obtain the group algebra of `G(r, 1, n)`:: + sage: # needs sage.rings.number_field sage: F = CyclotomicField(3) sage: zeta3 = F.gen() sage: H = algebras.ArikiKoike(3, 4, q=1, u=[1, zeta3, zeta3^2], R=F) diff --git a/src/sage/algebras/hecke_algebras/cubic_hecke_algebra.py b/src/sage/algebras/hecke_algebras/cubic_hecke_algebra.py index fdc94b13907..6a336d9932c 100644 --- a/src/sage/algebras/hecke_algebras/cubic_hecke_algebra.py +++ b/src/sage/algebras/hecke_algebras/cubic_hecke_algebra.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.groups sage.modules r""" Cubic Hecke Algebras @@ -93,14 +93,15 @@ initializing. However, you can do calculations inside the infinite algebra as well:: - sage: CHA6 = algebras.CubicHecke(6) # optional - database_cubic_hecke - sage: CHA6.inject_variables() # optional - database_cubic_hecke + sage: # optional - database_cubic_hecke + sage: CHA6 = algebras.CubicHecke(6) + sage: CHA6.inject_variables() Defining c0, c1, c2, c3, c4 - sage: s = c0*c1*c2*c3*c4; s # optional - database_cubic_hecke + sage: s = c0*c1*c2*c3*c4; s c0*c1*c2*c3*c4 - sage: s^2 # optional - database_cubic_hecke + sage: s^2 (c0*c1*c2*c3*c4)^2 - sage: t = CHA6.an_element() * c4; t # optional - database_cubic_hecke + sage: t = CHA6.an_element() * c4; t (-w)*c0*c1^-1*c4 + v*c0*c2^-1*c4 + u*c2*c1*c4 + ((-v*w+u)/w)*c4 REFERENCES: @@ -1833,18 +1834,19 @@ def _init_basis_extension(self): EXAMPLES:: - sage: CHA5 = algebras.CubicHecke(5) # optional - database_cubic_hecke # indirect doctest - sage: fc = CHA5._filecache # optional - database_cubic_hecke - sage: be = fc.section.basis_extensions # optional - database_cubic_hecke - sage: CHA5.reset_filecache(be) # optional - database_cubic_hecke - sage: fc.read(be) # optional - database_cubic_hecke + sage: # optional - database_cubic_hecke + sage: CHA5 = algebras.CubicHecke(5) + sage: fc = CHA5._filecache + sage: be = fc.section.basis_extensions + sage: CHA5.reset_filecache(be) + sage: fc.read(be) [[4], [-4]] - sage: ele = CHA5.an_element() # optional - database_cubic_hecke - sage: CHA5.inject_variables() # optional - database_cubic_hecke + sage: ele = CHA5.an_element() + sage: CHA5.inject_variables() Defining c0, c1, c2, c3 - sage: ele2 = ele * c3 # optional - database_cubic_hecke - sage: bex = fc.read(be) # optional - database_cubic_hecke - sage: bex.sort(); bex # optional - database_cubic_hecke + sage: ele2 = ele * c3 + sage: bex = fc.read(be) + sage: bex.sort(); bex [[-4], [1, -3, 4], [1, -2, 4], [3, 2, 4], [4]] """ self._basis_extension = [] @@ -2220,14 +2222,15 @@ def _braid_image_by_basis_extension(self, braid_tietze): EXAMPLES:: - sage: CHA5 = algebras.CubicHecke(5) # optional - database_cubic_hecke - sage: be = CHA5.filecache_section().basis_extensions # optional - database_cubic_hecke - sage: CHA5.reset_filecache(be) # optional - database_cubic_hecke - sage: CHA5._basis_extension # optional - database_cubic_hecke + sage: # optional - database_cubic_hecke + sage: CHA5 = algebras.CubicHecke(5) + sage: be = CHA5.filecache_section().basis_extensions + sage: CHA5.reset_filecache(be) + sage: CHA5._basis_extension [[4], [-4]] - sage: CHA5._braid_image_by_basis_extension((4,1)) # optional - database_cubic_hecke + sage: CHA5._braid_image_by_basis_extension((4,1)) c3*c0 - sage: CHA5._basis_extension # optional - database_cubic_hecke + sage: CHA5._basis_extension [[4], [-4], [4, 1]] case where the braid already has an corresponding basis element:: @@ -2524,15 +2527,16 @@ def _cubic_braid_append_to_basis(self, cubic_braid): EXAMPLES:: - sage: CHA5 = algebras.CubicHecke(5) # optional - database_cubic_hecke - sage: be = CHA5.filecache_section().basis_extensions # optional - database_cubic_hecke - sage: CHA5.reset_filecache(be) # optional - database_cubic_hecke - sage: CHA5._basis_extension # optional - database_cubic_hecke + sage: # optional - database_cubic_hecke + sage: CHA5 = algebras.CubicHecke(5) + sage: be = CHA5.filecache_section().basis_extensions + sage: CHA5.reset_filecache(be) + sage: CHA5._basis_extension [[4], [-4]] - sage: CBG = CHA5.cubic_braid_group() # optional - database_cubic_hecke - sage: CHA5._cubic_braid_append_to_basis(CBG((4,1))) # optional - database_cubic_hecke + sage: CBG = CHA5.cubic_braid_group() + sage: CHA5._cubic_braid_append_to_basis(CBG((4,1))) c3*c0 - sage: CHA5._basis_extension # optional - database_cubic_hecke + sage: CHA5._basis_extension [[4], [-4], [4, 1]] """ @@ -2807,12 +2811,13 @@ def reset_filecache(self, section=None, commit=True): EXAMPLES:: - sage: CHA5 = algebras.CubicHecke(5) # optional - database_cubic_hecke - sage: be = CHA5.filecache_section().basis_extensions # optional - database_cubic_hecke - sage: CHA5.is_filecache_empty(be) # optional - database_cubic_hecke + sage: # optional - database_cubic_hecke + sage: CHA5 = algebras.CubicHecke(5) + sage: be = CHA5.filecache_section().basis_extensions + sage: CHA5.is_filecache_empty(be) False - sage: CHA5.reset_filecache(be) # optional - database_cubic_hecke - sage: CHA5.is_filecache_empty(be) # optional - database_cubic_hecke + sage: CHA5.reset_filecache(be) + sage: CHA5.is_filecache_empty(be) True """ fc = self._filecache diff --git a/src/sage/algebras/hecke_algebras/cubic_hecke_base_ring.py b/src/sage/algebras/hecke_algebras/cubic_hecke_base_ring.py index 7c2fe4a2210..90d6657d309 100644 --- a/src/sage/algebras/hecke_algebras/cubic_hecke_base_ring.py +++ b/src/sage/algebras/hecke_algebras/cubic_hecke_base_ring.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.libs.pari (for factorization) r""" Cubic Hecke Base Rings @@ -297,14 +298,15 @@ def _element_constructor_(self, x, mon=None): EXAMPLES:: - sage: CHA3 = algebras.CubicHecke(3) # optional gap3 - sage: GER = CHA3.extension_ring(generic=True) # optional gap3 - sage: sch7 = CHA3.chevie().SchurElements()[7] # optional gap3 - sage: GER(sch7) # optional gap3 + sage: # optional - gap3 + sage: CHA3 = algebras.CubicHecke(3) + sage: GER = CHA3.extension_ring(generic=True) + sage: sch7 = CHA3.chevie().SchurElements()[7] + sage: GER(sch7) a*b*c^-2 + a^2*b^-1*c^-1 + a^-1*b^2*c^-1 + 2 + a*b^-2*c + a^-2*b*c + a^-1*b^-1*c^2 - sage: rep4_gap3 = CHA3.chevie().Representations(4) # optional gap3 - sage: matrix(GER, rep4_gap3[1]) # optional gap3 + sage: rep4_gap3 = CHA3.chevie().Representations(4) + sage: matrix(GER, rep4_gap3[1]) [ b 0] [-b c] """ diff --git a/src/sage/algebras/hecke_algebras/cubic_hecke_matrix_rep.py b/src/sage/algebras/hecke_algebras/cubic_hecke_matrix_rep.py index 1e8cd3ae0c4..02689e2b11c 100644 --- a/src/sage/algebras/hecke_algebras/cubic_hecke_matrix_rep.py +++ b/src/sage/algebras/hecke_algebras/cubic_hecke_matrix_rep.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.modules r""" Cubic Hecke matrix representations diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 0b6696af043..a599c28a488 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.graphs sage.modules r""" Iwahori-Hecke Algebras @@ -51,15 +52,15 @@ def normalized_laurent_polynomial(R, p): the base ring. This function is a hack to recover from this. This occurs somewhat haphazardly with Laurent polynomial rings:: - sage: R.=LaurentPolynomialRing(ZZ) + sage: R. = LaurentPolynomialRing(ZZ) sage: [type(c) for c in (q**-1).coefficients()] [] It also happens in any ring when dividing by units:: - sage: type ( 3/1 ) + sage: type(3/1) - sage: type ( -1/-1 ) + sage: type(-1/-1) This function is a variation on a suggested workaround of Nils Bruin. @@ -67,19 +68,19 @@ def normalized_laurent_polynomial(R, p): EXAMPLES:: sage: from sage.algebras.iwahori_hecke_algebra import normalized_laurent_polynomial - sage: type ( normalized_laurent_polynomial(ZZ, 3/1) ) + sage: type(normalized_laurent_polynomial(ZZ, 3/1)) - sage: R.=LaurentPolynomialRing(ZZ) + sage: R. = LaurentPolynomialRing(ZZ) sage: [type(c) for c in normalized_laurent_polynomial(R, q**-1).coefficients()] [] - sage: R.=LaurentPolynomialRing(ZZ,2) - sage: p=normalized_laurent_polynomial(R, 2*u**-1*v**-1+u*v) - sage: ui=normalized_laurent_polynomial(R, u^-1) - sage: vi=normalized_laurent_polynomial(R, v^-1) - sage: p(ui,vi) + sage: R. = LaurentPolynomialRing(ZZ,2) + sage: p = normalized_laurent_polynomial(R, 2*u**-1*v**-1 + u*v) + sage: ui = normalized_laurent_polynomial(R, u^-1) + sage: vi = normalized_laurent_polynomial(R, v^-1) + sage: p(ui, vi) 2*u*v + u^-1*v^-1 - sage: q= u+v+ui - sage: q(ui,vi) + sage: q = u+v+ui + sage: q(ui, vi) u + v^-1 + u^-1 """ try: @@ -207,8 +208,8 @@ class IwahoriHeckeAlgebra(Parent, UniqueRepresentation): The Kazhdan-Lusztig bases are implemented inside `H` whenever `-q_1 q_2` has a square root:: - sage: H = IwahoriHeckeAlgebra('A3', u^2,-v^2) - sage: T=H.T(); Cp= H.Cp(); C=H.C() + sage: H = IwahoriHeckeAlgebra('A3', u^2, -v^2) + sage: T = H.T(); Cp = H.Cp(); C = H.C() sage: T(Cp[1]) (u^-1*v^-1)*T[1] + (u^-1*v) sage: T(C[1]) @@ -1954,12 +1955,13 @@ class Cp(_KLHeckeBasis): implemented with ``coxeter3`` to avoid unnecessary conversions, as in the following example with the same product computed in the last one:: - sage: R = LaurentPolynomialRing(QQ, 'v') # optional - coxeter3 - sage: v = R.gen(0) # optional - coxeter3 - sage: W = CoxeterGroup('A9', implementation='coxeter3') # optional - coxeter3 - sage: H = IwahoriHeckeAlgebra(W, v**2) # optional - coxeter3 - sage: Cp = H.Cp() # optional - coxeter3 - sage: Cp[1,2,1,8,9,8]*Cp[1,2,3,7,8,9] # optional - coxeter3 + sage: # optional - coxeter3 + sage: R = LaurentPolynomialRing(QQ, 'v') + sage: v = R.gen(0) + sage: W = CoxeterGroup('A9', implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(W, v**2) + sage: Cp = H.Cp() + sage: Cp[1,2,1,8,9,8]*Cp[1,2,3,7,8,9] (v^-2+2+v^2)*Cp[1,2,1,3,7,8,7,9,8,7] + (v^-2+2+v^2)*Cp[1,2,1,3,8,9,8,7] + (v^-3+3*v^-1+3*v+v^3)*Cp[1,2,1,3,8,9,8] @@ -1983,17 +1985,18 @@ def __init__(self, IHAlgebra, prefix=None): r""" TESTS:: - sage: R. = LaurentPolynomialRing(QQ) # optional - coxeter3 - sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: H = IwahoriHeckeAlgebra(W, v**2) # optional - coxeter3 - sage: Cp = H.Cp() # optional - coxeter3 - sage: Cp._delta == v + ~v # optional - coxeter3 + sage: # optional - coxeter3 + sage: R. = LaurentPolynomialRing(QQ) + sage: W = CoxeterGroup('A3', implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(W, v**2) + sage: Cp = H.Cp() + sage: Cp._delta == v + ~v True - sage: Cp._W_Coxeter3 == H._W # optional - coxeter3 + sage: Cp._W_Coxeter3 == H._W True - sage: H = IwahoriHeckeAlgebra(W, QQ(1)) # optional - coxeter3 - sage: Cp = H.Cp() # optional - coxeter3 - sage: Cp._W_Coxeter3 is None # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, QQ(1)) + sage: Cp = H.Cp() + sage: Cp._W_Coxeter3 is None True """ super().__init__(IHAlgebra, prefix) @@ -2127,12 +2130,13 @@ def product_on_basis(self, w1, w2): EXAMPLES:: - sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 - sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp() # optional - coxeter3 - sage: Cp.product_on_basis(W([1,2,1]), W([3,1])) # optional - coxeter3 + sage: # optional - coxeter3 + sage: R. = LaurentPolynomialRing(ZZ, 'v') + sage: W = CoxeterGroup('A3', implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp() + sage: Cp.product_on_basis(W([1,2,1]), W([3,1])) (v^-1+v)*Cp[1,2,1,3] - sage: Cp.product_on_basis(W([1,2,1]), W([3,1,2])) # optional - coxeter3 + sage: Cp.product_on_basis(W([1,2,1]), W([3,1,2])) (v^-1+v)*Cp[1,2,1,3,2] + (v^-1+v)*Cp[1,2,1] """ if self._W_Coxeter3 is None: @@ -2194,14 +2198,15 @@ def _product_with_generator_on_basis(self, s, w, side='left'): EXAMPLES:: - sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 - sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: H = IwahoriHeckeAlgebra(W, v**2); Cp = H.Cp() # optional - coxeter3 - sage: Cp._product_with_generator_on_basis(1, W([2,1]), 'left') # optional - coxeter3 + sage: # optional - coxeter3 + sage: R. = LaurentPolynomialRing(ZZ, 'v') + sage: W = CoxeterGroup('A3', implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(W, v**2); Cp = H.Cp() + sage: Cp._product_with_generator_on_basis(1, W([2,1]), 'left') Cp[1,2,1] + Cp[1] - sage: Cp._product_with_generator_on_basis(1, W([2,1]), 'right') # optional - coxeter3 + sage: Cp._product_with_generator_on_basis(1, W([2,1]), 'right') (v^-1+v)*Cp[2,1] - sage: Cp._product_with_generator_on_basis(2, W([1,3,2,1,3]), 'right') # optional - coxeter3 + sage: Cp._product_with_generator_on_basis(2, W([1,3,2,1,3]), 'right') Cp[1,2,1,3,2,1] + Cp[1,2,3,2] + Cp[1,3,2,1] """ # use the product formula described in the class' documentation @@ -2236,12 +2241,13 @@ def _product_with_generator(self, s, x, side='left'): EXAMPLES:: - sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 - sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 - sage: H = IwahoriHeckeAlgebra(W, v**2); Cp = H.Cp() # optional - coxeter3 - sage: Cp._product_with_generator(1, Cp[1]+Cp[2], 'left') # optional - coxeter3 + sage: # optional - coxeter3 + sage: R. = LaurentPolynomialRing(ZZ, 'v') + sage: W = CoxeterGroup('A3', implementation='coxeter3') + sage: H = IwahoriHeckeAlgebra(W, v**2); Cp = H.Cp() + sage: Cp._product_with_generator(1, Cp[1]+Cp[2], 'left') Cp[1,2] + (v^-1+v)*Cp[1] - sage: Cp._product_with_generator(1, Cp[1]+Cp[2], 'right') # optional - coxeter3 + sage: Cp._product_with_generator(1, Cp[1]+Cp[2], 'right') Cp[2,1] + (v^-1+v)*Cp[1] """ return self.linear_combination((self._product_with_generator_on_basis(s, w, side), coeff) for (w, coeff) in x) diff --git a/src/sage/algebras/jordan_algebra.py b/src/sage/algebras/jordan_algebra.py index 81c40105f8a..f783dc890c8 100644 --- a/src/sage/algebras/jordan_algebra.py +++ b/src/sage/algebras/jordan_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Jordan Algebras diff --git a/src/sage/algebras/lie_algebras/lie_algebra_element.pyx b/src/sage/algebras/lie_algebras/lie_algebra_element.pyx index ed9680a0af5..f221fe6ab55 100644 --- a/src/sage/algebras/lie_algebras/lie_algebra_element.pyx +++ b/src/sage/algebras/lie_algebras/lie_algebra_element.pyx @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat """ Lie Algebra Elements diff --git a/src/sage/algebras/lie_algebras/morphism.py b/src/sage/algebras/lie_algebras/morphism.py index f71001ce98f..3fa39f8ff78 100644 --- a/src/sage/algebras/lie_algebras/morphism.py +++ b/src/sage/algebras/lie_algebras/morphism.py @@ -461,8 +461,8 @@ class LieAlgebraMorphism_from_generators(LieAlgebraHomomorphism_im_gens): A quotient type Lie algebra morphism:: - sage: K. = LieAlgebra(SR, abelian=True) - sage: L.morphism({X: A, Y: B}) + sage: K. = LieAlgebra(SR, abelian=True) # needs sage.symbolic + sage: L.morphism({X: A, Y: B}) # needs sage.symbolic Lie algebra morphism: From: Lie algebra on 4 generators (X, Y, Z, W) over Rational Field To: Abelian Lie algebra on 2 generators (A, B) over Symbolic Ring @@ -623,17 +623,17 @@ def _call_(self, x): EXAMPLES:: sage: L. = LieAlgebra(QQ, {('X','Y'): {'Z':1}, ('X','Z'): {'W':1}}) - sage: K. = LieAlgebra(SR, abelian=True) - sage: phi = L.morphism({X: A, Y: B}) - sage: phi(X) + sage: K. = LieAlgebra(SR, abelian=True) # needs sage.symbolic + sage: phi = L.morphism({X: A, Y: B}) # needs sage.symbolic + sage: phi(X) # needs sage.symbolic A - sage: phi(Y) + sage: phi(Y) # needs sage.symbolic B - sage: phi(Z) + sage: phi(Z) # needs sage.symbolic 0 - sage: phi(W) + sage: phi(W) # needs sage.symbolic 0 - sage: phi(-X + 3*Y) + sage: phi(-X + 3*Y) # needs sage.symbolic -A + 3*B sage: K. = LieAlgebra(QQ, {('A','B'): {'C':2}}) diff --git a/src/sage/algebras/lie_algebras/quotient.py b/src/sage/algebras/lie_algebras/quotient.py index 7fe6b29677f..ed64e6ee279 100644 --- a/src/sage/algebras/lie_algebras/quotient.py +++ b/src/sage/algebras/lie_algebras/quotient.py @@ -242,6 +242,7 @@ def __init__(self, I, L, names, index_set, category=None): TESTS:: + sage: # needs sage.symbolic sage: L. = LieAlgebra(SR, {('x','y'): {'x':1}}) sage: K = L.quotient(y) sage: K.dimension() diff --git a/src/sage/algebras/lie_algebras/structure_coefficients.py b/src/sage/algebras/lie_algebras/structure_coefficients.py index 16c2cf51029..ed200875e32 100644 --- a/src/sage/algebras/lie_algebras/structure_coefficients.py +++ b/src/sage/algebras/lie_algebras/structure_coefficients.py @@ -411,8 +411,8 @@ def change_ring(self, R): sage: LQQ = L.change_ring(QQ) sage: LQQ.structure_coefficients() Finite family {('x', 'y'): z} - sage: LSR = LQQ.change_ring(SR) - sage: LSR.structure_coefficients() + sage: LSR = LQQ.change_ring(SR) # needs sage.symbolic + sage: LSR.structure_coefficients() # needs sage.symbolic Finite family {('x', 'y'): z} """ return LieAlgebraWithStructureCoefficients( diff --git a/src/sage/algebras/lie_algebras/subalgebra.py b/src/sage/algebras/lie_algebras/subalgebra.py index 90779eb91fc..7dc6e8ef37e 100644 --- a/src/sage/algebras/lie_algebras/subalgebra.py +++ b/src/sage/algebras/lie_algebras/subalgebra.py @@ -75,6 +75,7 @@ class LieSubalgebra_finite_dimensional_with_basis(Parent, UniqueRepresentation): Elements of the ambient Lie algebra can be reduced modulo an ideal or subalgebra:: + sage: # needs sage.symbolic sage: L. = LieAlgebra(SR, {('X','Y'): {'Z': 1}}) sage: I = L.ideal(Y) sage: I.reduce(X + 2*Y + 3*Z) @@ -87,6 +88,7 @@ class LieSubalgebra_finite_dimensional_with_basis(Parent, UniqueRepresentation): When the base ring is a field, the complementary subspace is spanned by those basis elements which are not leading supports of the basis:: + sage: # needs sage.symbolic sage: I = L.ideal(X + Y) sage: I.basis() Family (X + Y, Z) @@ -97,10 +99,10 @@ class LieSubalgebra_finite_dimensional_with_basis(Parent, UniqueRepresentation): Giving a different ``order`` may change the reduction of elements:: - sage: I = L.ideal(X + Y, order=lambda s: ['Z','Y','X'].index(s)) - sage: I.basis() + sage: I = L.ideal(X + Y, order=lambda s: ['Z','Y','X'].index(s)) # needs sage.symbolic + sage: I.basis() # needs sage.symbolic Family (Z, X + Y) - sage: I.reduce(el) + sage: I.reduce(el) # needs sage.symbolic (-x+y)*Y A subalgebra of a subalgebra is a subalgebra of the original:: diff --git a/src/sage/algebras/lie_conformal_algebras/abelian_lie_conformal_algebra.py b/src/sage/algebras/lie_conformal_algebras/abelian_lie_conformal_algebra.py index aa8b71901e1..80df46c57d3 100644 --- a/src/sage/algebras/lie_conformal_algebras/abelian_lie_conformal_algebra.py +++ b/src/sage/algebras/lie_conformal_algebras/abelian_lie_conformal_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Abelian Lie Conformal Algebra diff --git a/src/sage/algebras/lie_conformal_algebras/affine_lie_conformal_algebra.py b/src/sage/algebras/lie_conformal_algebras/affine_lie_conformal_algebra.py index 9fdf888fe39..f5d39cacbf2 100644 --- a/src/sage/algebras/lie_conformal_algebras/affine_lie_conformal_algebra.py +++ b/src/sage/algebras/lie_conformal_algebras/affine_lie_conformal_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Affine Lie Conformal Algebra diff --git a/src/sage/algebras/lie_conformal_algebras/bosonic_ghosts_lie_conformal_algebra.py b/src/sage/algebras/lie_conformal_algebras/bosonic_ghosts_lie_conformal_algebra.py index 178493b13e8..0b0b61b4e25 100644 --- a/src/sage/algebras/lie_conformal_algebras/bosonic_ghosts_lie_conformal_algebra.py +++ b/src/sage/algebras/lie_conformal_algebras/bosonic_ghosts_lie_conformal_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Bosonic Ghosts Lie Conformal Algebra diff --git a/src/sage/algebras/lie_conformal_algebras/fermionic_ghosts_lie_conformal_algebra.py b/src/sage/algebras/lie_conformal_algebras/fermionic_ghosts_lie_conformal_algebra.py index e6bca4de671..098644908e6 100644 --- a/src/sage/algebras/lie_conformal_algebras/fermionic_ghosts_lie_conformal_algebra.py +++ b/src/sage/algebras/lie_conformal_algebras/fermionic_ghosts_lie_conformal_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Fermionic Ghosts Super Lie Conformal Algebra diff --git a/src/sage/algebras/lie_conformal_algebras/finitely_freely_generated_lca.py b/src/sage/algebras/lie_conformal_algebras/finitely_freely_generated_lca.py index 9077ef8f6a2..8aefdd9d3a6 100644 --- a/src/sage/algebras/lie_conformal_algebras/finitely_freely_generated_lca.py +++ b/src/sage/algebras/lie_conformal_algebras/finitely_freely_generated_lca.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Finitely and Freely Generated Lie Conformal Algebras. diff --git a/src/sage/algebras/lie_conformal_algebras/free_bosons_lie_conformal_algebra.py b/src/sage/algebras/lie_conformal_algebras/free_bosons_lie_conformal_algebra.py index 53952f38c91..0787226252d 100644 --- a/src/sage/algebras/lie_conformal_algebras/free_bosons_lie_conformal_algebra.py +++ b/src/sage/algebras/lie_conformal_algebras/free_bosons_lie_conformal_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Free Bosons Lie Conformal Algebra diff --git a/src/sage/algebras/lie_conformal_algebras/free_fermions_lie_conformal_algebra.py b/src/sage/algebras/lie_conformal_algebras/free_fermions_lie_conformal_algebra.py index 8cc6533b781..1e7525ae1d3 100644 --- a/src/sage/algebras/lie_conformal_algebras/free_fermions_lie_conformal_algebra.py +++ b/src/sage/algebras/lie_conformal_algebras/free_fermions_lie_conformal_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Free Fermions Super Lie Conformal Algebra. diff --git a/src/sage/algebras/lie_conformal_algebras/freely_generated_lie_conformal_algebra.py b/src/sage/algebras/lie_conformal_algebras/freely_generated_lie_conformal_algebra.py index 8fa5460d29a..b26d0bb4ca0 100644 --- a/src/sage/algebras/lie_conformal_algebras/freely_generated_lie_conformal_algebra.py +++ b/src/sage/algebras/lie_conformal_algebras/freely_generated_lie_conformal_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Freely Generated Lie Conformal Algebras diff --git a/src/sage/algebras/lie_conformal_algebras/graded_lie_conformal_algebra.py b/src/sage/algebras/lie_conformal_algebras/graded_lie_conformal_algebra.py index 35863aece41..c335daf98f7 100644 --- a/src/sage/algebras/lie_conformal_algebras/graded_lie_conformal_algebra.py +++ b/src/sage/algebras/lie_conformal_algebras/graded_lie_conformal_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Graded Lie Conformal Algebras diff --git a/src/sage/algebras/lie_conformal_algebras/lie_conformal_algebra.py b/src/sage/algebras/lie_conformal_algebras/lie_conformal_algebra.py index 1007488e165..5ca0c8f6d07 100644 --- a/src/sage/algebras/lie_conformal_algebras/lie_conformal_algebra.py +++ b/src/sage/algebras/lie_conformal_algebras/lie_conformal_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Lie Conformal Algebra diff --git a/src/sage/algebras/lie_conformal_algebras/lie_conformal_algebra_element.py b/src/sage/algebras/lie_conformal_algebras/lie_conformal_algebra_element.py index 723ae5c385a..09fb63a0a4c 100644 --- a/src/sage/algebras/lie_conformal_algebras/lie_conformal_algebra_element.py +++ b/src/sage/algebras/lie_conformal_algebras/lie_conformal_algebra_element.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Lie Conformal Algebra Element diff --git a/src/sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_basis.py b/src/sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_basis.py index ae4882dbad0..4fef0fcf2e6 100644 --- a/src/sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_basis.py +++ b/src/sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_basis.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Lie Conformal Algebras With Basis diff --git a/src/sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_structure_coefs.py b/src/sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_structure_coefs.py index 7581daf0ddb..3c4252ce905 100644 --- a/src/sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_structure_coefs.py +++ b/src/sage/algebras/lie_conformal_algebras/lie_conformal_algebra_with_structure_coefs.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Lie Conformal Algebras With Structure Coefficients diff --git a/src/sage/algebras/lie_conformal_algebras/n2_lie_conformal_algebra.py b/src/sage/algebras/lie_conformal_algebras/n2_lie_conformal_algebra.py index 045bfb6e57a..baf7a896144 100644 --- a/src/sage/algebras/lie_conformal_algebras/n2_lie_conformal_algebra.py +++ b/src/sage/algebras/lie_conformal_algebras/n2_lie_conformal_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules sage.rings.number_field r""" N=2 Super Lie Conformal Algebra diff --git a/src/sage/algebras/lie_conformal_algebras/neveu_schwarz_lie_conformal_algebra.py b/src/sage/algebras/lie_conformal_algebras/neveu_schwarz_lie_conformal_algebra.py index 8f5756f993f..5542b9fc097 100644 --- a/src/sage/algebras/lie_conformal_algebras/neveu_schwarz_lie_conformal_algebra.py +++ b/src/sage/algebras/lie_conformal_algebras/neveu_schwarz_lie_conformal_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Neveu-Schwarz Super Lie Conformal Algebra diff --git a/src/sage/algebras/lie_conformal_algebras/virasoro_lie_conformal_algebra.py b/src/sage/algebras/lie_conformal_algebras/virasoro_lie_conformal_algebra.py index cc11ec06a0a..0db2d545290 100644 --- a/src/sage/algebras/lie_conformal_algebras/virasoro_lie_conformal_algebra.py +++ b/src/sage/algebras/lie_conformal_algebras/virasoro_lie_conformal_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Virasoro Lie Conformal Algebra diff --git a/src/sage/algebras/lie_conformal_algebras/weyl_lie_conformal_algebra.py b/src/sage/algebras/lie_conformal_algebras/weyl_lie_conformal_algebra.py index 343ee8a66f9..3c319db7ca3 100644 --- a/src/sage/algebras/lie_conformal_algebras/weyl_lie_conformal_algebra.py +++ b/src/sage/algebras/lie_conformal_algebras/weyl_lie_conformal_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Weyl Lie Conformal Algebra diff --git a/src/sage/algebras/nil_coxeter_algebra.py b/src/sage/algebras/nil_coxeter_algebra.py index 862fdc3b97e..b5dbd2d62c8 100644 --- a/src/sage/algebras/nil_coxeter_algebra.py +++ b/src/sage/algebras/nil_coxeter_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Nil-Coxeter Algebra """ diff --git a/src/sage/algebras/octonion_algebra.pyx b/src/sage/algebras/octonion_algebra.pyx index aef4f54aa9d..ee69aca6a7e 100644 --- a/src/sage/algebras/octonion_algebra.pyx +++ b/src/sage/algebras/octonion_algebra.pyx @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.modules """ Octonion Algebras @@ -415,7 +416,7 @@ cdef class Octonion_generic(AlgebraElement): sage: O = OctonionAlgebra(QQ, 1, 3, 7) sage: elt = sum(i * b for i, b in enumerate(O.basis(), start=2)) - sage: elt.norm() + sage: elt.norm() # needs sage.symbolic 2*sqrt(-61) sage: elt = sum(O.basis()) sage: elt.norm() @@ -438,7 +439,7 @@ cdef class Octonion_generic(AlgebraElement): sage: O = OctonionAlgebra(QQ, 1, 3, 7) sage: elt = sum(i * b for i, b in enumerate(O.basis(), start=2)) - sage: elt.abs() + sage: elt.abs() # needs sage.symbolic 2*sqrt(-61) sage: elt = sum(O.basis()) sage: elt.abs() @@ -576,10 +577,10 @@ cdef class Octonion(Octonion_generic): sage: O = OctonionAlgebra(QQ) sage: elt = sum(i * b for i, b in enumerate(O.basis(), start=2)) - sage: elt.norm() + sage: elt.norm() # needs sage.symbolic 2*sqrt(71) sage: elt = sum(O.basis()) - sage: elt.norm() + sage: elt.norm() # needs sage.symbolic 2*sqrt(2) """ return self.vec.norm() @@ -750,7 +751,7 @@ class OctonionAlgebra(UniqueRepresentation, Parent): EXAMPLES:: sage: O = OctonionAlgebra(QQ) - sage: TestSuite(O).run() + sage: TestSuite(O).run() # needs sage.symbolic sage: O = OctonionAlgebra(QQ, 1, 3, 7) sage: TestSuite(O).run() diff --git a/src/sage/algebras/orlik_solomon.py b/src/sage/algebras/orlik_solomon.py index 920056787c6..76ed00aa855 100644 --- a/src/sage/algebras/orlik_solomon.py +++ b/src/sage/algebras/orlik_solomon.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.modules r""" Orlik-Solomon Algebras """ @@ -114,9 +115,10 @@ def __init__(self, R, M, ordering=None): We check on the matroid associated to the graph with 3 vertices and 2 edges between each vertex:: + sage: # needs sage.graphs sage: G = Graph([[1,2],[1,2],[2,3],[2,3],[1,3],[1,3]], multiedges=True) - sage: M = Matroid(G) - sage: OS = M.orlik_solomon_algebra(QQ) + sage: MG = Matroid(G) + sage: OS = MG.orlik_solomon_algebra(QQ) sage: elts = OS.some_elements() + list(OS.algebra_generators()) sage: TestSuite(OS).run(elements=elts) """ @@ -253,10 +255,11 @@ def product_on_basis(self, a, b): Let us check that `e_{s_1} e_{s_2} \cdots e_{s_k} = e_S` for any subset `S = \{ s_1 < s_2 < \cdots < s_k \}` of the ground set:: + sage: # needs sage.graphs sage: G = Graph([[1,2],[1,2],[2,3],[3,4],[4,2]], multiedges=True) - sage: M = Matroid(G).regular_matroid() - sage: E = M.groundset_list() - sage: OS = M.orlik_solomon_algebra(ZZ) + sage: MG = Matroid(G).regular_matroid() + sage: E = MG.groundset_list() + sage: OS = MG.orlik_solomon_algebra(ZZ) sage: G = OS.algebra_generators() sage: import itertools sage: def test_prod(F): @@ -326,31 +329,33 @@ def subset_image(self, S): ([2, 5], -OS{0, 2} + OS{0, 5}) ([4, 5], -OS{3, 4} + OS{3, 5}) + sage: # needs sage.graphs sage: M4 = matroids.CompleteGraphic(4) - sage: OS = M4.orlik_solomon_algebra(QQ) - sage: OS.subset_image(frozenset({2,3,4})) + sage: OSM4 = M4.orlik_solomon_algebra(QQ) + sage: OSM4.subset_image(frozenset({2,3,4})) OS{0, 2, 3} + OS{0, 3, 4} An example of a custom ordering:: + sage: # needs sage.graphs sage: G = Graph([[3, 4], [4, 1], [1, 2], [2, 3], [3, 5], [5, 6], [6, 3]]) - sage: M = Matroid(G) + sage: MG = Matroid(G) sage: s = [(5, 6), (1, 2), (3, 5), (2, 3), (1, 4), (3, 6), (3, 4)] - sage: sorted([sorted(c) for c in M.circuits()]) + sage: sorted([sorted(c) for c in MG.circuits()]) [[(1, 2), (1, 4), (2, 3), (3, 4)], [(3, 5), (3, 6), (5, 6)]] - sage: OS = M.orlik_solomon_algebra(QQ, ordering=s) - sage: OS.subset_image(frozenset([])) + sage: OSMG = MG.orlik_solomon_algebra(QQ, ordering=s) + sage: OSMG.subset_image(frozenset([])) OS{} - sage: OS.subset_image(frozenset([(1,2),(3,4),(1,4),(2,3)])) + sage: OSMG.subset_image(frozenset([(1,2),(3,4),(1,4),(2,3)])) 0 - sage: OS.subset_image(frozenset([(2,3),(1,2),(3,4)])) + sage: OSMG.subset_image(frozenset([(2,3),(1,2),(3,4)])) OS{(1, 2), (2, 3), (3, 4)} - sage: OS.subset_image(frozenset([(1,4),(3,4),(2,3),(3,6),(5,6)])) + sage: OSMG.subset_image(frozenset([(1,4),(3,4),(2,3),(3,6),(5,6)])) -OS{(1, 2), (1, 4), (2, 3), (3, 6), (5, 6)} + OS{(1, 2), (1, 4), (3, 4), (3, 6), (5, 6)} - OS{(1, 2), (2, 3), (3, 4), (3, 6), (5, 6)} - sage: OS.subset_image(frozenset([(1,4),(3,4),(2,3),(3,6),(3,5)])) + sage: OSMG.subset_image(frozenset([(1,4),(3,4),(2,3),(3,6),(3,5)])) OS{(1, 2), (1, 4), (2, 3), (3, 5), (5, 6)} - OS{(1, 2), (1, 4), (2, 3), (3, 6), (5, 6)} + OS{(1, 2), (1, 4), (3, 4), (3, 5), (5, 6)} @@ -360,34 +365,36 @@ def subset_image(self, S): TESTS:: + sage: # needs sage.graphs sage: G = Graph([[1,2],[1,2],[2,3],[2,3],[1,3],[1,3]], multiedges=True) - sage: M = Matroid(G) - sage: sorted([sorted(c) for c in M.circuits()]) + sage: MG = Matroid(G) + sage: sorted([sorted(c) for c in MG.circuits()]) [[0, 1], [0, 2, 4], [0, 2, 5], [0, 3, 4], [0, 3, 5], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3, 5], [2, 3], [4, 5]] - sage: OS = M.orlik_solomon_algebra(QQ) - sage: OS.subset_image(frozenset([])) + sage: OSMG = MG.orlik_solomon_algebra(QQ) + sage: OSMG.subset_image(frozenset([])) OS{} - sage: OS.subset_image(frozenset([1, 2, 3])) + sage: OSMG.subset_image(frozenset([1, 2, 3])) 0 - sage: OS.subset_image(frozenset([1, 3, 5])) + sage: OSMG.subset_image(frozenset([1, 3, 5])) 0 - sage: OS.subset_image(frozenset([1, 2])) + sage: OSMG.subset_image(frozenset([1, 2])) OS{0, 2} - sage: OS.subset_image(frozenset([3, 4])) + sage: OSMG.subset_image(frozenset([3, 4])) -OS{0, 2} + OS{0, 4} - sage: OS.subset_image(frozenset([1, 5])) + sage: OSMG.subset_image(frozenset([1, 5])) OS{0, 4} + sage: # needs sage.graphs sage: G = Graph([[1,2],[1,2],[2,3],[3,4],[4,2]], multiedges=True) - sage: M = Matroid(G) - sage: sorted([sorted(c) for c in M.circuits()]) + sage: MG = Matroid(G) + sage: sorted([sorted(c) for c in MG.circuits()]) [[0, 1], [2, 3, 4]] - sage: OS = M.orlik_solomon_algebra(QQ) - sage: OS.subset_image(frozenset([])) + sage: OSMG = MG.orlik_solomon_algebra(QQ) + sage: OSMG.subset_image(frozenset([])) OS{} - sage: OS.subset_image(frozenset([1, 3, 4])) + sage: OSMG.subset_image(frozenset([1, 3, 4])) -OS{0, 2, 3} + OS{0, 2, 4} We check on a non-standard ordering:: @@ -452,6 +459,7 @@ def as_gca(self): EXAMPLES:: + sage: # needs sage.geometry.polyhedron sage.graphs sage: H = hyperplane_arrangements.braid(3) sage: O = H.orlik_solomon_algebra(QQ) sage: O.as_gca() @@ -462,7 +470,7 @@ def as_gca(self): sage: N = matroids.named_matroids.Fano() sage: O = N.orlik_solomon_algebra(QQ) - sage: O.as_gca() + sage: O.as_gca() # needs sage.libs.singular Graded Commutative Algebra with generators ('e0', 'e1', 'e2', 'e3', 'e4', 'e5', 'e6') in degrees (1, 1, 1, 1, 1, 1, 1) with relations [e1*e2 - e1*e3 + e2*e3, e0*e1*e3 - e0*e1*e4 + e0*e3*e4 - e1*e3*e4, @@ -476,6 +484,7 @@ def as_gca(self): TESTS:: + sage: # needs sage.geometry.polyhedron sage: H = hyperplane_arrangements.Catalan(3,QQ).cone() sage: O = H.orlik_solomon_algebra(QQ) sage: A = O.as_gca() @@ -515,6 +524,7 @@ def as_cdga(self): EXAMPLES:: + sage: # needs sage.geometry.polyhedron sage.graphs sage: H = hyperplane_arrangements.braid(3) sage: O = H.orlik_solomon_algebra(QQ) sage: O.as_cdga() @@ -545,10 +555,11 @@ class OrlikSolomonInvariantAlgebra(FiniteDimensionalInvariantModule): Lets start with the action of `S_3` on the rank `2` braid matroid:: + sage: # needs sage.graphs sage: M = matroids.CompleteGraphic(3) sage: M.groundset() frozenset({0, 1, 2}) - sage: G = SymmetricGroup(3) + sage: G = SymmetricGroup(3) # needs sage.groups Calling elements ``g`` of ``G`` on an element `i` of `\{1, 2, 3\}` defines the action we want, but since the groundset is `\{0, 1, 2\}` @@ -560,6 +571,7 @@ class OrlikSolomonInvariantAlgebra(FiniteDimensionalInvariantModule): Now that we have defined an action we can create the invariant, and get its basis:: + sage: # needs sage.graphs sage.groups sage: OSG = M.orlik_solomon_algebra(QQ, invariant=(G, on_groundset)) sage: OSG.basis() Finite family {0: B[0], 1: B[1]} @@ -568,6 +580,7 @@ class OrlikSolomonInvariantAlgebra(FiniteDimensionalInvariantModule): Since it is invariant, the action of any ``g`` in ``G`` is trivial:: + sage: # needs sage.graphs sage.groups sage: x = OSG.an_element(); x 2*B[0] + 2*B[1] sage: g = G.an_element(); g @@ -575,6 +588,7 @@ class OrlikSolomonInvariantAlgebra(FiniteDimensionalInvariantModule): sage: g * x 2*B[0] + 2*B[1] + sage: # needs sage.graphs sage.groups sage: x = OSG.random_element() sage: g = G.random_element() sage: g * x == x @@ -583,7 +597,7 @@ class OrlikSolomonInvariantAlgebra(FiniteDimensionalInvariantModule): The underlying ambient module is the Orlik-Solomon algebra, which is accessible via :meth:`ambient()`:: - sage: M.orlik_solomon_algebra(QQ) is OSG.ambient() + sage: M.orlik_solomon_algebra(QQ) is OSG.ambient() # needs sage.graphs sage.groups True There is not much structure here, so lets look at a bigger example. @@ -591,6 +605,7 @@ class OrlikSolomonInvariantAlgebra(FiniteDimensionalInvariantModule): easier, we'll start the indexing at `1` so that the `S_6` action on the groundset is simply calling `g`:: + sage: # needs sage.graphs sage.groups sage: M = matroids.CompleteGraphic(4); M.groundset() frozenset({0, 1, 2, 3, 4, 5}) sage: new_bases = [frozenset(i+1 for i in j) for j in M.bases()] @@ -610,6 +625,7 @@ class OrlikSolomonInvariantAlgebra(FiniteDimensionalInvariantModule): Next, we look at the same matroid but with an `S_3 \times S_3` action (here realized as a Young subgroup of `S_6`):: + sage: # needs sage.graphs sage.groups sage: H = G.young_subgroup([3, 3]) sage: OSH = M.orlik_solomon_algebra(QQ, invariant=H) sage: OSH.basis() @@ -619,6 +635,7 @@ class OrlikSolomonInvariantAlgebra(FiniteDimensionalInvariantModule): We implement an `S_4` action on the vertices:: + sage: # needs sage.graphs sage.groups sage: M = matroids.CompleteGraphic(4) sage: G = SymmetricGroup(4) sage: edge_map = {i: M.groundset_to_edges([i])[0][:2] @@ -634,6 +651,7 @@ class OrlikSolomonInvariantAlgebra(FiniteDimensionalInvariantModule): We use this to describe the Young subgroup `S_2 \times S_2` action:: + sage: # needs sage.graphs sage.groups sage: H = G.young_subgroup([2,2]) sage: OSH = M.orlik_solomon_algebra(QQ, invariant=(H, vert_action)) sage: B = OSH.basis() @@ -645,7 +663,7 @@ class OrlikSolomonInvariantAlgebra(FiniteDimensionalInvariantModule): We demonstrate the algebra structure:: - sage: matrix([[b*bp for b in B] for bp in B]) + sage: matrix([[b*bp for b in B] for bp in B]) # needs sage.graphs sage.groups [ B[0] B[1] B[2] B[3] B[4] B[5] B[6] B[7]] [ B[1] 0 2*B[4] B[5] 0 0 2*B[7] 0] [ B[2] -2*B[4] 0 B[6] 0 -2*B[7] 0 0] @@ -668,6 +686,7 @@ def __init__(self, R, M, G, action_on_groundset=None, *args, **kwargs): EXAMPLES:: + sage: # needs sage.graphs sage.groups sage: M = matroids.CompleteGraphic(4) sage: new_bases = [frozenset(i+1 for i in j) for j in M.bases()] sage: M = Matroid(bases=new_bases) @@ -756,11 +775,12 @@ def _basis_action(self, g, f): EXAMPLES:: + sage: # needs sage.graphs sage.groups sage: M = matroids.CompleteGraphic(3) sage: M.groundset() frozenset({0, 1, 2}) sage: G = SymmetricGroup(3) - sage: def on_groundset(g,x): + sage: def on_groundset(g, x): ....: return g(x+1)-1 sage: OSG = M.orlik_solomon_algebra(QQ, invariant=(G,on_groundset)) sage: act = lambda g: (OSG._basis_action(g,frozenset({0,1})), @@ -775,6 +795,7 @@ def _basis_action(self, g, f): We also check that the ordering is respected:: + sage: # needs sage.graphs sage.groups sage: fset = frozenset({1,2}) sage: OS1 = M.orlik_solomon_algebra(QQ) sage: OS1.subset_image(fset) @@ -782,7 +803,6 @@ def _basis_action(self, g, f): sage: OS2 = M.orlik_solomon_algebra(QQ, range(2,-1,-1)) sage: OS2.subset_image(fset) OS{1, 2} - sage: OSG2 = M.orlik_solomon_algebra(QQ, ....: invariant=(G,on_groundset), ....: ordering=range(2,-1,-1)) @@ -792,9 +812,9 @@ def _basis_action(self, g, f): This choice of ``g`` acting on this choice of ``fset`` reverses the sign:: - sage: OSG._basis_action(g, fset) + sage: OSG._basis_action(g, fset) # needs sage.graphs sage.groups OS{0, 1} - OS{0, 2} - sage: OSG2._basis_action(g, fset) + sage: OSG2._basis_action(g, fset) # needs sage.graphs sage.groups -OS{1, 2} """ OS = self._ambient diff --git a/src/sage/algebras/orlik_terao.py b/src/sage/algebras/orlik_terao.py index 55fd2bdb641..81158f3e9b7 100644 --- a/src/sage/algebras/orlik_terao.py +++ b/src/sage/algebras/orlik_terao.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.modules r""" Orlik-Terao Algebras """ @@ -130,10 +131,12 @@ def __init__(self, R, M, ordering=None): sage: OT = M.orlik_terao_algebra(QQ) sage: TestSuite(OT).run(elements=OT.basis()) + sage: # needs sage.graphs sage: M = matroids.CompleteGraphic(4).ternary_matroid() sage: OT = M.orlik_terao_algebra(GF(3)['t']) sage: TestSuite(OT).run(elements=OT.basis()) + sage: # needs sage.geometry.polyhedron sage: H = hyperplane_arrangements.Catalan(4).cone() sage: M = H.matroid() sage: OT = M.orlik_terao_algebra() @@ -144,6 +147,7 @@ def __init__(self, R, M, ordering=None): We check on the matroid associated to the graph with 3 vertices and 2 edges between each vertex:: + sage: # needs sage.graphs sage: G = Graph([[1,2],[1,2],[2,3],[2,3],[1,3],[1,3]], multiedges=True) sage: M = Matroid(G).regular_matroid() sage: OT = M.orlik_terao_algebra(QQ) @@ -321,6 +325,7 @@ def product_on_basis(self, a, b): Let us check that `e_{s_1} e_{s_2} \cdots e_{s_k} = e_S` for any subset `S = \{ s_1 < s_2 < \cdots < s_k \}` of the ground set:: + sage: # needs sage.graphs sage: G = Graph([[1,2],[1,2],[2,3],[3,4],[4,2]], multiedges=True) sage: M = Matroid(G).regular_matroid() sage: E = M.groundset_list() @@ -370,6 +375,7 @@ def subset_image(self, S): ([2, 5], -OT{0, 2} + OT{0, 5}) ([4, 5], -OT{3, 4} - OT{3, 5}) + sage: # needs sage.graphs sage: M4 = matroids.CompleteGraphic(4).ternary_matroid() sage: OT = M4.orlik_terao_algebra() sage: OT.subset_image(frozenset({2,3,4})) @@ -377,6 +383,7 @@ def subset_image(self, S): An example of a custom ordering:: + sage: # needs sage.graphs sage: G = Graph([[3, 4], [4, 1], [1, 2], [2, 3], [3, 5], [5, 6], [6, 3]]) sage: M = Matroid(G).regular_matroid() sage: s = [(5, 6), (1, 2), (3, 5), (2, 3), (1, 4), (3, 6), (3, 4)] @@ -404,6 +411,7 @@ def subset_image(self, S): TESTS:: + sage: # needs sage.graphs sage: G = Graph([[1,2],[1,2],[2,3],[2,3],[1,3],[1,3]], multiedges=True) sage: M = Matroid(G).regular_matroid() sage: sorted([sorted(c) for c in M.circuits()]) @@ -424,6 +432,7 @@ def subset_image(self, S): sage: OT.subset_image(frozenset([1, 5])) OT{0, 4} + sage: # needs sage.graphs sage: G = Graph([[1,2],[1,2],[2,3],[3,4],[4,2]], multiedges=True) sage: M = Matroid(G).regular_matroid() sage: sorted([sorted(c) for c in M.circuits()]) @@ -498,6 +507,7 @@ def _chi(self, X): EXAMPLES:: + sage: # needs sage.geometry.polyhedron sage: H = hyperplane_arrangements.Catalan(2).cone() sage: M = H.matroid() sage: OT = M.orlik_terao_algebra() @@ -541,7 +551,7 @@ class OrlikTeraoInvariantAlgebra(FiniteDimensionalInvariantModule): sage: M = Matroid(A) sage: M.groundset() frozenset({0, 1, 2}) - sage: G = SymmetricGroup(3) + sage: G = SymmetricGroup(3) # needs sage.groups Calling elements ``g`` of ``G`` on an element `i` of `\{1,2,3\}` defines the action we want, but since the groundset is `\{0,1,2\}` @@ -553,7 +563,8 @@ class OrlikTeraoInvariantAlgebra(FiniteDimensionalInvariantModule): Now that we have defined an action we can create the invariant, and get its basis:: - sage: OTG = M.orlik_terao_algebra(QQ, invariant = (G, on_groundset)) + sage: # needs sage.groups + sage: OTG = M.orlik_terao_algebra(QQ, invariant=(G, on_groundset)) sage: OTG.basis() Finite family {0: B[0], 1: B[1]} sage: [OTG.lift(b) for b in OTG.basis()] @@ -561,6 +572,7 @@ class OrlikTeraoInvariantAlgebra(FiniteDimensionalInvariantModule): Since it is invariant, the action of any ``g`` in ``G`` is trivial:: + sage: # needs sage.groups sage: x = OTG.an_element(); x 2*B[0] + 2*B[1] sage: g = G.an_element(); g @@ -568,6 +580,7 @@ class OrlikTeraoInvariantAlgebra(FiniteDimensionalInvariantModule): sage: g*x 2*B[0] + 2*B[1] + sage: # needs sage.groups sage: x = OTG.random_element() sage: g = G.random_element() sage: g*x == x @@ -576,11 +589,12 @@ class OrlikTeraoInvariantAlgebra(FiniteDimensionalInvariantModule): The underlying ambient module is the Orlik-Terao algebra, which is accessible via :meth:`ambient()`:: - sage: M.orlik_terao_algebra(QQ) is OTG.ambient() + sage: M.orlik_terao_algebra(QQ) is OTG.ambient() # needs sage.groups True For a bigger example, here we will look at the rank-`3` braid matroid:: + sage: # needs sage.groups sage: A = matrix([[1,1,1,0,0,0],[-1,0,0,1,1,0], ....: [0,-1,0,-1,0,1],[0,0,-1,0,-1,-1]]); A [ 1 1 1 0 0 0] @@ -590,9 +604,11 @@ class OrlikTeraoInvariantAlgebra(FiniteDimensionalInvariantModule): sage: M = Matroid(A); M.groundset() frozenset({0, 1, 2, 3, 4, 5}) sage: G = SymmetricGroup(6) - sage: OTG = M.orlik_terao_algebra(QQ, invariant = (G, on_groundset)) + sage: OTG = M.orlik_terao_algebra(QQ, invariant=(G, on_groundset)) sage: OTG.ambient() - Orlik-Terao algebra of Linear matroid of rank 3 on 6 elements represented over the Rational Field over Rational Field + Orlik-Terao algebra of + Linear matroid of rank 3 on 6 elements represented over the Rational Field + over Rational Field sage: OTG.basis() Finite family {0: B[0], 1: B[1]} sage: [OTG.lift(b) for b in OTG.basis()] @@ -605,6 +621,7 @@ def __init__(self, R, M, G, action_on_groundset=None, *args, **kwargs): EXAMPLES:: + sage: # needs sage.groups sage: A = matrix([[1,1,1,0,0,0],[-1,0,0,1,1,0],[0,-1,0,-1,0,1], ....: [0,0,-1,0,-1,-1]]) sage: M = Matroid(A); @@ -668,6 +685,7 @@ def construction(self): TESTS:: + sage: # needs sage.groups sage: A = matrix([[1,1,0],[-1,0,1],[0,-1,-1]]) sage: M = Matroid(A) sage: G = SymmetricGroup(3) @@ -696,6 +714,7 @@ def _basis_action(self, g, f): EXAMPLES:: + sage: # needs sage.groups sage: A = matrix([[1,1,0],[-1,0,1],[0,-1,-1]]) sage: M = Matroid(A) sage: M.groundset() @@ -718,6 +737,7 @@ def _basis_action(self, g, f): We also check that the ordering is respected:: + sage: # needs sage.groups sage: fset = frozenset({1,2}) sage: OT1 = M.orlik_terao_algebra(QQ) sage: OT1.subset_image(fset) @@ -726,6 +746,7 @@ def _basis_action(self, g, f): sage: OT2.subset_image(fset) OT{1, 2} + sage: # needs sage.groups sage: OTG2 = M.orlik_terao_algebra(QQ, ....: invariant=(G,on_groundset), ....: ordering=range(2,-1,-1)) @@ -734,6 +755,7 @@ def _basis_action(self, g, f): This choice of ``g`` fixes these elements:: + sage: # needs sage.groups sage: OTG._basis_action(g, fset) -OT{0, 1} + OT{0, 2} sage: OTG2._basis_action(g, fset) @@ -741,6 +763,7 @@ def _basis_action(self, g, f): TESTS:: + sage: # needs sage.groups sage: [on_groundset(g, e) for e in M.groundset()] [0, 2, 1] sage: [OTG._groundset_action(g,e) for e in M.groundset()] diff --git a/src/sage/algebras/q_commuting_polynomials.py b/src/sage/algebras/q_commuting_polynomials.py index a50b2335787..10f5f55a987 100644 --- a/src/sage/algebras/q_commuting_polynomials.py +++ b/src/sage/algebras/q_commuting_polynomials.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.groups sage.modules r""" `q`-Commuting Polynomials diff --git a/src/sage/algebras/q_system.py b/src/sage/algebras/q_system.py index f7d495aac50..d35c51a32a5 100644 --- a/src/sage/algebras/q_system.py +++ b/src/sage/algebras/q_system.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.graphs sage.modules r""" Q-Systems diff --git a/src/sage/algebras/quantum_clifford.py b/src/sage/algebras/quantum_clifford.py index 2b85615cf20..dc61084f2f8 100644 --- a/src/sage/algebras/quantum_clifford.py +++ b/src/sage/algebras/quantum_clifford.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.modules r""" Quantum Clifford Algebras diff --git a/src/sage/algebras/quantum_groups/ace_quantum_onsager.py b/src/sage/algebras/quantum_groups/ace_quantum_onsager.py index 91138258e5a..9d983529c73 100644 --- a/src/sage/algebras/quantum_groups/ace_quantum_onsager.py +++ b/src/sage/algebras/quantum_groups/ace_quantum_onsager.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Alternating Central Extension Quantum Onsager Algebra diff --git a/src/sage/algebras/quantum_groups/fock_space.py b/src/sage/algebras/quantum_groups/fock_space.py index 3352f143a7c..22665746325 100644 --- a/src/sage/algebras/quantum_groups/fock_space.py +++ b/src/sage/algebras/quantum_groups/fock_space.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Fock Space diff --git a/src/sage/algebras/quantum_groups/quantum_group_gap.py b/src/sage/algebras/quantum_groups/quantum_group_gap.py index 8925c047916..4998af7b588 100644 --- a/src/sage/algebras/quantum_groups/quantum_group_gap.py +++ b/src/sage/algebras/quantum_groups/quantum_group_gap.py @@ -1,4 +1,4 @@ -# sage.doctest: optional - gap_package_quagroup +# sage.doctest: optional - gap_package_quagroup sage.combinat sage.libs.gap sage.modules """ Quantum Groups Using GAP's QuaGroup Package @@ -21,7 +21,12 @@ # https://www.gnu.org/licenses/ # **************************************************************************** +import re + +from copy import copy + from sage.misc.lazy_attribute import lazy_attribute +from sage.misc.lazy_import import lazy_import from sage.misc.cachefunc import cached_method from sage.structure.parent import Parent from sage.structure.element import Element @@ -33,7 +38,6 @@ from sage.combinat.root_system.cartan_type import CartanType from sage.libs.gap.libgap import libgap from sage.features.gap import GapPackage -from sage.graphs.digraph import DiGraph from sage.rings.rational_field import QQ from sage.categories.algebras import Algebras from sage.categories.cartesian_product import cartesian_product @@ -44,8 +48,7 @@ from sage.categories.morphism import Morphism from sage.categories.rings import Rings -from copy import copy -import re +lazy_import('sage.graphs.digraph', 'DiGraph') class QuaGroupModuleElement(Element): diff --git a/src/sage/algebras/quantum_groups/representations.py b/src/sage/algebras/quantum_groups/representations.py index b874d264669..cea110137db 100644 --- a/src/sage/algebras/quantum_groups/representations.py +++ b/src/sage/algebras/quantum_groups/representations.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.graphs sage.modules r""" Quantum Group Representations diff --git a/src/sage/algebras/quantum_matrix_coordinate_algebra.py b/src/sage/algebras/quantum_matrix_coordinate_algebra.py index 1579896fa86..c9f7e312788 100644 --- a/src/sage/algebras/quantum_matrix_coordinate_algebra.py +++ b/src/sage/algebras/quantum_matrix_coordinate_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Quantum Matrix Coordinate Algebras diff --git a/src/sage/algebras/quatalg/quaternion_algebra.py b/src/sage/algebras/quatalg/quaternion_algebra.py index 1b6001209a0..9c1562041e4 100644 --- a/src/sage/algebras/quatalg/quaternion_algebra.py +++ b/src/sage/algebras/quatalg/quaternion_algebra.py @@ -119,15 +119,17 @@ class QuaternionAlgebraFactory(UniqueFactory): Quaternion Algebra (2, 3) with base ring Finite Field of size 5 sage: QuaternionAlgebra(2, GF(5)(3)) Quaternion Algebra (2, 3) with base ring Finite Field of size 5 - sage: QuaternionAlgebra(QQ[sqrt(2)](-1), -5) - Quaternion Algebra (-1, -5) with base ring Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095? - sage: QuaternionAlgebra(sqrt(-1), sqrt(-3)) + sage: QuaternionAlgebra(QQ[sqrt(2)](-1), -5) # needs sage.symbolic + Quaternion Algebra (-1, -5) with base ring Number Field in sqrt2 + with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095? + sage: QuaternionAlgebra(sqrt(-1), sqrt(-3)) # needs sage.symbolic Quaternion Algebra (I, sqrt(-3)) with base ring Symbolic Ring sage: QuaternionAlgebra(1r,1) Quaternion Algebra (1, 1) with base ring Rational Field sage: A. = ZZ[] sage: QuaternionAlgebra(-1, t) - Quaternion Algebra (-1, t) with base ring Fraction Field of Univariate Polynomial Ring in t over Integer Ring + Quaternion Algebra (-1, t) with base ring + Fraction Field of Univariate Polynomial Ring in t over Integer Ring Python ints and floats may be passed to the ``QuaternionAlgebra(a, b)`` constructor, as may all pairs of @@ -138,11 +140,13 @@ class QuaternionAlgebraFactory(UniqueFactory): sage: QuaternionAlgebra(1r,1) Quaternion Algebra (1, 1) with base ring Rational Field sage: QuaternionAlgebra(1,1.0r) - Quaternion Algebra (1.00000000000000, 1.00000000000000) with base ring Real Field with 53 bits of precision + Quaternion Algebra (1.00000000000000, 1.00000000000000) with base ring + Real Field with 53 bits of precision sage: QuaternionAlgebra(0,0) Traceback (most recent call last): ... - ValueError: defining elements of quaternion algebra (0, 0) are not invertible in Rational Field + ValueError: defining elements of quaternion algebra (0, 0) + are not invertible in Rational Field sage: QuaternionAlgebra(GF(2)(1),1) Traceback (most recent call last): ... @@ -158,8 +162,9 @@ class QuaternionAlgebraFactory(UniqueFactory): sage: QuaternionAlgebra(QQ, -7, -21) Quaternion Algebra (-7, -21) with base ring Rational Field - sage: QuaternionAlgebra(QQ[sqrt(2)], -2,-3) - Quaternion Algebra (-2, -3) with base ring Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095? + sage: QuaternionAlgebra(QQ[sqrt(2)], -2,-3) # needs sage.symbolic + Quaternion Algebra (-2, -3) with base ring Number Field in sqrt2 + with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095? ``QuaternionAlgebra(D)`` -- `D` is a squarefree integer; return a rational quaternion algebra of discriminant `D`:: @@ -540,8 +545,8 @@ def random_element(self, *args, **kwds): EXAMPLES:: - sage: g = QuaternionAlgebra(QQ[sqrt(2)], -3, 7).random_element() - sage: g.parent() is QuaternionAlgebra(QQ[sqrt(2)], -3, 7) + sage: g = QuaternionAlgebra(QQ[sqrt(2)], -3, 7).random_element() # needs sage.symbolic + sage: g.parent() is QuaternionAlgebra(QQ[sqrt(2)], -3, 7) # needs sage.symbolic True sage: g = QuaternionAlgebra(-3, 19).random_element() sage: g.parent() is QuaternionAlgebra(-3, 19) @@ -576,12 +581,13 @@ def free_module(self): sage: A. = LaurentPolynomialRing(GF(3)) sage: B = QuaternionAlgebra(A, -1, t) sage: B.free_module() - Ambient free quadratic module of rank 4 over the principal ideal domain Univariate Laurent Polynomial Ring in t over Finite Field of size 3 - Inner product matrix: - [2 0 0 0] - [0 2 0 0] - [0 0 t 0] - [0 0 0 t] + Ambient free quadratic module of rank 4 over the principal ideal domain + Univariate Laurent Polynomial Ring in t over Finite Field of size 3 + Inner product matrix: + [2 0 0 0] + [0 2 0 0] + [0 0 t 0] + [0 0 0 t] """ return FreeModule(self.base_ring(), 4, inner_product_matrix=self.inner_product_matrix()) @@ -594,10 +600,10 @@ def vector_space(self): sage: QuaternionAlgebra(-3,19).vector_space() Ambient quadratic space of dimension 4 over Rational Field Inner product matrix: - [ 2 0 0 0] - [ 0 6 0 0] - [ 0 0 -38 0] - [ 0 0 0 -114] + [ 2 0 0 0] + [ 0 6 0 0] + [ 0 0 -38 0] + [ 0 0 0 -114] """ return self.free_module() @@ -697,7 +703,8 @@ def maximal_order(self, take_shortcuts=True): EXAMPLES:: sage: QuaternionAlgebra(-1,-7).maximal_order() - Order of Quaternion Algebra (-1, -7) with base ring Rational Field with basis (1/2 + 1/2*j, 1/2*i + 1/2*k, j, k) + Order of Quaternion Algebra (-1, -7) with base ring Rational Field + with basis (1/2 + 1/2*j, 1/2*i + 1/2*k, j, k) sage: QuaternionAlgebra(-1,-1).maximal_order().basis() (1/2 + 1/2*i + 1/2*j + 1/2*k, i, j, k) @@ -732,13 +739,16 @@ def maximal_order(self, take_shortcuts=True): If you want bases containing 1, switch off ``take_shortcuts``:: sage: QuaternionAlgebra(-3,-89).maximal_order(take_shortcuts=False) - Order of Quaternion Algebra (-3, -89) with base ring Rational Field with basis (1, 1/2 + 1/2*i, j, 1/2 + 1/6*i + 1/2*j + 1/6*k) + Order of Quaternion Algebra (-3, -89) with base ring Rational Field + with basis (1, 1/2 + 1/2*i, j, 1/2 + 1/6*i + 1/2*j + 1/6*k) sage: QuaternionAlgebra(1,1).maximal_order(take_shortcuts=False) # Matrix ring - Order of Quaternion Algebra (1, 1) with base ring Rational Field with basis (1, 1/2 + 1/2*i, j, 1/2*j + 1/2*k) + Order of Quaternion Algebra (1, 1) with base ring Rational Field + with basis (1, 1/2 + 1/2*i, j, 1/2*j + 1/2*k) sage: QuaternionAlgebra(-22,210).maximal_order(take_shortcuts=False) - Order of Quaternion Algebra (-22, 210) with base ring Rational Field with basis (1, i, 1/2*i + 1/2*j, 1/2 + 17/22*i + 1/44*k) + Order of Quaternion Algebra (-22, 210) with base ring Rational Field + with basis (1, i, 1/2*i + 1/2*j, 1/2 + 17/22*i + 1/44*k) sage: for d in ( m for m in range(1, 750) if is_squarefree(m) ): # long time (3s) ....: A = QuaternionAlgebra(d) @@ -751,7 +761,8 @@ def maximal_order(self, take_shortcuts=True): sage: QuaternionAlgebra(K,-1,-1).maximal_order() Traceback (most recent call last): ... - NotImplementedError: maximal order only implemented for rational quaternion algebras + NotImplementedError: maximal order only implemented + for rational quaternion algebras """ if self.base_ring() != QQ: raise NotImplementedError("maximal order only implemented for rational quaternion algebras") @@ -1037,7 +1048,7 @@ def discriminant(self): sage: B.discriminant() Fractional ideal (2) - sage: QuaternionAlgebra(QQ[sqrt(2)],3,19).discriminant() + sage: QuaternionAlgebra(QQ[sqrt(2)], 3, 19).discriminant() # needs sage.symbolic Fractional ideal (1) """ if not is_RationalField(self.base_ring()): @@ -1082,11 +1093,13 @@ def _magma_init_(self, magma): A more complicated example involving a quaternion algebra over a number field:: - sage: K. = QQ[sqrt(2)]; Q = QuaternionAlgebra(K,-1,a); Q - Quaternion Algebra (-1, sqrt2) with base ring Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095? - sage: magma(Q) # optional - magma - Quaternion Algebra with base ring Number Field with defining polynomial x^2 - 2 over the Rational Field, defined by i^2 = -1, j^2 = sqrt2 - sage: Q._magma_init_(magma) # optional - magma + sage: K. = QQ[sqrt(2)]; Q = QuaternionAlgebra(K,-1,a); Q # needs sage.symbolic + Quaternion Algebra (-1, sqrt2) with base ring Number Field in sqrt2 + with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095? + sage: magma(Q) # optional - magma, needs sage.symbolic + Quaternion Algebra with base ring Number Field with defining polynomial + x^2 - 2 over the Rational Field, defined by i^2 = -1, j^2 = sqrt2 + sage: Q._magma_init_(magma) # optional - magma, needs sage.symbolic 'QuaternionAlgebra(_sage_[...],(_sage_[...]![-1, 0]),(_sage_[...]![0, 1]))' """ R = magma(self.base_ring()) @@ -1107,14 +1120,17 @@ def quaternion_order(self, basis, check=True): sage: Q. = QuaternionAlgebra(-11,-1) sage: Q.quaternion_order([1,i,j,k]) - Order of Quaternion Algebra (-11, -1) with base ring Rational Field with basis (1, i, j, k) + Order of Quaternion Algebra (-11, -1) with base ring Rational Field + with basis (1, i, j, k) We test out ``check=False``:: sage: Q.quaternion_order([1,i,j,k], check=False) - Order of Quaternion Algebra (-11, -1) with base ring Rational Field with basis (1, i, j, k) + Order of Quaternion Algebra (-11, -1) with base ring Rational Field + with basis (1, i, j, k) sage: Q.quaternion_order([i,j,k], check=False) - Order of Quaternion Algebra (-11, -1) with base ring Rational Field with basis (i, j, k) + Order of Quaternion Algebra (-11, -1) with base ring Rational Field + with basis (i, j, k) """ return QuaternionOrder(self, basis, check=check) @@ -1210,7 +1226,9 @@ def modp_splitting_data(self, p): sage: Q.modp_splitting_data(5) Traceback (most recent call last): ... - NotImplementedError: algorithm for computing local splittings not implemented in general (currently require the first invariant to be coprime to p) + NotImplementedError: algorithm for computing local splittings + not implemented in general (currently require the first invariant + to be coprime to p) sage: Q.modp_splitting_data(2) Traceback (most recent call last): @@ -1363,7 +1381,8 @@ def __init__(self, A, basis, check=True): sage: K = QuadraticField(10) sage: A. = QuaternionAlgebra(K,-1,-1) sage: A.quaternion_order([1,i,j,k]) - Order of Quaternion Algebra (-1, -1) with base ring Number Field in a with defining polynomial x^2 - 10 with a = 3.162277660168380? with basis (1, i, j, k) + Order of Quaternion Algebra (-1, -1) with base ring Number Field in a + with defining polynomial x^2 - 10 with a = 3.162277660168380? with basis (1, i, j, k) sage: A.quaternion_order([1,i/2,j,k]) Traceback (most recent call last): ... @@ -1508,7 +1527,8 @@ def gen(self, n): EXAMPLES:: sage: R = QuaternionAlgebra(-11,-1).maximal_order(); R - Order of Quaternion Algebra (-11, -1) with base ring Rational Field with basis (1/2 + 1/2*i, 1/2*j - 1/2*k, i, -k) + Order of Quaternion Algebra (-11, -1) with base ring Rational Field + with basis (1/2 + 1/2*i, 1/2*j - 1/2*k, i, -k) sage: R.gen(0) 1/2 + 1/2*i sage: R.gen(1) @@ -1649,20 +1669,23 @@ def intersection(self, other): sage: R = QuaternionAlgebra(-11,-1).maximal_order() sage: R.intersection(R) - Order of Quaternion Algebra (-11, -1) with base ring Rational Field with basis (1/2 + 1/2*i, i, 1/2*j + 1/2*k, k) + Order of Quaternion Algebra (-11, -1) with base ring Rational Field + with basis (1/2 + 1/2*i, i, 1/2*j + 1/2*k, k) We intersect various orders in the quaternion algebra ramified at 11:: sage: B = BrandtModule(11,3) sage: R = B.maximal_order(); S = B.order_of_level_N() sage: R.intersection(S) - Order of Quaternion Algebra (-1, -11) with base ring Rational Field with basis (1/2 + 1/2*j, 1/2*i + 5/2*k, j, 3*k) + Order of Quaternion Algebra (-1, -11) with base ring Rational Field + with basis (1/2 + 1/2*j, 1/2*i + 5/2*k, j, 3*k) sage: R.intersection(S) == S True sage: B = BrandtModule(11,5) sage: T = B.order_of_level_N() sage: S.intersection(T) - Order of Quaternion Algebra (-1, -11) with base ring Rational Field with basis (1/2 + 1/2*j, 1/2*i + 23/2*k, j, 15*k) + Order of Quaternion Algebra (-1, -11) with base ring Rational Field + with basis (1/2 + 1/2*j, 1/2*i + 23/2*k, j, 15*k) """ if not isinstance(other, QuaternionOrder): raise TypeError("other must be a QuaternionOrder") @@ -2021,7 +2044,8 @@ def scale(self, alpha, left=False): EXAMPLES:: - sage: B = BrandtModule(5,37); I = B.right_ideals()[0]; i,j,k = B.quaternion_algebra().gens(); I + sage: B = BrandtModule(5,37); I = B.right_ideals()[0] + sage: i,j,k = B.quaternion_algebra().gens(); I Fractional ideal (2 + 2*j + 106*k, i + 2*j + 105*k, 4*j + 64*k, 148*k) sage: I.scale(i) Fractional ideal (2*i + 212*j - 2*k, -2 + 210*j - 2*k, 128*j - 4*k, 296*j) @@ -2101,9 +2125,11 @@ def _compute_order(self, side='left'): sage: R. = QuaternionAlgebra(-1,-11) sage: I = R.ideal([2 + 2*j + 140*k, 2*i + 4*j + 150*k, 8*j + 104*k, 152*k]) sage: Ol = I._compute_order('left'); Ol - Order of Quaternion Algebra (-1, -11) with base ring Rational Field with basis (1/2 + 1/2*j + 35*k, 1/4*i + 1/2*j + 75/4*k, j + 32*k, 38*k) + Order of Quaternion Algebra (-1, -11) with base ring Rational Field + with basis (1/2 + 1/2*j + 35*k, 1/4*i + 1/2*j + 75/4*k, j + 32*k, 38*k) sage: Or = I._compute_order('right'); Or - Order of Quaternion Algebra (-1, -11) with base ring Rational Field with basis (1/2 + 1/2*j + 16*k, 1/2*i + 11/2*k, j + 13*k, 19*k) + Order of Quaternion Algebra (-1, -11) with base ring Rational Field + with basis (1/2 + 1/2*j + 16*k, 1/2*i + 11/2*k, j + 13*k, 19*k) sage: Ol.discriminant() 209 sage: Or.discriminant() @@ -2163,7 +2189,8 @@ def left_order(self): sage: R = B.maximal_order() sage: I = R.unit_ideal() sage: I.left_order() - Order of Quaternion Algebra (-1, -11) with base ring Rational Field with basis (1/2 + 1/2*j, 1/2*i + 1/2*k, j, k) + Order of Quaternion Algebra (-1, -11) with base ring Rational Field + with basis (1/2 + 1/2*j, 1/2*i + 1/2*k, j, k) We do a consistency check:: @@ -2186,9 +2213,11 @@ def right_order(self): sage: I = BrandtModule(389).right_ideals()[1]; I Fractional ideal (2 + 6*j + 2*k, i + 2*j + k, 8*j, 8*k) sage: I.right_order() - Order of Quaternion Algebra (-2, -389) with base ring Rational Field with basis (1/2 + 1/2*j + 1/2*k, 1/4*i + 1/2*j + 1/4*k, j, k) + Order of Quaternion Algebra (-2, -389) with base ring Rational Field + with basis (1/2 + 1/2*j + 1/2*k, 1/4*i + 1/2*j + 1/4*k, j, k) sage: I.left_order() - Order of Quaternion Algebra (-2, -389) with base ring Rational Field with basis (1/2 + 1/2*j + 3/2*k, 1/8*i + 1/4*j + 9/8*k, j + k, 2*k) + Order of Quaternion Algebra (-2, -389) with base ring Rational Field + with basis (1/2 + 1/2*j + 3/2*k, 1/8*i + 1/4*j + 9/8*k, j + k, 2*k) The following is a big consistency check. We take reps for all the right ideal classes of a certain order, take the @@ -2238,7 +2267,8 @@ def quaternion_order(self): sage: R = QuaternionAlgebra(-11,-1).maximal_order() sage: R.unit_ideal().quaternion_order() is R - doctest:...: DeprecationWarning: quaternion_order() is deprecated, please use left_order() or right_order() + doctest:...: DeprecationWarning: quaternion_order() is deprecated, + please use left_order() or right_order() See https://github.com/sagemath/sage/issues/31583 for details. True """ @@ -2516,12 +2546,13 @@ def norm(self): sage: [I.norm() for I in C] [16, 32, 32] - sage: (a,b) = M.quaternion_algebra().invariants() # optional - magma - sage: magma.eval('A := QuaternionAlgebra' % (a,b)) # optional - magma + sage: # optional - magma + sage: (a,b) = M.quaternion_algebra().invariants() + sage: magma.eval('A := QuaternionAlgebra' % (a,b)) '' - sage: magma.eval('O := QuaternionOrder(%s)' % str(list(C[0].right_order().basis()))) # optional - magma + sage: magma.eval('O := QuaternionOrder(%s)' % str(list(C[0].right_order().basis()))) '' - sage: [ magma('rideal' % str(list(I.basis()))).Norm() for I in C] # optional - magma + sage: [ magma('rideal' % str(list(I.basis()))).Norm() for I in C] [16, 32, 32] sage: A. = QuaternionAlgebra(-1,-1) @@ -2838,31 +2869,47 @@ def cyclic_right_subideals(self, p, alpha=None): sage: B = BrandtModule(2,37); I = B.right_ideals()[0] sage: I.cyclic_right_subideals(3) - [Fractional ideal (2 + 2*i + 10*j + 90*k, 4*i + 4*j + 152*k, 12*j + 132*k, 444*k), Fractional ideal (2 + 2*i + 2*j + 150*k, 4*i + 8*j + 196*k, 12*j + 132*k, 444*k), Fractional ideal (2 + 2*i + 6*j + 194*k, 4*i + 8*j + 344*k, 12*j + 132*k, 444*k), Fractional ideal (2 + 2*i + 6*j + 46*k, 4*i + 4*j + 4*k, 12*j + 132*k, 444*k)] + [Fractional ideal (2 + 2*i + 10*j + 90*k, 4*i + 4*j + 152*k, 12*j + 132*k, 444*k), + Fractional ideal (2 + 2*i + 2*j + 150*k, 4*i + 8*j + 196*k, 12*j + 132*k, 444*k), + Fractional ideal (2 + 2*i + 6*j + 194*k, 4*i + 8*j + 344*k, 12*j + 132*k, 444*k), + Fractional ideal (2 + 2*i + 6*j + 46*k, 4*i + 4*j + 4*k, 12*j + 132*k, 444*k)] sage: B = BrandtModule(5,389); I = B.right_ideals()[0] sage: C = I.cyclic_right_subideals(3); C - [Fractional ideal (2 + 10*j + 546*k, i + 6*j + 133*k, 12*j + 3456*k, 4668*k), Fractional ideal (2 + 2*j + 2910*k, i + 6*j + 3245*k, 12*j + 3456*k, 4668*k), Fractional ideal (2 + i + 2295*k, 3*i + 2*j + 3571*k, 4*j + 2708*k, 4668*k), Fractional ideal (2 + 2*i + 2*j + 4388*k, 3*i + 2*j + 2015*k, 4*j + 4264*k, 4668*k)] + [Fractional ideal (2 + 10*j + 546*k, i + 6*j + 133*k, 12*j + 3456*k, 4668*k), + Fractional ideal (2 + 2*j + 2910*k, i + 6*j + 3245*k, 12*j + 3456*k, 4668*k), + Fractional ideal (2 + i + 2295*k, 3*i + 2*j + 3571*k, 4*j + 2708*k, 4668*k), + Fractional ideal (2 + 2*i + 2*j + 4388*k, 3*i + 2*j + 2015*k, 4*j + 4264*k, 4668*k)] sage: [(I.free_module()/J.free_module()).invariants() for J in C] [(3, 3), (3, 3), (3, 3), (3, 3)] sage: I.scale(3).cyclic_right_subideals(3) - [Fractional ideal (6 + 30*j + 1638*k, 3*i + 18*j + 399*k, 36*j + 10368*k, 14004*k), Fractional ideal (6 + 6*j + 8730*k, 3*i + 18*j + 9735*k, 36*j + 10368*k, 14004*k), Fractional ideal (6 + 3*i + 6885*k, 9*i + 6*j + 10713*k, 12*j + 8124*k, 14004*k), Fractional ideal (6 + 6*i + 6*j + 13164*k, 9*i + 6*j + 6045*k, 12*j + 12792*k, 14004*k)] + [Fractional ideal (6 + 30*j + 1638*k, 3*i + 18*j + 399*k, 36*j + 10368*k, 14004*k), + Fractional ideal (6 + 6*j + 8730*k, 3*i + 18*j + 9735*k, 36*j + 10368*k, 14004*k), + Fractional ideal (6 + 3*i + 6885*k, 9*i + 6*j + 10713*k, 12*j + 8124*k, 14004*k), + Fractional ideal (6 + 6*i + 6*j + 13164*k, 9*i + 6*j + 6045*k, 12*j + 12792*k, 14004*k)] sage: C = I.scale(1/9).cyclic_right_subideals(3); C - [Fractional ideal (2/9 + 10/9*j + 182/3*k, 1/9*i + 2/3*j + 133/9*k, 4/3*j + 384*k, 1556/3*k), Fractional ideal (2/9 + 2/9*j + 970/3*k, 1/9*i + 2/3*j + 3245/9*k, 4/3*j + 384*k, 1556/3*k), Fractional ideal (2/9 + 1/9*i + 255*k, 1/3*i + 2/9*j + 3571/9*k, 4/9*j + 2708/9*k, 1556/3*k), Fractional ideal (2/9 + 2/9*i + 2/9*j + 4388/9*k, 1/3*i + 2/9*j + 2015/9*k, 4/9*j + 4264/9*k, 1556/3*k)] + [Fractional ideal (2/9 + 10/9*j + 182/3*k, 1/9*i + 2/3*j + 133/9*k, 4/3*j + 384*k, 1556/3*k), + Fractional ideal (2/9 + 2/9*j + 970/3*k, 1/9*i + 2/3*j + 3245/9*k, 4/3*j + 384*k, 1556/3*k), + Fractional ideal (2/9 + 1/9*i + 255*k, 1/3*i + 2/9*j + 3571/9*k, 4/9*j + 2708/9*k, 1556/3*k), + Fractional ideal (2/9 + 2/9*i + 2/9*j + 4388/9*k, 1/3*i + 2/9*j + 2015/9*k, 4/9*j + 4264/9*k, 1556/3*k)] sage: [(I.scale(1/9).free_module()/J.free_module()).invariants() for J in C] [(3, 3), (3, 3), (3, 3), (3, 3)] sage: Q. = QuaternionAlgebra(-2,-5) sage: I = Q.ideal([Q(1),i,j,k]) sage: I.cyclic_right_subideals(3) - [Fractional ideal (1 + 2*j, i + k, 3*j, 3*k), Fractional ideal (1 + j, i + 2*k, 3*j, 3*k), Fractional ideal (1 + 2*i, 3*i, j + 2*k, 3*k), Fractional ideal (1 + i, 3*i, j + k, 3*k)] + [Fractional ideal (1 + 2*j, i + k, 3*j, 3*k), + Fractional ideal (1 + j, i + 2*k, 3*j, 3*k), + Fractional ideal (1 + 2*i, 3*i, j + 2*k, 3*k), + Fractional ideal (1 + i, 3*i, j + k, 3*k)] The general algorithm is not yet implemented here:: sage: I.cyclic_right_subideals(3)[0].cyclic_right_subideals(3) Traceback (most recent call last): ... - NotImplementedError: general algorithm not implemented (The given basis vectors must be linearly independent.) + NotImplementedError: general algorithm not implemented + (The given basis vectors must be linearly independent.) """ R = self.right_order() Q = self.quaternion_algebra() @@ -3075,7 +3122,8 @@ def normalize_basis_at_p(e, p, B=QuaternionAlgebraElement_abstract.pair): sage: A. = QuaternionAlgebra(-1,-7) sage: e = [A(1), k, j, 1/2 + 1/2*i + 1/2*j + 1/2*k] sage: normalize_basis_at_p(e, 2) - [(1, 0), (1/2 + 1/2*i + 1/2*j + 1/2*k, 0), (-34/105*i - 463/735*j + 71/105*k, 1), (-34/105*i - 463/735*j + 71/105*k, 1)] + [(1, 0), (1/2 + 1/2*i + 1/2*j + 1/2*k, 0), (-34/105*i - 463/735*j + 71/105*k, 1), + (-34/105*i - 463/735*j + 71/105*k, 1)] """ N = len(e) diff --git a/src/sage/algebras/quatalg/quaternion_algebra_element.pyx b/src/sage/algebras/quatalg/quaternion_algebra_element.pyx index a1dd86a224c..b4c5eed5b49 100644 --- a/src/sage/algebras/quatalg/quaternion_algebra_element.pyx +++ b/src/sage/algebras/quatalg/quaternion_algebra_element.pyx @@ -1658,8 +1658,8 @@ cdef class QuaternionAlgebraElement_number_field(QuaternionAlgebraElement_abstra EXAMPLES:: - sage: K. = QQ[2^(1/5)]; Q. = QuaternionAlgebra(K,-a,a*17/3) - sage: Q([a,-2/3,a^2-1/2,a*2]) # implicit doctest + sage: K. = QQ[2^(1/5)]; Q. = QuaternionAlgebra(K,-a,a*17/3) # needs sage.symbolic + sage: Q([a,-2/3,a^2-1/2,a*2]) # implicit doctest # needs sage.symbolic a + (-2/3)*i + (a^2 - 1/2)*j + 2*a*k """ fmpz_poly_init(self.x) @@ -1688,8 +1688,8 @@ cdef class QuaternionAlgebraElement_number_field(QuaternionAlgebraElement_abstra """ EXAMPLES:: - sage: K. = QQ[2^(1/3)]; Q. = QuaternionAlgebra(K,-a,a+1) - sage: Q([a,-2/3,a^2-1/2,a*2]) # implicit doctest + sage: K. = QQ[2^(1/3)]; Q. = QuaternionAlgebra(K,-a,a+1) # needs sage.symbolic + sage: Q([a,-2/3,a^2-1/2,a*2]) # implicit doctest # needs sage.symbolic a + (-2/3)*i + (a^2 - 1/2)*j + 2*a*k """ self._parent = parent @@ -1732,6 +1732,7 @@ cdef class QuaternionAlgebraElement_number_field(QuaternionAlgebraElement_abstra """ EXAMPLES:: + sage: # needs sage.symbolic sage: K. = QQ[2^(1/3)]; Q. = QuaternionAlgebra(K,-a,a+1) sage: Q([a,-2/3,a^2-1/2,a*2]) a + (-2/3)*i + (a^2 - 1/2)*j + 2*a*k @@ -1773,6 +1774,7 @@ cdef class QuaternionAlgebraElement_number_field(QuaternionAlgebraElement_abstra """ EXAMPLES:: + sage: # needs sage.symbolic sage: K. = QQ[2^(1/3)]; Q. = QuaternionAlgebra(K, -3, a) sage: z = (i+j+k+a)^2; z a^2 + 4*a - 3 + 2*a*i + 2*a*j + 2*a*k @@ -1791,8 +1793,10 @@ cdef class QuaternionAlgebraElement_number_field(QuaternionAlgebraElement_abstra EXAMPLES:: + sage: # needs sage.symbolic sage: K. = QQ[2^(1/3)]; Q. = QuaternionAlgebra(K, -3, a) - sage: z = a + i + (2/3)*a^3*j + (1+a)*k; w = a - i - (2/3)*a^3*j + (1/3+a)*k + sage: z = a + i + (2/3)*a^3*j + (1+a)*k + sage: w = a - i - (2/3)*a^3*j + (1/3+a)*k sage: type(z) sage: z._add_(w) @@ -1863,8 +1867,10 @@ cdef class QuaternionAlgebraElement_number_field(QuaternionAlgebraElement_abstra EXAMPLES:: + sage: # needs sage.symbolic sage: K. = QQ[2^(1/3)]; Q. = QuaternionAlgebra(K, -3, a) - sage: z = a + i + (2/3)*a^3*j + (1+a)*k; w = a - i - (2/3)*a^3*j + (1/3+a)*k + sage: z = a + i + (2/3)*a^3*j + (1+a)*k + sage: w = a - i - (2/3)*a^3*j + (1/3+a)*k sage: type(z) sage: z._sub_(w) @@ -1912,8 +1918,10 @@ cdef class QuaternionAlgebraElement_number_field(QuaternionAlgebraElement_abstra EXAMPLES:: + sage: # needs sage.symbolic sage: K. = QQ[2^(1/3)]; Q. = QuaternionAlgebra(K, -3, a) - sage: z = a + i + (2/3)*a^3*j + (1+a)*k; w = a - i - (2/3)*a^3*j + (1/3+a)*k + sage: z = a + i + (2/3)*a^3*j + (1+a)*k + sage: w = a - i - (2/3)*a^3*j + (1/3+a)*k sage: type(z) sage: z._mul_(w) @@ -2060,11 +2068,13 @@ cdef class QuaternionAlgebraElement_number_field(QuaternionAlgebraElement_abstra TESTS:: + sage: # needs sage.symbolic sage: F = QQ[3^(1/3)] sage: a = F.gen() sage: K. = QuaternionAlgebra(F, -10 + a, -7 - a) sage: ((1/4 + 1/2 * i + a^3/7 * j + a/28 * k)*14*i)^3 # implicit doctest - 34503/2*a^2 + 132195/2*a + 791399/4 + (203/8*a^2 - 10591*a + 169225/4)*i + (-84695/4*a^2 + 483413/8*a + 18591/4)*j + (-87/2*a^2 + 18156*a - 72525)*k + 34503/2*a^2 + 132195/2*a + 791399/4 + (203/8*a^2 - 10591*a + 169225/4)*i + + (-84695/4*a^2 + 483413/8*a + 18591/4)*j + (-87/2*a^2 + 18156*a - 72525)*k """ # Note: this function changes the module-level global variables @@ -2137,6 +2147,7 @@ def unpickle_QuaternionAlgebraElement_number_field_v0(*args): """ EXAMPLES:: + sage: # needs sage.symbolic sage: K. = QQ[2^(1/3)]; Q. = QuaternionAlgebra(K, -3, a); z = i + j sage: f, t = z.__reduce__() sage: sage.algebras.quatalg.quaternion_algebra_element.unpickle_QuaternionAlgebraElement_number_field_v0(*t) diff --git a/src/sage/algebras/quaternion_algebra.py b/src/sage/algebras/quaternion_algebra.py index 0f577bbd0b9..4e92b73de69 100644 --- a/src/sage/algebras/quaternion_algebra.py +++ b/src/sage/algebras/quaternion_algebra.py @@ -1,3 +1,5 @@ +# sage.doctest: needs sage.modules + ############################################################ # Backwards compatible unpickling ############################################################ diff --git a/src/sage/algebras/quaternion_algebra_element.py b/src/sage/algebras/quaternion_algebra_element.py index ef527e2f269..ed0baaf0152 100644 --- a/src/sage/algebras/quaternion_algebra_element.py +++ b/src/sage/algebras/quaternion_algebra_element.py @@ -1,3 +1,5 @@ +# sage.doctest: needs sage.modules + ####################################################################### # Backward compatible unpickle functions ####################################################################### @@ -37,6 +39,7 @@ def unpickle_QuaternionAlgebraElement_number_field_v0(*args): """ EXAMPLES:: + sage: # needs sage.symbolic sage: K. = QQ[2^(1/3)]; Q. = QuaternionAlgebra(K, -3, a); z = i + j sage: f, t = z.__reduce__() sage: import sage.algebras.quaternion_algebra_element diff --git a/src/sage/algebras/rational_cherednik_algebra.py b/src/sage/algebras/rational_cherednik_algebra.py index 3b85c1e13a3..58b3ce5441d 100644 --- a/src/sage/algebras/rational_cherednik_algebra.py +++ b/src/sage/algebras/rational_cherednik_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules """ Rational Cherednik Algebras """ diff --git a/src/sage/algebras/schur_algebra.py b/src/sage/algebras/schur_algebra.py index ff960e56dd9..4fca609ecf7 100644 --- a/src/sage/algebras/schur_algebra.py +++ b/src/sage/algebras/schur_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.groups sage.modules r""" Schur algebras for `GL_n` diff --git a/src/sage/algebras/shuffle_algebra.py b/src/sage/algebras/shuffle_algebra.py index 5d383f8dfab..2db55513d66 100644 --- a/src/sage/algebras/shuffle_algebra.py +++ b/src/sage/algebras/shuffle_algebra.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" Shuffle algebras diff --git a/src/sage/algebras/splitting_algebra.py b/src/sage/algebras/splitting_algebra.py index 3b0dfce4586..8913932ffac 100644 --- a/src/sage/algebras/splitting_algebra.py +++ b/src/sage/algebras/splitting_algebra.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.libs.pari sage.modules r""" Splitting Algebras diff --git a/src/sage/algebras/steenrod/steenrod_algebra.py b/src/sage/algebras/steenrod/steenrod_algebra.py index 7c4d444f81c..993e94dc828 100644 --- a/src/sage/algebras/steenrod/steenrod_algebra.py +++ b/src/sage/algebras/steenrod/steenrod_algebra.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.combinat sage.modules r""" The Steenrod algebra @@ -552,8 +552,8 @@ def __init__(self, p=2, basis='milnor', **kwds): sage: TestSuite(SteenrodAlgebra(profile=[4,3,2,2,1])).run() sage: TestSuite(SteenrodAlgebra(basis='adem')).run() sage: TestSuite(SteenrodAlgebra(basis='wall')).run() - sage: TestSuite(SteenrodAlgebra(basis='arnonc')).run() # long time - sage: TestSuite(SteenrodAlgebra(basis='woody')).run() # long time + sage: TestSuite(SteenrodAlgebra(basis='arnonc')).run() # long time + sage: TestSuite(SteenrodAlgebra(basis='woody')).run() # long time sage: A3 = SteenrodAlgebra(3) sage: A3.category() Category of supercocommutative super hopf algebras @@ -562,7 +562,7 @@ def __init__(self, p=2, basis='milnor', **kwds): sage: TestSuite(SteenrodAlgebra(basis='adem', p=3)).run() sage: TestSuite(SteenrodAlgebra(basis='pst_llex', p=7)).run() # long time sage: TestSuite(SteenrodAlgebra(basis='comm_deg', p=5)).run() # long time - sage: TestSuite(SteenrodAlgebra(p=2, generic=True)).run() # long time + sage: TestSuite(SteenrodAlgebra(p=2, generic=True)).run() # long time Two Steenrod algebras are equal iff their associated primes, bases, and profile functions (if present) are equal. Because @@ -753,8 +753,8 @@ def _repr_(self): mod 3 Steenrod algebra, milnor basis sage: SteenrodAlgebra(2, basis='adem') mod 2 Steenrod algebra, serre-cartan basis - sage: B = SteenrodAlgebra(2003) - sage: B._repr_() + sage: B = SteenrodAlgebra(2003) # needs sage.rings.finite_rings + sage: B._repr_() # needs sage.rings.finite_rings 'mod 2003 Steenrod algebra, milnor basis' sage: SteenrodAlgebra(generic=True, basis='adem') generic mod 2 Steenrod algebra, serre-cartan basis @@ -1393,14 +1393,14 @@ def coproduct(self, x, algorithm='milnor'): INPUT: - - ``x`` -- element of self + - ``x`` -- element of ``self`` - - ``algorithm`` -- ``None`` or a string, either 'milnor' or - 'serre-cartan' (or anything which will be converted to one + - ``algorithm`` -- ``None`` or a string, either ``'milnor'`` or + ``'serre-cartan'`` (or anything which will be converted to one of these by the function :func:`get_basis_name `. - If ``None``, default to 'serre-cartan' if current basis is - 'serre-cartan'; otherwise use 'milnor'. + If ``None``, default to ``'serre-cartan'`` if current basis is + ``'serre-cartan'``; otherwise use ``'milnor'``. This calls :meth:`coproduct_on_basis` on the summands of ``x`` and extends linearly. @@ -1440,12 +1440,12 @@ def antipode_on_basis(self, t): INPUT: - - ``t`` -- tuple, the index of a basis element of self + - ``t`` -- tuple, the index of a basis element of ``self`` OUTPUT: the antipode of the corresponding basis element, - as an element of self. + as an element of ``self``. ALGORITHM: according to a result of Milnor's, the antipode of `\text{Sq}(n)` is the sum of all of the Milnor basis elements @@ -1490,7 +1490,7 @@ def antipode_on_basis(self, t): TESTS:: sage: Milnor = SteenrodAlgebra() - sage: all(x.antipode().antipode() == x for x in Milnor.basis(11)) # long time + sage: all(x.antipode().antipode() == x for x in Milnor.basis(11)) # long time True sage: A5 = SteenrodAlgebra(p=5, basis='adem') sage: all(x.antipode().antipode() == x for x in A5.basis(25)) @@ -1531,7 +1531,7 @@ def counit_on_basis(self, t): INPUT: - - ``t`` -- tuple, the index of a basis element of self + - ``t`` -- tuple, the index of a basis element of ``self`` EXAMPLES:: @@ -2237,7 +2237,9 @@ def basis(self, d=None): This does not print in a very helpful way, unfortunately:: sage: A7.basis() - Lazy family (Term map from basis key family of mod 7 Steenrod algebra, milnor basis to mod 7 Steenrod algebra, milnor basis(i))_{i in basis key family of mod 7 Steenrod algebra, milnor basis} + Lazy family (Term map from basis key family of mod 7 Steenrod algebra, milnor basis + to mod 7 Steenrod algebra, milnor basis(i))_{i in basis key family + of mod 7 Steenrod algebra, milnor basis} sage: for (idx,a) in zip((1,..,9),A7.basis()): ....: print("{} {}".format(idx, a)) 1 1 @@ -2251,7 +2253,8 @@ def basis(self, d=None): 9 Q_0 P(2) sage: D = SteenrodAlgebra(p=3, profile=([1], [2,2])) sage: sorted(D.basis()) - [1, P(1), P(2), Q_0, Q_0 P(1), Q_0 P(2), Q_0 Q_1, Q_0 Q_1 P(1), Q_0 Q_1 P(2), Q_1, Q_1 P(1), Q_1 P(2)] + [1, P(1), P(2), Q_0, Q_0 P(1), Q_0 P(2), Q_0 Q_1, + Q_0 Q_1 P(1), Q_0 Q_1 P(2), Q_1, Q_1 P(1), Q_1 P(2)] """ from sage.sets.family import Family if d is None: @@ -2573,7 +2576,7 @@ def pst(self,s,t): def ngens(self): r""" - Number of generators of self. + Number of generators of ``self``. OUTPUT: number or Infinity @@ -2601,7 +2604,7 @@ def ngens(self): 3 sage: SteenrodAlgebra(profile=[3,2,1], basis='pst').ngens() 3 - sage: SteenrodAlgebra(p=3, profile=[[3,2,1], [2,2,2,2]]).ngens() # A(3) at p=3 + sage: SteenrodAlgebra(p=3, profile=[[3,2,1], [2,2,2,2]]).ngens() # A(3) at p=3 4 sage: SteenrodAlgebra(profile=[1,2,1,1]).ngens() 5 @@ -2647,7 +2650,8 @@ def gens(self): sage: A3 = SteenrodAlgebra(3, 'adem') sage: A3.gens() - Lazy family ((i))_{i in Non negative integers} + Lazy family ((i))_{i in Non negative integers} sage: A3.gens()[0] beta sage: A3.gens()[1] @@ -2666,7 +2670,9 @@ def gens(self): sage: SteenrodAlgebra(p=5, profile=[[2,1], [2,2,2]]).gens() Family (Q_0, P(1), P(5)) sage: SteenrodAlgebra(profile=lambda n: n).gens() - Lazy family ((i))_{i in Non negative integers} + Lazy family ((i))_{i in Non negative integers} You may also use ``algebra_generators`` instead of ``gens``:: @@ -2932,16 +2938,16 @@ def top_class(self): EXAMPLES:: - sage: SteenrodAlgebra(2,profile=(3,2,1)).top_class() + sage: SteenrodAlgebra(2, profile=(3,2,1)).top_class() Sq(7,3,1) - sage: SteenrodAlgebra(3,profile=((2,2,1),(1,2,2,2,2))).top_class() + sage: SteenrodAlgebra(3, profile=((2,2,1),(1,2,2,2,2))).top_class() Q_1 Q_2 Q_3 Q_4 P(8,8,2) TESTS:: - sage: SteenrodAlgebra(2,profile=(3,2,1),basis='pst').top_class() + sage: SteenrodAlgebra(2, profile=(3,2,1), basis='pst').top_class() P^0_1 P^0_2 P^1_1 P^0_3 P^1_2 P^2_1 - sage: SteenrodAlgebra(5,profile=((0,),(2,1,2,2))).top_class() + sage: SteenrodAlgebra(5, profile=((0,),(2,1,2,2))).top_class() Q_0 Q_2 Q_3 sage: SteenrodAlgebra(5).top_class() Traceback (most recent call last): @@ -2953,12 +2959,12 @@ def top_class(self): but far from optimal for the 'pst' basis. Occasionally, it also gives an awkward leading coefficient:: - sage: SteenrodAlgebra(3,profile=((2,1),(1,2,2)),basis='pst').top_class() + sage: SteenrodAlgebra(3, profile=((2,1),(1,2,2)), basis='pst').top_class() 2 Q_1 Q_2 (P^0_1)^2 (P^0_2)^2 (P^1_1)^2 TESTS:: - sage: A=SteenrodAlgebra(2,profile=(3,2,1),basis='pst') + sage: A=SteenrodAlgebra(2, profile=(3,2,1), basis='pst') sage: A.top_class().parent() is A True """ @@ -3080,7 +3086,7 @@ def is_generic(self): True sage: SteenrodAlgebra(2).is_generic() False - sage: SteenrodAlgebra(2,generic=True).is_generic() + sage: SteenrodAlgebra(2, generic=True).is_generic() True """ return self._generic @@ -4146,7 +4152,8 @@ def SteenrodAlgebra(p=2, basis='milnor', generic='auto', **kwds): sage: EA = SteenrodAlgebra(p=2,generic=True) ; EA generic mod 2 Steenrod algebra, milnor basis sage: EA[8] - Vector space spanned by (Q_0 Q_2, Q_0 Q_1 P(2), P(1,1), P(4)) over Finite Field of size 2 + Vector space spanned by (Q_0 Q_2, Q_0 Q_1 P(2), P(1,1), P(4)) + over Finite Field of size 2 TESTS: @@ -4201,9 +4208,11 @@ def AA(n=None, p=2): sage: A() mod 2 Steenrod algebra, milnor basis sage: A(2) - sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis, profile function [3, 2, 1] + sub-Hopf algebra of mod 2 Steenrod algebra, milnor basis, + profile function [3, 2, 1] sage: A(2, p=5) - sub-Hopf algebra of mod 5 Steenrod algebra, milnor basis, profile function ([2, 1], [2, 2, 2]) + sub-Hopf algebra of mod 5 Steenrod algebra, milnor basis, + profile function ([2, 1], [2, 2, 2]) """ if n is None: return SteenrodAlgebra(p=p) diff --git a/src/sage/algebras/steenrod/steenrod_algebra_bases.py b/src/sage/algebras/steenrod/steenrod_algebra_bases.py index c289b284fe1..9c8cc0935c8 100644 --- a/src/sage/algebras/steenrod/steenrod_algebra_bases.py +++ b/src/sage/algebras/steenrod/steenrod_algebra_bases.py @@ -20,29 +20,29 @@ Monks [Mon1998]_ and Wood [Woo1998]_ for more information about them. For commutator bases, see the preprint by Palmieri and Zhang [PZ2008]_. -- 'milnor': Milnor basis. +- ``'milnor'``: Milnor basis. -- 'serre-cartan' or 'adem' or 'admissible': Serre-Cartan basis. +- ``'serre-cartan'`` or ``'adem'`` or ``'admissible'``: Serre-Cartan basis. Most of the rest of the bases are only defined when `p=2`. The only exceptions are the `P^s_t`-bases and the commutator bases, which are defined at all primes. -- 'wood_y': Wood's Y basis. +- ``'wood_y'``: Wood's Y basis. -- 'wood_z': Wood's Z basis. +- ``'wood_z'``: Wood's Z basis. -- 'wall', 'wall_long': Wall's basis. +- ``'wall'``, ``'wall_long'``: Wall's basis. -- 'arnon_a', 'arnon_a_long': Arnon's A basis. +- ``'arnon_a'``, ``'arnon_a_long'``: Arnon's A basis. -- 'arnon_c': Arnon's C basis. +- ``'arnon_c'``: Arnon's C basis. -- 'pst', 'pst_rlex', 'pst_llex', 'pst_deg', 'pst_revz': +- ``'pst'``, ``'pst_rlex'``, ``'pst_llex'``, ``'pst_deg'``, ``'pst_revz'``: various `P^s_t`-bases. -- 'comm', 'comm_rlex', 'comm_llex', 'comm_deg', 'comm_revz', - or these with '_long' appended: various commutator bases. +- ``'comm'``, ``'comm_rlex'``, ``'comm_llex'``, ``'comm_deg'``, ``'comm_revz'``, + or these with ``'_long'`` appended: various commutator bases. The main functions provided here are @@ -121,23 +121,24 @@ def convert_to_milnor_matrix(n, basis, p=2, generic='auto'): INPUT: - - ``n`` - non-negative integer, the dimension - - ``basis`` - string, the basis from which to convert - - ``p`` - positive prime number (optional, default 2) + - ``n`` -- non-negative integer, the dimension + - ``basis`` -- string, the basis from which to convert + - ``p`` -- positive prime number (optional, default 2) OUTPUT: - ``matrix`` - change-of-basis matrix, a square matrix over ``GF(p)`` + ``matrix`` -- change-of-basis matrix, a square matrix over `\GF{p}` EXAMPLES:: + sage: # needs sage.modules sage: from sage.algebras.steenrod.steenrod_algebra_bases import convert_to_milnor_matrix - sage: convert_to_milnor_matrix(5, 'adem') # indirect doctest + sage: convert_to_milnor_matrix(5, 'adem') # indirect doctest [0 1] [1 1] sage: convert_to_milnor_matrix(45, 'milnor') 111 x 111 dense matrix over Finite Field of size 2 (use the '.str()' method to see the entries) - sage: convert_to_milnor_matrix(12,'wall') + sage: convert_to_milnor_matrix(12, 'wall') [1 0 0 1 0 0 0] [1 1 0 0 0 1 0] [0 1 0 1 0 0 0] @@ -149,15 +150,16 @@ def convert_to_milnor_matrix(n, basis, p=2, generic='auto'): The function takes an optional argument, the prime `p` over which to work:: - sage: convert_to_milnor_matrix(17,'adem',3) + sage: # needs sage.modules + sage: convert_to_milnor_matrix(17, 'adem', 3) [0 0 1 1] [0 0 0 1] [1 1 1 1] [0 1 0 1] - sage: convert_to_milnor_matrix(48,'adem',5) + sage: convert_to_milnor_matrix(48, 'adem', 5) [0 1] [1 1] - sage: convert_to_milnor_matrix(36,'adem',3) + sage: convert_to_milnor_matrix(36, 'adem', 3) [0 0 1] [0 1 0] [1 2 0] @@ -182,20 +184,19 @@ def convert_to_milnor_matrix(n, basis, p=2, generic='auto'): def convert_from_milnor_matrix(n, basis, p=2, generic='auto'): r""" - Change-of-basis matrix, Milnor to 'basis', in dimension - `n`. + Change-of-basis matrix, Milnor to ``basis``, in dimension `n`. INPUT: - - ``n`` - non-negative integer, the dimension + - ``n`` -- non-negative integer, the dimension - - ``basis`` - string, the basis to which to convert + - ``basis`` -- string, the basis to which to convert - - ``p`` - positive prime number (optional, default 2) + - ``p`` -- positive prime number (optional, default 2) OUTPUT: - ``matrix`` - change-of-basis matrix, a square matrix over GF(p) + ``matrix`` -- change-of-basis matrix, a square matrix over `\GF{p}` .. note:: @@ -205,8 +206,9 @@ def convert_from_milnor_matrix(n, basis, p=2, generic='auto'): EXAMPLES:: + sage: # needs sage.modules sage: from sage.algebras.steenrod.steenrod_algebra_bases import convert_from_milnor_matrix, convert_to_milnor_matrix - sage: convert_from_milnor_matrix(12,'wall') + sage: convert_from_milnor_matrix(12, 'wall') [1 0 0 1 0 0 0] [0 0 1 1 0 0 0] [0 0 0 1 0 1 1] @@ -214,10 +216,10 @@ def convert_from_milnor_matrix(n, basis, p=2, generic='auto'): [1 0 1 0 1 0 0] [1 1 1 0 0 0 0] [1 0 1 0 1 0 1] - sage: convert_from_milnor_matrix(38,'serre_cartan') + sage: convert_from_milnor_matrix(38, 'serre_cartan') 72 x 72 dense matrix over Finite Field of size 2 (use the '.str()' method to see the entries) - sage: x = convert_to_milnor_matrix(20,'wood_y') - sage: y = convert_from_milnor_matrix(20,'wood_y') + sage: x = convert_to_milnor_matrix(20, 'wood_y') + sage: y = convert_from_milnor_matrix(20, 'wood_y') sage: x*y [1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] [0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] @@ -240,7 +242,7 @@ def convert_from_milnor_matrix(n, basis, p=2, generic='auto'): The function takes an optional argument, the prime `p` over which to work:: - sage: convert_from_milnor_matrix(17,'adem',3) + sage: convert_from_milnor_matrix(17, 'adem', 3) # needs sage.modules [2 1 1 2] [0 2 0 1] [1 2 0 0] @@ -259,17 +261,17 @@ def steenrod_algebra_basis(n, basis='milnor', p=2, **kwds): INPUT: - - ``n`` - non-negative integer - - ``basis`` - string, which basis to use (optional, default = 'milnor') - - ``p`` - positive prime number (optional, default = 2) - - ``profile`` - profile function (optional, default None). This + - ``n`` -- non-negative integer + - ``basis`` -- string, which basis to use (optional, default: ``'milnor'``) + - ``p`` -- positive prime number (optional, default: 2) + - ``profile`` -- profile function (optional, default: ``None``). This is just passed on to the functions :func:`milnor_basis` and :func:`pst_basis`. - - ``truncation_type`` - truncation type, either 0 or Infinity + - ``truncation_type`` -- truncation type, either 0 or Infinity (optional, default Infinity if no profile function is specified, 0 otherwise). This is just passed on to the function :func:`milnor_basis`. - - ``generic`` - boolean (optional, default = None) + - ``generic`` -- boolean (optional, default: ``None``) OUTPUT: @@ -280,25 +282,25 @@ def steenrod_algebra_basis(n, basis='milnor', p=2, **kwds): documentation for :mod:`sage.algebras.steenrod.steenrod_algebra` for details on each basis: - - 'milnor': Milnor basis. - - 'serre-cartan' or 'adem' or 'admissible': Serre-Cartan basis. - - 'pst', 'pst_rlex', 'pst_llex', 'pst_deg', 'pst_revz': + - ``'milnor'``: Milnor basis. + - ``'serre-cartan'`` or ``'adem'`` or ``'admissible'``: Serre-Cartan basis. + - ``'pst'``, ``'pst_rlex'``, ``'pst_llex'``, ``'pst_deg'``, ``'pst_revz'``: various `P^s_t`-bases. - - 'comm', 'comm_rlex', 'comm_llex', 'comm_deg', 'comm_revz', or - any of these with '_long' appended: various commutator bases. + - ``'comm'``, ``'comm_rlex'``, ``'comm_llex'``, ``'comm_deg'``, ``'comm_revz'``, or + any of these with ``'_long'`` appended: various commutator bases. The rest of these bases are only defined when `p=2`. - - 'wood_y': Wood's Y basis. - - 'wood_z': Wood's Z basis. - - 'wall' or 'wall_long': Wall's basis. - - 'arnon_a' or 'arnon_a_long': Arnon's A basis. - - 'arnon_c': Arnon's C basis. + - ``'wood_y'``: Wood's Y basis. + - ``'wood_z'``: Wood's Z basis. + - ``'wall'`` or ``'wall_long'``: Wall's basis. + - ``'arnon_a'`` or ``'arnon_a_long'``: Arnon's A basis. + - ``'arnon_c'``: Arnon's C basis. EXAMPLES:: sage: from sage.algebras.steenrod.steenrod_algebra_bases import steenrod_algebra_basis - sage: steenrod_algebra_basis(7,'milnor') # indirect doctest + sage: steenrod_algebra_basis(7, 'milnor') # indirect doctest ((0, 0, 1), (1, 2), (4, 1), (7,)) sage: steenrod_algebra_basis(5) # milnor basis is the default ((2, 1), (5,)) @@ -320,15 +322,15 @@ def steenrod_algebra_basis(n, basis='milnor', p=2, **kwds): Other bases:: - sage: steenrod_algebra_basis(7,'admissible') + sage: steenrod_algebra_basis(7, 'admissible') ((7,), (6, 1), (4, 2, 1), (5, 2)) - sage: steenrod_algebra_basis(13,'admissible',p=3) + sage: steenrod_algebra_basis(13, 'admissible', p=3) ((1, 3, 0), (0, 3, 1)) - sage: steenrod_algebra_basis(5,'wall') + sage: steenrod_algebra_basis(5, 'wall') (((2, 2), (0, 0)), ((1, 1), (1, 0))) - sage: steenrod_algebra_basis(5,'wall_long') + sage: steenrod_algebra_basis(5, 'wall_long') (((2, 2), (0, 0)), ((1, 1), (1, 0))) - sage: steenrod_algebra_basis(5,'pst-rlex') + sage: steenrod_algebra_basis(5, 'pst-rlex') (((0, 1), (2, 1)), ((1, 1), (0, 2))) """ from .steenrod_algebra_misc import get_basis_name @@ -375,14 +377,14 @@ def steenrod_algebra_basis(n, basis='milnor', p=2, **kwds): def restricted_partitions(n, l, no_repeats=False): """ - List of 'restricted' partitions of n: partitions with parts taken - from list. + List of 'restricted' partitions of `n`: partitions with parts taken + from list `l`. INPUT: - - ``n`` - non-negative integer - - ``l`` - list of positive integers - - ``no_repeats`` - boolean (optional, default = False), if True, + - ``n`` -- non-negative integer + - ``l`` -- list of positive integers + - ``no_repeats`` -- boolean (optional, default: ``False``), if ``True``, only return partitions with no repeated parts OUTPUT: list of lists @@ -406,10 +408,10 @@ def restricted_partitions(n, l, no_repeats=False): sage: restricted_partitions(10, [6,4,2], no_repeats=True) [[6, 4]] - 'l' may have repeated elements. If 'no_repeats' is False, this - has no effect. If 'no_repeats' is True, and if the repeated - elements appear consecutively in 'l', then each element may be - used only as many times as it appears in 'l':: + ``l`` may have repeated elements. If ``no_repeats`` is ``False``, this + has no effect. If ``no_repeats`` is ``True``, and if the repeated + elements appear consecutively in ``l``, then each element may be + used only as many times as it appears in ``l``:: sage: restricted_partitions(10, [6,4,2,2], no_repeats=True) [[6, 4], [6, 2, 2]] @@ -420,7 +422,7 @@ def restricted_partitions(n, l, no_repeats=False): are likely meaningless, containing several partitions more than once, for example.) - In the following examples, 'no_repeats' is False:: + In the following examples, ``no_repeats`` is ``False``:: sage: restricted_partitions(10, [6,4,2]) [[6, 4], [6, 2, 2], [4, 4, 2], [4, 2, 2, 2], [2, 2, 2, 2, 2]] @@ -448,25 +450,25 @@ def restricted_partitions(n, l, no_repeats=False): old_i = i return results -def xi_degrees(n,p=2, reverse=True): +def xi_degrees(n, p=2, reverse=True): r""" - Decreasing list of degrees of the xi_i's, starting in degree n. + Decreasing list of degrees of the `\xi_i`'s, starting in degree `n`. INPUT: - - `n` - integer - - `p` - prime number, optional (default 2) - - ``reverse`` - bool, optional (default True) + - ``n`` -- integer + - ``p`` -- prime number, optional (default: 2) + - ``reverse`` -- bool, optional (default: ``True``) - OUTPUT: ``list`` - list of integers + OUTPUT: ``list`` -- list of integers When `p=2`: decreasing list of the degrees of the `\xi_i`'s with - degree at most n. + degree at most `n`. At odd primes: decreasing list of these degrees, each divided by `2(p-1)`. - If ``reverse`` is False, then return an increasing list rather + If ``reverse`` is ``False``, then return an increasing list rather than a decreasing one. EXAMPLES:: @@ -475,9 +477,9 @@ def xi_degrees(n,p=2, reverse=True): [15, 7, 3, 1] sage: sage.algebras.steenrod.steenrod_algebra_bases.xi_degrees(17, reverse=False) [1, 3, 7, 15] - sage: sage.algebras.steenrod.steenrod_algebra_bases.xi_degrees(17,p=3) + sage: sage.algebras.steenrod.steenrod_algebra_bases.xi_degrees(17, p=3) [13, 4, 1] - sage: sage.algebras.steenrod.steenrod_algebra_bases.xi_degrees(400,p=17) + sage: sage.algebras.steenrod.steenrod_algebra_bases.xi_degrees(400, p=17) [307, 18, 1] """ from sage.rings.integer import Integer @@ -505,23 +507,23 @@ def milnor_basis(n, p=2, **kwds): INPUT: - - ``n`` - non-negative integer + - ``n`` -- non-negative integer - - ``p`` - positive prime number (optional, default 2) + - ``p`` -- positive prime number (optional, default 2) - - ``profile`` - profile function (optional, default None). + - ``profile`` - profile function (optional, default ``None``). Together with ``truncation_type``, specify the profile function - to be used; None means the profile function for the entire + to be used; ``None`` means the profile function for the entire Steenrod algebra. See :mod:`sage.algebras.steenrod.steenrod_algebra` and :func:`SteenrodAlgebra ` for information on profile functions. - - ``truncation_type`` - truncation type, either 0 or Infinity + - ``truncation_type`` -- truncation type, either 0 or Infinity (optional, default Infinity if no profile function is specified, 0 otherwise) - OUTPUT: tuple of mod p Milnor basis elements in dimension n + OUTPUT: tuple of mod `p` Milnor basis elements in dimension `n` At the prime 2, the Milnor basis consists of symbols of the form `\text{Sq}(m_1, m_2, ..., m_t)`, where each @@ -669,11 +671,11 @@ def serre_cartan_basis(n, p=2, bound=1, **kwds): INPUT: - - ``n`` - non-negative integer - - ``bound`` - positive integer (optional) - - ``prime`` - positive prime number (optional, default 2) + - ``n`` -- non-negative integer + - ``bound`` -- positive integer (optional) + - ``prime`` -- positive prime number (optional, default 2) - OUTPUT: tuple of mod p Serre-Cartan basis elements in dimension n + OUTPUT: tuple of mod `p` Serre-Cartan basis elements in dimension `n` The Serre-Cartan basis consists of 'admissible monomials in the Steenrod squares'. Thus at the prime 2, it consists of monomials @@ -694,8 +696,8 @@ def serre_cartan_basis(n, p=2, bound=1, **kwds): ((1, 5, 0, 1, 1), (1, 6, 1)) If optional argument ``bound`` is present, include only those monomials - whose last term is at least ``bound`` (when p=2), or those for which - `s_k - e_k \geq bound` (when p is odd). :: + whose last term is at least ``bound`` (when `p=2`), or those for which + `s_k - e_k \geq bound` (when `p` is odd). :: sage: serre_cartan_basis(7, bound=2) ((7,), (5, 2)) @@ -753,27 +755,28 @@ def atomic_basis(n, basis, **kwds): INPUT: - - ``n`` - non-negative integer - - ``basis`` - string, the name of the basis + - ``n`` -- non-negative integer - - ``profile`` - profile function (optional, default None). + - ``basis`` -- string, the name of the basis + + - ``profile`` -- profile function (optional, default: ``None``). Together with ``truncation_type``, specify the profile function - to be used; None means the profile function for the entire + to be used; ``None`` means the profile function for the entire Steenrod algebra. See :mod:`sage.algebras.steenrod.steenrod_algebra` and :func:`SteenrodAlgebra` for information on profile functions. - - ``truncation_type`` - truncation type, either 0 or Infinity + - ``truncation_type`` -- truncation type, either 0 or Infinity (optional, default Infinity if no profile function is specified, 0 otherwise). - OUTPUT: tuple of basis elements in dimension n + OUTPUT: tuple of basis elements in dimension `n` The atomic bases include Wood's Y and Z bases, Wall's basis, Arnon's A basis, the `P^s_t`-bases, and the commutator bases. (All of these bases are constructed similarly, hence their constructions have been consolidated into a single function. Also, - see the documentation for 'steenrod_algebra_basis' for + see the documentation for :func:`steenrod_algebra_basis` for descriptions of them.) For `P^s_t`-bases, you may also specify a profile function and truncation type; profile functions are ignored for the other bases. @@ -824,12 +827,12 @@ def atomic_basis(n, basis, **kwds): """ def degree_dictionary(n, basis): """ - Dictionary of atomic degrees for basis up to degree n. + Dictionary of atomic degrees for basis up to degree `n`. - The keys for the dictionary are the atomic degrees - the numbers of - the form 2^i (2^j - 1) - which are less than or equal to n. The value + The keys for the dictionary are the atomic degrees -- the numbers of + the form `2^i (2^j - 1)` -- which are less than or equal to `n`. The value associated to such a degree depends on basis; it has the form - (s,t), where (s,t) is a pair of integers which indexes the + `(s,t)`, where `(s,t)` is a pair of integers which indexes the corresponding element. """ dict = {} @@ -931,11 +934,11 @@ def arnonC_basis(n,bound=1): INPUT: - - ``n`` - non-negative integer + - ``n`` -- non-negative integer - - ``bound`` - positive integer (optional) + - ``bound`` -- positive integer (optional) - OUTPUT: tuple of basis elements in dimension n + OUTPUT: tuple of basis elements in dimension `n` The elements of Arnon's C basis are monomials of the form `\text{Sq}^{t_1} ... \text{Sq}^{t_m}` where for each @@ -978,22 +981,24 @@ def atomic_basis_odd(n, basis, p, **kwds): INPUT: - - ``n`` - non-negative integer - - ``basis`` - string, the name of the basis - - ``p`` - positive prime number + - ``n`` -- non-negative integer + + - ``basis`` -- string, the name of the basis + + - ``p`` -- positive prime number - - ``profile`` - profile function (optional, default None). + - ``profile`` -- profile function (optional, default: ``None``). Together with ``truncation_type``, specify the profile function - to be used; None means the profile function for the entire + to be used; ``None`` means the profile function for the entire Steenrod algebra. See :mod:`sage.algebras.steenrod.steenrod_algebra` and :func:`SteenrodAlgebra` for information on profile functions. - - ``truncation_type`` - truncation type, either 0 or Infinity + - ``truncation_type`` -- truncation type, either 0 or Infinity (optional, default Infinity if no profile function is specified, 0 otherwise). - OUTPUT: tuple of basis elements in dimension n + OUTPUT: tuple of basis elements in dimension `n` The only possible difference in the implementations for `P^s_t` bases and commutator bases is that the former make sense, and @@ -1091,8 +1096,8 @@ def steenrod_basis_error_check(dim, p, **kwds): INPUT: - - ``dim`` - non-negative integer - - ``p`` - positive prime number + - ``dim`` -- non-negative integer + - ``p`` -- positive prime number OUTPUT: None @@ -1100,7 +1105,7 @@ def steenrod_basis_error_check(dim, p, **kwds): if the change-of-basis matrices are invertible. If something goes wrong, an error message is printed. - This function checks at the prime ``p`` as the dimension goes up + This function checks at the prime `p` as the dimension goes up from 0 to ``dim``. If you set the Sage verbosity level to a positive integer (using @@ -1108,11 +1113,12 @@ def steenrod_basis_error_check(dim, p, **kwds): EXAMPLES:: + sage: # long time sage: from sage.algebras.steenrod.steenrod_algebra_bases import steenrod_basis_error_check - sage: steenrod_basis_error_check(15,2) # long time - sage: steenrod_basis_error_check(15,2,generic=True) # long time - sage: steenrod_basis_error_check(40,3) # long time - sage: steenrod_basis_error_check(80,5) # long time + sage: steenrod_basis_error_check(15, 2) + sage: steenrod_basis_error_check(15, 2, generic=True) + sage: steenrod_basis_error_check(40, 3) + sage: steenrod_basis_error_check(80, 5) """ from sage.misc.verbose import verbose generic = kwds.get('generic', p != 2) diff --git a/src/sage/algebras/steenrod/steenrod_algebra_mult.py b/src/sage/algebras/steenrod/steenrod_algebra_mult.py index 1fb52aba028..e2d48f616b7 100644 --- a/src/sage/algebras/steenrod/steenrod_algebra_mult.py +++ b/src/sage/algebras/steenrod/steenrod_algebra_mult.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.rings.finite_rings r""" Multiplication for elements of the Steenrod algebra diff --git a/src/sage/algebras/tensor_algebra.py b/src/sage/algebras/tensor_algebra.py index 664027ee6ae..a14ab916336 100644 --- a/src/sage/algebras/tensor_algebra.py +++ b/src/sage/algebras/tensor_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Tensor Algebras diff --git a/src/sage/algebras/weyl_algebra.py b/src/sage/algebras/weyl_algebra.py index 13604578430..b033a24065c 100644 --- a/src/sage/algebras/weyl_algebra.py +++ b/src/sage/algebras/weyl_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Weyl Algebras @@ -53,12 +54,12 @@ def repr_from_monomials(monomials, term_repr, use_latex=False): sage: from sage.algebras.weyl_algebra import repr_from_monomials sage: R. = QQ[] - sage: d = [(z, 4/7), (y, sqrt(2)), (x, -5)] - sage: repr_from_monomials(d, lambda m: repr(m)) + sage: d = [(z, 4/7), (y, sqrt(2)), (x, -5)] # needs sage.symbolic + sage: repr_from_monomials(d, lambda m: repr(m)) # needs sage.symbolic '4/7*z + sqrt(2)*y - 5*x' - sage: a = repr_from_monomials(d, lambda m: latex(m), True); a + sage: a = repr_from_monomials(d, lambda m: latex(m), True); a # needs sage.symbolic \frac{4}{7} z + \sqrt{2} y - 5 x - sage: type(a) + sage: type(a) # needs sage.symbolic The zero element:: @@ -90,6 +91,7 @@ def repr_from_monomials(monomials, term_repr, use_latex=False): Leading minus signs are dealt with appropriately:: + sage: # needs sage.symbolic sage: d = [(z, -4/7), (y, -sqrt(2)), (x, -5)] sage: repr_from_monomials(d, lambda m: repr(m)) '-4/7*z - sqrt(2)*y - 5*x' diff --git a/src/sage/algebras/yangian.py b/src/sage/algebras/yangian.py index 55bb61fccf5..8e19b92ba07 100644 --- a/src/sage/algebras/yangian.py +++ b/src/sage/algebras/yangian.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Yangians diff --git a/src/sage/algebras/yokonuma_hecke_algebra.py b/src/sage/algebras/yokonuma_hecke_algebra.py index df474b8d4f7..779beb95ffe 100644 --- a/src/sage/algebras/yokonuma_hecke_algebra.py +++ b/src/sage/algebras/yokonuma_hecke_algebra.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.modules """ Yokonuma-Hecke Algebras diff --git a/src/sage/arith/all.py b/src/sage/arith/all.py index c93e9f05bc9..3446336de68 100644 --- a/src/sage/arith/all.py +++ b/src/sage/arith/all.py @@ -1,35 +1,96 @@ from sage.misc.lazy_import import lazy_import -from .misc import (algdep, bernoulli, is_prime, is_prime_power, - is_pseudoprime, is_pseudoprime_power, - prime_powers, primes_first_n, eratosthenes, primes, - next_prime_power, next_probable_prime, next_prime, - previous_prime, previous_prime_power, random_prime, - divisors, sigma, gcd, GCD, xlcm, xgcd, xkcd, - inverse_mod, get_gcd, get_inverse_mod, power_mod, - rational_reconstruction, mqrr_rational_reconstruction, - trial_division, factor, prime_divisors, odd_part, prime_to_m_part, - is_square, is_squarefree, euler_phi, carmichael_lambda, crt, CRT, - CRT_list, CRT_basis, CRT_vectors, multinomial, multinomial_coefficients, - binomial, factorial, kronecker_symbol, kronecker, legendre_symbol, - primitive_root, nth_prime, quadratic_residues, moebius, - continuant, number_of_divisors, hilbert_symbol, hilbert_conductor, - hilbert_conductor_inverse, falling_factorial, rising_factorial, - integer_ceil, integer_floor, - two_squares, three_squares, four_squares, sum_of_k_squares, - subfactorial, is_power_of_two, differences, +from sage.arith.misc import ( + algdep, + bernoulli, + is_prime, + is_prime_power, + is_pseudoprime, + is_pseudoprime_power, + prime_powers, + primes_first_n, + eratosthenes, + primes, + next_prime_power, + next_probable_prime, + next_prime, + previous_prime, + previous_prime_power, + random_prime, + divisors, + sigma, + gcd, + GCD, + xlcm, + xgcd, + xkcd, + inverse_mod, + get_gcd, + get_inverse_mod, + power_mod, + rational_reconstruction, + mqrr_rational_reconstruction, + trial_division, + factor, + prime_divisors, + odd_part, + prime_to_m_part, + is_square, + is_squarefree, + euler_phi, + carmichael_lambda, + crt, + CRT, + CRT_list, + CRT_basis, + CRT_vectors, + multinomial, + multinomial_coefficients, + binomial, + factorial, + kronecker_symbol, + kronecker, + legendre_symbol, + primitive_root, + nth_prime, + quadratic_residues, + moebius, + continuant, + number_of_divisors, + hilbert_symbol, + hilbert_conductor, + hilbert_conductor_inverse, + falling_factorial, + rising_factorial, + integer_ceil, + integer_floor, + two_squares, + three_squares, + four_squares, + sum_of_k_squares, + subfactorial, + is_power_of_two, + differences, sort_complex_numbers_for_display, - fundamental_discriminant, squarefree_divisors, - radical, binomial_coefficients, jacobi_symbol, + fundamental_discriminant, + squarefree_divisors, + radical, + binomial_coefficients, + jacobi_symbol, dedekind_sum, - prime_factors, prime_range, valuation) + prime_factors, + prime_range, + valuation, +) -lazy_import('sage.arith.misc', ('Sigma', 'Moebius', 'Euler_Phi'), deprecation=30322) +lazy_import("sage.arith.misc", ("Sigma", "Moebius", "Euler_Phi"), deprecation=30322) + +from sage.arith.functions import lcm -from .functions import lcm LCM = lcm -from .srange import xsrange, srange, ellipsis_iter, ellipsis_range +from sage.arith.srange import xsrange, srange, ellipsis_iter, ellipsis_range + sxrange = xsrange σ = sigma diff --git a/src/sage/arith/misc.py b/src/sage/arith/misc.py index aa0174580a1..5d3ef49f7c5 100644 --- a/src/sage/arith/misc.py +++ b/src/sage/arith/misc.py @@ -3584,10 +3584,6 @@ def CRT_basis(moduli): `a_i` is congruent to 1 modulo `m_i` and to 0 modulo `m_j` for `j\not=i`. - .. note:: - - The pairwise coprimality of the input is not checked. - EXAMPLES:: sage: a1 = ZZ(mod(42,5)) @@ -3610,7 +3606,14 @@ def CRT_basis(moduli): if n == 0: return [] M = prod(moduli) - return [((xgcd(m,M//m)[2])*(M//m)) % M for m in moduli] + cs = [] + for m in moduli: + Mm = M // m + d, _, v = xgcd(m, Mm) + if not d.is_one(): + raise ValueError('moduli must be coprime') + cs.append((v * Mm) % M) + return cs def CRT_vectors(X, moduli): diff --git a/src/sage/arith/power.pyx b/src/sage/arith/power.pyx index 65090f23c23..2b4cbd099d1 100644 --- a/src/sage/arith/power.pyx +++ b/src/sage/arith/power.pyx @@ -17,7 +17,7 @@ square-and-multiply algorithm. from cysignals.signals cimport sig_check -from .long cimport integer_check_long +from sage.arith.long cimport integer_check_long cpdef generic_power(a, n) noexcept: diff --git a/src/sage/categories/action.pxd b/src/sage/categories/action.pxd index 444fcc1f38f..a22a37cc22a 100644 --- a/src/sage/categories/action.pxd +++ b/src/sage/categories/action.pxd @@ -1,7 +1,7 @@ from sage.structure.element cimport Element -from .morphism cimport Morphism -from .map cimport Map -from .functor cimport Functor +from sage.categories.morphism cimport Morphism +from sage.categories.map cimport Map +from sage.categories.functor cimport Functor cdef class Action(Functor): cdef readonly G diff --git a/src/sage/categories/action.pyx b/src/sage/categories/action.pyx index 46effeecc42..b164e9213ce 100644 --- a/src/sage/categories/action.pyx +++ b/src/sage/categories/action.pyx @@ -56,13 +56,13 @@ AUTHOR: from cpython.tuple cimport PyTuple_GET_ITEM -from .functor cimport Functor -from .morphism cimport Morphism -from .map cimport Map +from sage.categories.functor cimport Functor +from sage.categories.morphism cimport Morphism +from sage.categories.map cimport Map from sage.structure.element cimport parent from sage.structure.parent cimport Parent -from . import homset +from sage.categories import homset from weakref import ref diff --git a/src/sage/categories/algebra_ideals.py b/src/sage/categories/algebra_ideals.py index 1d6e3775e7b..c33fa0ef7b0 100644 --- a/src/sage/categories/algebra_ideals.py +++ b/src/sage/categories/algebra_ideals.py @@ -10,10 +10,10 @@ # https://www.gnu.org/licenses/ # ***************************************************************************** -from .algebra_modules import AlgebraModules -from .algebras import Algebras -from .rings import Rings -from .category_types import Category_ideal +from sage.categories.algebra_modules import AlgebraModules +from sage.categories.algebras import Algebras +from sage.categories.category_types import Category_ideal +from sage.categories.rings import Rings class AlgebraIdeals(Category_ideal): diff --git a/src/sage/categories/algebra_modules.py b/src/sage/categories/algebra_modules.py index 7be7de2c471..e827cc7130d 100644 --- a/src/sage/categories/algebra_modules.py +++ b/src/sage/categories/algebra_modules.py @@ -10,10 +10,11 @@ # http://www.gnu.org/licenses/ #****************************************************************************** -from .category_types import Category_module -from .commutative_algebras import CommutativeAlgebras -from .commutative_rings import CommutativeRings -from .modules import Modules +from sage.categories.category_types import Category_module +from sage.categories.commutative_algebras import CommutativeAlgebras +from sage.categories.commutative_rings import CommutativeRings +from sage.categories.modules import Modules + class AlgebraModules(Category_module): """ diff --git a/src/sage/categories/algebras_with_basis.py b/src/sage/categories/algebras_with_basis.py index 28177a1ff45..dfd693a9520 100644 --- a/src/sage/categories/algebras_with_basis.py +++ b/src/sage/categories/algebras_with_basis.py @@ -9,13 +9,13 @@ # https://www.gnu.org/licenses/ #****************************************************************************** +from sage.categories.cartesian_product import CartesianProductsCategory +from sage.categories.category_with_axiom import CategoryWithAxiom_over_base_ring +from sage.categories.tensor import TensorProductsCategory, tensor +from sage.categories.unital_algebras import UnitalAlgebras from sage.misc.cachefunc import cached_method from sage.misc.lazy_attribute import lazy_attribute from sage.misc.lazy_import import LazyImport -from sage.categories.tensor import TensorProductsCategory, tensor -from sage.categories.cartesian_product import CartesianProductsCategory -from sage.categories.category_with_axiom import CategoryWithAxiom_over_base_ring -from .unital_algebras import UnitalAlgebras class AlgebrasWithBasis(CategoryWithAxiom_over_base_ring): diff --git a/src/sage/categories/all.py b/src/sage/categories/all.py index 110a9954da3..9c2b8bd6518 100644 --- a/src/sage/categories/all.py +++ b/src/sage/categories/all.py @@ -27,128 +27,128 @@ from sage.misc.namespace_package import install_doc install_doc(__package__, __doc__) -from . import primer +from sage.categories import primer from sage.misc.lazy_import import lazy_import -from .all__sagemath_objects import * +from sage.categories.all__sagemath_objects import * -from .basic import * +from sage.categories.basic import * -from .chain_complexes import ChainComplexes, HomologyFunctor +from sage.categories.chain_complexes import ChainComplexes, HomologyFunctor -from .simplicial_complexes import SimplicialComplexes +from sage.categories.simplicial_complexes import SimplicialComplexes -from .tensor import tensor -from .signed_tensor import tensor_signed +from sage.categories.tensor import tensor +from sage.categories.signed_tensor import tensor_signed -from .g_sets import GSets -from .pointed_sets import PointedSets +from sage.categories.g_sets import GSets +from sage.categories.pointed_sets import PointedSets -from .sets_with_grading import SetsWithGrading +from sage.categories.sets_with_grading import SetsWithGrading -from .groupoid import Groupoid -from .permutation_groups import PermutationGroups +from sage.categories.groupoid import Groupoid +from sage.categories.permutation_groups import PermutationGroups # enumerated sets -from .finite_sets import FiniteSets -from .enumerated_sets import EnumeratedSets -from .finite_enumerated_sets import FiniteEnumeratedSets -from .infinite_enumerated_sets import InfiniteEnumeratedSets +from sage.categories.finite_sets import FiniteSets +from sage.categories.enumerated_sets import EnumeratedSets +from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets +from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets # posets -from .posets import Posets -from .finite_posets import FinitePosets -from .lattice_posets import LatticePosets -from .finite_lattice_posets import FiniteLatticePosets +from sage.categories.posets import Posets +from sage.categories.finite_posets import FinitePosets +from sage.categories.lattice_posets import LatticePosets +from sage.categories.finite_lattice_posets import FiniteLatticePosets # finite groups/... -from .finite_semigroups import FiniteSemigroups -from .finite_monoids import FiniteMonoids -from .finite_groups import FiniteGroups -from .finite_permutation_groups import FinitePermutationGroups +from sage.categories.finite_semigroups import FiniteSemigroups +from sage.categories.finite_monoids import FiniteMonoids +from sage.categories.finite_groups import FiniteGroups +from sage.categories.finite_permutation_groups import FinitePermutationGroups # fields -from .number_fields import NumberFields -from .function_fields import FunctionFields +from sage.categories.number_fields import NumberFields +from sage.categories.function_fields import FunctionFields # modules -from .left_modules import LeftModules -from .right_modules import RightModules -from .bimodules import Bimodules +from sage.categories.left_modules import LeftModules +from sage.categories.right_modules import RightModules +from sage.categories.bimodules import Bimodules -from .modules import Modules +from sage.categories.modules import Modules RingModules = Modules -from .vector_spaces import VectorSpaces +from sage.categories.vector_spaces import VectorSpaces # (hopf) algebra structures -from .algebras import Algebras -from .commutative_algebras import CommutativeAlgebras -from .coalgebras import Coalgebras -from .bialgebras import Bialgebras -from .hopf_algebras import HopfAlgebras -from .lie_algebras import LieAlgebras +from sage.categories.algebras import Algebras +from sage.categories.commutative_algebras import CommutativeAlgebras +from sage.categories.coalgebras import Coalgebras +from sage.categories.bialgebras import Bialgebras +from sage.categories.hopf_algebras import HopfAlgebras +from sage.categories.lie_algebras import LieAlgebras # specific algebras -from .monoid_algebras import MonoidAlgebras -from .group_algebras import GroupAlgebras -from .matrix_algebras import MatrixAlgebras +from sage.categories.monoid_algebras import MonoidAlgebras +from sage.categories.group_algebras import GroupAlgebras +from sage.categories.matrix_algebras import MatrixAlgebras # ideals -from .ring_ideals import RingIdeals +from sage.categories.ring_ideals import RingIdeals Ideals = RingIdeals -from .commutative_ring_ideals import CommutativeRingIdeals -from .algebra_modules import AlgebraModules -from .algebra_ideals import AlgebraIdeals -from .commutative_algebra_ideals import CommutativeAlgebraIdeals +from sage.categories.commutative_ring_ideals import CommutativeRingIdeals +from sage.categories.algebra_modules import AlgebraModules +from sage.categories.algebra_ideals import AlgebraIdeals +from sage.categories.commutative_algebra_ideals import CommutativeAlgebraIdeals # schemes and varieties -from .modular_abelian_varieties import ModularAbelianVarieties -from .schemes import Schemes +from sage.categories.modular_abelian_varieties import ModularAbelianVarieties +from sage.categories.schemes import Schemes # * with basis -from .modules_with_basis import ModulesWithBasis +from sage.categories.modules_with_basis import ModulesWithBasis FreeModules = ModulesWithBasis -from .hecke_modules import HeckeModules -from .algebras_with_basis import AlgebrasWithBasis -from .coalgebras_with_basis import CoalgebrasWithBasis -from .bialgebras_with_basis import BialgebrasWithBasis -from .hopf_algebras_with_basis import HopfAlgebrasWithBasis +from sage.categories.hecke_modules import HeckeModules +from sage.categories.algebras_with_basis import AlgebrasWithBasis +from sage.categories.coalgebras_with_basis import CoalgebrasWithBasis +from sage.categories.bialgebras_with_basis import BialgebrasWithBasis +from sage.categories.hopf_algebras_with_basis import HopfAlgebrasWithBasis # finite dimensional * with basis -from .finite_dimensional_modules_with_basis import FiniteDimensionalModulesWithBasis -from .finite_dimensional_algebras_with_basis import FiniteDimensionalAlgebrasWithBasis -from .finite_dimensional_coalgebras_with_basis import FiniteDimensionalCoalgebrasWithBasis -from .finite_dimensional_bialgebras_with_basis import FiniteDimensionalBialgebrasWithBasis -from .finite_dimensional_hopf_algebras_with_basis import FiniteDimensionalHopfAlgebrasWithBasis +from sage.categories.finite_dimensional_modules_with_basis import FiniteDimensionalModulesWithBasis +from sage.categories.finite_dimensional_algebras_with_basis import FiniteDimensionalAlgebrasWithBasis +from sage.categories.finite_dimensional_coalgebras_with_basis import FiniteDimensionalCoalgebrasWithBasis +from sage.categories.finite_dimensional_bialgebras_with_basis import FiniteDimensionalBialgebrasWithBasis +from sage.categories.finite_dimensional_hopf_algebras_with_basis import FiniteDimensionalHopfAlgebrasWithBasis # graded * -from .graded_modules import GradedModules -from .graded_algebras import GradedAlgebras -from .graded_coalgebras import GradedCoalgebras -from .graded_bialgebras import GradedBialgebras -from .graded_hopf_algebras import GradedHopfAlgebras +from sage.categories.graded_modules import GradedModules +from sage.categories.graded_algebras import GradedAlgebras +from sage.categories.graded_coalgebras import GradedCoalgebras +from sage.categories.graded_bialgebras import GradedBialgebras +from sage.categories.graded_hopf_algebras import GradedHopfAlgebras # graded * with basis -from .graded_modules_with_basis import GradedModulesWithBasis -from .graded_algebras_with_basis import GradedAlgebrasWithBasis -from .graded_coalgebras_with_basis import GradedCoalgebrasWithBasis -from .graded_bialgebras_with_basis import GradedBialgebrasWithBasis -from .graded_hopf_algebras_with_basis import GradedHopfAlgebrasWithBasis +from sage.categories.graded_modules_with_basis import GradedModulesWithBasis +from sage.categories.graded_algebras_with_basis import GradedAlgebrasWithBasis +from sage.categories.graded_coalgebras_with_basis import GradedCoalgebrasWithBasis +from sage.categories.graded_bialgebras_with_basis import GradedBialgebrasWithBasis +from sage.categories.graded_hopf_algebras_with_basis import GradedHopfAlgebrasWithBasis # Coxeter groups -from .coxeter_groups import CoxeterGroups +from sage.categories.coxeter_groups import CoxeterGroups lazy_import('sage.categories.finite_coxeter_groups', 'FiniteCoxeterGroups') -from .weyl_groups import WeylGroups -from .finite_weyl_groups import FiniteWeylGroups -from .affine_weyl_groups import AffineWeylGroups +from sage.categories.weyl_groups import WeylGroups +from sage.categories.finite_weyl_groups import FiniteWeylGroups +from sage.categories.affine_weyl_groups import AffineWeylGroups # crystal bases -from .crystals import Crystals -from .highest_weight_crystals import HighestWeightCrystals -from .regular_crystals import RegularCrystals -from .finite_crystals import FiniteCrystals -from .classical_crystals import ClassicalCrystals +from sage.categories.crystals import Crystals +from sage.categories.highest_weight_crystals import HighestWeightCrystals +from sage.categories.regular_crystals import RegularCrystals +from sage.categories.finite_crystals import FiniteCrystals +from sage.categories.classical_crystals import ClassicalCrystals # polyhedra lazy_import('sage.categories.polyhedra', 'PolyhedralSets') diff --git a/src/sage/categories/all__sagemath_objects.py b/src/sage/categories/all__sagemath_objects.py index dee0881d787..d87b4a1d20e 100644 --- a/src/sage/categories/all__sagemath_objects.py +++ b/src/sage/categories/all__sagemath_objects.py @@ -4,28 +4,25 @@ # Resolve a circular import so that "import sage.categories.all" can succeed # in initializing the category system. -import sage.structure.category_object # imports sage.categories.category +import sage.structure.category_object # imports sage.categories.category -# Small part of "from .basic import *": -from .objects import Objects -from .sets_cat import Sets, EmptySetError +# Small part of "from sage.categories.basic import *": +from sage.categories.objects import Objects +from sage.categories.sets_cat import Sets, EmptySetError -from .category import Category +from sage.categories.category import Category -from .category_types import Elements +from sage.categories.category_types import Elements -from .cartesian_product import cartesian_product +from sage.categories.cartesian_product import cartesian_product -from .functor import (ForgetfulFunctor, - IdentityFunctor) +from sage.categories.functor import ForgetfulFunctor, IdentityFunctor -from .homset import (Hom, hom, - End, end, - Homset, HomsetWithBase) +from sage.categories.homset import Hom, hom, End, end, Homset, HomsetWithBase -from .morphism import Morphism +from sage.categories.morphism import Morphism -from .realizations import Realizations +from sage.categories.realizations import Realizations -from .sets_with_partial_maps import SetsWithPartialMaps +from sage.categories.sets_with_partial_maps import SetsWithPartialMaps diff --git a/src/sage/categories/basic.py b/src/sage/categories/basic.py index b3cf1d3a29c..f3574db469d 100644 --- a/src/sage/categories/basic.py +++ b/src/sage/categories/basic.py @@ -2,49 +2,59 @@ A subset of sage.categories.all with just the basic categories needed for sage startup (i.e. to define ZZ, QQ, ...). """ -#***************************************************************************** +# ***************************************************************************** # Copyright (C) 2008-2009 Nicolas M. Thiery # # Distributed under the terms of the GNU General Public License (GPL) # http://www.gnu.org/licenses/ -#****************************************************************************** +# ****************************************************************************** + +from sage.categories.objects import Objects +from sage.categories.sets_cat import Sets, EmptySetError +from sage.categories.posets import Posets -from .objects import Objects -from .sets_cat import Sets, EmptySetError -from .posets import Posets # For backward compatibility; will be deprecated at some point PartiallyOrderedSets = Posets OrderedSets = Posets -from .additive_magmas import AdditiveMagmas -from .commutative_additive_semigroups import CommutativeAdditiveSemigroups -from .commutative_additive_monoids import CommutativeAdditiveMonoids -from .commutative_additive_groups import CommutativeAdditiveGroups +from sage.categories.additive_magmas import AdditiveMagmas +from sage.categories.commutative_additive_semigroups import ( + CommutativeAdditiveSemigroups, +) +from sage.categories.commutative_additive_monoids import CommutativeAdditiveMonoids +from sage.categories.commutative_additive_groups import CommutativeAdditiveGroups + +from sage.categories.magmas import Magmas +from sage.categories.semigroups import Semigroups +from sage.categories.monoids import Monoids +from sage.categories.groups import Groups +from sage.categories.partially_ordered_monoids import PartiallyOrderedMonoids -from .magmas import Magmas -from .semigroups import Semigroups -from .monoids import Monoids -from .groups import Groups -from .partially_ordered_monoids import PartiallyOrderedMonoids # For backward compatibility; might be deprecated at some point OrderedMonoids = PartiallyOrderedMonoids -from .rngs import Rngs -from .semirings import Semirings -from .rings import Rings -from .domains import Domains -from .division_rings import DivisionRings - -from .commutative_rings import CommutativeRings -from .integral_domains import IntegralDomains -from .gcd_domains import GcdDomains -from .principal_ideal_domains import PrincipalIdealDomains -from .euclidean_domains import EuclideanDomains -from .unique_factorization_domains import UniqueFactorizationDomains -from .complete_discrete_valuation import CompleteDiscreteValuationRings - -from .fields import Fields -from .quotient_fields import QuotientFields -from .finite_fields import FiniteFields -from .discrete_valuation import DiscreteValuationRings, DiscreteValuationFields -from .complete_discrete_valuation import CompleteDiscreteValuationRings, CompleteDiscreteValuationFields +from sage.categories.rngs import Rngs +from sage.categories.semirings import Semirings +from sage.categories.rings import Rings +from sage.categories.domains import Domains +from sage.categories.division_rings import DivisionRings + +from sage.categories.commutative_rings import CommutativeRings +from sage.categories.integral_domains import IntegralDomains +from sage.categories.gcd_domains import GcdDomains +from sage.categories.principal_ideal_domains import PrincipalIdealDomains +from sage.categories.euclidean_domains import EuclideanDomains +from sage.categories.unique_factorization_domains import UniqueFactorizationDomains +from sage.categories.complete_discrete_valuation import CompleteDiscreteValuationRings + +from sage.categories.fields import Fields +from sage.categories.quotient_fields import QuotientFields +from sage.categories.finite_fields import FiniteFields +from sage.categories.discrete_valuation import ( + DiscreteValuationRings, + DiscreteValuationFields, +) +from sage.categories.complete_discrete_valuation import ( + CompleteDiscreteValuationRings, + CompleteDiscreteValuationFields, +) diff --git a/src/sage/categories/category_types.py b/src/sage/categories/category_types.py index 3c1aae55c5a..4ead4f23530 100644 --- a/src/sage/categories/category_types.py +++ b/src/sage/categories/category_types.py @@ -14,9 +14,10 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from sage.misc.unknown import Unknown -from .category import JoinCategory, Category, CategoryWithParameters +from sage.categories.category import Category, CategoryWithParameters, JoinCategory from sage.misc.lazy_import import lazy_import +from sage.misc.unknown import Unknown + lazy_import('sage.categories.objects', 'Objects') lazy_import('sage.misc.latex', 'latex') @@ -198,6 +199,7 @@ def _test_category_over_bases(self, **options): """ tester = self._tester(**options) from sage.categories.category_singleton import Category_singleton + from .bimodules import Bimodules from .schemes import Schemes for cat in self.super_categories(): diff --git a/src/sage/categories/chain_complexes.py b/src/sage/categories/chain_complexes.py index db9c5d03f56..9616aa608c4 100644 --- a/src/sage/categories/chain_complexes.py +++ b/src/sage/categories/chain_complexes.py @@ -13,11 +13,12 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from .category_types import Category_module -from .commutative_additive_groups import CommutativeAdditiveGroups -from .functor import Functor +from sage.categories.category_types import Category_module +from sage.categories.commutative_additive_groups import CommutativeAdditiveGroups +from sage.categories.functor import Functor from sage.misc.abstract_method import abstract_method + ############################################################# # ChainComplex ############################################################# @@ -259,8 +260,8 @@ def _apply_functor_to_morphism(self, f): sage: id_star(one) [one] """ - from .morphism import SetMorphism - from .homset import Hom + from sage.categories.homset import Hom + from sage.categories.morphism import SetMorphism domain = f.domain() codomain = f.codomain() diff --git a/src/sage/categories/coalgebras.py b/src/sage/categories/coalgebras.py index abe36aef0bb..b69fdf29784 100644 --- a/src/sage/categories/coalgebras.py +++ b/src/sage/categories/coalgebras.py @@ -10,14 +10,14 @@ # https://www.gnu.org/licenses/ # ***************************************************************************** -from .category_types import Category_over_base_ring -from sage.categories.modules import Modules +from sage.categories.category_types import Category_over_base_ring from sage.categories.category_with_axiom import CategoryWithAxiom_over_base_ring -from sage.categories.tensor import TensorProductsCategory from sage.categories.dual import DualObjectsCategory from sage.categories.filtered_modules import FilteredModulesCategory -from sage.categories.super_modules import SuperModulesCategory +from sage.categories.modules import Modules from sage.categories.realizations import RealizationsCategory +from sage.categories.super_modules import SuperModulesCategory +from sage.categories.tensor import TensorProductsCategory from sage.categories.with_realizations import WithRealizationsCategory from sage.misc.abstract_method import abstract_method from sage.misc.cachefunc import cached_method diff --git a/src/sage/categories/commutative_algebra_ideals.py b/src/sage/categories/commutative_algebra_ideals.py index 070503ae6c8..e47e1c4f87e 100644 --- a/src/sage/categories/commutative_algebra_ideals.py +++ b/src/sage/categories/commutative_algebra_ideals.py @@ -10,10 +10,10 @@ # http://www.gnu.org/licenses/ #****************************************************************************** -from .algebra_ideals import AlgebraIdeals -from .category_types import Category_ideal, Category_in_ambient -from .commutative_algebras import CommutativeAlgebras -from .commutative_rings import CommutativeRings +from sage.categories.algebra_ideals import AlgebraIdeals +from sage.categories.category_types import Category_ideal, Category_in_ambient +from sage.categories.commutative_algebras import CommutativeAlgebras +from sage.categories.commutative_rings import CommutativeRings class CommutativeAlgebraIdeals(Category_ideal): diff --git a/src/sage/categories/commutative_ring_ideals.py b/src/sage/categories/commutative_ring_ideals.py index 5aef6d7d31d..8659b0c793b 100644 --- a/src/sage/categories/commutative_ring_ideals.py +++ b/src/sage/categories/commutative_ring_ideals.py @@ -10,9 +10,10 @@ # http://www.gnu.org/licenses/ #****************************************************************************** -from .category_types import Category_ideal +from sage.categories.category_types import Category_ideal from sage.categories.commutative_rings import CommutativeRings -from .ring_ideals import RingIdeals +from sage.categories.ring_ideals import RingIdeals + class CommutativeRingIdeals(Category_ideal): """ diff --git a/src/sage/categories/complete_discrete_valuation.py b/src/sage/categories/complete_discrete_valuation.py index 442360465a1..7376d947530 100644 --- a/src/sage/categories/complete_discrete_valuation.py +++ b/src/sage/categories/complete_discrete_valuation.py @@ -9,10 +9,13 @@ #************************************************************************** +from sage.categories.category_singleton import Category_singleton +from sage.categories.discrete_valuation import ( + DiscreteValuationFields, + DiscreteValuationRings, +) from sage.misc.abstract_method import abstract_method -from sage.categories.category_singleton import Category_singleton -from .discrete_valuation import DiscreteValuationRings, DiscreteValuationFields #from sage.misc.cachefunc import cached_method diff --git a/src/sage/categories/finite_dimensional_semisimple_algebras_with_basis.py b/src/sage/categories/finite_dimensional_semisimple_algebras_with_basis.py index 531ee7145a4..da4b297ddde 100644 --- a/src/sage/categories/finite_dimensional_semisimple_algebras_with_basis.py +++ b/src/sage/categories/finite_dimensional_semisimple_algebras_with_basis.py @@ -9,10 +9,11 @@ # http://www.gnu.org/licenses/ #****************************************************************************** +from sage.categories.algebras import Algebras from sage.categories.category_with_axiom import CategoryWithAxiom_over_base_ring +from sage.categories.semisimple_algebras import SemisimpleAlgebras from sage.misc.cachefunc import cached_method -from .algebras import Algebras -from .semisimple_algebras import SemisimpleAlgebras + class FiniteDimensionalSemisimpleAlgebrasWithBasis(CategoryWithAxiom_over_base_ring): """ diff --git a/src/sage/categories/functor.pyx b/src/sage/categories/functor.pyx index c25e99f2164..32bd079fc73 100644 --- a/src/sage/categories/functor.pyx +++ b/src/sage/categories/functor.pyx @@ -33,7 +33,7 @@ AUTHORS: # https://www.gnu.org/licenses/ # **************************************************************************** -from . import category +from sage.categories import category def _Functor_unpickle(Cl, D, domain, codomain): diff --git a/src/sage/categories/g_sets.py b/src/sage/categories/g_sets.py index 7fd09bafea4..5967fcf7d5f 100644 --- a/src/sage/categories/g_sets.py +++ b/src/sage/categories/g_sets.py @@ -11,7 +11,8 @@ #****************************************************************************** from sage.categories.category import Category -from .sets_cat import Sets +from sage.categories.sets_cat import Sets + ############################################################# # GSets diff --git a/src/sage/categories/groupoid.py b/src/sage/categories/groupoid.py index 850e63a2c09..95af5df164c 100644 --- a/src/sage/categories/groupoid.py +++ b/src/sage/categories/groupoid.py @@ -12,7 +12,8 @@ #****************************************************************************** from sage.categories.category import CategoryWithParameters -from .sets_cat import Sets +from sage.categories.sets_cat import Sets + class Groupoid(CategoryWithParameters): """ diff --git a/src/sage/categories/homset.py b/src/sage/categories/homset.py index 2a8b8aeedeb..d2203299512 100644 --- a/src/sage/categories/homset.py +++ b/src/sage/categories/homset.py @@ -65,12 +65,9 @@ # https://www.gnu.org/licenses/ # **************************************************************************** +from sage.categories import morphism from sage.categories.category import Category, JoinCategory -from . import morphism -from sage.structure.parent import Parent, Set_generic from sage.misc.fast_methods import WithEqualityById -from sage.structure.dynamic_class import dynamic_class -from sage.structure.unique_representation import UniqueRepresentation from sage.misc.lazy_attribute import lazy_attribute ################################### @@ -78,8 +75,11 @@ # introduced in github issue #715 # with weak values, as introduced in # github issue #14159 - from sage.structure.coerce_dict import TripleDict +from sage.structure.dynamic_class import dynamic_class +from sage.structure.parent import Parent, Set_generic +from sage.structure.unique_representation import UniqueRepresentation + _cache = TripleDict(weak_values=True) diff --git a/src/sage/categories/hopf_algebras.py b/src/sage/categories/hopf_algebras.py index 41e349690fe..218abc1ca27 100644 --- a/src/sage/categories/hopf_algebras.py +++ b/src/sage/categories/hopf_algebras.py @@ -8,14 +8,14 @@ # Distributed under the terms of the GNU General Public License (GPL) # https://www.gnu.org/licenses/ # ***************************************************************************** -from sage.misc.lazy_import import LazyImport -from .category import Category -from .category_types import Category_over_base_ring from sage.categories.bialgebras import Bialgebras -from sage.categories.tensor import TensorProductsCategory # tensor +from sage.categories.category import Category +from sage.categories.category_types import Category_over_base_ring from sage.categories.realizations import RealizationsCategory from sage.categories.super_modules import SuperModulesCategory +from sage.categories.tensor import TensorProductsCategory # tensor from sage.misc.cachefunc import cached_method +from sage.misc.lazy_import import LazyImport class HopfAlgebras(Category_over_base_ring): diff --git a/src/sage/categories/l_trivial_semigroups.py b/src/sage/categories/l_trivial_semigroups.py index 53f03701e6f..9c483dcd3d1 100644 --- a/src/sage/categories/l_trivial_semigroups.py +++ b/src/sage/categories/l_trivial_semigroups.py @@ -13,8 +13,9 @@ #***************************************************************************** from sage.categories.category_with_axiom import CategoryWithAxiom -from .magmas import Magmas -from .semigroups import Semigroups +from sage.categories.magmas import Magmas +from sage.categories.semigroups import Semigroups + class LTrivialSemigroups(CategoryWithAxiom): def extra_super_categories(self): diff --git a/src/sage/categories/lambda_bracket_algebras.py b/src/sage/categories/lambda_bracket_algebras.py index 40cb5ed70c4..16dbd7c7fa9 100644 --- a/src/sage/categories/lambda_bracket_algebras.py +++ b/src/sage/categories/lambda_bracket_algebras.py @@ -16,13 +16,14 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from .category_types import Category_over_base_ring -from sage.misc.abstract_method import abstract_method +from sage.categories.category_types import Category_over_base_ring +from sage.categories.commutative_rings import CommutativeRings from sage.categories.modules import Modules -from sage.structure.element import coerce_binop +from sage.misc.abstract_method import abstract_method from sage.misc.cachefunc import cached_method -from sage.categories.commutative_rings import CommutativeRings from sage.misc.lazy_import import LazyImport +from sage.structure.element import coerce_binop + _CommutativeRings = CommutativeRings() @@ -53,7 +54,7 @@ def __classcall_private__(cls, R, check=True): Category of Lie conformal algebras over Integer Ring """ if check: - if not (R in _CommutativeRings): + if R not in _CommutativeRings: raise ValueError("base must be a commutative ring got {}".format(R)) return super().__classcall__(cls, R) diff --git a/src/sage/categories/left_modules.py b/src/sage/categories/left_modules.py index c92a13f7979..51de3497a53 100644 --- a/src/sage/categories/left_modules.py +++ b/src/sage/categories/left_modules.py @@ -8,9 +8,10 @@ # http://www.gnu.org/licenses/ #****************************************************************************** -from .category_types import Category_over_base_ring +from sage.categories.category_types import Category_over_base_ring from sage.categories.commutative_additive_groups import CommutativeAdditiveGroups + #?class LeftModules(Category_over_base_rng): class LeftModules(Category_over_base_ring): """ diff --git a/src/sage/categories/lie_conformal_algebras.py b/src/sage/categories/lie_conformal_algebras.py index ee48889dd0b..8ade3811845 100644 --- a/src/sage/categories/lie_conformal_algebras.py +++ b/src/sage/categories/lie_conformal_algebras.py @@ -125,11 +125,12 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from .category_types import Category_over_base_ring -from sage.misc.cachefunc import cached_method +from sage.categories.category_types import Category_over_base_ring from sage.categories.lambda_bracket_algebras import LambdaBracketAlgebras +from sage.misc.cachefunc import cached_method from sage.misc.lazy_import import LazyImport + class LieConformalAlgebras(Category_over_base_ring): r""" The category of Lie conformal algebras. @@ -224,8 +225,9 @@ def example(self): sage: LieConformalAlgebras(QQ).example() # needs sage.combinat sage.modules The Virasoro Lie conformal algebra over Rational Field """ - from sage.algebras.lie_conformal_algebras.virasoro_lie_conformal_algebra\ - import VirasoroLieConformalAlgebra + from sage.algebras.lie_conformal_algebras.virasoro_lie_conformal_algebra import ( + VirasoroLieConformalAlgebra, + ) return VirasoroLieConformalAlgebra(self.base_ring()) def _repr_object_names(self): @@ -284,8 +286,8 @@ def _test_jacobi(self, **options): """ tester = self._tester(**options) S = tester.some_elements() - from sage.misc.misc import some_tuples from sage.arith.misc import binomial + from sage.misc.misc import some_tuples pz = tester._instance.zero() for x,y,z in some_tuples(S, 3, tester._max_runs): brxy = x.bracket(y) diff --git a/src/sage/categories/map.pyx b/src/sage/categories/map.pyx index 8f09e3aa00d..fadd066d7f4 100644 --- a/src/sage/categories/map.pyx +++ b/src/sage/categories/map.pyx @@ -21,7 +21,7 @@ AUTHORS: # https://www.gnu.org/licenses/ # **************************************************************************** -from . import homset +from sage.categories import homset import weakref from sage.ext.stdsage cimport HAS_DICTIONARY from sage.arith.power cimport generic_power diff --git a/src/sage/categories/matrix_algebras.py b/src/sage/categories/matrix_algebras.py index 90eef738be6..08b102d7451 100644 --- a/src/sage/categories/matrix_algebras.py +++ b/src/sage/categories/matrix_algebras.py @@ -10,8 +10,9 @@ # http://www.gnu.org/licenses/ #****************************************************************************** -from .category_types import Category_over_base_ring -from .algebras import Algebras +from sage.categories.algebras import Algebras +from sage.categories.category_types import Category_over_base_ring + class MatrixAlgebras(Category_over_base_ring): """ diff --git a/src/sage/categories/modular_abelian_varieties.py b/src/sage/categories/modular_abelian_varieties.py index a1337e700cd..804361a7f99 100644 --- a/src/sage/categories/modular_abelian_varieties.py +++ b/src/sage/categories/modular_abelian_varieties.py @@ -10,11 +10,12 @@ # http://www.gnu.org/licenses/ #****************************************************************************** -from .category_types import Category_over_base -from .category_with_axiom import CategoryWithAxiom -from .homsets import HomsetsCategory -from .rings import Rings -from .sets_cat import Sets +from sage.categories.category_types import Category_over_base +from sage.categories.category_with_axiom import CategoryWithAxiom +from sage.categories.homsets import HomsetsCategory +from sage.categories.rings import Rings +from sage.categories.sets_cat import Sets + class ModularAbelianVarieties(Category_over_base): """ diff --git a/src/sage/categories/modules.py b/src/sage/categories/modules.py index e65bab4faf8..c4f5127306f 100644 --- a/src/sage/categories/modules.py +++ b/src/sage/categories/modules.py @@ -11,21 +11,22 @@ # https://www.gnu.org/licenses/ # ***************************************************************************** -from sage.misc.cachefunc import cached_method -from sage.misc.abstract_method import abstract_method -from sage.misc.lazy_import import LazyImport +from sage.categories.bimodules import Bimodules +from sage.categories.cartesian_product import CartesianProductsCategory +from sage.categories.category import Category +from sage.categories.category_types import Category_module from sage.categories.category_with_axiom import CategoryWithAxiom_over_base_ring -from sage.categories.morphism import SetMorphism -from sage.categories.homsets import HomsetsCategory +from sage.categories.dual import DualObjectsCategory +from sage.categories.fields import Fields from sage.categories.homset import Hom -from .category import Category -from .category_types import Category_module -from sage.categories.tensor import TensorProductsCategory, TensorProductFunctor, tensor -from .dual import DualObjectsCategory -from sage.categories.cartesian_product import CartesianProductsCategory +from sage.categories.homsets import HomsetsCategory +from sage.categories.morphism import SetMorphism from sage.categories.sets_cat import Sets -from sage.categories.bimodules import Bimodules -from sage.categories.fields import Fields +from sage.categories.tensor import TensorProductFunctor, TensorProductsCategory, tensor +from sage.misc.abstract_method import abstract_method +from sage.misc.cachefunc import cached_method +from sage.misc.lazy_import import LazyImport + _Fields = Fields() diff --git a/src/sage/categories/morphism.pxd b/src/sage/categories/morphism.pxd index 1a941b62b33..e5befc8207e 100644 --- a/src/sage/categories/morphism.pxd +++ b/src/sage/categories/morphism.pxd @@ -1,5 +1,5 @@ from sage.structure.element cimport Element -from .map cimport Map +from sage.categories.map cimport Map cdef class Morphism(Map): diff --git a/src/sage/categories/pointed_sets.py b/src/sage/categories/pointed_sets.py index fd91b3b07f3..27376140dbe 100644 --- a/src/sage/categories/pointed_sets.py +++ b/src/sage/categories/pointed_sets.py @@ -11,7 +11,8 @@ #****************************************************************************** from sage.categories.category_singleton import Category_singleton -from .sets_cat import Sets +from sage.categories.sets_cat import Sets + class PointedSets(Category_singleton): """ diff --git a/src/sage/categories/pushout.py b/src/sage/categories/pushout.py index 3b7b8238d52..a23557037b0 100644 --- a/src/sage/categories/pushout.py +++ b/src/sage/categories/pushout.py @@ -27,9 +27,9 @@ import operator +from sage.categories.functor import Functor, IdentityFunctor_generic from sage.misc.lazy_import import lazy_import from sage.structure.coerce_exceptions import CoercionException -from .functor import Functor, IdentityFunctor_generic lazy_import('sage.categories.commutative_additive_groups', 'CommutativeAdditiveGroups') lazy_import('sage.categories.commutative_rings', 'CommutativeRings') @@ -902,7 +902,9 @@ def _apply_functor_to_morphism(self, f): From: Integer Ring To: Finite Field of size 3 """ - from sage.rings.polynomial.polynomial_ring_homomorphism import PolynomialRingHomomorphism_from_base + from sage.rings.polynomial.polynomial_ring_homomorphism import ( + PolynomialRingHomomorphism_from_base, + ) R = self._apply_functor(f.domain()) S = self._apply_functor(f.codomain()) return PolynomialRingHomomorphism_from_base(R.Hom(S), f) @@ -1329,7 +1331,9 @@ def _apply_functor(self, R): Infinite polynomial ring in a, b, x over Univariate Polynomial Ring in t over Rational Field """ - from sage.rings.polynomial.infinite_polynomial_ring import InfinitePolynomialRing + from sage.rings.polynomial.infinite_polynomial_ring import ( + InfinitePolynomialRing, + ) return InfinitePolynomialRing(R, self._gens, order=self._order, implementation=self._imple) def _repr_(self): @@ -1795,7 +1799,9 @@ def _apply_functor(self, R): """ from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing - from sage.rings.polynomial.laurent_polynomial_ring_base import LaurentPolynomialRing_generic + from sage.rings.polynomial.laurent_polynomial_ring_base import ( + LaurentPolynomialRing_generic, + ) if self.multi_variate and isinstance(R, LaurentPolynomialRing_generic): return LaurentPolynomialRing(R.base_ring(), list(R.variable_names()) + [self.var]) else: @@ -2474,8 +2480,8 @@ def __init__(self): sage: F(ZZ['t']) Fraction Field of Univariate Polynomial Ring in t over Integer Ring """ - from sage.categories.integral_domains import IntegralDomains from sage.categories.fields import Fields + from sage.categories.integral_domains import IntegralDomains Functor.__init__(self, IntegralDomains(), Fields()) def _apply_functor(self, R): @@ -3383,8 +3389,8 @@ def _apply_functor(self, R): 3-adic Eisenstein Extension Field in a defined by a^2 - 3 """ - from sage.rings.rational_field import QQ from sage.rings.integer_ring import ZZ + from sage.rings.rational_field import QQ if self.cyclotomic: from sage.rings.number_field.number_field import CyclotomicField if R == QQ: diff --git a/src/sage/categories/r_trivial_semigroups.py b/src/sage/categories/r_trivial_semigroups.py index 93ba9e61ca8..7b5c9fea5ed 100644 --- a/src/sage/categories/r_trivial_semigroups.py +++ b/src/sage/categories/r_trivial_semigroups.py @@ -13,7 +13,8 @@ #***************************************************************************** from sage.categories.category_with_axiom import CategoryWithAxiom -from .semigroups import Semigroups +from sage.categories.semigroups import Semigroups + class RTrivialSemigroups(CategoryWithAxiom): def extra_super_categories(self): diff --git a/src/sage/categories/right_modules.py b/src/sage/categories/right_modules.py index 5a7557c4663..47a8081d2a9 100644 --- a/src/sage/categories/right_modules.py +++ b/src/sage/categories/right_modules.py @@ -8,9 +8,10 @@ # http://www.gnu.org/licenses/ #****************************************************************************** -from .category_types import Category_over_base_ring +from sage.categories.category_types import Category_over_base_ring from sage.categories.commutative_additive_groups import CommutativeAdditiveGroups + ##?class RightModules(Category_over_base_rng): class RightModules(Category_over_base_ring): """ diff --git a/src/sage/categories/ring_ideals.py b/src/sage/categories/ring_ideals.py index 51573635ef0..fd634f1caef 100644 --- a/src/sage/categories/ring_ideals.py +++ b/src/sage/categories/ring_ideals.py @@ -10,9 +10,10 @@ # https://www.gnu.org/licenses/ # ***************************************************************************** -from .category_types import Category_ideal -from .modules import Modules +from sage.categories.category_types import Category_ideal +from sage.categories.modules import Modules from sage.categories.rings import Rings + _Rings = Rings() diff --git a/src/sage/categories/semirings.py b/src/sage/categories/semirings.py index cbff0b29a8e..62e6f7d918f 100644 --- a/src/sage/categories/semirings.py +++ b/src/sage/categories/semirings.py @@ -9,7 +9,8 @@ #****************************************************************************** from sage.categories.category_with_axiom import CategoryWithAxiom -from .magmas_and_additive_magmas import MagmasAndAdditiveMagmas +from sage.categories.magmas_and_additive_magmas import MagmasAndAdditiveMagmas + class Semirings(CategoryWithAxiom): """ diff --git a/src/sage/categories/semisimple_algebras.py b/src/sage/categories/semisimple_algebras.py index 9a310614290..453b854b7e7 100644 --- a/src/sage/categories/semisimple_algebras.py +++ b/src/sage/categories/semisimple_algebras.py @@ -8,12 +8,13 @@ # http://www.gnu.org/licenses/ #****************************************************************************** +from sage.categories.algebras import Algebras +from sage.categories.category_types import Category_over_base_ring +from sage.categories.category_with_axiom import CategoryWithAxiom_over_base_ring from sage.misc.bindable_class import BoundClass from sage.misc.cachefunc import cached_method from sage.misc.lazy_import import LazyImport -from .category_types import Category_over_base_ring -from sage.categories.category_with_axiom import CategoryWithAxiom_over_base_ring -from .algebras import Algebras + class SemisimpleAlgebras(Category_over_base_ring): """ diff --git a/src/sage/categories/sets_with_grading.py b/src/sage/categories/sets_with_grading.py index b1e321f67f2..a29d8c9c59c 100644 --- a/src/sage/categories/sets_with_grading.py +++ b/src/sage/categories/sets_with_grading.py @@ -8,11 +8,11 @@ # https://www.gnu.org/licenses/ # ***************************************************************************** -from sage.misc.cachefunc import cached_method -from sage.misc.abstract_method import abstract_method -from .category_types import Category -from sage.categories.sets_cat import Sets +from sage.categories.category_types import Category from sage.categories.enumerated_sets import EnumeratedSets +from sage.categories.sets_cat import Sets +from sage.misc.abstract_method import abstract_method +from sage.misc.cachefunc import cached_method class SetsWithGrading(Category): @@ -220,9 +220,9 @@ def generating_series(self): - Very likely, this should always return a lazy power series. """ - from sage.sets.non_negative_integers import NonNegativeIntegers - from sage.rings.lazy_series_ring import LazyPowerSeriesRing from sage.rings.integer_ring import ZZ + from sage.rings.lazy_series_ring import LazyPowerSeriesRing + from sage.sets.non_negative_integers import NonNegativeIntegers if isinstance(self.grading_set(), NonNegativeIntegers): R = LazyPowerSeriesRing(ZZ, names="z") return R(lambda n: self.graded_component(n).cardinality()) diff --git a/src/sage/categories/sets_with_partial_maps.py b/src/sage/categories/sets_with_partial_maps.py index 5b2f9b35427..4210548b0fd 100644 --- a/src/sage/categories/sets_with_partial_maps.py +++ b/src/sage/categories/sets_with_partial_maps.py @@ -11,7 +11,7 @@ #****************************************************************************** from sage.categories.category_singleton import Category_singleton -from .objects import Objects +from sage.categories.objects import Objects class SetsWithPartialMaps(Category_singleton): diff --git a/src/sage/combinat/species/characteristic_species.py b/src/sage/combinat/species/characteristic_species.py index e529dc97bd1..37ce75abe28 100644 --- a/src/sage/combinat/species/characteristic_species.py +++ b/src/sage/combinat/species/characteristic_species.py @@ -60,16 +60,15 @@ def canonical_label(self): def transport(self, perm): """ - Returns the transport of this structure along the permutation - perm. + Return the transport of this structure along the permutation ``perm``. EXAMPLES:: sage: F = species.CharacteristicSpecies(3) sage: a = F.structures(["a", "b", "c"]).random_element(); a {'a', 'b', 'c'} - sage: p = PermutationGroupElement((1,2)) - sage: a.transport(p) + sage: p = PermutationGroupElement((1,2)) # needs sage.groups + sage: a.transport(p) # needs sage.groups {'a', 'b', 'c'} """ return self @@ -85,7 +84,7 @@ def automorphism_group(self): sage: F = species.CharacteristicSpecies(3) sage: a = F.structures(["a", "b", "c"]).random_element(); a {'a', 'b', 'c'} - sage: a.automorphism_group() + sage: a.automorphism_group() # needs sage.groups Symmetric group of order 3! as a permutation group """ from sage.groups.perm_gps.permgroup_named import SymmetricGroup @@ -111,7 +110,7 @@ def __init__(self, n, min=None, max=None, weight=None): [0, 1, 0, 0] sage: X.isotype_generating_series()[0:4] [0, 1, 0, 0] - sage: X.cycle_index_series()[0:4] + sage: X.cycle_index_series()[0:4] # needs sage.modules [0, p[1], 0, 0] sage: F = species.CharacteristicSpecies(3) @@ -204,8 +203,8 @@ def _cis_term(self, base_ring): EXAMPLES:: sage: F = species.CharacteristicSpecies(2) - sage: g = F.cycle_index_series() - sage: g[0:5] + sage: g = F.cycle_index_series() # needs sage.modules + sage: g[0:5] # needs sage.modules [0, 0, 1/2*p[1, 1] + 1/2*p[2], 0, 0] """ cis = SetSpecies(weight=self._weight).cycle_index_series(base_ring) @@ -220,11 +219,11 @@ def _equation(self, var_mapping): EXAMPLES:: sage: C = species.CharacteristicSpecies(2) - sage: Qz = QQ['z'] - sage: R. = Qz[] - sage: var_mapping = {'z':Qz.gen(), 'node0':R.gen()} - sage: C._equation(var_mapping) - z^2 + sage: Qz = QQ['z'] + sage: R. = Qz[] + sage: var_mapping = {'z':Qz.gen(), 'node0':R.gen()} + sage: C._equation(var_mapping) + z^2 """ return var_mapping['z']**(self._n) @@ -252,7 +251,7 @@ def __init__(self, min=None, max=None, weight=None): [1, 0, 0, 0] sage: X.isotype_generating_series()[0:4] [1, 0, 0, 0] - sage: X.cycle_index_series()[0:4] + sage: X.cycle_index_series()[0:4] # needs sage.modules [p[], 0, 0, 0] TESTS:: @@ -296,7 +295,7 @@ def __init__(self, min=None, max=None, weight=None): [0, 1, 0, 0] sage: X.isotype_generating_series()[0:4] [0, 1, 0, 0] - sage: X.cycle_index_series()[0:4] + sage: X.cycle_index_series()[0:4] # needs sage.modules [0, p[1], 0, 0] TESTS:: diff --git a/src/sage/combinat/species/composition_species.py b/src/sage/combinat/species/composition_species.py index c96f3161ba5..b60e5348985 100644 --- a/src/sage/combinat/species/composition_species.py +++ b/src/sage/combinat/species/composition_species.py @@ -28,8 +28,8 @@ def __init__(self, parent, labels, pi, f, gs): sage: E = species.SetSpecies(); C = species.CycleSpecies() sage: L = E(C) - sage: a = L.structures(['a','b','c']).random_element() - sage: a == loads(dumps(a)) + sage: a = L.structures(['a','b','c']).random_element() # needs sage.libs.flint + sage: a == loads(dumps(a)) # needs sage.libs.flint True """ self._partition = pi @@ -41,7 +41,7 @@ def __repr__(self): sage: E = species.SetSpecies(); C = species.CycleSpecies() sage: L = E(C) - sage: L.structures(['a','b','c'])[0] + sage: L.structures(['a','b','c'])[0] # needs sage.libs.flint F-structure: {{'a', 'b', 'c'}}; G-structures: (('a', 'b', 'c'),) """ f, gs = self._list @@ -51,13 +51,13 @@ def transport(self, perm): """ EXAMPLES:: - sage: p = PermutationGroupElement((2,3)) + sage: p = PermutationGroupElement((2,3)) # needs sage.groups sage: E = species.SetSpecies(); C = species.CycleSpecies() sage: L = E(C) - sage: S = L.structures(['a','b','c']).list() - sage: a = S[2]; a + sage: S = L.structures(['a','b','c']).list() # needs sage.libs.flint + sage: a = S[2]; a # needs sage.libs.flint F-structure: {{'a', 'c'}, {'b'}}; G-structures: (('a', 'c'), ('b')) - sage: a.transport(p) + sage: a.transport(p) # needs sage.groups sage.libs.flint F-structure: {{'a', 'b'}, {'c'}}; G-structures: (('a', 'c'), ('b')) """ f, gs = self._list @@ -83,10 +83,10 @@ def change_labels(self, labels): sage: E = species.SetSpecies(); C = species.CycleSpecies() sage: L = E(C) - sage: S = L.structures(['a','b','c']).list() - sage: a = S[2]; a + sage: S = L.structures(['a','b','c']).list() # needs sage.libs.flint + sage: a = S[2]; a # needs sage.libs.flint F-structure: {{'a', 'c'}, {'b'}}; G-structures: (('a', 'c'), ('b')) - sage: a.change_labels([1,2,3]) + sage: a.change_labels([1,2,3]) # needs sage.libs.flint F-structure: {{1, 3}, {2}}; G-structures: [(1, 3), (2)] """ f, gs = self._list @@ -116,7 +116,7 @@ def __init__(self, F, G, min=None, max=None, weight=None): sage: E = species.SetSpecies(); C = species.CycleSpecies() sage: L = E(C) sage: c = L.generating_series()[:3] - sage: L._check() #False due to isomorphism types not being implemented + sage: L._check() #False due to isomorphism types not being implemented # needs sage.libs.flint False sage: L == loads(dumps(L)) True @@ -135,7 +135,7 @@ def _structures(self, structure_class, labels): sage: E = species.SetSpecies(); C = species.CycleSpecies() sage: L = E(C) - sage: L.structures(['a','b','c']).list() + sage: L.structures(['a','b','c']).list() # needs sage.libs.flint [F-structure: {{'a', 'b', 'c'}}; G-structures: (('a', 'b', 'c'),), F-structure: {{'a', 'b', 'c'}}; G-structures: (('a', 'c', 'b'),), F-structure: {{'a', 'c'}, {'b'}}; G-structures: (('a', 'c'), ('b')), @@ -145,6 +145,7 @@ def _structures(self, structure_class, labels): TESTS:: + sage: # needs sage.libs.flint sage: a = _[2] sage: f, gs = a._list sage: f @@ -180,7 +181,7 @@ def _isotypes(self, structure_class, labels): sage: E = species.SetSpecies(); C = species.CycleSpecies() sage: L = E(C) - sage: L.isotypes(['a','b','c']).list() + sage: L.isotypes(['a','b','c']).list() # needs sage.modules Traceback (most recent call last): ... NotImplementedError @@ -204,7 +205,7 @@ def _itgs(self, series_ring, base_ring): sage: E = species.SetSpecies(); C = species.CycleSpecies() sage: L = E(C) - sage: L.isotype_generating_series()[:10] + sage: L.isotype_generating_series()[:10] # needs sage.modules [1, 1, 2, 3, 5, 7, 11, 15, 22, 30] """ cis = self.cycle_index_series(base_ring) @@ -216,7 +217,7 @@ def _cis(self, series_ring, base_ring): sage: E = species.SetSpecies(); C = species.CycleSpecies() sage: L = E(C) - sage: L.cycle_index_series()[:5] + sage: L.cycle_index_series()[:5] # needs sage.modules [p[], p[1], p[1, 1] + p[2], @@ -233,7 +234,7 @@ def _cis(self, series_ring, base_ring): sage: E = species.SetSpecies() sage: C = species.CycleSpecies(weight=t) sage: S = E(C) - sage: S.isotype_generating_series()[:5] #indirect + sage: S.isotype_generating_series()[:5] #indirect # needs sage.modules [1, t, t^2 + t, t^3 + t^2 + t, t^4 + t^3 + 2*t^2 + t] We do the same thing with set partitions weighted by the number of @@ -245,7 +246,7 @@ def _cis(self, series_ring, base_ring): sage: E = species.SetSpecies() sage: E_t = species.SetSpecies(min=1,weight=t) sage: Par = E(E_t) - sage: Par.isotype_generating_series()[:5] + sage: Par.isotype_generating_series()[:5] # needs sage.modules [1, t, t^2 + t, t^3 + t^2 + t, t^4 + t^3 + 2*t^2 + t] """ f_cis = self._F.cycle_index_series(base_ring) diff --git a/src/sage/combinat/species/cycle_species.py b/src/sage/combinat/species/cycle_species.py index ed442e75ba9..c808f6a0db1 100644 --- a/src/sage/combinat/species/cycle_species.py +++ b/src/sage/combinat/species/cycle_species.py @@ -51,7 +51,7 @@ def permutation_group_element(self): sage: F = species.CycleSpecies() sage: a = F.structures(["a", "b", "c"])[0]; a ('a', 'b', 'c') - sage: a.permutation_group_element() + sage: a.permutation_group_element() # needs sage.groups (1,2,3) """ from sage.groups.perm_gps.constructor import PermutationGroupElement @@ -67,8 +67,8 @@ def transport(self, perm): sage: F = species.CycleSpecies() sage: a = F.structures(["a", "b", "c"])[0]; a ('a', 'b', 'c') - sage: p = PermutationGroupElement((1,2)) - sage: a.transport(p) + sage: p = PermutationGroupElement((1,2)) # needs sage.groups + sage: a.transport(p) # needs sage.groups ('a', 'c', 'b') """ p = self.permutation_group_element() @@ -88,12 +88,12 @@ def automorphism_group(self): sage: P = species.CycleSpecies() sage: a = P.structures([1, 2, 3, 4])[0]; a (1, 2, 3, 4) - sage: a.automorphism_group() + sage: a.automorphism_group() # needs sage.groups Permutation Group with generators [(1,2,3,4)] :: - sage: [a.transport(perm) for perm in a.automorphism_group()] + sage: [a.transport(perm) for perm in a.automorphism_group()] # needs sage.groups [(1, 2, 3, 4), (1, 2, 3, 4), (1, 2, 3, 4), (1, 2, 3, 4)] """ from sage.groups.perm_gps.permgroup_named import SymmetricGroup @@ -255,8 +255,8 @@ def _cis_callable(self, base_ring, n): EXAMPLES:: sage: P = species.CycleSpecies() - sage: cis = P.cycle_index_series() - sage: cis[0:7] + sage: cis = P.cycle_index_series() # needs sage.modules + sage: cis[0:7] # needs sage.modules [0, p[1], 1/2*p[1, 1] + 1/2*p[2], diff --git a/src/sage/combinat/species/empty_species.py b/src/sage/combinat/species/empty_species.py index e66019360ac..5c4762cb34d 100644 --- a/src/sage/combinat/species/empty_species.py +++ b/src/sage/combinat/species/empty_species.py @@ -38,7 +38,7 @@ class EmptySpecies(GenericCombinatorialSpecies, UniqueRepresentation): [0, 0, 0, 0] sage: X.isotype_generating_series()[0:4] [0, 0, 0, 0] - sage: X.cycle_index_series()[0:4] + sage: X.cycle_index_series()[0:4] # needs sage.modules [0, 0, 0, 0] The empty species is the zero of the semi-ring of species. @@ -55,7 +55,7 @@ class EmptySpecies(GenericCombinatorialSpecies, UniqueRepresentation): sage: (X.isotype_generating_series()[0:4] == ....: S.isotype_generating_series()[0:4]) True - sage: (X.cycle_index_series()[0:4] == + sage: (X.cycle_index_series()[0:4] == # needs sage.modules ....: S.cycle_index_series()[0:4]) True @@ -69,7 +69,7 @@ class EmptySpecies(GenericCombinatorialSpecies, UniqueRepresentation): [0, 0, 0, 0] sage: Y.isotype_generating_series()[0:4] [0, 0, 0, 0] - sage: Y.cycle_index_series()[0:4] + sage: Y.cycle_index_series()[0:4] # needs sage.modules [0, 0, 0, 0] TESTS:: diff --git a/src/sage/combinat/species/functorial_composition_species.py b/src/sage/combinat/species/functorial_composition_species.py index 118e924d426..b327492a54a 100644 --- a/src/sage/combinat/species/functorial_composition_species.py +++ b/src/sage/combinat/species/functorial_composition_species.py @@ -35,7 +35,7 @@ def __init__(self, F, G, min=None, max=None, weight=None): sage: WP = species.SubsetSpecies() sage: P2 = E2*E sage: G = WP.functorial_composition(P2) - sage: G.isotype_generating_series()[0:5] + sage: G.isotype_generating_series()[0:5] # needs sage.modules [1, 1, 2, 4, 11] sage: G = species.SimpleGraphSpecies() @@ -44,7 +44,7 @@ def __init__(self, F, G, min=None, max=None, weight=None): sage: G == loads(dumps(G)) True - sage: G._check() #False due to isomorphism types not being implemented + sage: G._check() # False due to isomorphism types not being implemented # needs sage.modules False """ self._F = F @@ -81,7 +81,7 @@ def _isotypes(self, structure_class, s): EXAMPLES:: sage: G = species.SimpleGraphSpecies() - sage: G.isotypes([1,2,3]).list() + sage: G.isotypes([1,2,3]).list() # needs sage.modules Traceback (most recent call last): ... NotImplementedError @@ -103,7 +103,7 @@ def _itgs(self, series_ring, base_ring): EXAMPLES:: sage: G = species.SimpleGraphSpecies() - sage: G.isotype_generating_series()[0:5] + sage: G.isotype_generating_series()[0:5] # needs sage.modules [1, 1, 2, 4, 11] """ return self.cycle_index_series(base_ring).isotype_generating_series() @@ -113,7 +113,7 @@ def _cis(self, series_ring, base_ring): EXAMPLES:: sage: G = species.SimpleGraphSpecies() - sage: G.cycle_index_series()[0:5] + sage: G.cycle_index_series()[0:5] # needs sage.modules [p[], p[1], p[1, 1] + p[2], diff --git a/src/sage/combinat/species/generating_series.py b/src/sage/combinat/species/generating_series.py index dca117a9971..b7b208c3d87 100644 --- a/src/sage/combinat/species/generating_series.py +++ b/src/sage/combinat/species/generating_series.py @@ -15,19 +15,20 @@ TESTS:: + sage: # needs sage.modules sage: from sage.combinat.species.generating_series import CycleIndexSeriesRing - sage: p = SymmetricFunctions(QQ).power() # optional - sage.modules + sage: p = SymmetricFunctions(QQ).power() sage: CIS = CycleIndexSeriesRing(QQ) - sage: geo1 = CIS(lambda i: p([1])^i) # optional - sage.modules - sage: geo2 = CIS(lambda i: p([2])^(i // 2) if is_even(i) else 0) # optional - sage.modules - sage: s = geo1 * geo2 # optional - sage.modules - sage: s[0] # optional - sage.modules + sage: geo1 = CIS(lambda i: p([1])^i) + sage: geo2 = CIS(lambda i: p([2])^(i // 2) if is_even(i) else 0) + sage: s = geo1 * geo2 + sage: s[0] p[] - sage: s[1] # optional - sage.modules + sage: s[1] p[1] - sage: s[2] # optional - sage.modules + sage: s[2] p[1, 1] + p[2] - sage: s[3] # optional - sage.modules + sage: s[3] p[1, 1, 1] + p[2, 1] """ @@ -46,11 +47,12 @@ from sage.rings.lazy_series_ring import LazyPowerSeriesRing, LazySymmetricFunctions from sage.rings.integer import Integer from sage.rings.rational_field import QQ -from sage.arith.misc import divisors +from sage.arith.misc import divisors, factorial from sage.combinat.partition import Partition, Partitions -from sage.combinat.sf.sf import SymmetricFunctions from sage.misc.cachefunc import cached_function -from sage.arith.misc import factorial +from sage.misc.lazy_import import lazy_import + +lazy_import('sage.combinat.sf.sf', 'SymmetricFunctions') class OrdinaryGeneratingSeries(LazyPowerSeries): @@ -284,15 +286,16 @@ def count(self, t): EXAMPLES:: + sage: # needs sage.modules sage: from sage.combinat.species.generating_series import CycleIndexSeriesRing - sage: p = SymmetricFunctions(QQ).power() # optional - sage.modules + sage: p = SymmetricFunctions(QQ).power() sage: CIS = CycleIndexSeriesRing(QQ) - sage: f = CIS([0, p([1]), 2*p([1,1]), 3*p([2,1])]) # optional - sage.modules - sage: f.count([1]) # optional - sage.modules + sage: f = CIS([0, p([1]), 2*p([1,1]), 3*p([2,1])]) + sage: f.count([1]) 1 - sage: f.count([1,1]) # optional - sage.modules + sage: f.count([1,1]) 4 - sage: f.count([2,1]) # optional - sage.modules + sage: f.count([2,1]) 6 """ t = Partition(t) @@ -304,15 +307,16 @@ def coefficient_cycle_type(self, t): EXAMPLES:: + sage: # needs sage.modules sage: from sage.combinat.species.generating_series import CycleIndexSeriesRing - sage: p = SymmetricFunctions(QQ).power() # optional - sage.modules + sage: p = SymmetricFunctions(QQ).power() sage: CIS = CycleIndexSeriesRing(QQ) - sage: f = CIS([0, p([1]), 2*p([1,1]),3*p([2,1])]) # optional - sage.modules - sage: f.coefficient_cycle_type([1]) # optional - sage.modules + sage: f = CIS([0, p([1]), 2*p([1,1]),3*p([2,1])]) + sage: f.coefficient_cycle_type([1]) 1 - sage: f.coefficient_cycle_type([1,1]) # optional - sage.modules + sage: f.coefficient_cycle_type([1,1]) 2 - sage: f.coefficient_cycle_type([2,1]) # optional - sage.modules + sage: f.coefficient_cycle_type([2,1]) 3 """ t = Partition(t) @@ -326,9 +330,9 @@ def isotype_generating_series(self): EXAMPLES:: sage: P = species.PermutationSpecies() - sage: cis = P.cycle_index_series() - sage: f = cis.isotype_generating_series() - sage: f[:10] + sage: cis = P.cycle_index_series() # needs sage.modules + sage: f = cis.isotype_generating_series() # needs sage.modules + sage: f[:10] # needs sage.modules [1, 1, 2, 3, 5, 7, 11, 15, 22, 30] """ R = self.base_ring() @@ -344,8 +348,8 @@ def _ogs_gen(self, n, ao): EXAMPLES:: sage: P = species.PermutationSpecies() - sage: cis = P.cycle_index_series() - sage: [cis._ogs_gen(i, 0) for i in range(10)] + sage: cis = P.cycle_index_series() # needs sage.modules + sage: [cis._ogs_gen(i, 0) for i in range(10)] # needs sage.modules [1, 1, 2, 3, 5, 7, 11, 15, 22, 30] """ if n < ao: @@ -359,9 +363,9 @@ def generating_series(self): EXAMPLES:: sage: P = species.PartitionSpecies() - sage: cis = P.cycle_index_series() - sage: f = cis.generating_series() - sage: f[:5] + sage: cis = P.cycle_index_series() # needs sage.modules + sage: f = cis.generating_series() # needs sage.modules + sage: f[:5] # needs sage.modules [1, 1, 1, 5/6, 5/8] """ R = self.base_ring() @@ -377,8 +381,8 @@ def _egs_gen(self, n, ao): EXAMPLES:: sage: P = species.PermutationSpecies() - sage: cis = P.cycle_index_series() - sage: [cis._egs_gen(i, 0) for i in range(10)] + sage: cis = P.cycle_index_series() # needs sage.modules + sage: [cis._egs_gen(i, 0) for i in range(10)] # needs sage.modules [1, 1, 1, 1, 1, 1, 1, 1, 1, 1] """ if n < ao: @@ -401,16 +405,16 @@ def derivative(self, n=1): The species `E` of sets satisfies the relationship `E' = E`:: - sage: E = species.SetSpecies().cycle_index_series() - sage: E[:8] == E.derivative()[:8] + sage: E = species.SetSpecies().cycle_index_series() # needs sage.modules + sage: E[:8] == E.derivative()[:8] # needs sage.modules True The species `C` of cyclic orderings and the species `L` of linear orderings satisfy the relationship `C' = L`:: - sage: C = species.CycleSpecies().cycle_index_series() - sage: L = species.LinearOrderSpecies().cycle_index_series() - sage: L[:8] == C.derivative()[:8] + sage: C = species.CycleSpecies().cycle_index_series() # needs sage.modules + sage: L = species.LinearOrderSpecies().cycle_index_series() # needs sage.modules + sage: L[:8] == C.derivative()[:8] # needs sage.modules True """ return self.derivative_with_respect_to_p1(n=n) @@ -431,9 +435,9 @@ def pointing(self): The species `E^{\bullet}` of "pointed sets" satisfies `E^{\bullet} = X \cdot E`:: - sage: E = species.SetSpecies().cycle_index_series() - sage: X = species.SingletonSpecies().cycle_index_series() - sage: E.pointing()[:8] == (X*E)[:8] + sage: E = species.SetSpecies().cycle_index_series() # needs sage.modules + sage: X = species.SingletonSpecies().cycle_index_series() # needs sage.modules + sage: E.pointing()[:8] == (X*E)[:8] # needs sage.modules True """ X = self.parent()([1], valuation=1) @@ -455,9 +459,9 @@ def exponential(self): Let `BT` be the species of binary trees, `BF` the species of binary forests, and `E` the species of sets. Then we have `BF = E \circ BT`:: - sage: BT = species.BinaryTreeSpecies().cycle_index_series() - sage: BF = species.BinaryForestSpecies().cycle_index_series() - sage: BT.exponential().isotype_generating_series()[:8] == BF.isotype_generating_series()[:8] + sage: BT = species.BinaryTreeSpecies().cycle_index_series() # needs sage.modules + sage: BF = species.BinaryForestSpecies().cycle_index_series() # needs sage.modules + sage: BT.exponential().isotype_generating_series()[:8] == BF.isotype_generating_series()[:8] # needs sage.modules True """ base_ring = self.parent().base_ring().base_ring() @@ -482,10 +486,10 @@ def logarithm(self): Let `G` be the species of nonempty graphs and `CG` be the species of nonempty connected graphs. Then `G = E^{+} \circ CG`, so `CG = \Omega \circ G`:: - sage: G = species.SimpleGraphSpecies().cycle_index_series() - 1 + sage: G = species.SimpleGraphSpecies().cycle_index_series() - 1 # needs sage.modules sage: from sage.combinat.species.generating_series import LogarithmCycleIndexSeries - sage: CG = LogarithmCycleIndexSeries()(G) - sage: CG.isotype_generating_series()[0:8] + sage: CG = LogarithmCycleIndexSeries()(G) # needs sage.modules + sage: CG.isotype_generating_series()[0:8] # needs sage.modules [0, 1, 1, 2, 6, 21, 112, 853] """ base_ring = self.parent().base_ring().base_ring() @@ -528,17 +532,17 @@ class CycleIndexSeriesRing(LazySymmetricFunctions): EXAMPLES:: sage: from sage.combinat.species.generating_series import CycleIndexSeriesRing - sage: R = CycleIndexSeriesRing(QQ); R # optional - sage.modules + sage: R = CycleIndexSeriesRing(QQ); R # needs sage.modules Cycle Index Series Ring over Rational Field - sage: p = SymmetricFunctions(QQ).p() # optional - sage.modules - sage: R(lambda n: p[n]) # optional - sage.modules + sage: p = SymmetricFunctions(QQ).p() # needs sage.modules + sage: R(lambda n: p[n]) # needs sage.modules p[] + p[1] + p[2] + p[3] + p[4] + p[5] + p[6] + O^7 TESTS: We test to make sure that caching works:: - sage: R is CycleIndexSeriesRing(QQ) + sage: R is CycleIndexSeriesRing(QQ) # needs sage.modules True """ Element = CycleIndexSeries @@ -551,8 +555,8 @@ def __init__(self, base_ring, sparse=True): sage: from sage.combinat.species.generating_series import CycleIndexSeriesRing sage: CycleIndexSeriesRing.options.halting_precision(12) - sage: R = CycleIndexSeriesRing(QQ) # optional - sage.modules - sage: TestSuite(R).run() # optional - sage.modules + sage: R = CycleIndexSeriesRing(QQ) # needs sage.modules + sage: TestSuite(R).run() # needs sage.modules sage: CycleIndexSeriesRing.options._reset() # reset options """ @@ -566,7 +570,7 @@ def _repr_(self): EXAMPLES:: sage: from sage.combinat.species.generating_series import CycleIndexSeriesRing - sage: CycleIndexSeriesRing(QQ) # optional - sage.modules + sage: CycleIndexSeriesRing(QQ) # needs sage.modules Cycle Index Series Ring over Rational Field """ return "Cycle Index Series Ring over %s" % self.base_ring() @@ -581,7 +585,7 @@ def _exp_term(n, R=QQ): EXAMPLES:: sage: from sage.combinat.species.generating_series import _exp_term - sage: [_exp_term(i) for i in range(4)] # optional - sage.modules + sage: [_exp_term(i) for i in range(4)] # needs sage.modules [p[], p[1], 1/2*p[1, 1] + 1/2*p[2], 1/6*p[1, 1, 1] + 1/2*p[2, 1] + 1/3*p[3]] """ p = SymmetricFunctions(R).power() @@ -603,7 +607,7 @@ def ExponentialCycleIndexSeries(R=QQ): EXAMPLES:: sage: from sage.combinat.species.generating_series import ExponentialCycleIndexSeries - sage: ExponentialCycleIndexSeries()[:5] # optional - sage.modules + sage: ExponentialCycleIndexSeries()[:5] # needs sage.modules [p[], p[1], 1/2*p[1, 1] + 1/2*p[2], 1/6*p[1, 1, 1] + 1/2*p[2, 1] + 1/3*p[3], 1/24*p[1, 1, 1, 1] + 1/4*p[2, 1, 1] + 1/8*p[2, 2] + 1/3*p[3, 1] + 1/4*p[4]] @@ -622,7 +626,7 @@ def _cl_term(n, R=QQ): EXAMPLES:: sage: from sage.combinat.species.generating_series import _cl_term - sage: [_cl_term(i) for i in range(4)] # optional - sage.modules + sage: [_cl_term(i) for i in range(4)] # needs sage.modules [0, p[1], -1/2*p[1, 1] - 1/2*p[2], 1/3*p[1, 1, 1] - 1/3*p[3]] """ n = Integer(n) # check that n is an integer @@ -654,15 +658,15 @@ def LogarithmCycleIndexSeries(R=QQ): its cycle index has negative coefficients:: sage: from sage.combinat.species.generating_series import LogarithmCycleIndexSeries - sage: LogarithmCycleIndexSeries()[0:4] # optional - sage.modules + sage: LogarithmCycleIndexSeries()[0:4] # needs sage.modules [0, p[1], -1/2*p[1, 1] - 1/2*p[2], 1/3*p[1, 1, 1] - 1/3*p[3]] Its defining property is that `\Omega \circ E^{+} = E^{+} \circ \Omega = X` (that is, that composition with `E^{+}` in both directions yields the multiplicative identity `X`):: - sage: Eplus = sage.combinat.species.set_species.SetSpecies(min=1).cycle_index_series() - sage: LogarithmCycleIndexSeries()(Eplus)[0:4] # optional - sage.modules + sage: Eplus = sage.combinat.species.set_species.SetSpecies(min=1).cycle_index_series() # needs sage.modules + sage: LogarithmCycleIndexSeries()(Eplus)[0:4] # needs sage.modules [0, p[1], 0, 0] """ CIS = CycleIndexSeriesRing(R) diff --git a/src/sage/combinat/species/library.py b/src/sage/combinat/species/library.py index d4235273a9f..c50a9fe75fa 100644 --- a/src/sage/combinat/species/library.py +++ b/src/sage/combinat/species/library.py @@ -43,25 +43,25 @@ def SimpleGraphSpecies(): sage: S = species.SimpleGraphSpecies() sage: S.generating_series().counts(10) [1, 1, 2, 8, 64, 1024, 32768, 2097152, 268435456, 68719476736] - sage: S.cycle_index_series()[:5] + sage: S.cycle_index_series()[:5] # needs sage.modules [p[], p[1], p[1, 1] + p[2], 4/3*p[1, 1, 1] + 2*p[2, 1] + 2/3*p[3], 8/3*p[1, 1, 1, 1] + 4*p[2, 1, 1] + 2*p[2, 2] + 4/3*p[3, 1] + p[4]] - sage: S.isotype_generating_series()[:6] + sage: S.isotype_generating_series()[:6] # needs sage.modules [1, 1, 2, 4, 11, 34] TESTS:: - sage: seq = S.isotype_generating_series().counts(6)[1:] - sage: oeis(seq)[0] # optional -- internet + sage: seq = S.isotype_generating_series().counts(6)[1:] # needs sage.modules + sage: oeis(seq)[0] # optional - internet # needs sage.modules A000088: Number of graphs on n unlabeled nodes. :: - sage: seq = S.generating_series().counts(10)[1:] - sage: oeis(seq)[0] # optional -- internet + sage: seq = S.generating_series().counts(10)[1:] # needs sage.modules + sage: oeis(seq)[0] # optional - internet # needs sage.modules A006125: a(n) = 2^(n*(n-1)/2). """ E = SetSpecies() @@ -94,7 +94,7 @@ def BinaryTreeSpecies(): sage: B = species.BinaryTreeSpecies() sage: a = B.structures([1,2,3,4,5])[187]; a 2*((5*3)*(4*1)) - sage: a.automorphism_group() + sage: a.automorphism_group() # needs sage.groups Permutation Group with generators [()] TESTS:: @@ -121,9 +121,9 @@ def BinaryForestSpecies(): sage: F = species.BinaryForestSpecies() sage: F.generating_series().counts(10) [1, 1, 3, 19, 193, 2721, 49171, 1084483, 28245729, 848456353] - sage: F.isotype_generating_series().counts(10) + sage: F.isotype_generating_series().counts(10) # needs sage.modules [1, 1, 2, 4, 10, 26, 77, 235, 758, 2504] - sage: F.cycle_index_series()[:7] + sage: F.cycle_index_series()[:7] # needs sage.modules [p[], p[1], 3/2*p[1, 1] + 1/2*p[2], @@ -134,8 +134,8 @@ def BinaryForestSpecies(): TESTS:: - sage: seq = F.isotype_generating_series().counts(10)[1:] - sage: oeis(seq)[0] # optional -- internet + sage: seq = F.isotype_generating_series().counts(10)[1:] # needs sage.modules + sage: oeis(seq)[0] # optional - internet # needs sage.modules A052854: Number of forests of ordered trees on n total nodes. """ B = BinaryTreeSpecies() diff --git a/src/sage/combinat/species/linear_order_species.py b/src/sage/combinat/species/linear_order_species.py index 6203442ec8f..0761dea576d 100644 --- a/src/sage/combinat/species/linear_order_species.py +++ b/src/sage/combinat/species/linear_order_species.py @@ -43,8 +43,8 @@ def transport(self, perm): sage: F = species.LinearOrderSpecies() sage: a = F.structures(["a", "b", "c"])[0]; a ['a', 'b', 'c'] - sage: p = PermutationGroupElement((1,2)) - sage: a.transport(p) + sage: p = PermutationGroupElement((1,2)) # needs sage.groups + sage: a.transport(p) # needs sage.groups ['b', 'a', 'c'] """ return LinearOrderSpeciesStructure(self.parent(), self._labels, [perm(i) for i in self._list]) @@ -60,7 +60,7 @@ def automorphism_group(self): sage: F = species.LinearOrderSpecies() sage: a = F.structures(["a", "b", "c"])[0]; a ['a', 'b', 'c'] - sage: a.automorphism_group() + sage: a.automorphism_group() # needs sage.groups Symmetric group of order 1! as a permutation group """ from sage.groups.perm_gps.permgroup_named import SymmetricGroup @@ -155,8 +155,8 @@ def _cis_callable(self, base_ring, n): EXAMPLES:: sage: L = species.LinearOrderSpecies() - sage: g = L.cycle_index_series() - sage: g[0:5] + sage: g = L.cycle_index_series() # needs sage.modules + sage: g[0:5] # needs sage.modules [p[], p[1], p[1, 1], p[1, 1, 1], p[1, 1, 1, 1]] """ from sage.combinat.sf.sf import SymmetricFunctions diff --git a/src/sage/combinat/species/misc.py b/src/sage/combinat/species/misc.py index a516beb56ae..12a9b2c8f70 100644 --- a/src/sage/combinat/species/misc.py +++ b/src/sage/combinat/species/misc.py @@ -17,13 +17,15 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from sage.groups.perm_gps.permgroup import PermutationGroup -from sage.groups.perm_gps.permgroup import PermutationGroup_generic -from sage.groups.perm_gps.constructor import PermutationGroupElement -from sage.groups.perm_gps.permgroup_named import SymmetricGroup -from sage.misc.misc_c import prod from functools import wraps +from sage.misc.misc_c import prod +from sage.misc.lazy_import import lazy_import + +lazy_import('sage.groups.perm_gps.permgroup', ['PermutationGroup', 'PermutationGroup_generic']) +lazy_import('sage.groups.perm_gps.constructor', 'PermutationGroupElement') +lazy_import('sage.groups.perm_gps.permgroup_named', 'SymmetricGroup') + def change_support(perm, support, change_perm=None): """ diff --git a/src/sage/combinat/species/partition_species.py b/src/sage/combinat/species/partition_species.py index f9044db7c73..dea38378a7a 100644 --- a/src/sage/combinat/species/partition_species.py +++ b/src/sage/combinat/species/partition_species.py @@ -141,7 +141,7 @@ def __classcall__(cls, *args, **kwds): sage: P = species.PartitionSpecies(); P Partition species - """ + """ return super().__classcall__(cls, *args, **kwds) def __init__(self, min=None, max=None, weight=None): @@ -272,8 +272,8 @@ def _cis(self, series_ring, base_ring): EXAMPLES:: sage: P = species.PartitionSpecies() - sage: g = P.cycle_index_series() - sage: g[0:5] + sage: g = P.cycle_index_series() # needs sage.modules + sage: g[0:5] # needs sage.modules [p[], p[1], p[1, 1] + p[2], diff --git a/src/sage/combinat/species/permutation_species.py b/src/sage/combinat/species/permutation_species.py index 64534c9e8bb..59f41bbad0a 100644 --- a/src/sage/combinat/species/permutation_species.py +++ b/src/sage/combinat/species/permutation_species.py @@ -225,8 +225,8 @@ def _cis(self, series_ring, base_ring): EXAMPLES:: sage: P = species.PermutationSpecies() - sage: g = P.cycle_index_series() - sage: g[0:5] + sage: g = P.cycle_index_series() # needs sage.modules + sage: g[0:5] # needs sage.modules [p[], p[1], p[1, 1] + p[2], @@ -244,7 +244,7 @@ def _cis_gen(self, base_ring, m, n): EXAMPLES:: sage: P = species.PermutationSpecies() - sage: [P._cis_gen(QQ, 2, i) for i in range(10)] + sage: [P._cis_gen(QQ, 2, i) for i in range(10)] # needs sage.modules [p[], 0, p[2], 0, p[2, 2], 0, p[2, 2, 2], 0, p[2, 2, 2, 2], 0] """ from sage.combinat.sf.sf import SymmetricFunctions diff --git a/src/sage/combinat/species/product_species.py b/src/sage/combinat/species/product_species.py index 0989d2a8f8c..90209e64776 100644 --- a/src/sage/combinat/species/product_species.py +++ b/src/sage/combinat/species/product_species.py @@ -58,6 +58,7 @@ def transport(self, perm): """ EXAMPLES:: + sage: # needs sage.groups sage: p = PermutationGroupElement((2,3)) sage: S = species.SetSpecies() sage: F = S * S @@ -151,6 +152,7 @@ def automorphism_group(self): """ EXAMPLES:: + sage: # needs sage.groups sage: p = PermutationGroupElement((2,3)) sage: S = species.SetSpecies() sage: F = S * S @@ -161,7 +163,7 @@ def automorphism_group(self): :: - sage: [a.transport(g) for g in a.automorphism_group()] + sage: [a.transport(g) for g in a.automorphism_group()] # needs sage.groups [{1}*{2, 3, 4}, {1}*{2, 3, 4}, {1}*{2, 3, 4}, @@ -171,9 +173,9 @@ def automorphism_group(self): :: - sage: a = F.structures([1,2,3,4])[8]; a + sage: a = F.structures([1,2,3,4])[8]; a # needs sage.groups {2, 3}*{1, 4} - sage: [a.transport(g) for g in a.automorphism_group()] + sage: [a.transport(g) for g in a.automorphism_group()] # needs sage.groups [{2, 3}*{1, 4}, {2, 3}*{1, 4}, {2, 3}*{1, 4}, {2, 3}*{1, 4}] """ from sage.groups.perm_gps.constructor import PermutationGroupElement @@ -215,7 +217,7 @@ def __init__(self, F, G, min=None, max=None, weight=None): Product of (Permutation species) and (Permutation species) sage: F == loads(dumps(F)) True - sage: F._check() + sage: F._check() # needs sage.libs.flint True TESTS:: @@ -340,7 +342,7 @@ def _itgs(self, series_ring, base_ring): sage: P = species.PermutationSpecies() sage: F = P * P - sage: F.isotype_generating_series()[0:5] + sage: F.isotype_generating_series()[0:5] # needs sage.libs.flint [1, 2, 5, 10, 20] """ res = (self.left_factor().isotype_generating_series(base_ring) * @@ -355,7 +357,7 @@ def _cis(self, series_ring, base_ring): sage: P = species.PermutationSpecies() sage: F = P * P - sage: F.cycle_index_series()[0:5] + sage: F.cycle_index_series()[0:5] # needs sage.modules [p[], 2*p[1], 3*p[1, 1] + 2*p[2], @@ -409,7 +411,7 @@ def _equation(self, var_mapping): sage: X = species.SingletonSpecies() sage: S = X * X - sage: S.algebraic_equation_system() + sage: S.algebraic_equation_system() # needs sage.graphs [node0 + (-z^2)] """ from sage.misc.misc_c import prod diff --git a/src/sage/combinat/species/recursive_species.py b/src/sage/combinat/species/recursive_species.py index 3cd073f9f9c..8eaabf0d2a8 100644 --- a/src/sage/combinat/species/recursive_species.py +++ b/src/sage/combinat/species/recursive_species.py @@ -263,7 +263,7 @@ def _cis(self, series_ring, base_ring): EXAMPLES:: sage: F = CombinatorialSpecies() - sage: F.cycle_index_series() + sage: F.cycle_index_series() # needs sage.modules Uninitialized Lazy Series """ if base_ring not in self._cycle_index_series: @@ -429,17 +429,17 @@ def _add_to_digraph(self, d): EXAMPLES:: - sage: d = DiGraph(multiedges=True) + sage: d = DiGraph(multiedges=True) # needs sage.graphs sage: X = species.SingletonSpecies() sage: B = species.CombinatorialSpecies() sage: B.define(X+B*B) - sage: B._add_to_digraph(d); d + sage: B._add_to_digraph(d); d # needs sage.graphs Multi-digraph on 4 vertices TESTS:: sage: C = species.CombinatorialSpecies() - sage: C._add_to_digraph(d) + sage: C._add_to_digraph(d) # needs sage.graphs Traceback (most recent call last): ... NotImplementedError @@ -461,7 +461,7 @@ def _equation(self, var_mapping): EXAMPLES:: sage: C = species.CombinatorialSpecies() - sage: C.algebraic_equation_system() + sage: C.algebraic_equation_system() # needs sage.graphs Traceback (most recent call last): ... NotImplementedError @@ -469,7 +469,7 @@ def _equation(self, var_mapping): :: sage: B = species.BinaryTreeSpecies() - sage: B.algebraic_equation_system() + sage: B.algebraic_equation_system() # needs sage.graphs [-node3^2 + node1, -node1 + node3 + (-z)] """ try: diff --git a/src/sage/combinat/species/set_species.py b/src/sage/combinat/species/set_species.py index daa7d7e5835..94aa893cf46 100644 --- a/src/sage/combinat/species/set_species.py +++ b/src/sage/combinat/species/set_species.py @@ -57,8 +57,8 @@ def transport(self, perm): sage: F = species.SetSpecies() sage: a = F.structures(["a", "b", "c"]).random_element(); a {'a', 'b', 'c'} - sage: p = PermutationGroupElement((1,2)) - sage: a.transport(p) + sage: p = PermutationGroupElement((1,2)) # needs sage.groups + sage: a.transport(p) # needs sage.groups {'a', 'b', 'c'} """ return self @@ -74,7 +74,7 @@ def automorphism_group(self): sage: F = species.SetSpecies() sage: a = F.structures(["a", "b", "c"]).random_element(); a {'a', 'b', 'c'} - sage: a.automorphism_group() + sage: a.automorphism_group() # needs sage.groups Symmetric group of order 3! as a permutation group """ from sage.groups.perm_gps.permgroup_named import SymmetricGroup @@ -170,8 +170,8 @@ def _cis(self, series_ring, base_ring): EXAMPLES:: sage: S = species.SetSpecies() - sage: g = S.cycle_index_series() - sage: g[0:5] + sage: g = S.cycle_index_series() # needs sage.modules + sage: g[0:5] # needs sage.modules [p[], p[1], 1/2*p[1, 1] + 1/2*p[2], diff --git a/src/sage/combinat/species/species.py b/src/sage/combinat/species/species.py index 4cd3403ae61..d3f1e9d3867 100644 --- a/src/sage/combinat/species/species.py +++ b/src/sage/combinat/species/species.py @@ -24,12 +24,12 @@ sage: L = species.LinearOrderSpecies(min=1) sage: T = species.CombinatorialSpecies(min=1) sage: T.define(leaf + internal_node*L(T)) - sage: T.isotype_generating_series()[0:6] + sage: T.isotype_generating_series()[0:6] # needs sage.modules [0, 1, q, q^2 + q, q^3 + 3*q^2 + q, q^4 + 6*q^3 + 6*q^2 + q] Consider the following:: - sage: T.isotype_generating_series().coefficient(4) + sage: T.isotype_generating_series().coefficient(4) # needs sage.modules q^3 + 3*q^2 + q This means that, among the trees on `4` nodes, one has a @@ -335,7 +335,7 @@ def functorial_composition(self, g): sage: WP = species.SubsetSpecies() sage: P2 = E2*E sage: G = WP.functorial_composition(P2) - sage: G.isotype_generating_series()[0:5] + sage: G.isotype_generating_series()[0:5] # needs sage.modules [1, 1, 2, 4, 11] """ from .functorial_composition_species import FunctorialCompositionSpecies @@ -401,7 +401,7 @@ def _check(self, n=5): EXAMPLES:: sage: P = species.PartitionSpecies() - sage: P._check() + sage: P._check() # needs sage.libs.flint True """ st = self.structures(range(n)) @@ -448,7 +448,7 @@ def __pow__(self, n): sage: X^1 is X True sage: A = X^32 - sage: A.digraph() + sage: A.digraph() # needs sage.graphs Multi-digraph on 6 vertices TESTS:: @@ -622,13 +622,13 @@ def isotype_generating_series(self, base_ring=None): sage: P = species.PermutationSpecies() sage: g = P.isotype_generating_series() - sage: g[0:4] + sage: g[0:4] # needs sage.libs.flint [1, 1, 2, 3] - sage: g.counts(4) + sage: g.counts(4) # needs sage.libs.flint [1, 1, 2, 3] - sage: P.isotypes([1,2,3]).list() + sage: P.isotypes([1,2,3]).list() # needs sage.libs.flint [[2, 3, 1], [2, 1, 3], [1, 2, 3]] - sage: len(_) + sage: len(_) # needs sage.libs.flint 3 """ return self._get_series(OrdinaryGeneratingSeriesRing, "itgs", base_ring) @@ -643,8 +643,8 @@ def cycle_index_series(self, base_ring=None): EXAMPLES:: sage: P = species.PermutationSpecies() - sage: g = P.cycle_index_series() - sage: g[0:4] + sage: g = P.cycle_index_series() # needs sage.modules + sage: g[0:4] # needs sage.modules [p[], p[1], p[1, 1] + p[2], p[1, 1, 1] + p[2, 1] + p[3]] """ return self._get_series(CycleIndexSeriesRing, "cis", base_ring) @@ -710,19 +710,19 @@ def digraph(self): sage: X = species.SingletonSpecies() sage: B = species.CombinatorialSpecies() sage: B.define(X+B*B) - sage: g = B.digraph(); g + sage: g = B.digraph(); g # needs sage.graphs Multi-digraph on 4 vertices - sage: sorted(g, key=str) + sage: sorted(g, key=str) # needs sage.graphs [Combinatorial species, Product of (Combinatorial species) and (Combinatorial species), Singleton species, Sum of (Singleton species) and (Product of (Combinatorial species) and (Combinatorial species))] - sage: d = {sp: i for i, sp in enumerate(g)} - sage: g.relabel(d) - sage: g.canonical_label().edges(sort=True) + sage: d = {sp: i for i, sp in enumerate(g)} # needs sage.graphs + sage: g.relabel(d) # needs sage.graphs + sage: g.canonical_label().edges(sort=True) # needs sage.graphs [(0, 3, None), (2, 0, None), (2, 0, None), (3, 1, None), (3, 2, None)] """ from sage.graphs.digraph import DiGraph @@ -739,6 +739,7 @@ def _add_to_digraph(self, d): EXAMPLES:: + sage: # needs sage.graphs sage: d = DiGraph(multiedges=True) sage: X = species.SingletonSpecies() sage: X._add_to_digraph(d); d @@ -770,21 +771,25 @@ def algebraic_equation_system(self): EXAMPLES:: sage: B = species.BinaryTreeSpecies() - sage: B.algebraic_equation_system() + sage: B.algebraic_equation_system() # needs sage.graphs [-node3^2 + node1, -node1 + node3 + (-z)] :: - sage: sorted(B.digraph().vertex_iterator(), key=str) + sage: sorted(B.digraph().vertex_iterator(), key=str) # needs sage.graphs [Combinatorial species with min=1, - Product of (Combinatorial species with min=1) and (Combinatorial species with min=1), + Product of (Combinatorial species with min=1) + and (Combinatorial species with min=1), Singleton species, - Sum of (Singleton species) and (Product of (Combinatorial species with min=1) and (Combinatorial species with min=1))] + Sum of (Singleton species) + and (Product of (Combinatorial species with min=1) + and (Combinatorial species with min=1))] :: - sage: B.algebraic_equation_system()[0].parent() - Multivariate Polynomial Ring in node0, node1, node2, node3 over Fraction Field of Univariate Polynomial Ring in z over Rational Field + sage: B.algebraic_equation_system()[0].parent() # needs sage.graphs + Multivariate Polynomial Ring in node0, node1, node2, node3 over + Fraction Field of Univariate Polynomial Ring in z over Rational Field """ d = self.digraph() diff --git a/src/sage/combinat/species/structure.py b/src/sage/combinat/species/structure.py index a4de6349c6d..b3003ed0f13 100644 --- a/src/sage/combinat/species/structure.py +++ b/src/sage/combinat/species/structure.py @@ -16,8 +16,8 @@ sage: bar = species.EmptySetSpecies() sage: BB = CombinatorialSpecies() sage: BB.define(ball + ball*BB + ball*bar*BB) - sage: o = var('o') # optional - sage.symbolic - sage: BB.isotypes([o]*3).list() # optional - sage.symbolic + sage: o = var('o') # needs sage.symbolic + sage: BB.isotypes([o]*3).list() # needs sage.symbolic [o*(o*o), o*((o*{})*o), (o*{})*(o*o), (o*{})*((o*{})*o)] If we ignore the parentheses, we can read off that the integer @@ -277,9 +277,9 @@ def transport(self, perm): EXAMPLES:: sage: P = species.PartitionSpecies() - sage: s = (P+P).structures([1,2,3])[1]; s + sage: s = (P+P).structures([1,2,3])[1]; s # needs sage.libs.flint {{1, 3}, {2}} - sage: s.transport(PermutationGroupElement((2,3))) + sage: s.transport(PermutationGroupElement((2,3))) # needs sage.groups sage.libs.flint {{1, 2}, {3}} """ return self.__class__(self._parent, self._s.transport(perm), **self._options) @@ -289,9 +289,9 @@ def canonical_label(self): EXAMPLES:: sage: P = species.PartitionSpecies() - sage: s = (P+P).structures([1,2,3])[1]; s + sage: s = (P+P).structures([1,2,3])[1]; s # needs sage.libs.flint {{1, 3}, {2}} - sage: s.canonical_label() + sage: s.canonical_label() # needs sage.libs.flint {{1, 2}, {3}} """ return self.__class__(self._parent, self._s.canonical_label(), **self._options) diff --git a/src/sage/combinat/species/subset_species.py b/src/sage/combinat/species/subset_species.py index 81156e5183d..2e7a6697e29 100644 --- a/src/sage/combinat/species/subset_species.py +++ b/src/sage/combinat/species/subset_species.py @@ -74,11 +74,11 @@ def transport(self, perm): sage: F = species.SubsetSpecies() sage: a = F.structures(["a", "b", "c"])[5]; a {'a', 'c'} - sage: p = PermutationGroupElement((1,2)) - sage: a.transport(p) + sage: p = PermutationGroupElement((1,2)) # needs sage.groups + sage: a.transport(p) # needs sage.groups {'b', 'c'} - sage: p = PermutationGroupElement((1,3)) - sage: a.transport(p) + sage: p = PermutationGroupElement((1,3)) # needs sage.groups + sage: a.transport(p) # needs sage.groups {'a', 'c'} """ l = sorted([perm(i) for i in self._list]) @@ -94,12 +94,12 @@ def automorphism_group(self): sage: F = species.SubsetSpecies() sage: a = F.structures([1,2,3,4])[6]; a {1, 3} - sage: a.automorphism_group() + sage: a.automorphism_group() # needs sage.groups Permutation Group with generators [(2,4), (1,3)] :: - sage: [a.transport(g) for g in a.automorphism_group()] + sage: [a.transport(g) for g in a.automorphism_group()] # needs sage.groups [{1, 3}, {1, 3}, {1, 3}, {1, 3}] """ from sage.groups.perm_gps.permgroup_named import SymmetricGroup @@ -224,7 +224,7 @@ def _cis(self, series_ring, base_ring): EXAMPLES:: sage: S = species.SubsetSpecies() - sage: S.cycle_index_series()[0:5] + sage: S.cycle_index_series()[0:5] # needs sage.modules [p[], 2*p[1], 2*p[1, 1] + p[2], diff --git a/src/sage/combinat/species/sum_species.py b/src/sage/combinat/species/sum_species.py index fe45a352943..b3ff129dc55 100644 --- a/src/sage/combinat/species/sum_species.py +++ b/src/sage/combinat/species/sum_species.py @@ -38,7 +38,7 @@ def __init__(self, F, G, min=None, max=None, weight=None): sage: P = species.PermutationSpecies() sage: F = P + P - sage: F._check() + sage: F._check() # needs sage.libs.flint True sage: F == loads(dumps(F)) True @@ -126,7 +126,7 @@ def _isotypes(self, structure_class, labels): sage: P = species.PermutationSpecies() sage: F = P + P - sage: F.isotypes([1,2]).list() + sage: F.isotypes([1,2]).list() # needs sage.libs.flint [[2, 1], [1, 2], [2, 1], [1, 2]] """ for res in self._F.isotypes(labels): @@ -157,7 +157,7 @@ def _itgs(self, series_ring, base_ring): sage: P = species.PermutationSpecies() sage: F = P + P - sage: F.isotype_generating_series()[:5] + sage: F.isotype_generating_series()[:5] # needs sage.libs.flint [2, 2, 4, 6, 10] """ return (self.left_summand().isotype_generating_series(base_ring) + @@ -171,7 +171,7 @@ def _cis(self, series_ring, base_ring): sage: P = species.PermutationSpecies() sage: F = P + P - sage: F.cycle_index_series()[:5] + sage: F.cycle_index_series()[:5] # needs sage.modules [2*p[], 2*p[1], 2*p[1, 1] + 2*p[2], @@ -214,7 +214,7 @@ def _equation(self, var_mapping): sage: X = species.SingletonSpecies() sage: S = X + X - sage: S.algebraic_equation_system() + sage: S.algebraic_equation_system() # needs sage.graphs [node1 + (-2*z)] """ return sum(var_mapping[operand] for operand in self._state_info) diff --git a/src/sage/combinat/words/abstract_word.py b/src/sage/combinat/words/abstract_word.py index 610dba1437a..eaf5cbd4975 100644 --- a/src/sage/combinat/words/abstract_word.py +++ b/src/sage/combinat/words/abstract_word.py @@ -1476,24 +1476,24 @@ def sum_digits(self, base=2, mod=None): Sum of digits modulo 2 of the prime numbers written in base 2:: - sage: Word(primes(1000)).sum_digits() # optional - sage.libs.pari + sage: Word(primes(1000)).sum_digits() # needs sage.libs.pari word: 1001110100111010111011001011101110011011... Sum of digits modulo 3 of the prime numbers written in base 3:: - sage: Word(primes(1000)).sum_digits(base=3) # optional - sage.libs.pari + sage: Word(primes(1000)).sum_digits(base=3) # needs sage.libs.pari word: 2100002020002221222121022221022122111022... - sage: Word(primes(1000)).sum_digits(base=3, mod=3) # optional - sage.libs.pari + sage: Word(primes(1000)).sum_digits(base=3, mod=3) # needs sage.libs.pari word: 2100002020002221222121022221022122111022... Sum of digits modulo 2 of the prime numbers written in base 3:: - sage: Word(primes(1000)).sum_digits(base=3, mod=2) # optional - sage.libs.pari + sage: Word(primes(1000)).sum_digits(base=3, mod=2) # needs sage.libs.pari word: 0111111111111111111111111111111111111111... Sum of digits modulo 7 of the prime numbers written in base 10:: - sage: Word(primes(1000)).sum_digits(base=10, mod=7) # optional - sage.libs.pari + sage: Word(primes(1000)).sum_digits(base=10, mod=7) # needs sage.libs.pari word: 2350241354435041006132432241353546006304... Negative entries:: diff --git a/src/sage/combinat/words/alphabet.py b/src/sage/combinat/words/alphabet.py index 3289ad5aa1a..1de8838df00 100644 --- a/src/sage/combinat/words/alphabet.py +++ b/src/sage/combinat/words/alphabet.py @@ -192,15 +192,15 @@ def build_alphabet(data=None, names=None, name=None): Traceback (most recent call last): ... ValueError: invalid value for names - sage: Alphabet(8, x) # optional - sage.symbolic + sage: Alphabet(8, x) # needs sage.symbolic Traceback (most recent call last): ... ValueError: invalid value for names - sage: Alphabet(name=x, names="punctuation") # optional - sage.symbolic + sage: Alphabet(name=x, names="punctuation") # needs sage.symbolic Traceback (most recent call last): ... ValueError: name cannot be specified with any other argument - sage: Alphabet(x) # optional - sage.symbolic + sage: Alphabet(x) # needs sage.symbolic Traceback (most recent call last): ... ValueError: unable to construct an alphabet from the given parameters diff --git a/src/sage/combinat/words/finite_word.py b/src/sage/combinat/words/finite_word.py index bf355d9d10a..35fd6e69c55 100644 --- a/src/sage/combinat/words/finite_word.py +++ b/src/sage/combinat/words/finite_word.py @@ -136,7 +136,7 @@ sage: st = w.suffix_tree() sage: st Implicit Suffix Tree of the word: abaabbba - sage: st.show(word_labels=True) # optional - sage.plot + sage: st.show(word_labels=True) # needs sage.plot :: @@ -190,9 +190,9 @@ Rauzy graphs:: sage: f = words.FibonacciWord()[:30] - sage: f.rauzy_graph(4) # optional - sage.graphs + sage: f.rauzy_graph(4) # needs sage.graphs Looped digraph on 5 vertices - sage: f.reduced_rauzy_graph(4) # optional - sage.graphs + sage: f.reduced_rauzy_graph(4) # needs sage.graphs Looped multi-digraph on 2 vertices Left-special and bispecial factors:: @@ -221,6 +221,7 @@ from sage.combinat.words.abstract_word import Word_class from sage.combinat.words.words import Words from sage.misc.cachefunc import cached_method +from sage.misc.lazy_import import lazy_import from sage.combinat.words.word_options import word_options from sage.rings.infinity import Infinity from sage.rings.integer import Integer @@ -228,6 +229,8 @@ from sage.rings.rational_field import QQ from sage.sets.set import Set +lazy_import('sage.groups.perm_gps.permgroup_element', 'PermutationGroupElement') + class FiniteWord_class(Word_class): def __str__(self): @@ -1461,16 +1464,16 @@ def topological_entropy(self, n): sage: W = Words([0, 1]) sage: w = W([0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1]) - sage: t = w.topological_entropy(3); t # optional - sage.symbolic + sage: t = w.topological_entropy(3); t # needs sage.symbolic 1/3*log(7)/log(2) - sage: n(t) # optional - sage.symbolic + sage: n(t) # needs sage.symbolic 0.935784974019201 :: sage: w = words.ThueMorseWord()[:100] sage: topo = w.topological_entropy - sage: for i in range(0, 41, 5): # optional - sage.symbolic + sage: for i in range(0, 41, 5): # needs sage.symbolic ....: print("{} {}".format(i, n(topo(i), digits=5))) 0 1.0000 5 0.71699 @@ -1494,7 +1497,7 @@ def topological_entropy(self, n): sage: W = Words(range(20)) sage: w = W(range(20)) - sage: w.topological_entropy(3) # optional - sage.symbolic + sage: w.topological_entropy(3) # needs sage.symbolic 1/3*log(18)/log(20) """ d = self.parent().alphabet().cardinality() @@ -1522,12 +1525,12 @@ def rauzy_graph(self, n): sage: w = Word(range(10)); w word: 0123456789 - sage: g = w.rauzy_graph(3); g # optional - sage.graphs + sage: g = w.rauzy_graph(3); g # needs sage.graphs Looped digraph on 8 vertices sage: WordOptions(identifier='') - sage: g.vertices(sort=True) # optional - sage.graphs + sage: g.vertices(sort=True) # needs sage.graphs [012, 123, 234, 345, 456, 567, 678, 789] - sage: g.edges(sort=True) # optional - sage.graphs + sage: g.edges(sort=True) # needs sage.graphs [(012, 123, 3), (123, 234, 4), (234, 345, 5), @@ -1540,20 +1543,20 @@ def rauzy_graph(self, n): :: sage: f = words.FibonacciWord()[:100] - sage: f.rauzy_graph(8) # optional - sage.graphs + sage: f.rauzy_graph(8) # needs sage.graphs Looped digraph on 9 vertices :: sage: w = Word('1111111') - sage: g = w.rauzy_graph(3) # optional - sage.graphs - sage: g.edges(sort=True) # optional - sage.graphs + sage: g = w.rauzy_graph(3) # needs sage.graphs + sage: g.edges(sort=True) # needs sage.graphs [(word: 111, word: 111, word: 1)] :: sage: w = Word('111') - sage: for i in range(5): w.rauzy_graph(i) # optional - sage.graphs + sage: for i in range(5): w.rauzy_graph(i) # needs sage.graphs Looped multi-digraph on 1 vertex Looped digraph on 1 vertex Looped digraph on 1 vertex @@ -1564,9 +1567,9 @@ def rauzy_graph(self, n): sage: W = Words('abcde') sage: w = W('abc') - sage: w.rauzy_graph(0) # optional - sage.graphs + sage: w.rauzy_graph(0) # needs sage.graphs Looped multi-digraph on 1 vertex - sage: _.edges(sort=True) # optional - sage.graphs + sage: _.edges(sort=True) # needs sage.graphs [(word: , word: , word: a), (word: , word: , word: b), (word: , word: , word: c)] @@ -1633,21 +1636,21 @@ def reduced_rauzy_graph(self, n): sage: w = Word(range(10)); w word: 0123456789 - sage: g = w.reduced_rauzy_graph(3); g # optional - sage.graphs + sage: g = w.reduced_rauzy_graph(3); g # needs sage.graphs Looped multi-digraph on 2 vertices - sage: g.vertices(sort=True) # optional - sage.graphs + sage: g.vertices(sort=True) # needs sage.graphs [word: 012, word: 789] - sage: g.edges(sort=True) # optional - sage.graphs + sage: g.edges(sort=True) # needs sage.graphs [(word: 012, word: 789, word: 3456789)] For the Fibonacci word:: sage: f = words.FibonacciWord()[:100] - sage: g = f.reduced_rauzy_graph(8);g # optional - sage.graphs + sage: g = f.reduced_rauzy_graph(8);g # needs sage.graphs Looped multi-digraph on 2 vertices - sage: g.vertices(sort=True) # optional - sage.graphs + sage: g.vertices(sort=True) # needs sage.graphs [word: 01001010, word: 01010010] - sage: g.edges(sort=True) # optional - sage.graphs + sage: g.edges(sort=True) # needs sage.graphs [(word: 01001010, word: 01010010, word: 010), (word: 01010010, word: 01001010, word: 01010), (word: 01010010, word: 01001010, word: 10)] @@ -1656,14 +1659,14 @@ def reduced_rauzy_graph(self, n): sage: from itertools import cycle sage: w = Word(cycle('abcd'))[:100] - sage: g = w.reduced_rauzy_graph(3) # optional - sage.graphs - sage: g.edges(sort=True) # optional - sage.graphs + sage: g = w.reduced_rauzy_graph(3) # needs sage.graphs + sage: g.edges(sort=True) # needs sage.graphs [(word: abc, word: abc, word: dabc)] :: sage: w = Word('111') - sage: for i in range(5): w.reduced_rauzy_graph(i) # optional - sage.graphs + sage: for i in range(5): w.reduced_rauzy_graph(i) # needs sage.graphs Looped digraph on 1 vertex Looped digraph on 1 vertex Looped digraph on 1 vertex @@ -1673,12 +1676,12 @@ def reduced_rauzy_graph(self, n): For ultimately periodic words:: sage: sigma = WordMorphism('a->abcd,b->cd,c->cd,d->cd') - sage: w = sigma.fixed_point('a')[:100]; w + sage: w = sigma.fixed_point('a')[:100]; w # needs sage.modules word: abcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcdcd... - sage: g = w.reduced_rauzy_graph(5) # optional - sage.graphs - sage: g.vertices(sort=True) # optional - sage.graphs + sage: g = w.reduced_rauzy_graph(5) # needs sage.graphs + sage: g.vertices(sort=True) # needs sage.graphs [word: abcdc, word: cdcdc] - sage: g.edges(sort=True) # optional - sage.graphs + sage: g.edges(sort=True) # needs sage.graphs [(word: abcdc, word: cdcdc, word: dc), (word: cdcdc, word: cdcdc, word: dc)] AUTHOR: @@ -3096,9 +3099,9 @@ def defect(self, f=None): sage: sa = WordMorphism('a->ab,b->b') sage: sb = WordMorphism('a->a,b->ba') sage: w = (sa*sb*sb*sa*sa*sa*sb).fixed_point('a') - sage: w[:30].defect() # optional - sage.modules + sage: w[:30].defect() # needs sage.modules 0 - sage: w[110:140].defect() # optional - sage.modules + sage: w[110:140].defect() # needs sage.modules 0 It is even conjectured that the defect of an aperiodic word which is @@ -3106,11 +3109,11 @@ def defect(self, f=None): (see [BBGL2008]_):: sage: w = words.ThueMorseWord() - sage: w[:50].defect() # optional - sage.modules + sage: w[:50].defect() # needs sage.modules 12 - sage: w[:100].defect() # optional - sage.modules + sage: w[:100].defect() # needs sage.modules 16 - sage: w[:300].defect() # optional - sage.modules + sage: w[:300].defect() # needs sage.modules 52 For generalized defect with an involution different from the identity, @@ -5974,7 +5977,7 @@ def is_sturmian_factor(self): sage: words.LowerMechanicalWord(random(),alphabet='01')[:100].is_sturmian_factor() True - sage: words.CharacteristicSturmianWord(random())[:100].is_sturmian_factor() + sage: words.CharacteristicSturmianWord(random())[:100].is_sturmian_factor() # needs sage.rings.real_mpfr True :: @@ -6746,13 +6749,12 @@ def apply_permutation_to_positions(self, permutation): word: badc sage: w.apply_permutation_to_positions(Permutation([2,1,4,3])) word: badc - sage: w.apply_permutation_to_positions(PermutationGroupElement([2,1,4,3])) + sage: w.apply_permutation_to_positions(PermutationGroupElement([2,1,4,3])) # needs sage.groups word: badc sage: Word([1,2,3,4]).apply_permutation_to_positions([3,4,2,1]) word: 3421 """ from sage.combinat.permutation import Permutation - from sage.groups.perm_gps.permgroup_element import PermutationGroupElement if not isinstance(permutation, Permutation): if isinstance(permutation, PermutationGroupElement): permutation = Permutation(permutation.domain()) @@ -6777,11 +6779,10 @@ def apply_permutation_to_letters(self, permutation): word: dcba sage: w.apply_permutation_to_letters(Permutation(p)) word: badc - sage: w.apply_permutation_to_letters(PermutationGroupElement(p)) + sage: w.apply_permutation_to_letters(PermutationGroupElement(p)) # needs sage.groups word: badc """ from sage.combinat.permutation import Permutation - from sage.groups.perm_gps.permgroup_element import PermutationGroupElement if not isinstance(permutation, Permutation): if isinstance(permutation, PermutationGroupElement): permutation = Permutation(permutation.domain()) @@ -6823,18 +6824,19 @@ def colored_vector(self, x=0, y=0, width='default', height=1, cmap='hsv', thickn EXAMPLES:: - sage: Word(range(20)).colored_vector() # optional - sage.plot + sage: # needs sage.plot + sage: Word(range(20)).colored_vector() Graphics object consisting of 21 graphics primitives - sage: Word(range(100)).colored_vector(0,0,10,1) # optional - sage.plot + sage: Word(range(100)).colored_vector(0,0,10,1) Graphics object consisting of 101 graphics primitives - sage: Words(range(100))(range(10)).colored_vector() # optional - sage.plot + sage: Words(range(100))(range(10)).colored_vector() Graphics object consisting of 11 graphics primitives sage: w = Word('abbabaab') - sage: w.colored_vector() # optional - sage.plot + sage: w.colored_vector() Graphics object consisting of 9 graphics primitives - sage: w.colored_vector(cmap='autumn') # optional - sage.plot + sage: w.colored_vector(cmap='autumn') Graphics object consisting of 9 graphics primitives - sage: Word(range(20)).colored_vector(label='Rainbow') # optional - sage.plot + sage: Word(range(20)).colored_vector(label='Rainbow') Graphics object consisting of 23 graphics primitives When two words are defined under the same parent, same letters are @@ -6843,25 +6845,25 @@ def colored_vector(self, x=0, y=0, width='default', height=1, cmap='hsv', thickn sage: W = Words(range(20)) sage: w = W(range(20)) sage: y = W(range(10,20)) - sage: y.colored_vector(y=1, x=10) + w.colored_vector() # optional - sage.plot + sage: y.colored_vector(y=1, x=10) + w.colored_vector() # needs sage.plot Graphics object consisting of 32 graphics primitives TESTS: The empty word:: - sage: Word().colored_vector() # optional - sage.plot + sage: Word().colored_vector() # needs sage.plot Graphics object consisting of 1 graphics primitive - sage: Word().colored_vector(label='empty') # optional - sage.plot + sage: Word().colored_vector(label='empty') # needs sage.plot Graphics object consisting of 3 graphics primitives Unknown cmap:: - sage: Word(range(100)).colored_vector(cmap='jolies') # optional - sage.plot + sage: Word(range(100)).colored_vector(cmap='jolies') # needs sage.plot Traceback (most recent call last): ... RuntimeError: Color map jolies not known - sage: Word(range(100)).colored_vector(cmap='__doc__') # optional - sage.plot + sage: Word(range(100)).colored_vector(cmap='__doc__') # needs sage.plot Traceback (most recent call last): ... RuntimeError: Color map __doc__ not known diff --git a/src/sage/combinat/words/lyndon_word.py b/src/sage/combinat/words/lyndon_word.py index 6adb96421e5..4c978680380 100644 --- a/src/sage/combinat/words/lyndon_word.py +++ b/src/sage/combinat/words/lyndon_word.py @@ -64,9 +64,9 @@ def LyndonWords(e=None, k=None): word: 1112 sage: LW.last() word: 2333 - sage: LW.random_element() # random + sage: LW.random_element() # random # needs sage.libs.pari word: 1232 - sage: LW.cardinality() + sage: LW.cardinality() # needs sage.libs.pari 18 If e is a (weak) composition, then it returns the class of Lyndon @@ -277,9 +277,9 @@ def cardinality(self): sage: LyndonWords([]).cardinality() 0 - sage: LyndonWords([2,2]).cardinality() + sage: LyndonWords([2,2]).cardinality() # needs sage.libs.pari 1 - sage: LyndonWords([2,3,2]).cardinality() + sage: LyndonWords([2,3,2]).cardinality() # needs sage.libs.pari 30 Check to make sure that the count matches up with the number of @@ -287,7 +287,7 @@ def cardinality(self): sage: comps = [[],[2,2],[3,2,7],[4,2]] + Compositions(4).list() sage: lws = [LyndonWords(comp) for comp in comps] - sage: all(lw.cardinality() == len(lw.list()) for lw in lws) + sage: all(lw.cardinality() == len(lw.list()) for lw in lws) # needs sage.libs.pari True """ evaluation = self._e @@ -417,7 +417,7 @@ def __call__(self, *args, **kwds): Make sure that the correct length is checked (:trac:`30186`):: sage: L = LyndonWords(2, 4) - sage: _ = L(L.random_element()) + sage: _ = L(L.random_element()) # needs sage.libs.pari """ w = self._words(*args, **kwds) if kwds.get('check', True) and not w.is_lyndon(): @@ -443,7 +443,7 @@ def cardinality(self): """ TESTS:: - sage: [ LyndonWords(3,i).cardinality() for i in range(1, 11) ] + sage: [ LyndonWords(3,i).cardinality() for i in range(1, 11) ] # needs sage.libs.pari [3, 3, 8, 18, 48, 116, 312, 810, 2184, 5880] """ if self._k == 0: @@ -470,7 +470,7 @@ def __iter__(self): sage: sum(1 for lw in LyndonWords(1, 1000)) 0 - sage: list(LyndonWords(1, 1)) + sage: list(LyndonWords(1, 1)) # needs sage.libs.pari [word: 1] """ W = self._words._element_classes['list'] diff --git a/src/sage/combinat/words/morphic.py b/src/sage/combinat/words/morphic.py index 389c37a9b65..0db7a8db6fe 100644 --- a/src/sage/combinat/words/morphic.py +++ b/src/sage/combinat/words/morphic.py @@ -14,8 +14,7 @@ Creation of the fixed point of a morphism:: sage: m = WordMorphism('a->abc,b->baba,c->ca') - sage: w = m.fixed_point('a') - sage: w + sage: w = m.fixed_point('a'); w word: abcbabacababaabcbabaabccaabcbabaabcbabaa... sage: w.length() +Infinity @@ -24,14 +23,16 @@ abstract numeration system associated to the morphism and the starting letter, see chapter 3 of the book [BR2010b]_:: - sage: w[10000000] # optional - sage.modules + sage: w[10000000] # needs sage.modules 'b' """ from sage.combinat.words.word_infinite_datatypes import WordDatatype_callable +from sage.misc.lazy_import import lazy_import from sage.rings.infinity import Infinity -from sage.modules.free_module_element import vector + +lazy_import('sage.modules.free_module_element', 'vector') class WordDatatype_morphic(WordDatatype_callable): @@ -57,7 +58,7 @@ def __init__(self, parent, morphism, letter, coding=None, length=Infinity): sage: w = m.fixed_point('a') sage: w word: abaababaabaababaababaabaababaabaababaaba... - sage: w[555:1000] # optional - sage.modules + sage: w[555:1000] # needs sage.modules word: abaababaabaababaababaabaababaabaababaaba... sage: w.length() +Infinity @@ -68,20 +69,19 @@ def __init__(self, parent, morphism, letter, coding=None, length=Infinity): sage: m.fixed_point('a') word: abcbabacababaabcbabaabccaabcbabaabcbabaa... sage: w = m.fixed_point('a') - sage: w[7] # optional - sage.modules + sage: w[7] # needs sage.modules 'c' - sage: w[2:7] # optional - sage.modules + sage: w[2:7] # needs sage.modules word: cbaba - sage: w[500:503] # optional - sage.modules + sage: w[500:503] # needs sage.modules word: caa When the morphic word is finite:: sage: m = WordMorphism("a->ab,b->") - sage: w = m.fixed_point("a") - sage: w + sage: w = m.fixed_point("a"); w word: ab - sage: w[0] # optional - sage.modules + sage: w[0] # needs sage.modules 'a' sage: w.length() 2 @@ -93,7 +93,7 @@ def __init__(self, parent, morphism, letter, coding=None, length=Infinity): sage: from sage.combinat.words.morphic import WordDatatype_morphic sage: coding = {'a':'x', 'b':'y'} sage: w = WordDatatype_morphic(W, m, 'a', coding=coding) - sage: [w[i] for i in range(10)] # optional - sage.modules + sage: [w[i] for i in range(10)] # needs sage.modules ['x', 'y', 'x', 'x', 'y', 'x', 'y', 'x', 'x', 'y'] TESTS:: @@ -104,9 +104,9 @@ def __init__(self, parent, morphism, letter, coding=None, length=Infinity): sage: for _ in range(10000): _ = next(it) sage: L = [next(it) for _ in range(10)]; L ['d', 'd', 'd', 'c', 'd', 'd', 'd', 'c', 'b', 'a'] - sage: w[10000:10010] # optional - sage.modules + sage: w[10000:10010] # needs sage.modules word: dddcdddcba - sage: list(w[10000:10010]) == L # optional - sage.modules + sage: list(w[10000:10010]) == L # needs sage.modules True """ @@ -177,18 +177,18 @@ def representation(self, n): sage: m = WordMorphism('a->ab,b->a') sage: w = m.fixed_point('a') - sage: w.representation(5) # optional - sage.modules + sage: w.representation(5) # needs sage.modules [1, 0, 0, 0] When the morphic word is finite:: sage: m = WordMorphism("a->ab,b->,c->cdab,d->dcab") sage: w = m.fixed_point("a") - sage: w.representation(0) # optional - sage.modules + sage: w.representation(0) # needs sage.modules [] - sage: w.representation(1) # optional - sage.modules + sage: w.representation(1) # needs sage.modules [1] - sage: w.representation(2) # optional - sage.modules + sage: w.representation(2) # needs sage.modules Traceback (most recent call last): ... IndexError: index (=2) out of range, the fixed point is finite and has length 2 @@ -204,7 +204,7 @@ def representation(self, n): sage: w = WordDatatype_morphic(W, m, 'a') sage: type(w) - sage: w.representation(5) # optional - sage.modules + sage: w.representation(5) # needs sage.modules [1, 0, 0, 0] """ letters_to_int = {a:i for (i,a) in enumerate(self._alphabet)} @@ -255,11 +255,11 @@ def _func(self, key): sage: m = WordMorphism("a->ab,b->a") sage: w = m.fixed_point("a") - sage: w[0] + sage: w[0] # needs sage.modules 'a' - sage: w[5] + sage: w[5] # needs sage.modules 'a' - sage: w[10000] + sage: w[10000] # needs sage.modules 'a' TESTS: @@ -271,7 +271,7 @@ def _func(self, key): sage: W = m.domain() sage: from sage.combinat.words.morphic import WordDatatype_morphic sage: w = WordDatatype_morphic(W, m, 'a') - sage: w._func(5) + sage: w._func(5) # needs sage.modules 'a' """ diff --git a/src/sage/combinat/words/morphism.py b/src/sage/combinat/words/morphism.py index 7e04e8646d0..279c238718e 100644 --- a/src/sage/combinat/words/morphism.py +++ b/src/sage/combinat/words/morphism.py @@ -66,7 +66,7 @@ Incidence matrix:: - sage: matrix(m) # optional - sage.modules + sage: matrix(m) # needs sage.modules [2 3 1] [1 3 0] [1 1 1] @@ -93,17 +93,19 @@ from sage.misc.callable_dict import CallableDict from sage.structure.sage_object import SageObject from sage.misc.cachefunc import cached_method +from sage.misc.lazy_import import lazy_import from sage.misc.lazy_list import lazy_list from sage.sets.set import Set from sage.rings.rational_field import QQ from sage.rings.infinity import Infinity from sage.rings.integer_ring import IntegerRing from sage.rings.integer import Integer -from sage.modules.free_module_element import vector -from sage.matrix.constructor import Matrix from sage.combinat.words.word import FiniteWord_class from sage.combinat.words.words import FiniteWords, FiniteOrInfiniteWords +lazy_import('sage.modules.free_module_element', 'vector') +lazy_import('sage.matrix.constructor', 'Matrix') + def get_cycles(f, domain): r""" @@ -344,7 +346,7 @@ def __init__(self, data, domain=None, codomain=None): The image of a letter can be a set, but the order is not preserved:: - sage: WordMorphism({2:[4,5,6],3:set([4,1,8])}) #random results + sage: WordMorphism({2:[4,5,6],3:set([4,1,8])}) # random results WordMorphism: 2->456, 3->814 If the image of a letter is not iterable, it is considered as a @@ -612,7 +614,7 @@ def __str__(self) -> str: :: sage: s = WordMorphism({1:[1,2],2:[1]}) - sage: s.dual_map() # optional - sage.modules + sage: s.dual_map() # needs sage.modules E_1^*(1->12, 2->1) TESTS:: @@ -707,7 +709,7 @@ def __call__(self, w, order=1): sage: tm('a', 6.7) Traceback (most recent call last): ... - TypeError: order (6.70000000000000) must be a non-negative integer or plus Infinity + TypeError: order (6.7...) must be a non-negative integer or plus Infinity Only the first letter is considered for infinitely iterated image of a word under a morphism:: @@ -974,7 +976,7 @@ def __pow__(self, exp): sage: m^1.5 Traceback (most recent call last): ... - ValueError: exponent (1.50000000000000) must be an integer + ValueError: exponent (1.5...) must be an integer sage: m^-2 Traceback (most recent call last): ... @@ -1097,23 +1099,24 @@ def _matrix_(self, R=None): EXAMPLES:: + sage: # needs sage.modules sage: fibo = WordMorphism('a->ab,b->a') sage: tm = WordMorphism('a->ab,b->ba') - sage: Mfibo = matrix(fibo); Mfibo # indirect doctest # optional - sage.modules + sage: Mfibo = matrix(fibo); Mfibo # indirect doctest [1 1] [1 0] - sage: Mtm = matrix(tm); Mtm # optional - sage.modules + sage: Mtm = matrix(tm); Mtm [1 1] [1 1] - sage: Mtm * Mfibo == matrix(tm*fibo) # indirect doctest # optional - sage.modules + sage: Mtm * Mfibo == matrix(tm*fibo) # indirect doctest True - sage: Mfibo * Mtm == matrix(fibo*tm) # indirect doctest # optional - sage.modules + sage: Mfibo * Mtm == matrix(fibo*tm) # indirect doctest True - sage: Mfibo.parent() # optional - sage.modules + sage: Mfibo.parent() Full MatrixSpace of 2 by 2 dense matrices over Integer Ring - sage: p = Mfibo.charpoly(); p # optional - sage.modules + sage: p = Mfibo.charpoly(); p x^2 - x - 1 - sage: p.roots(ring=RR, multiplicities=False) # optional - sage.modules + sage: p.roots(ring=RR, multiplicities=False) [-0.618033988749895, 1.61803398874989] """ if R is None: @@ -1134,12 +1137,12 @@ def incidence_matrix(self): EXAMPLES:: sage: m = WordMorphism('a->abc,b->a,c->c') - sage: m.incidence_matrix() # optional - sage.modules + sage: m.incidence_matrix() # needs sage.modules [1 1 0] [1 0 0] [1 0 1] sage: m = WordMorphism('a->abc,b->a,c->c,d->abbccccabca,e->abc') - sage: m.incidence_matrix() # optional - sage.modules + sage: m.incidence_matrix() # needs sage.modules [1 1 0 3 1] [1 0 0 3 1] [1 0 1 5 1] @@ -1202,10 +1205,10 @@ def is_endomorphism(self): We check that :trac:`8674` is fixed:: - sage: P = WordPaths('abcd') # optional - sage.modules - sage: m = WordMorphism('a->adab,b->ab,c->cbcd,d->cd', # optional - sage.modules + sage: P = WordPaths('abcd') # needs sage.modules + sage: m = WordMorphism('a->adab,b->ab,c->cbcd,d->cd', # needs sage.modules ....: domain=P, codomain=P) - sage: m.is_endomorphism() # optional - sage.modules + sage: m.is_endomorphism() # needs sage.modules True """ return self.codomain() == self.domain() @@ -1404,19 +1407,19 @@ def partition_of_domain_alphabet(self): EXAMPLES:: sage: m = WordMorphism('a->b,b->a') - sage: m.partition_of_domain_alphabet() #random ordering + sage: m.partition_of_domain_alphabet() # random ordering ({'a'}, {'b'}, {}) sage: m = WordMorphism('a->b,b->a,c->c') - sage: m.partition_of_domain_alphabet() #random ordering + sage: m.partition_of_domain_alphabet() # random ordering ({'a'}, {'b'}, {'c'}) sage: m = WordMorphism('a->a,b->b,c->c') - sage: m.partition_of_domain_alphabet() #random ordering + sage: m.partition_of_domain_alphabet() # random ordering ({}, {}, {'a', 'c', 'b'}) sage: m = WordMorphism('A->T,T->A,C->G,G->C') - sage: m.partition_of_domain_alphabet() #random ordering + sage: m.partition_of_domain_alphabet() # random ordering ({'A', 'C'}, {'T', 'G'}, {}) sage: I = WordMorphism({0:oo,oo:0,1:-1,-1:1,2:-2,-2:2,3:-3,-3:3}) - sage: I.partition_of_domain_alphabet() #random ordering + sage: I.partition_of_domain_alphabet() # random ordering ({0, -1, -3, -2}, {1, 2, 3, +Infinity}, {}) TESTS:: @@ -1494,11 +1497,11 @@ def pisot_eigenvector_right(self): EXAMPLES:: sage: m = WordMorphism('a->aaaabbc,b->aaabbc,c->aabc') - sage: matrix(m) # optional - sage.modules + sage: matrix(m) # needs sage.modules [4 3 2] [2 2 1] [1 1 1] - sage: m.pisot_eigenvector_right() # optional - sage.modules sage.rings.number_field + sage: m.pisot_eigenvector_right() # needs sage.modules sage.rings.number_field (1, 0.5436890126920763?, 0.2955977425220848?) """ eig = self.incidence_matrix().eigenvectors_right() @@ -1524,11 +1527,11 @@ def pisot_eigenvector_left(self): EXAMPLES:: sage: m = WordMorphism('a->aaaabbc,b->aaabbc,c->aabc') - sage: matrix(m) # optional - sage.modules + sage: matrix(m) # needs sage.modules [4 3 2] [2 2 1] [1 1 1] - sage: m.pisot_eigenvector_left() # optional - sage.modules sage.rings.number_field + sage: m.pisot_eigenvector_left() # needs sage.modules sage.rings.number_field (1, 0.8392867552141611?, 0.5436890126920763?) """ eig = self.incidence_matrix().eigenvectors_left() @@ -1588,25 +1591,25 @@ def is_primitive(self): EXAMPLES:: sage: tm = WordMorphism('a->ab,b->ba') - sage: tm.is_primitive() + sage: tm.is_primitive() # needs sage.modules True sage: fibo = WordMorphism('a->ab,b->a') - sage: fibo.is_primitive() + sage: fibo.is_primitive() # needs sage.modules True sage: m = WordMorphism('a->bb,b->aa') - sage: m.is_primitive() + sage: m.is_primitive() # needs sage.modules False sage: f = WordMorphism({0:[1],1:[0]}) - sage: f.is_primitive() + sage: f.is_primitive() # needs sage.modules False :: sage: s = WordMorphism('a->b,b->c,c->ab') - sage: s.is_primitive() + sage: s.is_primitive() # needs sage.modules True sage: s = WordMorphism('a->b,b->c,c->d,d->e,e->f,f->g,g->h,h->ab') - sage: s.is_primitive() + sage: s.is_primitive() # needs sage.modules True TESTS:: @@ -1616,8 +1619,8 @@ def is_primitive(self): Traceback (most recent call last): ... TypeError: self (=a->bb, b->aac) is not an endomorphism - sage: m = WordMorphism('a->,b->',codomain=Words('ab')) - sage: m.is_primitive() + sage: m = WordMorphism('a->,b->', codomain=Words('ab')) + sage: m.is_primitive() # needs sage.modules False sage: m = WordMorphism('a->,b->') sage: m.is_primitive() @@ -1681,9 +1684,9 @@ def is_prolongable(self, letter): :: - sage: n0, n1 = matrix(2,[1,1,1,0]), matrix(2,[2,1,1,0]) - sage: n = {'a':n0, 'b':n1} - sage: WordMorphism(n).is_prolongable(letter='a') #todo: not implemented + sage: n0, n1 = matrix(2,[1,1,1,0]), matrix(2,[2,1,1,0]) # needs sage.modules + sage: n = {'a':n0, 'b':n1} # needs sage.modules + sage: WordMorphism(n).is_prolongable(letter='a') # not implemented, needs sage.modules Traceback (most recent call last): ... TypeError: codomain of self must be an instance of Words @@ -2074,37 +2077,37 @@ def language(self, n, u=None): The fibonacci morphism:: sage: s = WordMorphism({0: [0,1], 1: [0]}) - sage: sorted(s.language(3)) # optional - sage.modules + sage: sorted(s.language(3)) # needs sage.modules [word: 001, word: 010, word: 100, word: 101] - sage: len(s.language(1000)) # optional - sage.modules + sage: len(s.language(1000)) # needs sage.modules 1001 - sage: all(len(s.language(n)) == n+1 for n in range(100)) # optional - sage.modules + sage: all(len(s.language(n)) == n+1 for n in range(100)) # needs sage.modules True A growing but non-primitive example. The DOL-languages generated by 0 and 2 are different:: - sage: s = WordMorphism({0: [0,1], 1:[0], 2:[2,0,2]}) + sage: s = WordMorphism({0: [0,1], 1: [0], 2: [2,0,2]}) sage: u = s.fixed_point(0) - sage: A0 = u[:200].factor_set(5) - sage: B0 = s.language(5, [0]) # optional - sage.modules - sage: set(A0) == B0 # optional - sage.modules + sage: A0 = u[:200].factor_set(5) # needs sage.modules + sage: B0 = s.language(5, [0]) # needs sage.modules + sage: set(A0) == B0 # needs sage.modules True sage: v = s.fixed_point(2) - sage: A2 = v[:200].factor_set(5) - sage: B2 = s.language(5, [2]) # optional - sage.modules - sage: set(A2) == B2 # optional - sage.modules + sage: A2 = v[:200].factor_set(5) # needs sage.modules + sage: B2 = s.language(5, [2]) # needs sage.modules + sage: set(A2) == B2 # needs sage.modules True - sage: len(A0), len(A2) + sage: len(A0), len(A2) # needs sage.modules (6, 20) The Chacon transformation (non-primitive):: sage: s = WordMorphism({0: [0,0,1,0], 1:[1]}) - sage: sorted(s.language(10)) # optional - sage.modules + sage: sorted(s.language(10)) # needs sage.modules [word: 0001000101, word: 0001010010, ... @@ -2459,7 +2462,7 @@ def dual_map(self, k=1): EXAMPLES:: sage: sigma = WordMorphism({1: [2], 2: [3], 3: [1,2]}) - sage: sigma.dual_map() # optional - sage.modules + sage: sigma.dual_map() # needs sage.modules E_1^*(1->2, 2->3, 3->12) :: @@ -2513,7 +2516,7 @@ def rauzy_fractal_projection(self, eig=None, prec=53): is:: sage: s = WordMorphism('1->12,2->13,3->1') - sage: s.rauzy_fractal_projection() # optional - sage.modules + sage: s.rauzy_fractal_projection() # needs sage.modules {'1': (1.00000000000000, 0.000000000000000), '2': (-1.41964337760708, -0.606290729207199), '3': (-0.771844506346038, 1.11514250803994)} @@ -2521,9 +2524,9 @@ def rauzy_fractal_projection(self, eig=None, prec=53): TESTS:: sage: t = WordMorphism('1->12,2->3,3->45,4->5,5->6,6->7,7->8,8->1') - sage: E = t.incidence_matrix().eigenvalues() # optional - sage.modules - sage: x = [x for x in E if -0.8 < x < -0.7][0] # optional - sage.modules - sage: t.rauzy_fractal_projection(prec=10) # optional - sage.modules + sage: E = t.incidence_matrix().eigenvalues() # needs sage.modules + sage: x = [x for x in E if -0.8 < x < -0.7][0] # needs sage.modules + sage: t.rauzy_fractal_projection(prec=10) # needs sage.modules {'1': (1.0, 0.00), '2': (-1.7, -0.56), '3': (0.79, 1.3), @@ -2532,7 +2535,7 @@ def rauzy_fractal_projection(self, eig=None, prec=53): '6': (0.79, 1.3), '7': (0.21, -1.3), '8': (-0.88, 0.74)} - sage: t.rauzy_fractal_projection(eig=x, prec=10) # optional - sage.modules + sage: t.rauzy_fractal_projection(eig=x, prec=10) # needs sage.modules {'1': (1.0, 0.00), '2': (-0.12, -0.74), '3': (-0.66, -0.56), @@ -2617,20 +2620,20 @@ def rauzy_fractal_points(self, n=None, exchange=False, eig=None, translate=None, and ``'3'`` are respectively:: sage: s = WordMorphism('1->12,2->13,3->1') - sage: D = s.rauzy_fractal_points(n=100) # optional - sage.modules - sage: len(D['1']) # optional - sage.modules + sage: D = s.rauzy_fractal_points(n=100) # needs sage.modules + sage: len(D['1']) # needs sage.modules 54 - sage: len(D['2']) # optional - sage.modules + sage: len(D['2']) # needs sage.modules 30 - sage: len(D['3']) # optional - sage.modules + sage: len(D['3']) # needs sage.modules 16 TESTS:: sage: s = WordMorphism('1->12,2->13,3->1') - sage: D = s.rauzy_fractal_points(n=100, exchange=True, # optional - sage.modules + sage: D = s.rauzy_fractal_points(n=100, exchange=True, # needs sage.modules ....: translate=[(3,1,-2), (5,-33,8)], prec=40) - sage: len(D['1']) # optional - sage.modules + sage: len(D['1']) # needs sage.modules 108 AUTHOR: @@ -2792,7 +2795,7 @@ def rauzy_fractal_plot(self, n=None, exchange=False, eig=None, #. The Rauzy fractal of the Tribonacci substitution:: sage: s = WordMorphism('1->12,2->13,3->1') - sage: s.rauzy_fractal_plot() # long time # optional - sage.plot + sage: s.rauzy_fractal_plot() # long time # needs sage.plot Graphics object consisting of 3 graphics primitives #. The "Hokkaido" fractal. We tweak the plot using the plotting options @@ -2841,8 +2844,8 @@ def rauzy_fractal_plot(self, n=None, exchange=False, eig=None, #. Different fractals can be obtained by choosing another (non-Pisot) eigenvalue:: sage: s = WordMorphism('1->12,2->3,3->45,4->5,5->6,6->7,7->8,8->1') - sage: E = s.incidence_matrix().eigenvalues() # optional - sage.modules - sage: x = [x for x in E if -0.8 < x < -0.7][0] # optional - sage.modules + sage: E = s.incidence_matrix().eigenvalues() # needs sage.modules + sage: x = [x for x in E if -0.8 < x < -0.7][0] # needs sage.modules sage: s.rauzy_fractal_plot() # not tested (> 1 second) sage: s.rauzy_fractal_plot(eig=x) # not tested (> 1 second) @@ -2885,8 +2888,8 @@ def rauzy_fractal_plot(self, n=None, exchange=False, eig=None, :: sage: t = WordMorphism("a->aC,b->d,C->de,d->a,e->ab") # substitution found by Julien Bernat - sage: V = [vector((0,0,1,0,-1)), vector((0,0,1,-1,0))] # optional - sage.modules - sage: S = set(map(tuple, [i*V[0] + j*V[1] + sage: V = [vector((0,0,1,0,-1)), vector((0,0,1,-1,0))] # needs sage.modules + sage: S = set(map(tuple, [i*V[0] + j*V[1] # needs sage.modules ....: for i in [-1,0,1] for j in [-1,0,1]])) sage: t.rauzy_fractal_plot(n=10000, # not tested (> 1 second) ....: translate=S, exchange=true) @@ -2909,7 +2912,7 @@ def rauzy_fractal_plot(self, n=None, exchange=False, eig=None, TESTS:: sage: s = WordMorphism('a->ab,b->c,c->d,d->e,e->a') - sage: s.rauzy_fractal_plot(n=1000, colormap='Set1', # optional - sage.modules sage.plot + sage: s.rauzy_fractal_plot(n=1000, colormap='Set1', # needs sage.modules sage.plot ....: opacity={'a':0.5,'b':1,'c':0.7,'d':0,'e':0.2}, ....: plot_origin=(100,"black"), plot_basis=True, ....: point_size=2.5) @@ -3329,24 +3332,25 @@ def abelian_rotation_subspace(self): EXAMPLES:: - sage: WordMorphism('0->1,1->0').abelian_rotation_subspace() # optional - sage.modules + sage: # needs sage.modules + sage: WordMorphism('0->1,1->0').abelian_rotation_subspace() Vector space of degree 2 and dimension 2 over Rational Field Basis matrix: [1 0] [0 1] - sage: WordMorphism('0->01,1->10').abelian_rotation_subspace() # optional - sage.modules + sage: WordMorphism('0->01,1->10').abelian_rotation_subspace() Vector space of degree 2 and dimension 0 over Rational Field Basis matrix: [] - sage: WordMorphism('0->01,1->1').abelian_rotation_subspace() # optional - sage.modules + sage: WordMorphism('0->01,1->1').abelian_rotation_subspace() Vector space of degree 2 and dimension 1 over Rational Field Basis matrix: [0 1] - sage: WordMorphism('1->122,2->211').abelian_rotation_subspace() # optional - sage.modules + sage: WordMorphism('1->122,2->211').abelian_rotation_subspace() Vector space of degree 2 and dimension 1 over Rational Field Basis matrix: [ 1 -1] - sage: WordMorphism('0->1,1->102,2->3,3->4,4->2').abelian_rotation_subspace() # optional - sage.modules + sage: WordMorphism('0->1,1->102,2->3,3->4,4->2').abelian_rotation_subspace() Vector space of degree 5 and dimension 3 over Rational Field Basis matrix: [0 0 1 0 0] @@ -3355,7 +3359,7 @@ def abelian_rotation_subspace(self): The domain needs to be equal to the codomain:: - sage: WordMorphism('0->1,1->',codomain=Words('01')).abelian_rotation_subspace() # optional - sage.modules + sage: WordMorphism('0->1,1->',codomain=Words('01')).abelian_rotation_subspace() # needs sage.modules Vector space of degree 2 and dimension 0 over Rational Field Basis matrix: [] diff --git a/src/sage/combinat/words/paths.py b/src/sage/combinat/words/paths.py index cc4aecd250b..5c84a784533 100644 --- a/src/sage/combinat/words/paths.py +++ b/src/sage/combinat/words/paths.py @@ -45,7 +45,7 @@ [(0, 0), (1, 2), (-2, 6), (-1, 8), (-1, 5), (-1, 2), (-4, 6), (-3, 8)] sage: p.is_closed() False - sage: p.plot() # optional - sage.plot + sage: p.plot() # needs sage.plot Graphics object consisting of 3 graphics primitives To obtain a list of all the available word path specific functions, @@ -104,14 +104,14 @@ Finite Dyck paths sage: d = D('()()()(())'); d Path: ()()()(()) - sage: d.plot() # optional - sage.plot + sage: d.plot() # needs sage.plot Graphics object consisting of 3 graphics primitives :: sage: P = WordPaths('abcdef', steps='triangle_grid') sage: p = P('babaddefadabcadefaadfafabacdefa') - sage: p.plot() # optional - sage.plot + sage: p.plot() # needs sage.plot Graphics object consisting of 3 graphics primitives Vector steps may be in more than 2 dimensions:: @@ -120,7 +120,7 @@ sage: P = WordPaths(alphabet='abc', steps=d); P Word Paths over 3 steps sage: p = P('abcabcabcabcaabacabcababcacbabacacabcaccbcac') - sage: p.plot() # optional - sage.plot + sage: p.plot() # needs sage.plot Graphics3d Object :: @@ -137,7 +137,7 @@ sage: CubePaths = WordPaths('abcABC', steps='cube_grid'); CubePaths Word Paths on the cube grid - sage: CubePaths('abcabaabcabAAAAA').plot() # optional - sage.plot + sage: CubePaths('abcabaabcabAAAAA').plot() # needs sage.plot Graphics3d Object The input data may be a str, a list, a tuple, @@ -188,7 +188,6 @@ lazy_import("sage.plot.all", ["arrow", "line", "polygon", "point", "Graphics"]) from sage.modules.free_module_element import vector from sage.rings.integer_ring import ZZ -from sage.rings.number_field.number_field import QuadraticField from sage.rings.real_mpfr import RR from .word_datatypes import (WordDatatype_str, WordDatatype_list, @@ -202,6 +201,8 @@ WordDatatype_callable) from sage.matrix.constructor import vector_on_axis_rotation_matrix +lazy_import('sage.rings.number_field.number_field', 'QuadraticField') + ####################################################################### # # @@ -1365,15 +1366,15 @@ def plot_projection(self, v=None, letters=None, color=None, ring=None, To remove the axis, do like this:: - sage: r = w.plot_projection(v) # optional - sage.plot - sage: r.axes(False) # optional - sage.plot - sage: r # long time (2s) # optional - sage.plot + sage: r = w.plot_projection(v) # needs sage.plot + sage: r.axes(False) # needs sage.plot + sage: r # long time (2s) # needs sage.plot Graphics object consisting of 200 graphics primitives You can assign different colors to each letter:: sage: color = {'1': 'purple', '2': (.2,.3,.4), '3': 'magenta'} - sage: w.plot_projection(v, color=color) # long time (2s) # optional - sage.plot + sage: w.plot_projection(v, color=color) # long time (2s) # needs sage.plot Graphics object consisting of 200 graphics primitives The 3d-Rauzy fractal:: @@ -1383,14 +1384,14 @@ def plot_projection(self, v=None, letters=None, color=None, ring=None, sage: v = s.pisot_eigenvector_right() sage: P = WordPaths('1234',[(1,0,0,0), (0,1,0,0), (0,0,1,0), (0,0,0,1)]) sage: w = P(D[:200]) - sage: w.plot_projection(v) # optional - sage.plot + sage: w.plot_projection(v) # needs sage.plot Graphics3d Object The dimension of vector space of the parent must be 3 or 4:: sage: P = WordPaths('ab', [(1, 0), (0, 1)]) sage: p = P('aabbabbab') - sage: p.plot_projection() # optional - sage.plot + sage: p.plot_projection() # needs sage.plot Traceback (most recent call last): ... TypeError: The dimension of the vector space (=2) must be 3 or 4 @@ -1444,7 +1445,7 @@ def projected_path(self, v=None, ring=None): sage: p = w.projected_path(v) sage: p Path: 1213121121312121312112131213121121312121... - sage: p[:20].plot() # optional - sage.plot + sage: p[:20].plot() # needs sage.plot Graphics object consisting of 3 graphics primitives The ``ring`` argument allows to change the precision of the @@ -1530,42 +1531,42 @@ def plot(self, pathoptions=dict(rgbcolor='red',thickness=3), A non closed path on the square grid:: sage: P = WordPaths('abAB') - sage: P('abababAABAB').plot() # optional - sage.plot + sage: P('abababAABAB').plot() # needs sage.plot Graphics object consisting of 3 graphics primitives A closed path on the square grid:: - sage: P('abababAABABB').plot() # optional - sage.plot + sage: P('abababAABABB').plot() # needs sage.plot Graphics object consisting of 4 graphics primitives A Dyck path:: sage: P = WordPaths('()', steps='dyck') - sage: P('()()()((()))').plot() # optional - sage.plot + sage: P('()()()((()))').plot() # needs sage.plot Graphics object consisting of 3 graphics primitives A path in the triangle grid:: sage: P = WordPaths('abcdef', steps='triangle_grid') - sage: P('abcdedededefab').plot() # optional - sage.plot + sage: P('abcdedededefab').plot() # needs sage.plot Graphics object consisting of 3 graphics primitives A polygon of length 220 that tiles the plane in two ways:: sage: P = WordPaths('abAB') - sage: P('aBababAbabaBaBABaBabaBaBABAbABABaBabaBaBABaBababAbabaBaBABaBabaBaBABAbABABaBABAbAbabAbABABaBABAbABABaBabaBaBABAbABABaBABAbAbabAbABAbAbabaBababAbABAbAbabAbABABaBABAbAbabAbABAbAbabaBababAbabaBaBABaBababAbabaBababAbABAbAbab').plot() # optional - sage.plot + sage: P('aBababAbabaBaBABaBabaBaBABAbABABaBabaBaBABaBababAbabaBaBABaBabaBaBABAbABABaBABAbAbabAbABABaBABAbABABaBabaBaBABAbABABaBABAbAbabAbABAbAbabaBababAbABAbAbabAbABABaBABAbAbabAbABAbAbabaBababAbabaBaBABaBababAbabaBababAbABAbAbab').plot() # needs sage.plot Graphics object consisting of 4 graphics primitives With gridlines:: - sage: P('ababababab').plot(gridlines=True) # optional - sage.plot + sage: P('ababababab').plot(gridlines=True) # needs sage.plot TESTS:: sage: P = WordPaths('abAB') - sage: P().plot() # optional - sage.plot + sage: P().plot() # needs sage.plot Graphics object consisting of 3 graphics primitives - sage: sum(map(plot,map(P,['a','A','b','B']))) # optional - sage.plot + sage: sum(map(plot,map(P,['a','A','b','B']))) # needs sage.plot Graphics object consisting of 12 graphics primitives """ G = Graphics() @@ -1614,44 +1615,45 @@ def animate(self): sage: P = WordPaths('abAB') sage: p = P('aaababbb') - sage: a = p.animate(); print(a) # optional - sage.plot + sage: a = p.animate(); print(a) # needs sage.plot Animation with 9 frames - sage: show(a) # long time # optional -- ImageMagick sage.plot - sage: show(a, delay=35, iterations=3) # long time # optional -- ImageMagick sage.plot + sage: show(a) # long time, optional - imagemagick, needs sage.plot + sage: show(a, delay=35, iterations=3) # long time, optional - imagemagick, needs sage.plot :: sage: P = WordPaths('abcdef',steps='triangle') sage: p = P('abcdef') - sage: a = p.animate(); print(a) # optional - sage.plot + sage: a = p.animate(); print(a) # needs sage.plot Animation with 8 frames - sage: show(a) # long time # optional -- ImageMagick sage.plot + sage: show(a) # long time, optional - imagemagick, needs sage.plot If the path is closed, the plain polygon is added at the end of the animation:: sage: P = WordPaths('abAB') sage: p = P('ababAbABABaB') - sage: a = p.animate(); print(a) # optional - sage.plot + sage: a = p.animate(); print(a) # needs sage.plot Animation with 14 frames - sage: show(a) # long time # optional -- ImageMagick sage.plot + sage: show(a) # long time, optional - imagemagick, needs sage.plot Another example illustrating a Fibonacci tile:: sage: w = words.fibonacci_tile(2) - sage: a = w.animate(); print(a) # optional - sage.plot + sage: a = w.animate(); print(a) # needs sage.plot Animation with 54 frames - sage: show(a) # long time # optional -- ImageMagick sage.plot + sage: show(a) # long time, optional - imagemagick, needs sage.plot The first 4 Fibonacci tiles in an animation:: - sage: a = words.fibonacci_tile(0).animate() # optional - sage.plot - sage: b = words.fibonacci_tile(1).animate() # optional - sage.plot - sage: c = words.fibonacci_tile(2).animate() # optional - sage.plot - sage: d = words.fibonacci_tile(3).animate() # optional - sage.plot - sage: print(a*b*c*d) # optional - sage.plot + sage: # needs sage.plot + sage: a = words.fibonacci_tile(0).animate() + sage: b = words.fibonacci_tile(1).animate() + sage: c = words.fibonacci_tile(2).animate() + sage: d = words.fibonacci_tile(3).animate() + sage: print(a*b*c*d) Animation with 296 frames - sage: show(a*b*c*d) # long time # optional -- ImageMagick sage.plot + sage: show(a*b*c*d) # long time, optional - imagemagick .. note:: @@ -1713,17 +1715,17 @@ def plot_directive_vector(self, options=dict(rgbcolor='blue')): Word Paths on the square grid sage: p = P('aaaccaccacacacaccccccbbdd'); p Path: aaaccaccacacacaccccccbbdd - sage: R = p.plot() + p.plot_directive_vector() # optional - sage.plot - sage: R.axes(False) # optional - sage.plot - sage: R.set_aspect_ratio(1) # optional - sage.plot - sage: R.plot() # optional - sage.plot + sage: R = p.plot() + p.plot_directive_vector() # needs sage.plot + sage: R.axes(False) # needs sage.plot + sage: R.set_aspect_ratio(1) # needs sage.plot + sage: R.plot() # needs sage.plot Graphics object consisting of 4 graphics primitives TESTS: A closed path:: - sage: P('acbd').plot_directive_vector() # optional - sage.plot + sage: P('acbd').plot_directive_vector() # needs sage.plot Graphics object consisting of 1 graphics primitive """ start = self.start_point() @@ -2020,12 +2022,12 @@ def plot(self, pathoptions=dict(rgbcolor='red',arrow_head=True,thickness=3), Word Paths over 2 steps sage: p = P('ababab'); p Path: ababab - sage: p.plot() # optional - sage.plot + sage: p.plot() # needs sage.plot Graphics3d Object sage: P = WordPaths('abcABC', steps='cube_grid') sage: p = P('abcabcAABBC') - sage: p.plot() # optional - sage.plot + sage: p.plot() # needs sage.plot Graphics3d Object """ diff --git a/src/sage/combinat/words/suffix_trees.py b/src/sage/combinat/words/suffix_trees.py index 5e4fa13ddea..8375bde1a8a 100644 --- a/src/sage/combinat/words/suffix_trees.py +++ b/src/sage/combinat/words/suffix_trees.py @@ -13,12 +13,15 @@ from itertools import chain from sage.structure.sage_object import SageObject -from sage.graphs.digraph import DiGraph from sage.sets.set import Set from sage.combinat.words.words import Words from sage.combinat.words.word import Word +from sage.misc.lazy_import import lazy_import from sage.rings.integer import Integer +lazy_import('sage.graphs.digraph', 'DiGraph') + + ################################################################################ # Suffix Tries ################################################################################ @@ -437,9 +440,9 @@ def to_digraph(self): sage: from sage.combinat.words.suffix_trees import SuffixTrie sage: w = Words("cao")("cac") sage: t = SuffixTrie(w) - sage: d = t.to_digraph(); d # optional - sage.graphs + sage: d = t.to_digraph(); d # needs sage.graphs Digraph on 6 vertices - sage: d.adjacency_matrix() # optional - sage.graphs sage.modules + sage: d.adjacency_matrix() # needs sage.graphs sage.modules [0 1 0 1 0 0] [0 0 1 0 0 0] [0 0 0 0 1 0] @@ -461,13 +464,13 @@ def plot(self, layout='tree', tree_root=0, tree_orientation='up', EXAMPLES:: sage: from sage.combinat.words.suffix_trees import SuffixTrie - sage: SuffixTrie(Word("cacao")).plot() # optional - sage.plot + sage: SuffixTrie(Word("cacao")).plot() # needs sage.plot Graphics object consisting of 38 graphics primitives TESTS:: sage: from sage.combinat.words.suffix_trees import SuffixTrie - sage: type(SuffixTrie(Word("cacao")).plot()) # optional - sage.plot + sage: type(SuffixTrie(Word("cacao")).plot()) # needs sage.plot """ tree = self.to_digraph() @@ -491,7 +494,7 @@ def show(self, *args, **kwds): sage: from sage.combinat.words.suffix_trees import SuffixTrie sage: w = Words("cao")("cac") sage: t = SuffixTrie(w) - sage: t.show() # optional - sage.plot + sage: t.show() # needs sage.plot """ self.plot(*args, **kwds).show() return @@ -829,7 +832,7 @@ def to_digraph(self, word_labels=False): sage: from sage.combinat.words.suffix_trees import ImplicitSuffixTree sage: W = Words([0,1,2]) sage: t = ImplicitSuffixTree(W([0,1,0,1,2])) - sage: t.to_digraph() # optional - sage.graphs + sage: t.to_digraph() # needs sage.graphs Digraph on 8 vertices """ if not self._letters: @@ -865,17 +868,17 @@ def plot(self, word_labels=False, layout='tree', tree_root=0, EXAMPLES:: sage: from sage.combinat.words.suffix_trees import ImplicitSuffixTree - sage: ImplicitSuffixTree(Word('cacao')).plot(word_labels=True) # optional - sage.graphs sage.plot + sage: ImplicitSuffixTree(Word('cacao')).plot(word_labels=True) # needs sage.graphs sage.plot Graphics object consisting of 23 graphics primitives - sage: ImplicitSuffixTree(Word('cacao')).plot(word_labels=False) # optional - sage.graphs sage.plot + sage: ImplicitSuffixTree(Word('cacao')).plot(word_labels=False) # needs sage.graphs sage.plot Graphics object consisting of 23 graphics primitives TESTS:: sage: from sage.combinat.words.suffix_trees import ImplicitSuffixTree - sage: type(ImplicitSuffixTree(Word('cacao')).plot(word_labels=True)) # optional - sage.graphs sage.plot + sage: type(ImplicitSuffixTree(Word('cacao')).plot(word_labels=True)) # needs sage.graphs sage.plot - sage: type(ImplicitSuffixTree(Word('cacao')).plot(word_labels=False)) # optional - sage.graphs sage.plot + sage: type(ImplicitSuffixTree(Word('cacao')).plot(word_labels=False)) # needs sage.graphs sage.plot """ tree = self.to_digraph(word_labels=word_labels) @@ -904,8 +907,8 @@ def show(self, word_labels=None, *args, **kwds): sage: from sage.combinat.words.suffix_trees import ImplicitSuffixTree sage: w = Words("cao")("cacao") sage: t = ImplicitSuffixTree(w) - sage: t.show(word_labels=True) # optional - sage.plot - sage: t.show(word_labels=False) # optional - sage.plot + sage: t.show(word_labels=True) # needs sage.plot + sage: t.show(word_labels=False) # needs sage.plot """ self.plot(word_labels=word_labels, *args, **kwds).show() return @@ -1506,7 +1509,7 @@ def uncompactify(self): sage: abbab = Words("ab")("abbab") sage: s = SuffixTrie(abbab) sage: t = ImplicitSuffixTree(abbab) - sage: t.uncompactify().is_isomorphic(s.to_digraph()) # optional - sage.graphs + sage: t.uncompactify().is_isomorphic(s.to_digraph()) # needs sage.graphs True """ tree = self.to_digraph(word_labels=True) diff --git a/src/sage/combinat/words/word.py b/src/sage/combinat/words/word.py index 4555c2df762..132195589e9 100644 --- a/src/sage/combinat/words/word.py +++ b/src/sage/combinat/words/word.py @@ -23,6 +23,7 @@ # (at your option) any later version. # http://www.gnu.org/licenses/ #***************************************************************************** +from sage.misc.lazy_import import lazy_import from sage.combinat.words.word_char import WordDatatype_char from sage.combinat.words.abstract_word import Word_class from sage.combinat.words.finite_word import FiniteWord_class @@ -36,7 +37,8 @@ WordDatatype_callable_with_caching, WordDatatype_callable) from .morphic import WordDatatype_morphic -from sage.monoids.free_monoid_element import FreeMonoidElement + +lazy_import('sage.monoids.free_monoid_element', 'FreeMonoidElement') # TODO. Word needs to be replaced by Word. Consider renaming # Word_class to Word and imbedding Word as its __call__ method. @@ -263,7 +265,7 @@ class FiniteWord_char(WordDatatype_char, FiniteWord_class): sage: len(w.factor_set()) 127 - sage: w.rauzy_graph(5) # optional - sage.graphs + sage: w.rauzy_graph(5) # needs sage.graphs Looped digraph on 9 vertices sage: u = W([1,2,3]) diff --git a/src/sage/combinat/words/word_char.pyx b/src/sage/combinat/words/word_char.pyx index f2b7b47edb2..1b68cd293ce 100644 --- a/src/sage/combinat/words/word_char.pyx +++ b/src/sage/combinat/words/word_char.pyx @@ -716,9 +716,9 @@ cdef class WordDatatype_char(WordDatatype): sage: W = Words([0,1]) sage: w = words.FibonacciWord() sage: w = W(list(w[:5000])) - sage: L = [[len(w[n:].longest_common_prefix(w[n+fibonacci(i):])) + sage: L = [[len(w[n:].longest_common_prefix(w[n+fibonacci(i):])) # needs sage.libs.pari ....: for i in range(5,15)] for n in range(1,1000)] - sage: for n,l in enumerate(L): + sage: for n,l in enumerate(L): # needs sage.libs.pari ....: if l.count(0) > 4: ....: print("{} {}".format(n+1,l)) 375 [0, 13, 0, 34, 0, 89, 0, 233, 0, 233] diff --git a/src/sage/combinat/words/word_generators.py b/src/sage/combinat/words/word_generators.py index d7093ae997c..58886bd9108 100644 --- a/src/sage/combinat/words/word_generators.py +++ b/src/sage/combinat/words/word_generators.py @@ -59,7 +59,6 @@ from random import randint from sage.misc.cachefunc import cached_method from sage.rings.integer_ring import ZZ -from sage.rings.real_mpfr import RR from sage.rings.infinity import Infinity from sage.combinat.words.abstract_word import Word_class from sage.combinat.words.word import FiniteWord_list @@ -68,6 +67,9 @@ from sage.combinat.words.morphism import WordMorphism from sage.arith.misc import gcd from sage.misc.decorators import rename_keyword +from sage.misc.lazy_import import lazy_import + +lazy_import('sage.rings.real_mpfr', 'RR') def _build_tab(sym, tab, W): @@ -241,10 +243,10 @@ def markoff_number(self): sage: w0 = words.LowerChristoffelWord(4,7) sage: w1, w2 = w0.standard_factorization() - sage: (m0,m1,m2) = (w.markoff_number() for w in (w0,w1,w2)) # optional - sage.modules - sage: (m0,m1,m2) # optional - sage.modules + sage: (m0,m1,m2) = (w.markoff_number() for w in (w0,w1,w2)) # needs sage.modules + sage: (m0,m1,m2) # needs sage.modules (294685, 13, 7561) - sage: m0**2 + m1**2 + m2**2 == 3*m0*m1*m2 # optional - sage.modules + sage: m0**2 + m1**2 + m2**2 == 3*m0*m1*m2 # needs sage.modules True """ from sage.matrix.constructor import matrix @@ -540,9 +542,9 @@ def FibonacciWord(self, alphabet=(0, 1), construction_method="recursive"): :: - sage: words.FibonacciWord([0,1], 'function') # optional - sage.symbolic + sage: words.FibonacciWord([0,1], 'function') # needs sage.symbolic word: 0100101001001010010100100101001001010010... - sage: words.FibonacciWord('ab', 'function') # optional - sage.symbolic + sage: words.FibonacciWord('ab', 'function') # needs sage.symbolic word: abaababaabaababaababaabaababaabaababaaba... TESTS:: @@ -640,7 +642,7 @@ def FixedPointOfMorphism(self, morphism, first_letter): sage: tm = words.FixedPointOfMorphism(mu,0); tm word: 0110100110010110100101100110100110010110... sage: TM = words.ThueMorseWord() - sage: tm[:1000] == TM[:1000] # optional - sage.modules + sage: tm[:1000] == TM[:1000] # needs sage.modules True :: @@ -650,7 +652,7 @@ def FixedPointOfMorphism(self, morphism, first_letter): word: 0100101001001010010100100101001001010010... sage: F = words.FibonacciWord(); F word: 0100101001001010010100100101001001010010... - sage: f[:1000] == F[:1000] # optional - sage.modules + sage: f[:1000] == F[:1000] # needs sage.modules True :: @@ -774,13 +776,13 @@ def CharacteristicSturmianWord(self, slope, alphabet=(0, 1), bits=None): From real slope:: - sage: words.CharacteristicSturmianWord(1/golden_ratio^2) # optional - sage.symbolic + sage: words.CharacteristicSturmianWord(1/golden_ratio^2) # needs sage.symbolic word: 0100101001001010010100100101001001010010... - sage: words.CharacteristicSturmianWord(4/5) + sage: words.CharacteristicSturmianWord(4/5) # needs sage.rings.real_mpfr word: 11110 - sage: words.CharacteristicSturmianWord(5/14) + sage: words.CharacteristicSturmianWord(5/14) # needs sage.rings.real_mpfr word: 01001001001001 - sage: words.CharacteristicSturmianWord(pi - 3) # optional - sage.symbolic + sage: words.CharacteristicSturmianWord(pi - 3) # needs sage.symbolic word: 0000001000000100000010000001000000100000... From an iterator of the continued fraction expansion of a real:: @@ -789,21 +791,21 @@ def CharacteristicSturmianWord(self, slope, alphabet=(0, 1), bits=None): ....: yield 0 ....: yield 2 ....: while True: yield 1 - sage: F = words.CharacteristicSturmianWord(cf()); F + sage: F = words.CharacteristicSturmianWord(cf()); F # needs sage.rings.real_mpfr word: 0100101001001010010100100101001001010010... sage: Fib = words.FibonacciWord(); Fib word: 0100101001001010010100100101001001010010... - sage: F[:10000] == Fib[:10000] + sage: F[:10000] == Fib[:10000] # needs sage.rings.real_mpfr True The alphabet may be specified:: - sage: words.CharacteristicSturmianWord(cf(), 'rs') + sage: words.CharacteristicSturmianWord(cf(), 'rs') # needs sage.rings.real_mpfr word: rsrrsrsrrsrrsrsrrsrsrrsrrsrsrrsrrsrsrrsr... The characteristic sturmian word of slope `(\sqrt{3}-1)/2`:: - sage: words.CharacteristicSturmianWord((sqrt(3)-1)/2) # optional - sage.symbolic + sage: words.CharacteristicSturmianWord((sqrt(3)-1)/2) # needs sage.symbolic word: 0100100101001001001010010010010100100101... The same word defined from the continued fraction expansion of @@ -846,17 +848,18 @@ def CharacteristicSturmianWord(self, slope, alphabet=(0, 1), bits=None): :: - sage: words.CharacteristicSturmianWord(1/golden_ratio^2) # optional - sage.symbolic + sage: words.CharacteristicSturmianWord(1/golden_ratio^2) # needs sage.symbolic word: 0100101001001010010100100101001001010010... - sage: _.length() # optional - sage.symbolic + sage: _.length() # needs sage.symbolic +Infinity :: - sage: a = words.LowerMechanicalWord(1/pi)[1:] # optional - sage.symbolic - sage: b = words.UpperMechanicalWord(1/pi)[1:] # optional - sage.symbolic - sage: c = words.CharacteristicSturmianWord(1/pi) # optional - sage.symbolic - sage: n = 500; a[:n] == b[:n] == c[:n] # optional - sage.symbolic + sage: # needs sage.symbolic + sage: a = words.LowerMechanicalWord(1/pi)[1:] + sage: b = words.UpperMechanicalWord(1/pi)[1:] + sage: c = words.CharacteristicSturmianWord(1/pi) + sage: n = 500; a[:n] == b[:n] == c[:n] True :: @@ -927,19 +930,20 @@ def _CharacteristicSturmianWord_LetterIterator(self, cf, alphabet=(0,1)): EXAMPLES:: - sage: continued_fraction(1/golden_ratio^2)[:8] # optional - sage.symbolic + sage: continued_fraction(1/golden_ratio^2)[:8] # needs sage.symbolic [0; 2, 1, 1, 1, 1, 2] - sage: cf = iter(_) # optional - sage.symbolic - sage: Word(words._CharacteristicSturmianWord_LetterIterator(cf)) # optional - sage.symbolic + sage: cf = iter(_) # needs sage.symbolic + sage: Word(words._CharacteristicSturmianWord_LetterIterator(cf)) # needs sage.symbolic word: 0100101001001010010100100101001010 :: - sage: alpha = (sqrt(3)-1)/2 # optional - sage.symbolic - sage: continued_fraction(alpha)[:10] # optional - sage.symbolic + sage: # needs sage.symbolic + sage: alpha = (sqrt(3)-1)/2 + sage: continued_fraction(alpha)[:10] [0; 2, 1, 2, 1, 2, 1, 2, 1, 2] - sage: cf = iter(_) # optional - sage.symbolic - sage: Word(words._CharacteristicSturmianWord_LetterIterator(cf)) # optional - sage.symbolic + sage: cf = iter(_) + sage: Word(words._CharacteristicSturmianWord_LetterIterator(cf)) word: 0100100101001001001010010010010100100101... """ try: @@ -1133,23 +1137,23 @@ def LowerMechanicalWord(self, alpha, rho=0, alphabet=None): EXAMPLES:: - sage: words.LowerMechanicalWord(1/golden_ratio^2) # optional - sage.symbolic + sage: words.LowerMechanicalWord(1/golden_ratio^2) # needs sage.symbolic word: 0010010100100101001010010010100100101001... - sage: words.LowerMechanicalWord(1/5) # optional - sage.symbolic + sage: words.LowerMechanicalWord(1/5) # needs sage.symbolic word: 0000100001000010000100001000010000100001... - sage: words.LowerMechanicalWord(1/pi) # optional - sage.symbolic + sage: words.LowerMechanicalWord(1/pi) # needs sage.symbolic word: 0001001001001001001001000100100100100100... TESTS:: - sage: m = words.LowerMechanicalWord(1/golden_ratio^2)[1:] # optional - sage.symbolic - sage: s = words.CharacteristicSturmianWord(1/golden_ratio^2) # optional - sage.symbolic - sage: m[:500] == s[:500] # optional - sage.symbolic + sage: m = words.LowerMechanicalWord(1/golden_ratio^2)[1:] # needs sage.symbolic + sage: s = words.CharacteristicSturmianWord(1/golden_ratio^2) # needs sage.symbolic + sage: m[:500] == s[:500] # needs sage.symbolic True Check that this returns a word in an alphabet (:trac:`10054`):: - sage: words.UpperMechanicalWord(1/golden_ratio^2).parent() # optional - sage.symbolic + sage: words.UpperMechanicalWord(1/golden_ratio^2).parent() # needs sage.symbolic Infinite words over {0, 1} """ if not 0 <= alpha <= 1: @@ -1193,23 +1197,23 @@ def UpperMechanicalWord(self, alpha, rho=0, alphabet=None): EXAMPLES:: - sage: words.UpperMechanicalWord(1/golden_ratio^2) # optional - sage.symbolic + sage: words.UpperMechanicalWord(1/golden_ratio^2) # needs sage.symbolic word: 1010010100100101001010010010100100101001... - sage: words.UpperMechanicalWord(1/5) # optional - sage.symbolic + sage: words.UpperMechanicalWord(1/5) # needs sage.symbolic word: 1000010000100001000010000100001000010000... - sage: words.UpperMechanicalWord(1/pi) # optional - sage.symbolic + sage: words.UpperMechanicalWord(1/pi) # needs sage.symbolic word: 1001001001001001001001000100100100100100... TESTS:: - sage: m = words.UpperMechanicalWord(1/golden_ratio^2)[1:] # optional - sage.symbolic - sage: s = words.CharacteristicSturmianWord(1/golden_ratio^2) # optional - sage.symbolic - sage: m[:500] == s[:500] # optional - sage.symbolic + sage: m = words.UpperMechanicalWord(1/golden_ratio^2)[1:] # needs sage.symbolic + sage: s = words.CharacteristicSturmianWord(1/golden_ratio^2) # needs sage.symbolic + sage: m[:500] == s[:500] # needs sage.symbolic True Check that this returns a word in an alphabet (:trac:`10054`):: - sage: words.UpperMechanicalWord(1/golden_ratio^2).parent() # optional - sage.symbolic + sage: words.UpperMechanicalWord(1/golden_ratio^2).parent() # needs sage.symbolic Infinite words over {0, 1} """ if not 0 <= alpha <= 1: @@ -1520,7 +1524,7 @@ def fibonacci_tile(self, n): EXAMPLES:: - sage: for i in range(3): words.fibonacci_tile(i) # optional - sage.modules + sage: for i in range(3): words.fibonacci_tile(i) # needs sage.modules Path: 3210 Path: 323030101212 Path: 3230301030323212323032321210121232121010... @@ -1538,7 +1542,7 @@ def dual_fibonacci_tile(self, n): EXAMPLES:: - sage: for i in range(4): words.dual_fibonacci_tile(i) # optional - sage.modules + sage: for i in range(4): words.dual_fibonacci_tile(i) # needs sage.modules Path: 3210 Path: 32123032301030121012 Path: 3212303230103230321232101232123032123210... diff --git a/src/sage/combinat/words/words.py b/src/sage/combinat/words/words.py index 63d6f1f0d05..0149df17598 100644 --- a/src/sage/combinat/words/words.py +++ b/src/sage/combinat/words/words.py @@ -705,9 +705,9 @@ def __call__(self, data=None, length=None, datatype=None, caching=True, check=Tr Construction of a word path from a finite word:: sage: W = FiniteWords('abcd') - sage: P = WordPaths('abcd') # optional - sage.modules + sage: P = WordPaths('abcd') # needs sage.modules sage: w = W('aaab') - sage: P(w) # optional - sage.modules + sage: P(w) # needs sage.modules Path: aaab Construction of a word path from a Christoffel word:: @@ -715,8 +715,8 @@ def __call__(self, data=None, length=None, datatype=None, caching=True, check=Tr sage: w = words.ChristoffelWord(5,8) sage: w word: 0010010100101 - sage: P = WordPaths([0,1,2,3]) # optional - sage.modules - sage: P(w) # optional - sage.modules + sage: P = WordPaths([0,1,2,3]) # needs sage.modules + sage: P(w) # needs sage.modules Path: 0010010100101 Construction of a word represented by a list from a word @@ -744,19 +744,19 @@ def __call__(self, data=None, length=None, datatype=None, caching=True, check=Tr sage: w = words.FibonacciWord() sage: f = w[:100] - sage: P = WordPaths([0,1,2,3]) # optional - sage.modules - sage: p = P(f); p # optional - sage.modules + sage: P = WordPaths([0,1,2,3]) # needs sage.modules + sage: p = P(f); p # needs sage.modules Path: 0100101001001010010100100101001001010010... - sage: p.length() # optional - sage.modules + sage: p.length() # needs sage.modules 100 Creation of a word path from a FiniteWord_callable:: sage: g = W(lambda n:n%2, length = 100) - sage: P = WordPaths([0,1,2,3]) # optional - sage.modules - sage: p = P(g); p # optional - sage.modules + sage: P = WordPaths([0,1,2,3]) # needs sage.modules + sage: p = P(g); p # needs sage.modules Path: 0101010101010101010101010101010101010101... - sage: p.length() # optional - sage.modules + sage: p.length() # needs sage.modules 100 Creation of a word from a pickled function:: @@ -1017,7 +1017,7 @@ def random_element(self, length=None, *args, **kwds): TESTS:: - sage: _ = FiniteWords(GF(5)).random_element() # optional - sage.rings.finite_rings + sage: _ = FiniteWords(GF(5)).random_element() # needs sage.rings.finite_rings """ if length is None: length = ZZ.random_element(0, 10) @@ -1928,9 +1928,9 @@ def __call__(self, data=None, length=None, datatype=None, caching=True, check=Tr Construction of a word path from a finite word:: sage: W = Words('abcd') - sage: P = WordPaths('abcd') # optional - sage.modules + sage: P = WordPaths('abcd') # needs sage.modules sage: w = W('aaab') - sage: P(w) # optional - sage.modules + sage: P(w) # needs sage.modules Path: aaab Construction of a word path from a Christoffel word:: @@ -1938,8 +1938,8 @@ def __call__(self, data=None, length=None, datatype=None, caching=True, check=Tr sage: w = words.ChristoffelWord(5,8) sage: w word: 0010010100101 - sage: P = WordPaths([0,1,2,3]) # optional - sage.modules - sage: P(w) # optional - sage.modules + sage: P = WordPaths([0,1,2,3]) # needs sage.modules + sage: P(w) # needs sage.modules Path: 0010010100101 Construction of a word represented by a list from a word @@ -1967,24 +1967,24 @@ def __call__(self, data=None, length=None, datatype=None, caching=True, check=Tr sage: w = words.FibonacciWord() sage: f = w[:100] - sage: P = WordPaths([0,1,2,3]) # optional - sage.modules - sage: p = P(f); p # optional - sage.modules + sage: P = WordPaths([0,1,2,3]) # needs sage.modules + sage: p = P(f); p # needs sage.modules Path: 0100101001001010010100100101001001010010... - sage: p.length() # optional - sage.modules + sage: p.length() # needs sage.modules 100 - Creation of a word path from a FiniteWord_callable:: + Creation of a word path from a :class:`FiniteWord_callable`:: sage: g = Word(lambda n: n%2, length=100) - sage: P = WordPaths([0,1,2,3]) # optional - sage.modules - sage: p = P(g); p # optional - sage.modules + sage: P = WordPaths([0,1,2,3]) # needs sage.modules + sage: p = P(g); p # needs sage.modules Path: 0101010101010101010101010101010101010101... - sage: p.length() # optional - sage.modules + sage: p.length() # needs sage.modules 100 Creation of a word from a pickled function:: - sage: f = lambda n : n % 10 + sage: f = lambda n: n % 10 sage: from sage.misc.fpickle import pickle_function sage: s = pickle_function(f) sage: Word(s, datatype='pickled_function') @@ -2216,7 +2216,7 @@ def random_element(self, *args, **kwds): TESTS:: - sage: _ = Words(GF(5),4).random_element() # optional - sage.rings.finite_rings + sage: _ = Words(GF(5),4).random_element() # needs sage.rings.finite_rings Check that :trac:`18283` is fixed:: diff --git a/src/sage/cpython/all.py b/src/sage/cpython/all.py index d35cd6f2e8a..d48ee4c7d45 100644 --- a/src/sage/cpython/all.py +++ b/src/sage/cpython/all.py @@ -1,2 +1,2 @@ -from .debug import getattr_debug, type_debug -from .getattr import raw_getattr +from sage.cpython.debug import getattr_debug, type_debug +from sage.cpython.getattr import raw_getattr diff --git a/src/sage/cpython/debug.pyx b/src/sage/cpython/debug.pyx index cdaca3a4854..0cfc1fc2388 100644 --- a/src/sage/cpython/debug.pyx +++ b/src/sage/cpython/debug.pyx @@ -21,7 +21,7 @@ cdef extern from "Python.h": cdef extern from "sage/cpython/debugimpl.c": void _type_debug(PyTypeObject*) -from .getattr cimport AttributeErrorMessage +from sage.cpython.getattr cimport AttributeErrorMessage # Determine subtype_traverse, subtype_clear, subtype_dealloc functions diff --git a/src/sage/data_structures/all.py b/src/sage/data_structures/all.py index 43c5de52d5a..eac1b4b8931 100644 --- a/src/sage/data_structures/all.py +++ b/src/sage/data_structures/all.py @@ -1,2 +1,2 @@ -from .bitset import Bitset, FrozenBitset +from sage.data_structures.bitset import Bitset, FrozenBitset diff --git a/src/sage/data_structures/bitset.pxd b/src/sage/data_structures/bitset.pxd index d8122c05165..0d72f7eb6ed 100644 --- a/src/sage/data_structures/bitset.pxd +++ b/src/sage/data_structures/bitset.pxd @@ -7,7 +7,7 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from .bitset_base cimport bitset_t +from sage.data_structures.bitset_base cimport bitset_t # Python layer over bitset_t cdef class FrozenBitset: diff --git a/src/sage/data_structures/bitset.pyx b/src/sage/data_structures/bitset.pyx index 0e3f6e3d640..5c341c8a003 100644 --- a/src/sage/data_structures/bitset.pyx +++ b/src/sage/data_structures/bitset.pyx @@ -31,7 +31,7 @@ linear in ``capacity``. # http://www.gnu.org/licenses/ #***************************************************************************** -from .bitset_base cimport * +from sage.data_structures.bitset_base cimport * from cpython.object cimport Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT, Py_GE diff --git a/src/sage/doctest/control.py b/src/sage/doctest/control.py index 633afd5c2e6..fd92dc386bf 100644 --- a/src/sage/doctest/control.py +++ b/src/sage/doctest/control.py @@ -418,7 +418,7 @@ def __init__(self, options, args): elif options.long: options.timeout = int(os.getenv('SAGE_TIMEOUT_LONG', 30 * 60)) else: - options.timeout = int(os.getenv('SAGE_TIMEOUT', 5 * 60)) + options.timeout = int(os.getenv('SAGE_TIMEOUT', 10 * 60)) # For non-default GC options, double the timeout if options.gc: options.timeout *= 2 @@ -1607,7 +1607,7 @@ def stringify(x): if not save_dtmode: if options.debug: raise ValueError("You should not try to run doctests with a debugger from within Sage: IPython objects to embedded shells") - from IPython import get_ipython + from IPython.core.getipython import get_ipython IP = get_ipython() if IP is not None: old_color = IP.colors diff --git a/src/sage/doctest/fixtures.py b/src/sage/doctest/fixtures.py index a3b5e9edda7..9fbfdf86db9 100644 --- a/src/sage/doctest/fixtures.py +++ b/src/sage/doctest/fixtures.py @@ -80,9 +80,9 @@ def reproducible_repr(val): frozenset(['a', 'b', 'c', 'd']) sage: print(reproducible_repr([1, frozenset("cab"), set("bar"), 0])) [1, frozenset(['a', 'b', 'c']), set(['a', 'b', 'r']), 0] - sage: print(reproducible_repr({3.0:"three","2":"two",1:"one"})) + sage: print(reproducible_repr({3.0: "three", "2": "two", 1: "one"})) # optional - sage.rings.real_mpfr {'2': 'two', 1: 'one', 3.00000000000000: 'three'} - sage: print(reproducible_repr("foo\nbar")) # demonstrate default case + sage: print(reproducible_repr("foo\nbar")) # demonstrate default case 'foo\nbar' """ diff --git a/src/sage/env.py b/src/sage/env.py index 4515e90e912..9ab6b1e1864 100644 --- a/src/sage/env.py +++ b/src/sage/env.py @@ -223,7 +223,6 @@ def var(key: str, *fallbacks: Optional[str], force: bool = False) -> Optional[st FOURTITWO_PPI = var("FOURTITWO_PPI") FOURTITWO_CIRCUITS = var("FOURTITWO_CIRCUITS") FOURTITWO_GROEBNER = var("FOURTITWO_GROEBNER") -ARB_LIBRARY = var("ARB_LIBRARY", "arb") CBLAS_PC_MODULES = var("CBLAS_PC_MODULES", "cblas:openblas:blas") ECL_CONFIG = var("ECL_CONFIG", "ecl-config") NTL_INCDIR = var("NTL_INCDIR") @@ -356,8 +355,7 @@ def cython_aliases(required_modules=None, sage: cython_aliases() {...} sage: sorted(cython_aliases().keys()) - ['ARB_LIBRARY', - 'CBLAS_CFLAGS', + ['CBLAS_CFLAGS', ..., 'ZLIB_LIBRARIES'] sage: cython_aliases(required_modules=('module-that-is-assumed-to-not-exist')) @@ -475,8 +473,6 @@ def uname_specific(name, value, alternative): if "LINBOX_CFLAGS" in aliases: aliases["LINBOX_CFLAGS"].append("-std=gnu++11") - aliases["ARB_LIBRARY"] = ARB_LIBRARY - # TODO: Remove Cygwin hack by installing a suitable cblas.pc if os.path.exists('/usr/lib/libblas.dll.a'): aliases["CBLAS_LIBS"] = ['gslcblas'] diff --git a/src/sage/ext/fast_callable.pyx b/src/sage/ext/fast_callable.pyx index bad30e0e605..0a1439b7530 100644 --- a/src/sage/ext/fast_callable.pyx +++ b/src/sage/ext/fast_callable.pyx @@ -1645,7 +1645,7 @@ class IntegerPowerFunction(): pi^2 sage: square(I) # needs sage.symbolic -1 - sage: square(RIF(-1, 1)).str(style='brackets') + sage: square(RIF(-1, 1)).str(style='brackets') # needs sage.rings.real_interval_field '[0.0000000000000000 .. 1.0000000000000000]' sage: IntegerPowerFunction(-1) (^(-1)) diff --git a/src/sage/features/fricas.py b/src/sage/features/fricas.py new file mode 100644 index 00000000000..a52e082d114 --- /dev/null +++ b/src/sage/features/fricas.py @@ -0,0 +1,65 @@ +r""" +Features for testing the presence of ``fricas`` +""" + +# ***************************************************************************** +# Copyright (C) 2023 Dima Pasechnik +# +# Distributed under the terms of the GNU General Public License (GPL) +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# https://www.gnu.org/licenses/ +# ***************************************************************************** + +import os +import subprocess +from . import Executable, FeatureTestResult + +class FriCAS(Executable): + r""" + A :class:`~sage.features.Feature` which checks for the :ref:`fricas ` binary. + + EXAMPLES:: + + sage: from sage.features.fricas import FriCAS + sage: FriCAS().is_present() # optional - fricas + FeatureTestResult('fricas', True) + """ + def __init__(self): + r""" + TESTS:: + + sage: from sage.features.fricas import FriCAS + sage: isinstance(FriCAS(), FriCAS) + True + """ + Executable.__init__(self, name="fricas", spkg="fricas", + executable="fricas", + url="https://fricas.github.io") + + def is_functional(self): + r""" + Check whether ``fricas`` works on trivial input. + + EXAMPLES:: + + sage: from sage.features.fricas import FriCAS + sage: FriCAS().is_functional() # optional - fricas + FeatureTestResult('fricas', True) + """ + command = ['fricas -nosman -eval ")quit"'] + try: + lines = subprocess.check_output(command, stderr=subprocess.STDOUT, shell=True) + except subprocess.CalledProcessError as e: + return FeatureTestResult(self, False, + reason="Call `{command}` failed with exit code {e.returncode}".format(command=" ".join(command), e=e)) + + expected = b"FriCAS" + if lines.find(expected) == -1: + return FeatureTestResult(self, False, + reason="Call `{command}` did not produce output which contains `{expected}`".format(command=" ".join(command), expected=expected)) + + return FeatureTestResult(self, True) + +def all_features(): + return [FriCAS()] diff --git a/src/sage/features/sagemath.py b/src/sage/features/sagemath.py index bc34d35dd1c..4097d3512b9 100644 --- a/src/sage/features/sagemath.py +++ b/src/sage/features/sagemath.py @@ -777,7 +777,7 @@ class sage__rings__number_field(JoinFeature): A :class:`~sage.features.Feature` describing the presence of :mod:`sage.rings.number_field`. Number fields are implemented in Sage using a complicated mixture of various libraries, - including :ref:`arb `, :ref:`FLINT `, :ref:`GAP `, + including :ref:`FLINT `, :ref:`GAP `, :ref:`MPFI `, :ref:`NTL `, and :ref:`PARI `. EXAMPLES: diff --git a/src/sage/functions/special.py b/src/sage/functions/special.py index 93e032d0677..9348b921685 100644 --- a/src/sage/functions/special.py +++ b/src/sage/functions/special.py @@ -511,7 +511,7 @@ def __init__(self): Check that :trac:`34085` is fixed:: sage: _ = var("x y") # needs sage.symbolic - sage: fricas(elliptic_e(x, y)) # optional - fricas, needs sage.symbolic + sage: fricas(elliptic_e(x, y)) # optional - fricas, needs sage.symbolic ellipticE(sin(x),y) However, the conversion is only correct in the interval @@ -525,7 +525,7 @@ def __init__(self): sage: f = lambda x, y: elliptic_e(arcsin(x), y).subs(x=x, y=y) sage: g = lambda x, y: fricas.ellipticE(x, y).sage() sage: d = lambda x, y: f(x, y) - g(x, y) - sage: [d(N(-pi/2 + x), y) # tol 1e-8 # optional - fricas, needs sage.symbolic + sage: [d(N(-pi/2 + x), y) # abs tol 1e-8 # optional - fricas, needs sage.symbolic ....: for x in range(1, 3) for y in range(-2, 2)] [0.000000000000000, 0.000000000000000, @@ -877,7 +877,7 @@ def __init__(self): Check that :trac:`34186` is fixed:: sage: _ = var("x y") # needs sage.symbolic - sage: fricas(elliptic_f(x, y)) # optional - fricas, needs sage.symbolic + sage: fricas(elliptic_f(x, y)) # optional - fricas, needs sage.symbolic ellipticF(sin(x),y) However, the conversion is only correct in the interval @@ -891,7 +891,7 @@ def __init__(self): sage: f = lambda x, y: elliptic_f(arcsin(x), y).subs(x=x, y=y) sage: g = lambda x, y: fricas.ellipticF(x, y).sage() sage: d = lambda x, y: f(x, y) - g(x, y) - sage: [d(N(-pi/2 + x), y) # tol 1e-8 # optional - fricas, needs sage.symbolic + sage: [d(N(-pi/2 + x), y) # abs tol 1e-8 # optional - fricas, needs sage.symbolic ....: for x in range(1, 3) for y in range(-2,2)] [0.000000000000000, 0.000000000000000, diff --git a/src/sage/geometry/lattice_polytope.py b/src/sage/geometry/lattice_polytope.py index 7847955db7b..1cd9f578113 100644 --- a/src/sage/geometry/lattice_polytope.py +++ b/src/sage/geometry/lattice_polytope.py @@ -93,8 +93,27 @@ """ # **************************************************************************** -# Copyright (C) 2007-2013 Andrey Novoseltsev -# Copyright (C) 2007-2013 William Stein +# Copyright (C) 2007-2017 Andrey Novoseltsev +# 2007-2013 William Stein +# 2009 Mike Hansen +# 2009-2020 John H. Palmieri +# 2010-2014 Volker Braun +# 2012 Samuel Gonshaw +# 2013 Jan Keitel +# 2014 André Apitzsch +# 2014 Wilfried Luebbe +# 2015-2022 Frédéric Chapoton +# 2015 Ursula Whitcher +# 2016 Jori Mäntysalo +# 2017 Travis Scrimshaw +# 2018 Christian Stump +# 2018 Vincent Klein +# 2019 Vincent Delecroix +# 2019 Jonathan Kliem +# 2020 Samuel Lelièvre +# 2021-2023 Matthias Koeppe +# 2022 David Coudert +# 2023 Luze Xu # # 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 @@ -2500,16 +2519,16 @@ def index(self): M(-1, 0) in 2-d lattice M - But they are in the same `GL(Z^n)` orbit and have the same + But they are in the same `GL(\ZZ^n)` orbit and have the same normal form:: - sage: d.normal_form() # needs palp + sage: d.normal_form() # needs sage.groups M( 1, 0), M( 0, 1), M( 0, -1), M(-1, 0) in 2-d lattice M - sage: lattice_polytope.ReflexivePolytope(2,3).normal_form() + sage: lattice_polytope.ReflexivePolytope(2,3).normal_form() # needs sage.groups M( 1, 0), M( 0, 1), M( 0, -1), @@ -2913,36 +2932,38 @@ def nfacets(self): return len(self.facet_normals()) if self.dim() > 0 else 0 @cached_method - def normal_form(self, algorithm="palp", permutation=False): + def normal_form(self, algorithm="palp_native", permutation=False): r""" Return the normal form of vertices of ``self``. Two full-dimensional lattice polytopes are in the same - ``GL(\ZZ)``-orbit if and only if their normal forms are the + `GL(\ZZ^n)`-orbit if and only if their normal forms are the same. Normal form is not defined and thus cannot be used for polytopes whose dimension is smaller than the dimension of the ambient space. The original algorithm was presented in [KS1998]_ and implemented in PALP. A modified version of the PALP algorithm is discussed in - [GK2013]_ and available here as "palp_modified". + [GK2013]_ and available here as ``"palp_modified"``. INPUT: - - ``algorithm`` -- (default: "palp") The algorithm which is used + - ``algorithm`` -- (default: ``"palp_native"``) The algorithm which is used to compute the normal form. Options are: - * "palp" -- Run external PALP code, usually the fastest option. + * ``"palp"`` -- Run external PALP code, usually the fastest option + when it works; but reproducible crashes have been observed in dimension + 5 and higher. - * "palp_native" -- The original PALP algorithm implemented - in sage. Currently considerably slower than PALP. + * ``"palp_native"`` -- The original PALP algorithm implemented + in sage. Currently competitive with PALP in many cases. - * "palp_modified" -- A modified version of the PALP + * ``"palp_modified"`` -- A modified version of the PALP algorithm which determines the maximal vertex-facet pairing matrix first and then computes its automorphisms, while the PALP algorithm does both things concurrently. - - ``permutation`` -- (default: ``False``) If ``True`` the permutation + - ``permutation`` -- boolean (default: ``False``); if ``True``, the permutation applied to vertices to obtain the normal form is returned as well. Note that the different algorithms may return different results that nevertheless lead to the same normal form. @@ -2963,7 +2984,7 @@ def normal_form(self, algorithm="palp", permutation=False): M(-1, 0), M( 0, -1) in 2-d lattice M - sage: d.normal_form() # needs palp + sage: d.normal_form() # needs sage.groups M( 1, 0), M( 0, 1), M( 0, -1), @@ -3013,6 +3034,163 @@ def normal_form(self, algorithm="palp", permutation=False): M( 0, -1), M(-1, 0) in 2-d lattice M + + The following examples demonstrate the speed of the available algorithms. + In low dimensions, the default algorithm, ``"palp_native"``, is the fastest. + As the dimension increases, ``"palp"`` is relatively faster than ``"palp_native"``. + ``"palp_native"`` is usually much faster than ``"palp_modified"``. + In some cases when the polytope has high symmetry, however, ``"palp_native"`` is slower:: + + sage: # not tested + sage: o = lattice_polytope.cross_polytope(2) + sage: %timeit o.normal_form.clear_cache(); o.normal_form("palp") + 625 loops, best of 3: 3.07 ms per loop + sage: %timeit o.normal_form.clear_cache(); o.normal_form("palp_native") + 625 loops, best of 3: 0.445 ms per loop + sage: %timeit o.normal_form.clear_cache(); o.normal_form("palp_modified") + 625 loops, best of 3: 5.01 ms per loop + sage: o = lattice_polytope.cross_polytope(3) + sage: %timeit o.normal_form.clear_cache(); o.normal_form("palp") + 625 loops, best of 3: 3.22 ms per loop + sage: %timeit o.normal_form.clear_cache(); o.normal_form("palp_native") + 625 loops, best of 3: 2.73 ms per loop + sage: %timeit o.normal_form.clear_cache(); o.normal_form("palp_modified") + 625 loops, best of 3: 20.7 ms per loop + sage: o = lattice_polytope.cross_polytope(4) + sage: %timeit o.normal_form.clear_cache(); o.normal_form("palp") + 625 loops, best of 3: 4.84 ms per loop + sage: %timeit o.normal_form.clear_cache(); o.normal_form("palp_native") + 625 loops, best of 3: 55.6 ms per loop + sage: %timeit o.normal_form.clear_cache(); o.normal_form("palp_modified") + 625 loops, best of 3: 129 ms per loop + sage: o = lattice_polytope.cross_polytope(5) + sage: %timeit o.normal_form.clear_cache(); o.normal_form("palp") + 10 loops, best of 3: 0.0364 s per loop + sage: %timeit o.normal_form.clear_cache(); o.normal_form("palp_native") + 10 loops, best of 3: 1.68 s per loop + sage: %timeit o.normal_form.clear_cache(); o.normal_form("palp_modified") + 10 loops, best of 3: 0.858 s per loop + + Note that the algorithm ``"palp"`` may crash for higher dimensions because of + the overflow errors as mentioned in :issue:`13525#comment:9`. + Then use ``"palp_native"`` instead, which is usually faster than ``"palp_modified"``. + Below is an example where ``"palp"`` fails and + ``"palp_native"`` is much faster than ``"palp_modified"``:: + + sage: P = LatticePolytope([[-3, -3, -6, -6, -1], [3, 3, 6, 6, 1], [-3, -3, -6, -6, 1], + ....: [-3, -3, -3, -6, 0], [-3, -3, -3, 0, 0], [-3, -3, 0, 0, 0], + ....: [-3, 0, -6, -6, 0], [-3, 0, -3, -6, 0], [-3, 0, -3, 0, 0], + ....: [-3, 0, 0, 0, -1], [3, 3, 6, 6, -1], [-3, 0, 0, 0, 1], + ....: [0, -3, -6, -6, 0], [0, -3, -3, -6, 0], [0, -3, -3, 0, 0], + ....: [0, -3, 0, 0, -1], [3, 3, 3, 6, 0], [0, -3, 0, 0, 1], + ....: [0, 0, -6, -6, 0], [0, 0, -3, -6, -1], [3, 3, 3, 0, 0], + ....: [0, 0, -3, -6, 1], [0, 0, -3, 0, -1], [3, 3, 0, 0, 0], + ....: [0, 0, -3, 0, 1], [0, 0, 3, 0, -1], [3, 0, 6, 6, 0], + ....: [0, 0, 3, 0, 1], [0, 0, 3, 6, -1], [3, 0, 3, 6, 0], + ....: [0, 0, 3, 6, 1], [0, 0, 6, 6, 0], [0, 3, 0, 0, -1], + ....: [3, 0, 3, 0, 0], [0, 3, 0, 0, 1], [0, 3, 3, 0, 0], + ....: [0, 3, 3, 6, 0], [0, 3, 6, 6, 0], [3, 0,0, 0, -1], [3, 0, 0, 0, 1]]) + sage: P.normal_form(algorithm="palp") # not tested + Traceback (most recent call last): + ... + RuntimeError: Error executing ... for a polytope sequence! + Output: + b'*** stack smashing detected ***: terminated\nAborted\n' + sage: P.normal_form(algorithm="palp_native") # needs sage.groups + M( 6, 0, 0, 0, 0), + M( -6, 0, 0, 0, 0), + M( 0, 1, 0, 0, 0), + M( 0, 0, 3, 0, 0), + M( 0, 1, 0, 3, 0), + M( 0, 0, 0, 0, 3), + M( -6, 1, 6, 3, -6), + M( -6, 0, 6, 0, -3), + M(-12, 1, 6, 3, -3), + M( -6, 1, 0, 3, 0), + M( -6, 0, 3, 3, 0), + M( 6, 0, -6, -3, 6), + M(-12, 1, 6, 3, -6), + M(-12, 0, 9, 3, -6), + M( 0, 0, 0, -3, 0), + M(-12, 1, 6, 6, -6), + M(-12, 0, 6, 3, -3), + M( 0, 1, -3, 0, 0), + M( 0, 0, -3, -3, 3), + M( 0, 1, 0, 3, -3), + M( 0, -1, 0, -3, 3), + M( 0, 0, 3, 3, -3), + M( 0, -1, 3, 0, 0), + M( 12, 0, -6, -3, 3), + M( 12, -1, -6, -6, 6), + M( 0, 0, 0, 3, 0), + M( 12, 0, -9, -3, 6), + M( 12, -1, -6, -3, 6), + M( -6, 0, 6, 3, -6), + M( 6, 0, -3, -3, 0), + M( 6, -1, 0, -3, 0), + M(-12, 1, 9, 6, -6), + M( 6, 0, -6, 0, 3), + M( 6, -1, -6, -3, 6), + M( 0, 0, 0, 0, -3), + M( 0, -1, 0, -3, 0), + M( 0, 0, -3, 0, 0), + M( 0, -1, 0, 0, 0), + M( 12, -1, -9, -6, 6), + M( 12, -1, -6, -3, 3) + in 5-d lattice M + sage: P.normal_form(algorithm="palp_modified") # not tested (22s; MemoryError on 32 bit), needs sage.groups + M( 6, 0, 0, 0, 0), + M( -6, 0, 0, 0, 0), + M( 0, 1, 0, 0, 0), + M( 0, 0, 3, 0, 0), + M( 0, 1, 0, 3, 0), + M( 0, 0, 0, 0, 3), + M( -6, 1, 6, 3, -6), + M( -6, 0, 6, 0, -3), + M(-12, 1, 6, 3, -3), + M( -6, 1, 0, 3, 0), + M( -6, 0, 3, 3, 0), + M( 6, 0, -6, -3, 6), + M(-12, 1, 6, 3, -6), + M(-12, 0, 9, 3, -6), + M( 0, 0, 0, -3, 0), + M(-12, 1, 6, 6, -6), + M(-12, 0, 6, 3, -3), + M( 0, 1, -3, 0, 0), + M( 0, 0, -3, -3, 3), + M( 0, 1, 0, 3, -3), + M( 0, -1, 0, -3, 3), + M( 0, 0, 3, 3, -3), + M( 0, -1, 3, 0, 0), + M( 12, 0, -6, -3, 3), + M( 12, -1, -6, -6, 6), + M( 0, 0, 0, 3, 0), + M( 12, 0, -9, -3, 6), + M( 12, -1, -6, -3, 6), + M( -6, 0, 6, 3, -6), + M( 6, 0, -3, -3, 0), + M( 6, -1, 0, -3, 0), + M(-12, 1, 9, 6, -6), + M( 6, 0, -6, 0, 3), + M( 6, -1, -6, -3, 6), + M( 0, 0, 0, 0, -3), + M( 0, -1, 0, -3, 0), + M( 0, 0, -3, 0, 0), + M( 0, -1, 0, 0, 0), + M( 12, -1, -9, -6, 6), + M( 12, -1, -6, -3, 3) + in 5-d lattice M + sage: %timeit P.normal_form.clear_cache(); P.normal_form("palp_native") # not tested + 10 loops, best of 3: 0.137 s per loop + sage: %timeit P.normal_form.clear_cache(); P.normal_form("palp_modified") # not tested + 10 loops, best of 3: 22.2 s per loop + + TESTS:: + + sage: d.normal_form("palp_fiction") + Traceback (most recent call last): + ... + ValueError: algorithm must be 'palp', 'palp_native', or 'palp_modified' """ if self.dim() < self.lattice_dim(): raise ValueError("normal form is not defined for %s" % self) @@ -3025,8 +3203,7 @@ def normal_form(self, algorithm="palp", permutation=False): elif algorithm == "palp_modified": result = self._palp_modified_normal_form(permutation=permutation) else: - raise ValueError('Algorithm must be palp, ' + - 'palp_native, or palp_modified.') + raise ValueError("algorithm must be 'palp', 'palp_native', or 'palp_modified'") if permutation: vertices, perm = result else: @@ -3049,7 +3226,7 @@ def _palp_modified_normal_form(self, permutation=False): INPUT: - - ``permutation`` -- a Boolean, whether to return the permutation of + - ``permutation`` -- boolean (default: ``False``); whether to return the permutation of the order of the vertices that was applied to obtain this matrix. OUTPUT: @@ -3155,8 +3332,8 @@ def _palp_PM_max(self, check=False): INPUT: - ``check`` -- Boolean (default: ``False``), whether to return - the permutations leaving the maximal vertex-facet pairing - matrix invariant. + the permutations leaving the maximal vertex-facet pairing + matrix invariant. OUTPUT: @@ -3198,206 +3375,21 @@ def _palp_PM_max(self, check=False): ....: for j, i in PMs ) sage: all(results) # long time True + + TESTS: + + Check that a bug introduced in :issue:`35997` is fixed:: + + sage: P = LatticePolytope([(-4,-6),(-4,-5),(0,0),(1,0),(5,6)]) + sage: P._palp_PM_max() + [9 5 4 0 0] + [6 0 6 5 0] + [1 5 0 0 4] + [0 6 0 1 6] + [0 0 3 5 3] """ - PM = self.vertex_facet_pairing_matrix() - n_v = PM.ncols() - n_f = PM.nrows() - S_v = SymmetricGroup(n_v) - S_f = SymmetricGroup(n_f) - - # and find all the ways of making the first row of PM_max - def index_of_max(iterable): - # returns the index of max of any iterable - return max(enumerate(iterable), key=lambda x: x[1])[0] - - n_s = 1 - permutations = {0: [S_f.one(), S_v.one()]} - for j in range(n_v): - m = index_of_max(PM[0, i] for i in range(j, n_v)) - if m > 0: - permutations[0][1] = S_v((j + 1, m + j + 1), check=False) * permutations[0][1] - first_row = list(PM[0]) - - # Arrange other rows one by one and compare with first row - for k in range(1, n_f): - # Error for k == 1 already! - permutations[n_s] = [S_f.one(), S_v.one()] - m = index_of_max(PM[k, permutations[n_s][1](j+1) - 1] for j in range(n_v)) - if m > 0: - permutations[n_s][1] = S_v((1, m + 1), check=False) * permutations[n_s][1] - d = (PM[k, permutations[n_s][1](1) - 1] - - permutations[0][1](first_row)[0]) - if d < 0: - # The largest elt of this row is smaller than largest elt - # in 1st row, so nothing to do - continue - # otherwise: - for i in range(1, n_v): - m = index_of_max(PM[k, permutations[n_s][1](j+1) - 1] for j in range(i,n_v)) - if m > 0: - permutations[n_s][1] = S_v((i + 1, m + i + 1), check=False) \ - * permutations[n_s][1] - if d == 0: - d = (PM[k, permutations[n_s][1](i+1) - 1] - - permutations[0][1](first_row)[i]) - if d < 0: - break - if d < 0: - # This row is smaller than 1st row, so nothing to do - del permutations[n_s] - continue - permutations[n_s][0] = S_f((1, k + 1), check=False) * permutations[n_s][0] - if d == 0: - # This row is the same, so we have a symmetry! - n_s += 1 - else: - # This row is larger, so it becomes the first row and - # the symmetries reset. - first_row = list(PM[k]) - permutations = {0: permutations[n_s]} - n_s = 1 - permutations = {k: permutations[k] for k in permutations if k < n_s} - - b = tuple(PM[permutations[0][0](1) - 1, permutations[0][1](j+1) - 1] for j in range(n_v)) - # Work out the restrictions the current permutations - # place on other permutations as a automorphisms - # of the first row - # The array is such that: - # S = [i, 1, ..., 1 (ith), j, i+1, ..., i+1 (jth), k ... ] - # describes the "symmetry blocks" - S = list(range(1, n_v + 1)) - for i in range(1, n_v): - if b[i-1] == b[i]: - S[i] = S[i-1] - S[S[i]-1] += 1 - else: - S[i] = i + 1 - - # We determine the other rows of PM_max in turn by use of perms and - # aut on previous rows. - for l in range(1, n_f - 1): - n_s = len(permutations) - n_s_bar = n_s - cf = 0 - l_r = [0]*n_v - # Search for possible local permutations based off previous - # global permutations. - for k in range(n_s_bar - 1, -1, -1): - # number of local permutations associated with current global - n_p = 0 - ccf = cf - permutations_bar = {0: copy(permutations[k])} - # We look for the line with the maximal entry in the first - # subsymmetry block, i.e. we are allowed to swap elements - # between 0 and S(0) - for s in range(l, n_f): - for j in range(1, S[0]): - v0 = PM[permutations_bar[n_p][0](s+1) - 1, permutations_bar[n_p][1](1) - 1] - vj = PM[permutations_bar[n_p][0](s+1) - 1, permutations_bar[n_p][1](j+1) - 1] - if v0 < vj: - permutations_bar[n_p][1] = S_v((1, j + 1), check=False) * permutations_bar[n_p][1] - if ccf == 0: - l_r[0] = PM[permutations_bar[n_p][0](s+1) - 1, permutations_bar[n_p][1](1) - 1] - if s != l: - permutations_bar[n_p][0] = S_f((l + 1, s + 1), check=False) * permutations_bar[n_p][0] - n_p += 1 - ccf = 1 - permutations_bar[n_p] = copy(permutations[k]) - else: - d1 = PM[permutations_bar[n_p][0](s+1) - 1, permutations_bar[n_p][1](1) - 1] - d = d1 - l_r[0] - if d < 0: - # We move to the next line - continue - elif d == 0: - # Maximal values agree, so possible symmetry - if s != l: - permutations_bar[n_p][0] = S_f((l + 1, s + 1), check=False) * permutations_bar[n_p][0] - n_p += 1 - permutations_bar[n_p] = copy(permutations[k]) - else: - # We found a greater maximal value for first entry. - # It becomes our new reference: - l_r[0] = d1 - if s != l: - permutations_bar[n_p][0] = S_f((l + 1, s + 1), check=False) * permutations_bar[n_p][0] - # Forget previous work done - cf = 0 - permutations_bar = {0:copy(permutations_bar[n_p])} - n_p = 1 - permutations_bar[n_p] = copy(permutations[k]) - n_s = k + 1 - # Check if the permutations found just now work - # with other elements - for c in range(1, n_v): - h = S[c] - ccf = cf - # Now let us find out where the end of the - # next symmetry block is: - if h < c + 1: - h = S[h - 1] - s = n_p - # Check through this block for each possible permutation - while s > 0: - s -= 1 - # Find the largest value in this symmetry block - for j in range(c + 1, h): - vc = PM[(permutations_bar[s][0])(l+1) - 1, (permutations_bar[s][1])(c+1) - 1] - vj = PM[(permutations_bar[s][0])(l+1) - 1, (permutations_bar[s][1])(j+1) - 1] - if (vc < vj): - permutations_bar[s][1] = S_v((c + 1, j + 1), check=False) * permutations_bar[s][1] - if ccf == 0: - # Set reference and carry on to next permutation - l_r[c] = PM[(permutations_bar[s][0])(l+1) - 1, (permutations_bar[s][1])(c+1) - 1] - ccf = 1 - else: - d1 = PM[(permutations_bar[s][0])(l+1) - 1, (permutations_bar[s][1])(c+1) - 1] - d = d1 - l_r[c] - if d < 0: - n_p -= 1 - if s < n_p: - permutations_bar[s] = copy(permutations_bar[n_p]) - elif d > 0: - # The current case leads to a smaller matrix, - # hence this case becomes our new reference - l_r[c] = d1 - cf = 0 - n_p = s + 1 - n_s = k + 1 - # Update permutations - if (n_s - 1) > k: - permutations[k] = copy(permutations[n_s - 1]) - n_s -= 1 - for s in range(n_p): - permutations[n_s] = copy(permutations_bar[s]) - n_s += 1 - cf = n_s - permutations = {k: permutations[k] for k in permutations if k < n_s} - # If the automorphisms are not already completely restricted, - # update them - if S != list(range(1, n_v + 1)): - # Take the old automorphisms and update by - # the restrictions the last worked out - # row imposes. - c = 0 - M = tuple(PM[permutations[0][0](l+1) - 1, permutations[0][1](j+1) - 1] for j in range(n_v)) - while c < n_v: - s = S[c] + 1 - S[c] = c + 1 - c += 1 - while c < (s - 1): - if M[c] == M[c - 1]: - S[c] = S[c - 1] - S[S[c] - 1] += 1 - else: - S[c] = c + 1 - c += 1 - # Now we have the perms, we construct PM_max using one of them - PM_max = PM.with_permuted_rows_and_columns(*permutations[0]) - if check: - return (PM_max, permutations) - else: - return PM_max + from .palp_normal_form import _palp_PM_max + return _palp_PM_max(self.vertex_facet_pairing_matrix(), check) def npoints(self): r""" @@ -5175,12 +5167,13 @@ def _palp_canonical_order(V, PM_max, permutations): - ``PM_max`` -- the maximal vertex-facet pairing matrix - - ``permutation`` -- the permutations of the vertices yielding + - ``permutations`` -- the permutations of the vertices yielding ``PM_max``. OUTPUT: - The PALP normal form as a :class:`point collection `. + The PALP normal form as a :class:`point collection ` + and a permutation. TESTS:: @@ -5195,32 +5188,15 @@ def _palp_canonical_order(V, PM_max, permutations): M(-1, 0) in 2-d lattice M, (1,3,2,4)) """ - n_v = PM_max.ncols() - S_v = SymmetricGroup(n_v) - p_c = S_v.one() - M_max = [max(row[j] for row in PM_max.rows()) for j in range(n_v)] - S_max = sum(PM_max) - for i in range(n_v): - k = i - for j in range(i + 1, n_v): - if M_max[j] < M_max[k] or \ - (M_max[j] == M_max[k] and S_max[j] < S_max[k]): - k = j - if not k == i: - M_max[i], M_max[k] = M_max[k], M_max[i] - S_max[i], S_max[k] = S_max[k], S_max[i] - p_c = S_v((1 + i, 1 + k), check=False) * p_c - # Create array of possible NFs. - permutations = [p_c * l[1] for l in permutations.values()] + from .palp_normal_form import _palp_canonical_order + Vmatrix = V.column_matrix() - Vs = [(Vmatrix.with_permuted_columns(sig).hermite_form(), sig) - for sig in permutations] - Vmin = min(Vs, key=lambda x:x[0]) Vmodule = V.module() - vertices = [Vmodule(_) for _ in Vmin[0].columns()] + vertices, permutation = _palp_canonical_order(Vmatrix, PM_max, permutations) + vertices = [Vmodule(v) for v in vertices] for v in vertices: v.set_immutable() - return (PointCollection(vertices, Vmodule), Vmin[1]) + return PointCollection(vertices, Vmodule), permutation def _palp_convert_permutation(permutation): @@ -5237,7 +5213,7 @@ def _palp_convert_permutation(permutation): OUTPUT: - A :class:`permutation group element `. + A :class:`permutation group element `. EXAMPLES:: diff --git a/src/sage/geometry/palp_normal_form.pyx b/src/sage/geometry/palp_normal_form.pyx new file mode 100644 index 00000000000..fa756fe65b0 --- /dev/null +++ b/src/sage/geometry/palp_normal_form.pyx @@ -0,0 +1,400 @@ +# sage.doctest: needs sage.groups +r""" +PALP normal form of vertices of a lattice polytope +""" +# **************************************************************************** +# Copyright (C) 2013 Jan Keitel +# 2014 Volker Braun +# 2018 Christian Stump +# 2019 Vincent Delecroix +# 2019 Jonathan Kliem +# 2021 Michael Orlitzky +# 2018-2022 Frédéric Chapoton +# 2023 Luze Xu +# 2023 Matthias Koeppe +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# https://www.gnu.org/licenses/ +# **************************************************************************** + +from sage.groups.perm_gps.permgroup_element cimport PermutationGroupElement +from sage.groups.perm_gps.permgroup_named import SymmetricGroup +from sage.matrix.matrix_integer_dense cimport Matrix_integer_dense +from sage.matrix.special import column_matrix +from sage.structure.element import Matrix + + +def _palp_PM_max(Matrix_integer_dense PM, check=False): + r""" + Compute the permutation normal form of the vertex facet pairing matrix. + + The permutation normal form of a matrix is defined as the lexicographic + maximum under all permutations of its rows and columns. For more + more detail, see also + :meth:`~sage.matrix.matrix2.Matrix.permutation_normal_form`. + + Instead of using the generic method for computing the permutation + normal form, this method uses the PALP algorithm to compute + the permutation normal form and its automorphisms concurrently. + + INPUT: + + - ``check`` -- Boolean (default: ``False``), whether to return + the permutations leaving the maximal vertex-facet pairing + matrix invariant. + + OUTPUT: + + A matrix or a tuple of a matrix and a dict whose values are the + permutation group elements corresponding to the permutations + that permute :meth:`vertices` such that the vertex-facet pairing + matrix is maximal. + + EXAMPLES:: + + sage: o = lattice_polytope.cross_polytope(2) + sage: PM = o.vertex_facet_pairing_matrix() + sage: PM_max = PM.permutation_normal_form() + sage: PM_max == o._palp_PM_max() + True + sage: P2 = ReflexivePolytope(2, 0) + sage: PM_max, permutations = P2._palp_PM_max(check=True) + sage: PM_max + [3 0 0] + [0 3 0] + [0 0 3] + sage: list(permutations.values()) + [[(1,2,3), (1,2,3)], + [(1,3,2), (1,3,2)], + [(1,3), (1,3)], + [(1,2), (1,2)], + [(), ()], + [(2,3), (2,3)]] + sage: PM_max.automorphisms_of_rows_and_columns() + [((), ()), + ((1,2,3), (1,2,3)), + ((1,3,2), (1,3,2)), + ((2,3), (2,3)), + ((1,2), (1,2)), + ((1,3), (1,3))] + sage: PMs = (i._palp_PM_max(check=True) + ....: for i in ReflexivePolytopes(2)) + sage: results = (len(i) == len(j.automorphisms_of_rows_and_columns()) + ....: for j, i in PMs) + sage: all(results) # long time + True + + TESTS: + + Check that a bug introduced in :issue:`35997` is fixed:: + + sage: from sage.geometry.palp_normal_form import _palp_PM_max, _palp_canonical_order + sage: P = Polyhedron([(-4,-6),(-4,-5),(0,0),(1,0),(5,6)]) + sage: PM = P.slack_matrix().transpose() + sage: _palp_PM_max(PM) + [9 5 4 0 0] + [6 0 6 5 0] + [1 5 0 0 4] + [0 6 0 1 6] + [0 0 3 5 3] + sage: PM_max, permutations = _palp_PM_max(PM, check=True) + sage: _palp_canonical_order(P.vertices(), PM_max, permutations) + ([(1, 0), (0, 0), (2, 4), (1, 5), (-1, 1)], (1,2,3)) + """ + cdef int n_v = PM.ncols() + cdef int n_f = PM.nrows() + S_v = SymmetricGroup(n_v) + S_f = SymmetricGroup(n_f) + + cdef int n_s = 1 + cdef dict permutations = {0: [S_f.one(), S_v.one()]} + cdef int j, k, m, d + cdef int element, max_element + + for j in range(n_v): + max_element = PM.get_unsafe_int(0, ( permutations[0][1])(j + 1) - 1) + m = 0 + for i in range(j + 1, n_v): + element = PM.get_unsafe_int(0, ( permutations[0][1])(i + 1) - 1) + if element > max_element: + max_element = element + m = i - j + if m > 0: + permutations[0][1] = ( permutations[0][1])._transpose_left(j + 1, m + j + 1) + + cdef first_row_index = 0 + + # Arrange other rows one by one and compare with first row + for k in range(1, n_f): + # Error for k == 1 already! + permutations[n_s] = [S_f.one(), S_v.one()] + max_element = PM.get_unsafe_int(k, ( permutations[n_s][1])(1) - 1) + m = 0 + for j in range(1, n_v): + element = PM.get_unsafe_int(k, ( permutations[n_s][1])(j + 1) - 1) + if element > max_element: + max_element = element + m = j + if m > 0: + permutations[n_s][1] = ( permutations[n_s][1])._transpose_left(1, m + 1) + d = (PM.get_unsafe_int(k, ( permutations[n_s][1])(1) - 1) + - PM.get_unsafe_int(first_row_index, ( permutations[0][1])(1) - 1)) + if d < 0: + # The largest elt of this row is smaller than largest elt + # in 1st row, so nothing to do + continue + # otherwise: + for i in range(1, n_v): + max_element = PM.get_unsafe_int(k, ( permutations[n_s][1])(i + 1) - 1) + m = i + for j in range(i + 1, n_v): + element = PM.get_unsafe_int(k, ( permutations[n_s][1])(j + 1) - 1) + if element > max_element: + max_element = element + m = j + if m > i: + permutations[n_s][1] = ( permutations[n_s][1])._transpose_left(i + 1, m + 1) + if d == 0: + d = (PM.get_unsafe_int(k, ( permutations[n_s][1])(i+1) - 1) + - PM.get_unsafe_int(first_row_index, ( permutations[0][1])(i + 1) - 1)) + if d < 0: + break + if d < 0: + # This row is smaller than 1st row, so nothing to do + del permutations[n_s] + continue + permutations[n_s][0] = ( permutations[n_s][0])._transpose_left(1, k + 1) + if d == 0: + # This row is the same, so we have a symmetry! + n_s += 1 + else: + # This row is larger, so it becomes the first row and + # the symmetries reset. + first_row_index = k + permutations = {0: permutations[n_s]} + n_s = 1 + permutations = {k: permutations[k] for k in permutations if k < n_s} + + cdef tuple b = tuple(PM.get_unsafe_int(( permutations[0][0])(1) - 1, + ( permutations[0][1])(j+1) - 1) + for j in range(n_v)) + # Work out the restrictions the current permutations + # place on other permutations as a automorphisms + # of the first row + # The array is such that: + # S = [i, 1, ..., 1 (ith), j, i+1, ..., i+1 (jth), k ... ] + # describes the "symmetry blocks" + cdef list S = list(range(1, n_v + 1)) + for i in range(1, n_v): + if b[i-1] == b[i]: + S[i] = S[i-1] + S[S[i]-1] += 1 + else: + S[i] = i + 1 + + cdef int l, np, cf, ccf, n_s_bar, d1, v0, vc, vj + cdef list l_r + + # We determine the other rows of PM_max in turn by use of perms and + # aut on previous rows. + for l in range(1, n_f - 1): + n_s = len(permutations) + n_s_bar = n_s + cf = 0 + l_r = [0]*n_v + # Search for possible local permutations based off previous + # global permutations. + for k in range(n_s_bar - 1, -1, -1): + # number of local permutations associated with current global + n_p = 0 + ccf = cf + permutations_bar = {0: list(permutations[k])} + # We look for the line with the maximal entry in the first + # subsymmetry block, i.e. we are allowed to swap elements + # between 0 and S(0) + for s in range(l, n_f): + for j in range(1, S[0]): + v0 = PM.get_unsafe_int(( permutations_bar[n_p][0])(s+1) - 1, + ( permutations_bar[n_p][1])(1) - 1) + vj = PM.get_unsafe_int(( permutations_bar[n_p][0])(s+1) - 1, + ( permutations_bar[n_p][1])(j+1) - 1) + if v0 < vj: + permutations_bar[n_p][1] = ( permutations_bar[n_p][1])._transpose_left(1, j + 1) + if ccf == 0: + l_r[0] = PM.get_unsafe_int(( permutations_bar[n_p][0])(s+1) - 1, + ( permutations_bar[n_p][1])(1) - 1) + if s != l: + permutations_bar[n_p][0] = ( permutations_bar[n_p][0])._transpose_left(l + 1, s + 1) + n_p += 1 + ccf = 1 + permutations_bar[n_p] = list(permutations[k]) + else: + d1 = PM.get_unsafe_int(( permutations_bar[n_p][0])(s+1) - 1, + ( permutations_bar[n_p][1])(1) - 1) + d = d1 - l_r[0] + if d < 0: + # We move to the next line + continue + elif d==0: + # Maximal values agree, so possible symmetry + if s != l: + permutations_bar[n_p][0] = ( permutations_bar[n_p][0])._transpose_left(l + 1, s + 1) + n_p += 1 + permutations_bar[n_p] = list(permutations[k]) + else: + # We found a greater maximal value for first entry. + # It becomes our new reference: + l_r[0] = d1 + if s != l: + permutations_bar[n_p][0] = ( permutations_bar[n_p][0])._transpose_left(l + 1, s + 1) + # Forget previous work done + cf = 0 + permutations_bar = {0: list(permutations_bar[n_p])} + n_p = 1 + permutations_bar[n_p] = list(permutations[k]) + n_s = k + 1 + # Check if the permutations found just now work + # with other elements + for c in range(1, n_v): + h = S[c] + ccf = cf + # Now let us find out where the end of the + # next symmetry block is: + if h < c + 1: + h = S[h - 1] + s = n_p + # Check through this block for each possible permutation + while s > 0: + s -= 1 + # Find the largest value in this symmetry block + for j in range(c + 1, h): + vc = PM.get_unsafe_int(( permutations_bar[s][0])(l+1) - 1, + ( permutations_bar[s][1])(c+1) - 1) + vj = PM.get_unsafe_int(( permutations_bar[s][0])(l+1) - 1, + ( permutations_bar[s][1])(j+1) - 1) + if vc < vj: + permutations_bar[s][1] = ( permutations_bar[s][1])._transpose_left(c + 1, j + 1) + if ccf == 0: + # Set reference and carry on to next permutation + l_r[c] = PM.get_unsafe_int(( permutations_bar[s][0])(l+1) - 1, + ( permutations_bar[s][1])(c+1) - 1) + ccf = 1 + else: + d1 = PM.get_unsafe_int(( permutations_bar[s][0])(l+1) - 1, + ( permutations_bar[s][1])(c+1) - 1) + d = d1 - l_r[c] + if d < 0: + n_p -= 1 + if s < n_p: + permutations_bar[s] = list(permutations_bar[n_p]) + elif d > 0: + # The current case leads to a smaller matrix, + # hence this case becomes our new reference + l_r[c] = d1 + cf = 0 + n_p = s + 1 + n_s = k + 1 + # Update permutations + if (n_s - 1) > k: + permutations[k] = list(permutations[n_s - 1]) + n_s -= 1 + for s in range(n_p): + permutations[n_s] = list(permutations_bar[s]) + n_s += 1 + cf = n_s + permutations = {k: permutations[k] for k in permutations if k < n_s} + # If the automorphisms are not already completely restricted, + # update them + if S != list(range(1, n_v + 1)): + # Take the old automorphisms and update by + # the restrictions the last worked out + # row imposes. + c = 0 + M = tuple(PM.get_unsafe_int(( permutations[0][0])(l+1) - 1, + ( permutations[0][1])(j+1) - 1) + for j in range(n_v)) + while c < n_v: + s = S[c] + 1 + S[c] = c + 1 + c += 1 + while c < (s - 1): + if M[c] == M[c - 1]: + S[c] = S[c - 1] + S[S[c] - 1] += 1 + else: + S[c] = c + 1 + c += 1 + # Now we have the perms, we construct PM_max using one of them + PM_max = PM.with_permuted_rows_and_columns(*permutations[0]) + if check: + return (PM_max, permutations) + else: + return PM_max + + +def _palp_canonical_order(vertices, PM_max, permutations): + r""" + Compute the PALP normal form of vertices of a lattice polytope + using auxiliary data computed elsewhere. + + This is a helper function for + :meth:`~sage.geometry.lattice_polytope.LatticePolytopeClass.normal_form` + and should not be called directly. + + Given an iterable of vertices, the maximal vertex-facet pairing matrix + and the permutations realizing this matrix, apply the last part of the + PALP algorithm and return the normal form. + + INPUT: + + - ``vertices`` -- iterable of iterables. The vertices. + + - ``PM_max`` -- the maximal vertex-facet pairing matrix + + - ``permutation`` -- the permutations of the vertices yielding ``PM_max``. + + OUTPUT: + + The PALP normal form as an iterable of integer vectors. + + TESTS:: + + sage: L = lattice_polytope.cross_polytope(2) + sage: V = L.vertices() + sage: PM_max, permutations = L._palp_PM_max(check=True) + sage: from sage.geometry.lattice_polytope import _palp_canonical_order + sage: _palp_canonical_order(V, PM_max, permutations) + (M( 1, 0), + M( 0, 1), + M( 0, -1), + M(-1, 0) + in 2-d lattice M, (1,3,2,4)) + """ + n_v = PM_max.ncols() + S_v = SymmetricGroup(n_v) + p_c = S_v.one() + M_max = [max(row[j] for row in PM_max.rows()) for j in range(n_v)] + S_max = sum(PM_max) + for i in range(n_v): + k = i + for j in range(i + 1, n_v): + if M_max[j] < M_max[k] or \ + (M_max[j] == M_max[k] and S_max[j] < S_max[k]): + k = j + if not k == i: + M_max[i], M_max[k] = M_max[k], M_max[i] + S_max[i], S_max[k] = S_max[k], S_max[i] + p_c = p_c._transpose_left(1 + i, 1 + k) + # Create array of possible NFs. + permutations = [p_c * l[1] for l in permutations.values()] + if isinstance(vertices, Matrix): + Vmatrix = vertices + else: + Vmatrix = column_matrix(vertices) + Vs = [(Vmatrix.with_permuted_columns(sig).hermite_form(), sig) + for sig in permutations] + Vmin = min(Vs, key=lambda x: x[0]) + return Vmin[0].columns(), Vmin[1] diff --git a/src/sage/geometry/polyhedron/base_ZZ.py b/src/sage/geometry/polyhedron/base_ZZ.py index 5e6633c7b3f..20b3c95bbcc 100644 --- a/src/sage/geometry/polyhedron/base_ZZ.py +++ b/src/sage/geometry/polyhedron/base_ZZ.py @@ -3,7 +3,14 @@ """ # **************************************************************************** -# Copyright (C) 2011 Volker Braun +# Copyright (C) 2011-2013 Volker Braun +# 2015 Nathann Cohen +# 2015 Vincent Delecroix +# 2017-2018 Frédéric Chapoton +# 2019 Sophia Elia +# 2019-2020 Jonathan Kliem +# 2023 Luze Xu +# 2023 Matthias Koeppe # # 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 @@ -834,3 +841,89 @@ def is_known_summand(poly): decompositions.append((X, Y)) summands += [X, Y] return tuple(decompositions) + + def normal_form(self, algorithm="palp_native", permutation=False): + r""" + Return the normal form of vertices of the lattice polytope ``self``. + + INPUT: + + - ``algorithm`` -- must be ``"palp_native"``, the default. + + - ``permutation`` -- boolean (default: ``False``); if ``True``, the permutation + applied to vertices to obtain the normal form is returned as well. + + For more more detail, + see :meth:`~sage.geometry.lattice_polytope.LatticePolytopeClass.normal_form`. + + EXAMPLES: + + We compute the normal form of the "diamond":: + + sage: d = Polyhedron([(1,0), (0,1), (-1,0), (0,-1)]) + sage: d.vertices() + (A vertex at (-1, 0), + A vertex at (0, -1), + A vertex at (0, 1), + A vertex at (1, 0)) + sage: d.normal_form() # needs sage.groups + [(1, 0), (0, 1), (0, -1), (-1, 0)] + sage: d.lattice_polytope().normal_form("palp_native") # needs sage.groups + M( 1, 0), + M( 0, 1), + M( 0, -1), + M(-1, 0) + in 2-d lattice M + + Using ``permutation=True``:: + + sage: d.normal_form(permutation=True) # needs sage.groups + ([(1, 0), (0, 1), (0, -1), (-1, 0)], ()) + + It is not possible to compute normal forms for polytopes which do not + span the space:: + + sage: p = Polyhedron([(1,0,0), (0,1,0), (-1,0,0), (0,-1,0)]) + sage: p.normal_form() + Traceback (most recent call last): + ... + ValueError: normal form is not defined for lower-dimensional polyhedra, got + A 2-dimensional polyhedron in ZZ^3 defined as the convex hull of 4 vertices + + The normal form is also not defined for unbounded polyhedra:: + + sage: p = Polyhedron(vertices=[[1, 1]], rays=[[1, 0], [0, 1]], base_ring=ZZ) + sage: p.normal_form() + Traceback (most recent call last): + ... + ValueError: normal form is not defined for unbounded polyhedra, got + A 2-dimensional polyhedron in ZZ^2 defined as the convex hull of 1 vertex and 2 rays + + See :issue:`15280` for proposed extensions to these cases. + + TESTS:: + + sage: d.normal_form(algorithm="palp_fiction") + Traceback (most recent call last): + ... + ValueError: algorithm must be 'palp_native' + """ + from sage.geometry.palp_normal_form import _palp_PM_max, _palp_canonical_order + + if algorithm != "palp_native": + raise ValueError("algorithm must be 'palp_native'") + + if self.dim() < self.ambient_dim(): + raise ValueError("normal form is not defined for lower-dimensional polyhedra, got %s" % self) + + if not self.is_compact(): + raise ValueError("normal form is not defined for unbounded polyhedra, got %s" % self) + + PM = self.slack_matrix().transpose() + PM_max, permutations = _palp_PM_max(PM, check=True) + out = _palp_canonical_order(self.vertices(), PM_max, permutations) + + if permutation: + return out + else: + return out[0] diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd index 61814b4f538..3506aab65bb 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd @@ -6,6 +6,7 @@ from sage.geometry.polyhedron.combinatorial_polyhedron.list_of_faces from sage.geometry.polyhedron.combinatorial_polyhedron.face_data_structure cimport face_t from sage.geometry.polyhedron.combinatorial_polyhedron.polyhedron_face_lattice cimport PolyhedronFaceLattice + @cython.final cdef class CombinatorialPolyhedron(SageObject): cdef public dict _cached_methods diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx index 11148d13a83..830d45f9b90 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx @@ -93,11 +93,10 @@ from sage.geometry.cone import ConvexRationalPolyhedralCone from sage.structure.element import Matrix from sage.matrix.matrix_dense cimport Matrix_dense from sage.misc.misc import is_iterator -from .conversions \ - import incidence_matrix_to_bit_rep_of_facets, \ - incidence_matrix_to_bit_rep_of_Vrep, \ - facets_tuple_to_bit_rep_of_facets, \ - facets_tuple_to_bit_rep_of_Vrep +from .conversions import (incidence_matrix_to_bit_rep_of_facets, + incidence_matrix_to_bit_rep_of_Vrep, + facets_tuple_to_bit_rep_of_facets, + facets_tuple_to_bit_rep_of_Vrep) from sage.geometry.polyhedron.combinatorial_polyhedron.conversions cimport Vrep_list_to_bit_rep from sage.misc.cachefunc import cached_method @@ -437,7 +436,7 @@ cdef class CombinatorialPolyhedron(SageObject): from sage.matrix.constructor import matrix from sage.rings.integer_ring import ZZ incidence_matrix = matrix(ZZ, data.incidence_matrix().rows() - + [[ZZ.one() for _ in range(len(data.facet_normals()))]]) + + [[ZZ.one() for _ in range(len(data.facet_normals()))]]) return self._init_from_incidence_matrix(incidence_matrix) cdef _init_facet_names(self, facets) noexcept: @@ -481,11 +480,10 @@ cdef class CombinatorialPolyhedron(SageObject): data.set_immutable() self.incidence_matrix.set_cache(data) - # Delete equations. data = data.delete_columns( [i for i in range(data.ncols()) - if all(data[j,i] for j in range(data.nrows()))], + if all(data[j, i] for j in range(data.nrows()))], check=False) # Initializing the facets in their Bit-representation. @@ -515,7 +513,7 @@ cdef class CombinatorialPolyhedron(SageObject): n_Vrepresentation = len(Vrep) if Vrep != range(len(Vrep)): self._Vrep = tuple(Vrep) - Vinv = {v: i for i,v in enumerate(self._Vrep)} + Vinv = {v: i for i, v in enumerate(self._Vrep)} else: # Assuming the user gave as correct names for the vertices # and labeled them instead by `0,...,n`. @@ -548,7 +546,7 @@ cdef class CombinatorialPolyhedron(SageObject): Initialize self from two ``ListOfFaces``. """ self._bitrep_facets = facets - self._bitrep_Vrep = Vrep + self._bitrep_Vrep = Vrep self._n_Hrepresentation = self._bitrep_facets.n_faces() self._n_Vrepresentation = self._bitrep_Vrep.n_faces() @@ -629,7 +627,7 @@ cdef class CombinatorialPolyhedron(SageObject): 'A 2-dimensional combinatorial polyhedron with 1 facet' """ desc = "A {}-dimensional combinatorial polyhedron with {} facet"\ - .format(self.dimension(), self.n_facets()) + .format(self.dimension(), self.n_facets()) if self.n_facets() != 1: desc += "s" return desc @@ -1694,7 +1692,7 @@ cdef class CombinatorialPolyhedron(SageObject): if not names: vertices = [i for i in range(n_facets + n_Vrep)] - edges = tuple((j, n_Vrep + n_facets - 1 - i) for i,facet in enumerate(facet_iter) for j in facet.ambient_V_indices()) + edges = tuple((j, n_Vrep + n_facets - 1 - i) for i, facet in enumerate(facet_iter) for j in facet.ambient_V_indices()) else: facet_names = self.facet_names() if facet_names is None: @@ -1707,7 +1705,7 @@ cdef class CombinatorialPolyhedron(SageObject): Vrep = [("V", i) for i in range(n_Vrep)] vertices = Vrep + facet_names - edges = tuple((Vrep[j], facet_names[n_facets - 1 - i]) for i,facet in enumerate(facet_iter) for j in facet.ambient_V_indices()) + edges = tuple((Vrep[j], facet_names[n_facets - 1 - i]) for i, facet in enumerate(facet_iter) for j in facet.ambient_V_indices()) return DiGraph([vertices, edges], format='vertices_and_edges', immutable=True) @cached_method @@ -2126,7 +2124,7 @@ cdef class CombinatorialPolyhedron(SageObject): cdef simpliciality = dim - 1 # For each face in the iterator, check if its a simplex. - face_iter.structure.lowest_dimension = 2 # every 1-face is a simplex + face_iter.structure.lowest_dimension = 2 # every 1-face is a simplex d = face_iter.next_dimension() while d < dim: sig_check() @@ -2237,7 +2235,7 @@ cdef class CombinatorialPolyhedron(SageObject): cdef simplicity = dim - 1 # For each coface in the iterator, check if its a simplex. - coface_iter.structure.lowest_dimension = 2 # every coface of dimension 1 is a simplex + coface_iter.structure.lowest_dimension = 2 # every coface of dimension 1 is a simplex d = coface_iter.next_dimension() while d < dim: sig_check() @@ -2623,7 +2621,6 @@ cdef class CombinatorialPolyhedron(SageObject): return (False, None) - def join_of_Vrep(self, *indices): r""" Return the smallest face containing all Vrepresentatives indicated by the indices. @@ -2793,7 +2790,6 @@ cdef class CombinatorialPolyhedron(SageObject): if 'dual' in kwds and dual == -1 and kwds['dual'] in (False, True): dual = int(kwds['dual']) - cdef FaceIterator face_iter if dual == -1: # Determine the faster way, to iterate through all faces. if not self.is_bounded() or self.n_facets() <= self.n_Vrepresentation(): @@ -3354,7 +3350,6 @@ cdef class CombinatorialPolyhedron(SageObject): and self.far_face_tuple() == other_C.far_face_tuple() and self.incidence_matrix() == other.incidence_matrix()) - # Methods to obtain a different combinatorial polyhedron. cpdef CombinatorialPolyhedron dual(self) noexcept: @@ -3484,7 +3479,6 @@ cdef class CombinatorialPolyhedron(SageObject): return CombinatorialPolyhedron((new_facets, new_Vrep), Vrep=new_Vrep_names, facets=new_facet_names) - # Internal methods. cdef int _compute_f_vector(self, size_t num_threads, size_t parallelization_depth, int dual) except -1: @@ -3497,7 +3491,6 @@ cdef class CombinatorialPolyhedron(SageObject): return 0 # There is no need to recompute the f_vector. cdef int dim = self.dimension() - cdef int d # dimension of the current face of the iterator cdef MemoryAllocator mem = MemoryAllocator() if num_threads == 0: @@ -3686,7 +3679,7 @@ cdef class CombinatorialPolyhedron(SageObject): from sage.arith.misc import binomial estimate_n_faces = self.dimension() * binomial(min(self.n_facets(), self.n_Vrepresentation()), - self.dimension() // 2) + self.dimension() // 2) # Note that the runtime per face already computes the coatoms of the next level, i.e. # the runtime for each facet suffices to compute all ridges in primal, diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pxd b/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pxd index e65f8eb678b..afc01904da2 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pxd +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pxd @@ -4,6 +4,7 @@ from sage.geometry.polyhedron.combinatorial_polyhedron.list_of_faces from sage.geometry.polyhedron.combinatorial_polyhedron.face_data_structure cimport face_t from sage.geometry.polyhedron.combinatorial_polyhedron.face_iterator cimport FaceIterator + @cython.final cdef class CombinatorialFace(SageObject): cdef readonly bint _dual # if 1, then iterate over dual Polyhedron diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx index 5e5b2dfd992..81dc7c269db 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/combinatorial_face.pyx @@ -173,9 +173,9 @@ cdef class CombinatorialFace(SageObject): # Copy data from FaceIterator. it = data - self._dual = it.dual - self.atoms = it.atoms - self.coatoms = it.coatoms + self._dual = it.dual + self.atoms = it.atoms + self.coatoms = it.coatoms if it.structure.face_status == FaceStatus.NOT_INITIALIZED: raise LookupError("face iterator not set to a face") @@ -183,15 +183,15 @@ cdef class CombinatorialFace(SageObject): face_init(self.face, self.coatoms.n_atoms(), self.coatoms.n_coatoms()) face_copy(self.face, it.structure.face) - self._dimension = it.structure.current_dimension + self._dimension = it.structure.current_dimension self._ambient_dimension = it.structure.dimension - self._ambient_Vrep = it._Vrep - self._ambient_facets = it._facet_names - self._n_ambient_facets = it._n_facets - self._equations = it._equations - self._n_equations = it._n_equations - self._hash_index = it.structure._index - self._ambient_bounded = it._bounded + self._ambient_Vrep = it._Vrep + self._ambient_facets = it._facet_names + self._n_ambient_facets = it._n_facets + self._equations = it._equations + self._n_equations = it._n_equations + self._hash_index = it.structure._index + self._ambient_bounded = it._bounded self._initialized_from_face_lattice = False @@ -203,35 +203,35 @@ cdef class CombinatorialFace(SageObject): assert 0 <= index < all_faces.f_vector[dimension + 1], "index is out of range" # Copy data from PolyhedronFaceLattice. - self._dual = all_faces.dual - self.atoms = all_faces.atoms - self.coatoms = all_faces.coatoms + self._dual = all_faces.dual + self.atoms = all_faces.atoms + self.coatoms = all_faces.coatoms face_init(self.face, self.coatoms.n_atoms(), self.coatoms.n_coatoms()) face_copy(self.face, all_faces.faces[dimension+1].faces[index]) - self._dimension = dimension + self._dimension = dimension self._ambient_dimension = all_faces.dimension - self._ambient_Vrep = all_faces._Vrep - self._ambient_facets = all_faces._facet_names - self._equations = all_faces._equations - self._n_equations = len(self._equations) if self._equations else 0 + self._ambient_Vrep = all_faces._Vrep + self._ambient_facets = all_faces._facet_names + self._equations = all_faces._equations + self._n_equations = len(self._equations) if self._equations else 0 if self._dual: self._n_ambient_facets = self.atoms.n_faces() else: self._n_ambient_facets = self.coatoms.n_faces() - self._ambient_bounded = all_faces._bounded + self._ambient_bounded = all_faces._bounded self._initialized_from_face_lattice = True self._hash_index = index - for i in range(-1,dimension): + for i in range(-1, dimension): self._hash_index += all_faces.f_vector[i+1] # Add the complete ``f-vector`` to the hash index, # such that hash values obtained by an iterator or by the face lattice # do not collide. - for i in range(-1,self._ambient_dimension+1): + for i in range(-1, self._ambient_dimension+1): self._hash_index += all_faces.f_vector[i+1] else: raise ValueError("data must be face iterator or a list of all faces") @@ -273,7 +273,7 @@ cdef class CombinatorialFace(SageObject): 'A 3-dimensional face of a 5-dimensional combinatorial polyhedron' """ return "A {}-dimensional face of a {}-dimensional combinatorial polyhedron"\ - .format(self.dimension(), self.ambient_dimension()) + .format(self.dimension(), self.ambient_dimension()) def __reduce__(self): r""" diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx index 26aa92a6575..951dd9e5420 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx @@ -58,15 +58,15 @@ AUTHOR: - Jonathan Kliem (2019-04) """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2019 Jonathan Kliem # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** from memory_allocator cimport MemoryAllocator @@ -94,6 +94,7 @@ def _Vrep_list_to_bit_rep_wrapper(tup): Vrep_list_to_bit_rep(tup, output.data.faces[0]) return output + cdef int Vrep_list_to_bit_rep(tuple Vrep_list, face_t output) except -1: r""" Convert a vertex list into Bit-representation. Store it in ``output``. @@ -135,6 +136,7 @@ cdef int Vrep_list_to_bit_rep(tuple Vrep_list, face_t output) except -1: for entry in Vrep_list: face_add_atom_safe(output, entry) + def _incidences_to_bit_rep_wrapper(tup): r""" A function to allow doctesting of :func:`incidences_to_bit_rep`. @@ -150,6 +152,7 @@ def _incidences_to_bit_rep_wrapper(tup): incidences_to_bit_rep(tup, output.data.faces[0]) return output + cdef int incidences_to_bit_rep(tuple incidences, face_t output) except -1: r""" Convert a tuple of incidences into Bit-representation. @@ -185,6 +188,7 @@ cdef int incidences_to_bit_rep(tuple incidences, face_t output) except -1: # Vrep ``entry`` is contained in the face, so set the corresponding bit face_add_atom_safe(output, entry) + def incidence_matrix_to_bit_rep_of_facets(Matrix_dense matrix): r""" Initialize facets in Bit-representation as :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.list_of_faces.ListOfFaces`. @@ -249,6 +253,7 @@ def incidence_matrix_to_bit_rep_of_facets(Matrix_dense matrix): face_add_atom_safe(output, entry) return facets + def incidence_matrix_to_bit_rep_of_Vrep(Matrix_dense matrix): r""" Initialize Vrepresentatives in Bit-representation as :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.list_of_faces.ListOfFaces`. @@ -307,6 +312,7 @@ def incidence_matrix_to_bit_rep_of_Vrep(Matrix_dense matrix): """ return incidence_matrix_to_bit_rep_of_facets(matrix.transpose()) + def facets_tuple_to_bit_rep_of_facets(tuple facets_input, size_t n_Vrep): r""" Initializes facets in Bit-representation as :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.list_of_faces.ListOfFaces`. @@ -348,6 +354,7 @@ def facets_tuple_to_bit_rep_of_facets(tuple facets_input, size_t n_Vrep): facet_set_coatom(facets.data.faces[i], i) return facets + def facets_tuple_to_bit_rep_of_Vrep(tuple facets_input, size_t n_Vrep): r""" Initialize Vrepresentatives in Bit-representation as :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.list_of_faces.ListOfFaces`. @@ -408,6 +415,7 @@ def facets_tuple_to_bit_rep_of_Vrep(tuple facets_input, size_t n_Vrep): face_add_atom_safe(Vrep_data[input_Vrep], input_facet) return Vrep + def _bit_rep_to_Vrep_list_wrapper(ListOfFaces faces, index=0): r""" A function to test :func:`bit_rep_to_Vrep_list`. @@ -433,10 +441,10 @@ def _bit_rep_to_Vrep_list_wrapper(ListOfFaces faces, index=0): output = mem.allocarray(faces.n_atoms(), sizeof(size_t)) - length = bit_rep_to_Vrep_list( - faces.data.faces[index], output) + length = bit_rep_to_Vrep_list(faces.data.faces[index], output) return tuple(output[i] for i in range(length)) + cdef inline size_t bit_rep_to_Vrep_list(face_t face, size_t *output) except -1: r""" Convert a bitrep-representation to a list of Vrep. Return length of representation. diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd b/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd index c906ddb51cc..87e3e87c1c6 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pxd @@ -80,10 +80,12 @@ cdef class FaceIterator_base(SageObject): cdef int only_subsets(self) except -1 cdef int find_face(self, face_t face) except -1 + @cython.final cdef class FaceIterator(FaceIterator_base): pass + @cython.final cdef class FaceIterator_geom(FaceIterator_base): cdef int _trivial_faces # Whether to yield the trivial faces. diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx index 734745c6b8e..76227cfe3cf 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_iterator.pyx @@ -164,15 +164,15 @@ AUTHOR: - Jonathan Kliem (2019-04) """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2019 Jonathan Kliem # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** from cython.parallel cimport prange, threadid from cysignals.memory cimport check_allocarray, sig_free @@ -243,7 +243,6 @@ cdef class FaceIterator_base(SageObject): if dual and not C.is_bounded(): raise ValueError("cannot iterate over dual of unbounded Polyedron") cdef int i - cdef size_t j self.dual = dual self.structure.dual = dual @@ -1188,7 +1187,7 @@ cdef class FaceIterator_base(SageObject): cdef size_t yet_to_visit = self.structure.yet_to_visit if unlikely(yet_to_visit >= faces[0].n_faces - or not faces_are_identical(faces[0].faces[yet_to_visit], self.structure.face)): + or not faces_are_identical(faces[0].faces[yet_to_visit], self.structure.face)): raise ValueError("iterator is not set to the correct face") swap_faces(faces[0].faces[yet_to_visit], faces[0].faces[faces[0].n_faces - 1]) @@ -1293,7 +1292,7 @@ cdef class FaceIterator_base(SageObject): self.structure.current_dimension = -1 return 0 - cdef int d = self.next_dimension() + self.next_dimension() while self.structure.current_dimension != self.structure.dimension: if face_issubset(face, self.structure.face): if face_issubset(self.structure.face, face): @@ -1303,7 +1302,7 @@ cdef class FaceIterator_base(SageObject): # The face is not a subface/supface of the current face. self.ignore_subsets() - d = self.next_dimension() + self.next_dimension() raise ValueError("the face appears to be incorrect") @@ -1882,7 +1881,7 @@ cdef class FaceIterator_geom(FaceIterator_base): if unlikely(self._trivial_faces): if self._trivial_faces == -1: raise StopIteration - if self._trivial_faces in (2,4): # Return the polyhedron. + if self._trivial_faces in (2, 4): # Return the polyhedron. if self._trivial_faces == 2: self._trivial_faces = 1 # Return the empty face next. else: @@ -2075,30 +2074,29 @@ cdef int parallel_f_vector(iter_t* structures, size_t num_threads, size_t parall if num_threads == 0: num_threads = 1 - cdef size_t thread_id cdef MemoryAllocator mem = MemoryAllocator() # Setting up for each thread some storage space. cdef parallel_f_t* parallel_structs = \ - mem.allocarray(num_threads, sizeof(parallel_f_t)) + mem.allocarray(num_threads, sizeof(parallel_f_t)) for i in range(num_threads): # Partial f-vectors. parallel_structs[i].f_vector = \ - mem.calloc(dim+2, sizeof(size_t)) + mem.calloc(dim+2, sizeof(size_t)) parallel_structs[i].current_job_id = \ - mem.calloc(parallelization_depth+1, sizeof(size_t)) + mem.calloc(parallelization_depth+1, sizeof(size_t)) # Keeping back of the original number of faces allows faster starting the next job. parallel_structs[i].original_n_faces = \ - mem.calloc(parallelization_depth+1, sizeof(size_t)) + mem.calloc(parallelization_depth+1, sizeof(size_t)) parallel_structs[i].original_n_faces[0] = \ - structures[0].new_faces[dim - 1].n_faces + structures[0].new_faces[dim - 1].n_faces parallel_structs[i].original_n_visited_all = \ - mem.calloc(parallelization_depth+1, sizeof(size_t)) + mem.calloc(parallelization_depth+1, sizeof(size_t)) parallel_structs[i].original_n_visited_all[0] = \ - structures[0].visited_all[dim - 1].n_faces + structures[0].visited_all[dim - 1].n_faces for i in prange(n_jobs, schedule='dynamic', chunksize=1, num_threads=num_threads, nogil=True): @@ -2154,9 +2152,9 @@ cdef inline int prepare_face_iterator_for_partial_job( # Recover all faces. structure.new_faces[d].n_faces = \ - parallel_struct.original_n_faces[current_depth -1] + parallel_struct.original_n_faces[current_depth -1] structure.visited_all[d].n_faces = \ - parallel_struct.original_n_visited_all[current_depth -1] + parallel_struct.original_n_visited_all[current_depth -1] structure.first_time[d] = True structure.yet_to_visit = 0 # just to be on the safe side @@ -2171,7 +2169,6 @@ cdef inline int prepare_face_iterator_for_partial_job( cdef size_t n_coatoms = structure.n_coatoms cdef size_t job_id_c cdef size_t i - cdef size_t diff cdef size_t new_faces_counter for current_depth in range(1, parallelization_depth + 1): diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pxd b/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pxd index 9867675fbec..50bbd7c4026 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pxd +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pxd @@ -188,7 +188,6 @@ cdef inline size_t find_face(face_t face, face_list_t faces) noexcept: cdef face_t* faces_pt = faces.faces cdef int val - while (n_faces > 1): # In each iteration step, we will look for ``face`` in # ``faces_pt[start:start+n_faces]``. @@ -367,6 +366,6 @@ cdef inline bint face_list_check_alignment(face_list_t faces) noexcept: """ cdef size_t i for i in range(faces.n_faces): - if not face_check_alignment(faces.faces[i]): - return False + if not face_check_alignment(faces.faces[i]): + return False return True diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pyx index 3f33aec8ec6..34adfb092dd 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/face_list_data_structure.pyx @@ -9,7 +9,7 @@ Sorting of a list of faces. # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # https://www.gnu.org/licenses/ -#**************************************************************************** +# *************************************************************************** cdef void sort_faces_list(face_list_t faces) noexcept: r""" diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pxd b/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pxd index d994f78ebec..c660240fbc4 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pxd +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pxd @@ -1,6 +1,7 @@ cimport cython from sage.geometry.polyhedron.combinatorial_polyhedron.face_list_data_structure cimport face_list_t, face_t + @cython.final cdef class ListOfFaces: # ``data`` points to the raw data. diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx index 59e72afad65..8c23470e0e3 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/list_of_faces.pyx @@ -294,7 +294,7 @@ cdef class ListOfFaces: # Calculating ``newfaces`` # such that ``newfaces`` points to all facets of ``faces[n_faces -1]``. - cdef size_t new_n_faces = get_next_level(self.data, new_faces.data, empty_forbidden) + get_next_level(self.data, new_faces.data, empty_forbidden) # Undo what ``get_next_level`` does. self.data.n_faces += 1 diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pxd b/src/sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pxd index 2cfd863835e..afe956672ff 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pxd +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pxd @@ -4,6 +4,7 @@ from sage.geometry.polyhedron.combinatorial_polyhedron.face_data_structure from sage.geometry.polyhedron.combinatorial_polyhedron.face_list_data_structure cimport face_list_t from sage.geometry.polyhedron.combinatorial_polyhedron.combinatorial_face cimport CombinatorialFace + @cython.final cdef class PolyhedronFaceLattice: cdef int dimension # dimension of Polyhedron diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx index 8ba0b7edc1d..5a2c31f6453 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/polyhedron_face_lattice.pyx @@ -50,7 +50,7 @@ AUTHOR: - Jonathan Kliem (2019-04) """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2019 Jonathan Kliem # # This program is free software: you can redistribute it and/or modify @@ -58,11 +58,10 @@ AUTHOR: # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # https://www.gnu.org/licenses/ -#***************************************************************************** +# **************************************************************************** -from .conversions \ - import facets_tuple_to_bit_rep_of_facets, \ - facets_tuple_to_bit_rep_of_Vrep +from .conversions import (facets_tuple_to_bit_rep_of_facets, + facets_tuple_to_bit_rep_of_Vrep) from sage.geometry.polyhedron.combinatorial_polyhedron.conversions cimport bit_rep_to_Vrep_list @@ -166,7 +165,6 @@ cdef class PolyhedronFaceLattice: self.atoms = face_iter.atoms self.coatoms = face_iter.coatoms - cdef size_t n_atoms = self.atoms.n_faces() self.atom_rep = check_allocarray(self.coatoms.n_atoms(), sizeof(size_t)) self.coatom_rep = check_allocarray(self.coatoms.n_faces(), sizeof(size_t)) @@ -361,7 +359,6 @@ cdef class PolyhedronFaceLattice: ....: face.ambient_V_indices() for face in it) True """ - cdef size_t length if self.dual: # if dual, the Vrepresentation corresponds to the coatom-representation dimension = self.dimension - 1 - dimension # if dual, the dimensions are reversed @@ -376,9 +373,9 @@ cdef class PolyhedronFaceLattice: This is a shortcut of :class:`sage.geometry.polyhedron.combinatorial_polyhedron.combinatorial_face.CombinatorialFace.set_coatom_rep` """ if unlikely(dimension < -1 or dimension > self.dimension): - raise ValueError("no face of dimension %s"%dimension) + raise ValueError("no face of dimension %s" % dimension) if unlikely(index >= self.f_vector[dimension + 1]): - raise IndexError("no %s-th face of dimension %s"%(index, dimension)) + raise IndexError("no %s-th face of dimension %s" % (index, dimension)) if unlikely(self.coatoms.n_faces() == 0): return 0 @@ -394,9 +391,9 @@ cdef class PolyhedronFaceLattice: This is a shortcut of :class:`sage.geometry.polyhedron.combinatorial_polyhedron.combinatorial_face.CombinatorialFace.set_atom_rep` """ if unlikely(dimension < -1 or dimension > self.dimension): - raise ValueError("no face of dimension %s"%dimension) + raise ValueError("no face of dimension %s" % dimension) if unlikely(index >= self.f_vector[dimension + 1]): - raise IndexError("no %s-th face of dimension %s"%(index, dimension)) + raise IndexError("no %s-th face of dimension %s" % (index, dimension)) cdef face_t face = self.faces[dimension+1].faces[index] return bit_rep_to_Vrep_list(face, self.atom_rep) @@ -412,13 +409,12 @@ cdef class PolyhedronFaceLattice: with empty and full polyhedron are implemented, which suffices for the face-lattice. """ - cdef size_t i if dimension_one == self.dimension: # The full polyhedron is incident to every face. if dimension_two < -1: - raise ValueError("no faces of dimension %s"%dimension_two) + raise ValueError("no faces of dimension %s" % dimension_two) if dimension_two > self.dimension: - raise ValueError("no faces of dimension %s"%dimension_two) + raise ValueError("no faces of dimension %s" % dimension_two) self.incidence_dim_one = dimension_one self.incidence_dim_two = dimension_two self.incidence_counter_one = 0 @@ -429,9 +425,9 @@ cdef class PolyhedronFaceLattice: if dimension_two == -1: # The empty polyhedron is incident to every face. if dimension_one < -1: - raise ValueError("no faces of dimension %s"%dimension_two) + raise ValueError("no faces of dimension %s" % dimension_two) if dimension_one > self.dimension: - raise ValueError("no faces of dimension %s"%dimension_two) + raise ValueError("no faces of dimension %s" % dimension_two) self.incidence_dim_one = dimension_one self.incidence_dim_two = dimension_two self.incidence_counter_one = 0 @@ -444,9 +440,9 @@ cdef class PolyhedronFaceLattice: # At the moment, this is not implemented. if dimension_one > self.dimension: - raise ValueError("no faces of dimension %s"%dimension_one) + raise ValueError("no faces of dimension %s" % dimension_one) if dimension_two < -1: - raise ValueError("no faces of dimension %s"%dimension_two) + raise ValueError("no faces of dimension %s" % dimension_two) self.incidence_dim_one = dimension_one self.incidence_dim_two = dimension_two diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index c3039f68968..7bbd96fd9be 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -7885,25 +7885,34 @@ def longest_path(self, s=None, t=None, use_edge_labels=False, algorithm="MILP", argument is set to ``None`` by default, which means that no constraint is set upon the first vertex in the path. + This parameter can only be used when ``algorithm`` is ``"MILP"``. + - ``t`` -- a vertex (default: ``None``); forces the destination of the path (the method then returns the longest path ending at ``t``). The argument is set to ``None`` by default, which means that no constraint is set upon the last vertex in the path. + This parameter can only be used when ``algorithm`` is ``"MILP"``. + - ``use_edge_labels`` -- boolean (default: ``False``); whether to compute a path with maximum weight where the weight of an edge is defined by its label (a label set to ``None`` or ``{}`` being considered as a weight of `1`), or to compute a path with the longest possible number of edges (i.e., edge weights are set to 1) + This parameter can only be used when ``algorithm`` is ``"MILP"``. + - ``algorithm`` -- string (default: ``"MILP"``); the algorithm to use - among ``"MILP"`` and ``"backtrack"``. Two remarks on this respect: + among ``"MILP"``, ``"backtrack"`` and ``"heuristic"``: - * While the MILP formulation returns an exact answer, the backtrack - algorithm is a randomized heuristic. + * ``"MILP"`` returns an exact answer. - * As the backtrack algorithm does not support edge weighting, setting - ``use_edge_labels=True`` will force the use of the MILP algorithm. + * ``"backtrack"`` is renamed ``"heuristic"`` (:issue:`36574`). + + * ``"heuristic"`` is a randomized heuristic for finding a long path in + an unweighted (di)graph. This heuristic does not take into account + parameters ``s``, ``t`` and ``use_edge_labels``. An error is raised + if these parameters are set. - ``solver`` -- string (default: ``None``); specify a Mixed Integer Linear Programming (MILP) solver to be used. If set to ``None``, the @@ -7948,7 +7957,7 @@ def longest_path(self, s=None, t=None, use_edge_labels=False, algorithm="MILP", The heuristic totally agrees:: sage: g = graphs.PetersenGraph() - sage: p = g.longest_path(algorithm="backtrack").edges(sort=True, labels=False) + sage: p = g.longest_path(algorithm="heuristic").edges(sort=True, labels=False) sage: len(p) 9 @@ -7970,13 +7979,13 @@ def longest_path(self, s=None, t=None, use_edge_labels=False, algorithm="MILP", TESTS: - The argument ``algorithm`` must be either ``'backtrack'`` or - ``'MILP'``:: + The argument ``algorithm`` must be either ``'backtrack'``, + ``'heuristic'`` or ``'MILP'``:: sage: graphs.PetersenGraph().longest_path(algorithm="abc") Traceback (most recent call last): ... - ValueError: algorithm must be either 'backtrack' or 'MILP' + ValueError: algorithm must be either 'backtrack', 'heuristic' or 'MILP' Disconnected graphs not weighted:: @@ -8049,13 +8058,43 @@ def longest_path(self, s=None, t=None, use_edge_labels=False, algorithm="MILP", sage: H = {(0, 3), (2, 0), (3, 4)} sage: H == {x for x in G.longest_path().edge_iterator(labels=False)} # needs sage.numerical.mip True + + :issue:`36574`:: + + sage: G = graphs.PathGraph(3) + sage: P = G.longest_path(algorithm='backtrack') + doctest:...: DeprecationWarning: algorithm 'backtrack' is deprecated. + Use algorithm 'heuristic' instead. + See https://github.com/sagemath/sage/issues/36574 for details. + sage: G.longest_path(algorithm='heuristic', s=0) + Traceback (most recent call last): + ... + ValueError: parameters s, t, and use_edge_labels can not be used in + combination with algorithm 'heuristic' + sage: G.longest_path(algorithm='heuristic', t=2) + Traceback (most recent call last): + ... + ValueError: parameters s, t, and use_edge_labels can not be used in + combination with algorithm 'heuristic' + sage: G.longest_path(algorithm='heuristic', use_edge_labels=True) + Traceback (most recent call last): + ... + ValueError: parameters s, t, and use_edge_labels can not be used in + combination with algorithm 'heuristic' """ self._scream_if_not_simple() - if use_edge_labels: - algorithm = "MILP" - if algorithm not in ("backtrack", "MILP"): - raise ValueError("algorithm must be either 'backtrack' or 'MILP'") + if algorithm not in ("backtrack", "heuristic", "MILP"): + raise ValueError("algorithm must be either 'backtrack', 'heuristic' or 'MILP'") + if algorithm == "backtrack": + from sage.misc.superseded import deprecation + deprecation(36574, "algorithm 'backtrack' is deprecated. " + "Use algorithm 'heuristic' instead.") + algorithm = 'heuristic' + if algorithm == 'heuristic': + if s is not None or t is not None or use_edge_labels: + raise ValueError("parameters s, t, and use_edge_labels can not " + "be used in combination with algorithm 'heuristic'") # Quick improvement if not self.is_connected(): @@ -8100,8 +8139,8 @@ def longest_path(self, s=None, t=None, use_edge_labels=False, algorithm="MILP", from sage.graphs.graph import Graph return [0, Graph()] if use_edge_labels else Graph() - # Calling the backtrack heuristic if asked - if algorithm == "backtrack": + # Calling the heuristic if asked + if algorithm == "heuristic": from sage.graphs.generic_graph_pyx import find_hamiltonian as fh x = fh(self, find_path=True)[1] return self.subgraph(vertices=x, edges=list(zip(x[:-1], x[1:]))) @@ -15746,6 +15785,95 @@ def distance_all_pairs(self, by_weight=False, algorithm=None, weight_function=weight_function, check_weight=check_weight)[0] + def power(self, k): + r""" + Return the `k`-th power graph of ``self``. + + In the `k`-th power graph of a graph `G`, there is an edge between + any pair of vertices at distance at most `k` in `G`, where the + distance is considered in the unweighted graph. In a directed graph, + there is an arc from a vertex `u` to a vertex `v` if there is a path + of length at most `k` in `G` from `u` to `v`. + + INPUT: + + - ``k`` -- integer; the maximum path length for considering edges in + the power graph. + + OUTPUT: + + - The kth power graph based on shortest distances between nodes. + + EXAMPLES: + + Testing on undirected graphs:: + + sage: G = Graph([(0, 1), (1, 2), (2, 3), (3, 0), (2, 4), (4, 5)]) + sage: PG = G.power(2) + sage: PG.edges(sort=True, labels=False) + [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (2, 5), (3, 4), (4, 5)] + + Testing on directed graphs:: + + sage: G = DiGraph([(0, 1), (1, 2), (2, 3), (3, 0), (2, 4), (4, 5)]) + sage: PG = G.power(3) + sage: PG.edges(sort=True, labels=False) + [(0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 2), (1, 3), (1, 4), (1, 5), (2, 0), (2, 1), (2, 3), (2, 4), (2, 5), (3, 0), (3, 1), (3, 2), (4, 5)] + + TESTS: + + Testing when k < 0:: + + sage: G = Graph([(0, 1), (1, 2), (2, 3), (3, 0), (2, 4), (4, 5)]) + sage: PG = G.power(-2) + Traceback (most recent call last): + ... + ValueError: distance must be a non-negative integer, not -2 + + Testing when k = 0:: + + sage: G = Graph([(0, 1), (1, 2), (2, 3), (3, 0), (2, 4), (4, 5)]) + sage: PG = G.power(0) + sage: PG.edges(sort=True, labels=False) + [] + + Testing when k = 1:: + + sage: G = Graph([(0, 1), (1, 2), (2, 3), (3, 0), (2, 4), (4, 5)]) + sage: PG = G.power(1) + sage: PG.edges(sort=True, labels=False) + [(0, 1), (0, 3), (1, 2), (2, 3), (2, 4), (4, 5)] + + Testing when k = Infinity:: + + sage: G = Graph([(0, 1), (1, 2), (2, 3), (3, 0), (2, 4), (4, 5)]) + sage: PG = G.power(Infinity) + Traceback (most recent call last): + ... + ValueError: distance must be a non-negative integer, not +Infinity + + Testing on graph with multiple edges:: + + sage: G = DiGraph([(0, 1), (0, 1), (1, 2), (2, 3), (3, 0), (2, 4), (4, 5)], multiedges=True) + sage: PG = G.power(3) + sage: PG.edges(sort=True, labels=False) + [(0, 1), (0, 2), (0, 3), (0, 4), (1, 0), (1, 2), (1, 3), (1, 4), (1, 5), (2, 0), (2, 1), (2, 3), (2, 4), (2, 5), (3, 0), (3, 1), (3, 2), (4, 5)] + """ + from sage.graphs.digraph import DiGraph + from sage.graphs.graph import Graph + + power_of_graph = DiGraph() if self.is_directed() else Graph() + + for u in self: + for v in self.breadth_first_search(u, distance=k): + if u != v: + power_of_graph.add_edge(u, v) + + if self.name(): + power_of_graph.name("power({})".format(self.name())) + + return power_of_graph + def girth(self, certificate=False): """ Return the girth of the graph. diff --git a/src/sage/graphs/graph_decompositions/tree_decomposition.pyx b/src/sage/graphs/graph_decompositions/tree_decomposition.pyx index 90f14298c5a..f1ebec67af7 100644 --- a/src/sage/graphs/graph_decompositions/tree_decomposition.pyx +++ b/src/sage/graphs/graph_decompositions/tree_decomposition.pyx @@ -75,6 +75,8 @@ The treewidth of a clique is `n-1` and its treelength is 1:: :meth:`treewidth` | Compute the treewidth of `G` (and provide a decomposition). :meth:`treelength` | Compute the treelength of `G` (and provide a decomposition). + :meth:`make_nice_tree_decomposition` | Return a *nice* tree decomposition (TD) of the TD `tree_decomp`. + :meth:`label_nice_tree_decomposition` | Return a nice tree decomposition with nodes labelled accordingly. :meth:`is_valid_tree_decomposition` | Check whether `T` is a valid tree-decomposition for `G`. :meth:`reduced_tree_decomposition` | Return a reduced tree-decomposition of `T`. :meth:`width_of_tree_decomposition` | Return the width of the tree decomposition `T` of `G`. @@ -82,9 +84,7 @@ The treewidth of a clique is `n-1` and its treelength is 1:: .. TODO: - - Add method to return a *nice* tree decomposition - - Approximation of treelength based on - :meth:`~sage.graphs.graph.Graph.lex_M` + - Approximation of treelength based on :meth:`~sage.graphs.graph.Graph.lex_M` - Approximation of treelength based on BFS Layering - upgrade tdlib to 0.9.0 :trac:`30813` @@ -104,13 +104,15 @@ Methods from sage.sets.set import Set from sage.misc.cachefunc import cached_function -from itertools import chain from sage.features import PythonModule from sage.sets.disjoint_set import DisjointSet from sage.rings.infinity import Infinity from sage.graphs.distances_all_pairs cimport c_distances_all_pairs from cysignals.memory cimport sig_calloc, sig_free +from itertools import chain +from collections.abc import Iterable + def is_valid_tree_decomposition(G, T): r""" @@ -206,9 +208,7 @@ def is_valid_tree_decomposition(G, T): raise ValueError("the second parameter must be a tree") for X in T: - try: - _ = list(X) - except TypeError: + if not isinstance(X, Iterable): raise ValueError("the vertices of T must be iterables") # 1. The union of the bags equals V @@ -432,18 +432,18 @@ def _from_tree_decompositions_of_atoms_to_tree_decomposition(T_atoms, cliques): return T -def treewidth(g, k=None, kmin=None, certificate=False, algorithm=None): +def treewidth(g, k=None, kmin=None, certificate=False, algorithm=None, nice=False): r""" Compute the treewidth of `g` (and provide a decomposition). INPUT: - - ``g`` -- a sage Graph + - ``g`` -- a Sage Graph - ``k`` -- integer (default: ``None``); indicates the width to be considered. When ``k`` is an integer, the method checks that the graph has treewidth `\leq k`. If ``k`` is ``None`` (default), the method computes - the optimal tree-width. + the optimal treewidth. - ``kmin`` -- integer (default: ``None``); when specified, search for a tree-decomposition of width at least ``kmin``. This parameter is useful @@ -457,21 +457,28 @@ def treewidth(g, k=None, kmin=None, certificate=False, algorithm=None): installation of the 'tdlib' package). The default behaviour is to use 'tdlib' if it is available, and Sage's own algorithm when it is not. + - ``nice`` -- boolean (default: ``False``); whether or not to return the + nice tree decomposition, provided ``certificate`` is ``True``. + OUTPUT: - ``g.treewidth()`` returns the treewidth of ``g``. When ``k`` is specified, - it returns ``False`` when no tree-decomposition of width `\leq k` exists or - ``True`` otherwise. When ``certificate=True``, the tree-decomposition is - also returned. + ``g.treewidth()`` returns treewidth of the graph ``g``. + + When ``k`` is specified, it returns ``False`` if there is no tree + decomposition of width `\leq k`, and ``True`` otherwise. + + When ``certificate=True``, the tree decomposition is returned. + + When ``nice=True``, the nice tree decomposition is returned. ALGORITHM: - This function virtually explores the graph of all pairs ``(vertex_cut,cc)``, + This function virtually explores the graph of all pairs ``(vertex_cut, cc)``, where ``vertex_cut`` is a vertex cut of the graph of cardinality `\leq k+1`, and ``connected_component`` is a connected component of the graph induced by ``G-vertex_cut``. - We deduce that the pair ``(vertex_cut,cc)`` is feasible with tree-width `k` + We deduce that the pair ``(vertex_cut, cc)`` is feasible with treewidth `k` if ``cc`` is empty, or if a vertex ``v`` from ``vertex_cut`` can be replaced with a vertex from ``cc``, such that the pair ``(vertex_cut+v,cc-v)`` is feasible. @@ -493,19 +500,36 @@ def treewidth(g, k=None, kmin=None, certificate=False, algorithm=None): The PetersenGraph has treewidth 4:: - sage: graphs.PetersenGraph().treewidth() + sage: petersen = graphs.PetersenGraph() + sage: petersen.treewidth(algorithm='sage') + 4 + sage: petersen.treewidth(algorithm='sage', certificate=True) + Tree decomposition: Graph on 6 vertices + + The PetersenGraph has treewidth 4 (with ``tdlib``):: + + sage: petersen = graphs.PetersenGraph() + sage: petersen.treewidth(algorithm='tdlib') # optional - tdlib 4 - sage: graphs.PetersenGraph().treewidth(certificate=True) + sage: petersen.treewidth(algorithm='tdlib', certificate=True) # optional - tdlib Tree decomposition: Graph on 6 vertices - The treewidth of a 2d grid is its smallest side:: + Nice tree decomposition of the PetersenGraph has 28 nodes:: + + sage: petersen = graphs.PetersenGraph() + sage: petersen.treewidth(algorithm='sage', certificate=True, nice=True) + Nice tree decomposition of Tree decomposition: Graph on 28 vertices + sage: petersen.treewidth(algorithm='tdlib', certificate=True, nice=True) # optional - tdlib + Nice tree decomposition of Tree decomposition: Graph on 28 vertices + + The treewidth of a 2-dimensional grid is its smallest side:: sage: graphs.Grid2dGraph(2,5).treewidth() 2 sage: graphs.Grid2dGraph(3,5).treewidth() 3 - When parameter ``kmin`` is specified, the method search for a + When parameter ``kmin`` is specified, the method searches for a tree-decomposition of width at least ``kmin``:: sage: g = graphs.PetersenGraph() @@ -545,7 +569,7 @@ def treewidth(g, k=None, kmin=None, certificate=False, algorithm=None): True sage: g.treewidth(k=3, certificate=True) False - sage: T = g.treewidth(k=4,certificate=True) + sage: T = g.treewidth(k=4, certificate=True) sage: T Tree decomposition: Graph on 6 vertices sage: from sage.graphs.graph_decompositions.tree_decomposition import is_valid_tree_decomposition @@ -598,7 +622,7 @@ def treewidth(g, k=None, kmin=None, certificate=False, algorithm=None): sage: graphs.PetersenGraph().treewidth(k=35) True - sage: graphs.PetersenGraph().treewidth(k=35,certificate=True) + sage: graphs.PetersenGraph().treewidth(k=35, certificate=True) Tree decomposition: Graph on 1 vertex Bad input:: @@ -609,34 +633,27 @@ def treewidth(g, k=None, kmin=None, certificate=False, algorithm=None): ValueError: k(=-3) must be a nonnegative integer """ # Check Input - if algorithm is None or algorithm == 'tdlib': - try: - import sage.graphs.graph_decompositions.tdlib as tdlib - tdlib_found = True - except ImportError: - tdlib_found = False - - elif algorithm != "sage": + if algorithm not in [None, 'tdlib', 'sage']: raise ValueError("'algorithm' must be equal to 'tdlib', 'sage', or None") + try: + import sage.graphs.graph_decompositions.tdlib as tdlib + tdlib_found = True + except ImportError: + tdlib_found = False + if algorithm is None: - if tdlib_found: - algorithm = 'tdlib' - else: - algorithm = 'sage' + algorithm = 'tdlib' if tdlib_found else 'sage' - if k is not None and k < 0: - raise ValueError("k(={}) must be a nonnegative integer".format(k)) + if (k is not None) and k < 0: + raise ValueError(f"k(={k}) must be a nonnegative integer") - # Stupid cases + # Silly cases from sage.graphs.graph import Graph if not g.order(): if certificate: return Graph() - elif k is None: - return -1 - else: - return True + return -1 if k is None else True if k is not None and k >= g.order() - 1: if certificate: @@ -656,15 +673,14 @@ def treewidth(g, k=None, kmin=None, certificate=False, algorithm=None): raise FeatureNotPresentError(PythonModule('sage.graphs.graph_decompositions.tdlib', spkg='tdlib')) - T = tdlib.treedecomposition_exact(g, -1 if k is None else k) - width = tdlib.get_width(T) + tree_decomp = tdlib.treedecomposition_exact(g, -1 if k is None else k) + width = tdlib.get_width(tree_decomp) if certificate: - return T if (k is None or width <= k) else False - elif k is None: - return width - else: - return width <= k + if k is None or width <= k: + return make_nice_tree_decomposition(g, tree_decomp) if nice else tree_decomp + return False + return width if k is None else width <= k # The treewidth of a graph is the maximum over its atoms. So, we decompose # the graph by clique minimal separators, compute the treewidth of each of @@ -672,6 +688,7 @@ def treewidth(g, k=None, kmin=None, certificate=False, algorithm=None): # This decomposition also deals with disconnected cases. atoms, cliques = g.atoms_and_clique_separators() if cliques: + # If we do not need the tree decomposition if not certificate: if k is None: for a in atoms: @@ -681,21 +698,24 @@ def treewidth(g, k=None, kmin=None, certificate=False, algorithm=None): return False else: return all(g.subgraph(a).treewidth(algorithm=algorithm, k=k) for a in atoms) - else: - # We compute the tree decomposition of each atom - T = [] - for a in atoms: - ga = g.subgraph(a) - Ta = ga.treewidth(algorithm=algorithm, certificate=True, kmin=kmin) - kmin = max(kmin, width_of_tree_decomposition(ga, Ta, check=False)) - T.append(Ta) - # and merge the resulting trees - return _from_tree_decompositions_of_atoms_to_tree_decomposition(T, cliques) + + # Otherwise, compute the tree decomposition of each atom + T = [] + for a in atoms: + ga = g.subgraph(a) + Ta = ga.treewidth(algorithm=algorithm, certificate=True, kmin=kmin) + kmin = max(kmin, width_of_tree_decomposition(ga, Ta, check=False)) + T.append(Ta) + + # Merge the resulting trees + tree_decomp = _from_tree_decompositions_of_atoms_to_tree_decomposition(T, cliques) + + return make_nice_tree_decomposition(g, tree_decomp) if nice else tree_decomp # Forcing k to be defined if k is None: for i in range(max(kmin, g.clique_number() - 1, min(g.degree())), g.order()): - ans = g.treewidth(algorithm=algorithm, k=i, certificate=certificate) + ans = g.treewidth(algorithm=algorithm, k=i, certificate=certificate, nice=nice) if ans: return ans if certificate else i @@ -761,18 +781,305 @@ def treewidth(g, k=None, kmin=None, certificate=False, algorithm=None): if not certificate: return True - # Building the Tree-Decomposition graph. Its vertices are cuts of the + # Building the tree-decomposition graph. Its vertices are cuts of the # decomposition, and there is an edge from a cut C1 to a cut C2 if C2 is an # immediate subcall of C1 - G = Graph() - G.add_edges(((Set(x), Set(y)) for x, y in TD), loops=False) + tree_decomp = Graph() + tree_decomp.add_edges(((Set(x), Set(y)) for x, y in TD), loops=False) - # The Tree-Decomposition may contain a lot of useless nodes. - # We merge all edges between two sets S,S' where S is a subset of S' - G = reduced_tree_decomposition(G) + # The tree-decomposition may contain a lot of useless nodes. + # We merge all edges between two sets S, S' where S is a subset of S' + tree_decomp = reduced_tree_decomposition(tree_decomp) + + tree_decomp.name("Tree decomposition") + if nice: + tree_decomp = make_nice_tree_decomposition(g, tree_decomp) + + return tree_decomp + +def make_nice_tree_decomposition(graph, tree_decomp): + r""" + Return a *nice* tree decomposition (TD) of the TD ``tree_decomp``. + + See page 161 of [CFKLMPPS15]_ for a description of the nice tree decomposition. + + A *nice* TD `NT` is a rooted tree with four types of nodes: + + - *Leaf* nodes have no children and bag size 1; + - *Introduce* nodes have one child: If `v \in NT` is an introduce node and + `w \in NT` its child, then `Bag(v) = Bag(w) \cup \{ x \}`, where `x` is the + introduced node; + - *Forget* nodes have one child: If `v \in NT` is a forget node and + `w \in NT` its child, then `Bag(v) = Bag(w) \setminus \{ x \}`, where `x` is the + forgotten node; + - *Join* nodes have two children, both identical to the parent. + + INPUT: + + - ``graph`` -- a Sage graph + - ``tree_decomp`` -- a tree decomposition + + OUTPUT: + + A nice tree decomposition. + + .. WARNING:: + + This method assumes that the vertices of the input tree `tree_decomp` + are hashable and have attribute ``issuperset``, e.g., ``frozenset`` or + :class:`~sage.sets.set.Set_object_enumerated_with_category`. + + EXAMPLES:: + + sage: from sage.graphs.graph_decompositions.tree_decomposition import make_nice_tree_decomposition + sage: petersen = graphs.PetersenGraph() + sage: petersen_TD = petersen.treewidth(certificate=True) + sage: make_nice_tree_decomposition(petersen, petersen_TD) + Nice tree decomposition of Tree decomposition: Graph on 28 vertices + + :: + + sage: from sage.graphs.graph_decompositions.tree_decomposition import make_nice_tree_decomposition + sage: cherry = graphs.CompleteBipartiteGraph(1, 2) + sage: cherry_TD = cherry.treewidth(certificate=True) + sage: make_nice_tree_decomposition(cherry, cherry_TD) + Nice tree decomposition of Tree decomposition: Graph on 7 vertices + + :: + + sage: from sage.graphs.graph_decompositions.tree_decomposition import make_nice_tree_decomposition + sage: bip_one_four = graphs.CompleteBipartiteGraph(1, 4) + sage: bip_one_four_TD = bip_one_four.treewidth(certificate=True) + sage: make_nice_tree_decomposition(bip_one_four, bip_one_four_TD) + Nice tree decomposition of Tree decomposition: Graph on 15 vertices + """ + if not is_valid_tree_decomposition(graph, tree_decomp): + raise ValueError("input must be a valid tree decomposition for this graph") + + name = f"Nice tree decomposition of {tree_decomp.name()}" + from sage.graphs.graph import Graph + if not tree_decomp: + return Graph(name=name) + + # Step 1: Ensure the tree is directed and has a root + # Choose a root and orient the edges from root-to-leaves direction + leaves = [u for u in tree_decomp if tree_decomp.degree(u) == 1] + root = leaves.pop() + from sage.graphs.digraph import DiGraph + directed_tree = DiGraph(tree_decomp.breadth_first_search(start=root, edges=True), + format='list_of_edges') + + # Relabel the graph in range (0, |tree_decomp| - 1) + bags_to_int = directed_tree.relabel(inplace=True, return_map=True) + # Get the new name of the root node + root = bags_to_int[root] + # Force bags to be of type Set to simplify code + bag = {ui: Set(u) for u, ui in bags_to_int.items()} + + # Step 2: Add the root node and the leaf nodes, with empty bags + # To each leaf node of `directed_tree`, we add a child with empty bag. + # We also add a new root with empty bag. + root, old_root = directed_tree.add_vertex(), root + directed_tree.add_edge(root, old_root) + bag[root] = Set() + for vi, u in enumerate(leaves, start=root + 1): + directed_tree.add_edge(bags_to_int[u], vi) + bag[vi] = Set() + + # Step 3: Ensure that each node of directed_tree has at most 2 children. + # If a node has more than 2 children, introduce new nodes to + # make sure each node has at most 2 children: + # + # If v has k > 2 children (w_1, w_2, ..., w_k), we disconnect (w_1, ..., w_{k-1}) + # from v, and introduce k - 2 new nodes (u_1, u_2, ..., u_{k-2}). + # We then let w_i be the children of u_i for 1 <= i <= k - 2. + # We also let w_{k-1} be the second child of u_{k-2}, and + # u_i the second child of u_{i-1}. + # Finally, we let u_1 the second child of u. + # Each node u_i has the same bag as u. + + # We need to call list(...) since we modify directed_tree + for ui in list(directed_tree): + if directed_tree.out_degree(ui) > 2: + children = directed_tree.neighbors_out(ui) + children.pop() # one vertex remains a child of ui + + directed_tree.delete_edges((ui, vi) for v in children) + + new_nodes = [directed_tree.add_vertex() for _ in range(len(children) - 1)] + + directed_tree.add_edge(ui, new_nodes[0]) + directed_tree.add_path(new_nodes) + directed_tree.add_edges(zip(new_nodes, children)) + directed_tree.add_edge(new_nodes[-1], children[-1]) + + bag.update((vi, bag[ui]) for vi in new_nodes) + + # Step 4: If current vertex v has two children w1 and w2, + # then bag[v] == bag[w1] == bag[w2] + for current_node in list(directed_tree): + if directed_tree.out_degree(current_node) < 2: + continue + for neighbor in directed_tree.neighbor_out_iterator(current_node): + if bag[current_node] != bag[neighbor]: + directed_tree.delete_edge(current_node, neighbor) + new_node = directed_tree.add_vertex() + directed_tree.add_path([current_node, new_node, neighbor]) + bag[new_node] = bag[current_node] + + # Step 5: If the node v has only one child, then it is either an introduce + # node or a forget node. + def add_path_of_intro_nodes(u, v): + """ + Replace the arc (u, v) by a path of introduce nodes. + """ + if len(bag[u]) + 1 == len(bag[v]): + return + + diff = list(bag[v] - bag[u]) + diff.pop() + + last_node = u + for w in diff: + new_node = directed_tree.add_vertex() + bag[new_node] = bag[last_node].union(Set((w,))) + directed_tree.add_edge(last_node, new_node) + last_node = new_node + + directed_tree.add_edge(last_node, v) + directed_tree.delete_edge(u, v) + + def add_path_of_forget_nodes(u, v): + """ + Replace the arc (u, v) by a path of forget nodes. + """ + if len(bag[v]) + 1 == len(bag[u]): + return + + diff = list(bag[u] - bag[v]) + diff.pop() + + last_node = u + for w in diff: + new_node = directed_tree.add_vertex() + bag[new_node] = bag[last_node] - {w} + directed_tree.add_edge(last_node, new_node) + last_node = new_node + + directed_tree.add_edge(last_node, v) + directed_tree.delete_edge(u, v) + + for ui in list(directed_tree): + if directed_tree.out_degree(ui) != 1: + continue + + vi = next(directed_tree.neighbor_out_iterator(ui)) + bag_ui, bag_vi = bag[ui], bag[vi] + + # Merge the nodes if the two bags are the same + if bag_ui == bag_vi: + if directed_tree.in_degree(ui) == 1: + parent = next(directed_tree.neighbor_in_iterator(ui)) + directed_tree.add_edge(parent, vi) + else: + root = vi + directed_tree.delete_vertex(ui) + + # Add paths of intro / forget nodes accordingly + + elif bag_ui.issubset(bag_vi): + add_path_of_intro_nodes(ui, vi) + + elif bag_vi.issubset(bag_ui): + add_path_of_forget_nodes(ui, vi) + + # Handle the case when the two nodes are not related in any way above + else: + wi = directed_tree.add_vertex() + bag[wi] = bag[ui] & bag[vi] + directed_tree.add_path([ui, wi, vi]) + directed_tree.delete_edge(ui, vi) + add_path_of_forget_nodes(ui, wi) + add_path_of_intro_nodes(wi, vi) + + # Return the nice tree decomposition after the processing + nice_tree_decomp = Graph(directed_tree, name=name) + + bfs_ordering = nice_tree_decomp.breadth_first_search(start=root) + relabeling = {u: (i, bag[u]) for i, u in enumerate(bfs_ordering)} + nice_tree_decomp.relabel(inplace=True, perm=relabeling) + + return nice_tree_decomp + +def label_nice_tree_decomposition(nice_TD, root): + r""" + Return a nice tree decomposition with nodes labelled accordingly. + + INPUT: + + - ``nice_TD`` -- a nice tree decomposition + + - ``root`` -- the root of the nice tree decomposition + + OUTPUT: + + A nice tree decomposition with nodes labelled. + + EXAMPLES:: + + sage: from sage.graphs.graph_decompositions.tree_decomposition import make_nice_tree_decomposition, label_nice_tree_decomposition + sage: bip_one_four = graphs.CompleteBipartiteGraph(1, 4) + sage: bip_one_four_TD = bip_one_four.treewidth(certificate=True) + sage: nice_TD = make_nice_tree_decomposition(bip_one_four, bip_one_four_TD) + sage: root = sorted(nice_TD.vertices())[0] + sage: label_TD = label_nice_tree_decomposition(nice_TD, root) + sage: for node in sorted(label_TD): + ....: print(node, label_TD.get_vertex(node)) + (0, {}) root + (1, {0}) forget + (2, {0, 1}) intro + (3, {0}) forget + (4, {0, 4}) join + (5, {0, 4}) intro + (6, {0, 4}) intro + (7, {0}) forget + (8, {0}) forget + (9, {0, 3}) intro + (10, {0, 2}) intro + (11, {3}) intro + (12, {2}) intro + (13, {}) leaf + (14, {}) leaf + """ + from sage.graphs.digraph import DiGraph + from sage.graphs.graph import Graph + + directed_TD = DiGraph(nice_TD.breadth_first_search(start=root, edges=True), + format='list_of_edges') + + # The loop starts from the root node + # We assume the tree decomposition is valid and nice, + # hence saving time on checking. + for node in directed_TD: + in_deg = directed_TD.in_degree(node) + out_deg = directed_TD.out_degree(node) + + if in_deg == 0: + directed_TD.set_vertex(node, 'root') + elif out_deg == 2: + directed_TD.set_vertex(node, 'join') + elif out_deg == 1: + current_bag = node[1] + child_bag = directed_TD.neighbors_out(node)[0][1] + + if len(current_bag) == len(child_bag) + 1: + directed_TD.set_vertex(node, 'intro') + else: + directed_TD.set_vertex(node, 'forget') + else: + directed_TD.set_vertex(node, 'leaf') - G.name("Tree decomposition") - return G + return Graph(directed_TD, name=nice_TD.name()) # @@ -1165,7 +1472,7 @@ cdef class TreelengthConnected: if not self.certificate: return True - # Building the Tree-Decomposition graph. Its vertices are cuts of the + # Building the tree-decomposition graph. Its vertices are cuts of the # decomposition, and there is an edge from a cut C1 to a cut C2 if C2 is an # immediate subcall of C1. If needed, the vertices are relabeled. if self.perm_inv: @@ -1511,7 +1818,7 @@ def treelength(G, k=None, certificate=False): # decompositions of its atoms. T = _from_tree_decompositions_of_atoms_to_tree_decomposition(result, cliques) - # The Tree-Decomposition may contain a lot of useless nodes. + # The tree-decomposition may contain a lot of useless nodes. # We merge all edges between two sets S,S' where S is a subset of S' T = reduced_tree_decomposition(T) T.name(name) diff --git a/src/sage/groups/cubic_braid.py b/src/sage/groups/cubic_braid.py index e8cb4a4e19f..debecbc0ba1 100644 --- a/src/sage/groups/cubic_braid.py +++ b/src/sage/groups/cubic_braid.py @@ -141,7 +141,7 @@ def eliminate_item(tietze_list): if second is None: return None middle = tietze_list[1:i] - end = tietze_list[i+1:l] + end = tietze_list[i+1:l] if first == second: return [-first] + middle + end else: @@ -490,7 +490,7 @@ def find_root(domain): if root[0] == 0: continue root_bur = root[0] - if root[1] == 1: + if root[1] == 1: break return root_bur @@ -747,7 +747,7 @@ def __init__(self, names, cbg_type=None): sage: U5 = AssionGroupU(5) # indirect doctest sage: TestSuite(U5).run() # long time """ - n = Integer(len(names)) + n = Integer(len(names)) if n < 1: raise ValueError("the number of strands must be an integer larger than one") @@ -759,12 +759,12 @@ def __init__(self, names, cbg_type=None): free_group = FreeGroup(names) self._cbg_type = cbg_type self._nstrands = n + 1 - self._ident = self._cbg_type.value + self._nstrands.str() + self._ident = self._cbg_type.value + self._nstrands.str() self._braid_group = BraidGroup(names) # internal naming of elements for convenience - b = [free_group([i]) for i in range(1, n+1)] - t = [free_group([i, i+1]) ** 3 for i in range(1, n)] + b = [free_group([i]) for i in range(1, n+1)] + t = [free_group([i, i+1]) ** 3 for i in range(1, n)] ti = [free_group([-i, -i-1]) ** 3 for i in range(1, n)] # first the braid relation @@ -796,12 +796,12 @@ def __init__(self, names, cbg_type=None): # the following global pointers to classical group realizations will be set in the private method # _create_classical_realization # ------------------------------------------------------------------------------------------------ - self._classical_group = None # This is the classical Group returned by as_classical_group - self._classical_base_group = None # this only differs for special cases for Assion groups from the former - self._classical_invariant_form = None # invariant form of the classical base group - self._classical_embedding = None # if self._classical_group different from self._classical_base_group - self._centralizing_matrix = None # for Assion groups: element in classical base group commuting with self - self._centralizing_element = None # image under nat. map of the former one in the proj. classical group + self._classical_group = None # This is the classical Group returned by as_classical_group + self._classical_base_group = None # this only differs for special cases for Assion groups from the former + self._classical_invariant_form = None # invariant form of the classical base group + self._classical_embedding = None # if self._classical_group different from self._classical_base_group + self._centralizing_matrix = None # for Assion groups: element in classical base group commuting with self + self._centralizing_element = None # image under nat. map of the former one in the proj. classical group return def _repr_(self): @@ -1095,7 +1095,7 @@ def set_classical_realization(self, base_group, proj_group, centralizing_matrix, # ------------------------------------------------------------------------------ # Setting the List of Braid Images # ------------------------------------------------------------------------------ - im_gens = [base_group(m) for m in transvec_matrices] + im_gens = [base_group(m) for m in transvec_matrices] # ------------------------------------------------------------------------------ # By the work of Assion no check on the group homomorphism is needed, at all. @@ -1109,7 +1109,7 @@ def set_classical_realization(self, base_group, proj_group, centralizing_matrix, # ------------------------------------------------------------------------------ # Do the projective group realization if needed # ------------------------------------------------------------------------------ - embedding = self._classical_embedding + embedding = self._classical_embedding classical_group = None if proj_group is None: classical_group = base_group @@ -1128,19 +1128,19 @@ def set_classical_realization(self, base_group, proj_group, centralizing_matrix, nat_hom = base_group.hom(proj_group.gens(), check=check) centralizing_element = nat_hom(centralizing_matrix) classical_group_gens = [nat_hom(m) for m in transvec_matrices] - classical_group = proj_group.subgroup(classical_group_gens, canonicalize=False) + classical_group = proj_group.subgroup(classical_group_gens, canonicalize=False) hom_to_classic = self.hom(classical_group.gens(), check=check) classical_group.register_conversion(hom_to_classic) # ------------------------------------------------------------------------------ # register constructed items # ------------------------------------------------------------------------------ - self._classical_group = classical_group - self._classical_base_group = base_group - self._classical_invariant_form = base_group.invariant_form() - self._centralizing_matrix = centralizing_matrix - self._centralizing_element = centralizing_element - self._classical_embedding = embedding + self._classical_group = classical_group + self._classical_base_group = base_group + self._classical_invariant_form = base_group.invariant_form() + self._centralizing_matrix = centralizing_matrix + self._centralizing_element = centralizing_element + self._classical_embedding = embedding return # ------------------------------------------------------------------------------- @@ -1211,7 +1211,7 @@ def transvec2mat(v, bas=bas, bform=bform, fact=1): # ------------------------------------------------------------------------------ centralizing_vector = xbas[mhalf-1] centralizing_matrix = base_group(transvec2mat(centralizing_vector, fact=1)) - transvec_matrices = [transvec2mat(v) for v in transvections] + transvec_matrices = [transvec2mat(v) for v in transvections] set_classical_realization(self, base_group, proj_group, centralizing_matrix, transvec_matrices) return @@ -1273,9 +1273,9 @@ def create_unitary_realization(self, m): for j in range(mthird): pos = 3*(j+1)-1 transvections.append(xbas[pos-1]) # t_{3i} = x_{3i-1} - if pos + 1 < m: + if pos + 1 < m: transvections.append(xbas[pos-1]+xbas[pos]+xbas[pos+1]) # t_{3i+1} = x_{3i-1} + x_{3i} + x_{3i+1} - if pos + 3 < m: + if pos + 3 < m: transvections.append(xbas[pos+1]+xbas[pos+2]+xbas[pos+3]) # t_{3i+2} = x_{3i+1} + x_{3i+2} + x_{3i+3} # ----------------------------------------------------------- @@ -1294,7 +1294,7 @@ def transvec2mat(v, bas=bas, bform=bform, fact=a): # ------------------------------------------------------------------------------ centralizing_vector = xbas[m-2]+xbas[m-1] centralizing_matrix = base_group(transvec2mat(centralizing_vector, fact=1)) - transvec_matrices = [transvec2mat(v) for v in transvections] + transvec_matrices = [transvec2mat(v) for v in transvections] set_classical_realization(self, base_group, proj_group, centralizing_matrix, transvec_matrices) return @@ -1314,13 +1314,13 @@ def transvec2mat(v, bas=bas, bform=bform, fact=a): # Setting the Classical group # ------------------------------------------------------------------------------- if self._cbg_type == CubicBraidGroup.type.AssionS: - dim_sympl_group = n-1 # S(n-1) = Sp(n-1, 3) - if n % 2 == 0: - dim_sympl_group = n # S(n-1) = subgroup of PSp(n, 3) + dim_sympl_group = n-1 # S(n-1) = Sp(n-1, 3) + if n % 2 == 0: + dim_sympl_group = n # S(n-1) = subgroup of PSp(n, 3) create_sympl_realization(self, dim_sympl_group) elif self._cbg_type == CubicBraidGroup.type.AssionU: dim_unitary_group = n-1 # U(n-1) = GU(n-1, 2) - if n % 3 == 0: + if n % 3 == 0: dim_unitary_group = n # U(n-1) = subgroup PGU(n, 3) create_unitary_realization(self, dim_unitary_group) else: @@ -1344,11 +1344,11 @@ def transvec2mat(v, bas=bas, bform=bform, fact=a): UCF = UniversalCyclotomicField() z12 = UCF.gen(12) classical_group = self.as_matrix_group(root_bur=~z12, domain=UCF, reduced='unitary') - self._classical_group = classical_group - self._classical_base_group = classical_group - self._classical_embedding = classical_group + self._classical_group = classical_group + self._classical_base_group = classical_group + self._classical_embedding = classical_group if self._classical_invariant_form is None: - self._classical_invariant_form = classical_group.ambient().invariant_form() + self._classical_invariant_form = classical_group.ambient().invariant_form() return def _element_constructor_(self, x, **kwds): diff --git a/src/sage/groups/finitely_presented.py b/src/sage/groups/finitely_presented.py index 96d03e90c83..a351e544ce7 100644 --- a/src/sage/groups/finitely_presented.py +++ b/src/sage/groups/finitely_presented.py @@ -145,6 +145,7 @@ from sage.sets.set import Set from sage.structure.unique_representation import UniqueRepresentation + class GroupMorphismWithGensImages(SetMorphism): r""" Class used for morphisms from finitely presented groups to @@ -1702,12 +1703,18 @@ def abelian_alexander_matrix(self, ring=QQ, simplified=True): sage: g = FreeGroup(1) / [] sage: g.abelian_alexander_matrix() ([], []) + sage: g.abelian_alexander_matrix()[0].base_ring() + Univariate Laurent Polynomial Ring in f1 over Rational Field sage: g = FreeGroup(0) / [] - sage: g.abelian_alexander_matrix() - ([], []) + sage: A, ideal = g.abelian_alexander_matrix(); A + [] + sage: A.base_ring() + Rational Field """ ab, R, ideal, images = self.abelianization_to_algebra(ring=ring) A = self.alexander_matrix(im_gens=images) + if A.base_ring() != R: + A = A.change_ring(R) if simplified: n, m = A.dimensions() if n == 0 or m == 0: @@ -1761,66 +1768,111 @@ def characteristic_varieties(self, ring=QQ, matrix_ideal=None, groebner=False): OUTPUT: - If ``groebner`` is ``False`` a list of ideals defining the characteristic varieties. - If it is ``True``, a list of lists for Gröbner bases for each ideal. + A dictionary with keys the indices of the varieties. If ``groebner`` is ``False`` + the values are the ideals defining the characteristic varieties. + If it is ``True``, lists for Gröbner bases for the ideal of each irreducible + component, stopping when the first time a characteristic variety is empty. EXAMPLES:: sage: L = [2*(i, j) + 2* (-i, -j) for i, j in ((1, 2), (2, 3), (3, 1))] sage: G = FreeGroup(3) / L sage: G.characteristic_varieties(groebner=True) - [[(f1 - 1, f2 - 1, f3 - 1), - (f1 + 1, f2 - 1, f3 - 1), - (f1 - 1, f2 - 1, f3 + 1), - (f3^2 + 1, f1 - f3, f2 - f3), - (f1 - 1, f2 + 1, f3 - 1)], - [(f1 - 1, f2 - 1, f3 - 1), - (f1*f3 + 1, f2 - 1), - (f1*f2 + 1, f3 - 1), - (f2*f3 + 1, f1 - 1), - (f2*f3 + 1, f1 - f2), - (f2*f3 + 1, f1 - f3), - (f1*f3 + 1, f2 - f3)]] + {0: [(0,)], + 1: [(f1 - 1, f2 - 1, f3 - 1), (f1*f3 + 1, f2 - 1), (f1*f2 + 1, f3 - 1), (f2*f3 + 1, f1 - 1), + (f2*f3 + 1, f1 - f2), (f2*f3 + 1, f1 - f3), (f1*f3 + 1, f2 - f3)], + 2: [(f1 - 1, f2 - 1, f3 - 1), (f1 + 1, f2 - 1, f3 - 1), (f1 - 1, f2 - 1, f3 + 1), + (f3^2 + 1, f1 - f3, f2 - f3), (f1 - 1, f2 + 1, f3 - 1)], + 3: [(f1 - 1, f2 - 1, f3 - 1)], + 4: []} sage: G = FreeGroup(2)/[2*(1,2,-1,-2)] sage: G.characteristic_varieties() - [Ideal (-2*f2 + 2, 2*f1 - 2) of Multivariate Laurent Polynomial Ring in f1, f2 over Rational Field] + {0: Ideal (0) of Multivariate Laurent Polynomial Ring in f1, f2 over Rational Field, + 1: Ideal (f2 - 1, f1 - 1) of Multivariate Laurent Polynomial Ring in f1, f2 over Rational Field, + 2: Ideal (f2 - 1, f1 - 1) of Multivariate Laurent Polynomial Ring in f1, f2 over Rational Field, + 3: Ideal (1) of Multivariate Laurent Polynomial Ring in f1, f2 over Rational Field} sage: G.characteristic_varieties(ring=ZZ) - [Ideal (-2*f2 + 2, 2*f1 - 2) of Multivariate Laurent Polynomial Ring in f1, f2 over Integer Ring] + {0: Ideal (0) of Multivariate Laurent Polynomial Ring in f1, f2 over Integer Ring, + 1: Ideal (2*f2 - 2, 2*f1 - 2) of Multivariate Laurent Polynomial Ring in f1, f2 over Integer Ring, + 2: Ideal (f2 - 1, f1 - 1) of Multivariate Laurent Polynomial Ring in f1, f2 over Integer Ring, + 3: Ideal (1) of Multivariate Laurent Polynomial Ring in f1, f2 over Integer Ring} sage: G = FreeGroup(2)/[(1,2,1,-2,-1,-2)] sage: G.characteristic_varieties() - [Ideal (1 - f2 + f2^2, -1 + f2 - f2^2) of Univariate Laurent Polynomial Ring in f2 over Rational Field] + {0: Ideal (0) of Univariate Laurent Polynomial Ring in f2 over Rational Field, + 1: Ideal (-1 + 2*f2 - 2*f2^2 + f2^3) of Univariate Laurent Polynomial Ring in f2 over Rational Field, + 2: Ideal (1) of Univariate Laurent Polynomial Ring in f2 over Rational Field} + sage: G.characteristic_varieties(groebner=True) + {0: [0], 1: [-1 + f2, 1 - f2 + f2^2], 2: []} + sage: G = FreeGroup(2)/[3 * (1, ), 2 * (2, )] sage: G.characteristic_varieties(groebner=True) - [[1 - f2 + f2^2]] + {0: [-1 + F1, 1 + F1, 1 - F1 + F1^2, 1 + F1 + F1^2], 1: [1 - F1 + F1^2], 2: []} + sage: G = FreeGroup(2)/[2 * (2, )] + sage: G.characteristic_varieties(groebner=True) + {0: [(f1 + 1,), (f1 - 1,)], 1: [(f1 + 1,), (f1 - 1, f2 - 1)], 2: []} + sage: G = (FreeGroup(0) / []) + sage: G.characteristic_varieties() + {0: Principal ideal (0) of Rational Field, + 1: Principal ideal (1) of Rational Field} + sage: G.characteristic_varieties(groebner=True) + {0: [(0,)], 1: [(1,)]} """ - A, ideal = self.abelian_alexander_matrix(ring=ring, simplified=True) + if self.ngens() == 0: + if groebner: + return {j: [(ring(j),)] for j in (0, 1)} + return {j: ring.ideal(j) for j in (0, 1)} + A, rels = self.abelian_alexander_matrix(ring=ring, simplified=True) R = A.base_ring() - res = [] + eval_1 = {x: ring(1) for x in R.gens()} + A_scalar = A.apply_map(lambda p: p.subs(eval_1)) + n = A.ncols() + n1 = n - A_scalar.rank() + ideal_1 = R.ideal([x - 1 for x in R.gens()]) S = R.polynomial_ring() - ideal = [S(elt) for elt in ideal] - for j in range(1, A.ncols()): - L = [p.monomial_reduction()[0] for p in A.minors(j)] - J = R.ideal(L + ideal) - res.append(J) - if not groebner or not R.base_ring().is_field(): + K = R.base_ring() + id_rels = R.ideal(rels) + res = dict() + bound = n + 1 + for j in range(bound + 1): + J = id_rels + A.fitting_ideal(j) + # J = R.ideal(id_rels.gens() + A.fitting_ideal(j).gens()) + if j <= n1: + J1 = K.ideal([K(p.subs(eval_1)) for p in J.gens()]) + if J1: + J *= ideal_1 + res[j] = R.ideal(J.gens_reduced()) + if R(1) in res[j].gens(): + bound = j + break + if not groebner or not ring.is_field(): return res if R.ngens() == 1: - res0 = [gcd(S(p) for p in J.gens()) for J in res] - res1 = [] - for p in res0: - if p == 0: - res1.append([R(0)]) + res = {j: gcd(S(p) for p in res[j].gens()) for j in range(bound + 1)} + char_var = dict() + strict = True + j = 0 + while strict and j <= bound: + if res[j] == 0: + char_var[j] = [R(0)] else: - fct = [q[0] for q in R(p).factor()] + fct = [q[0] for q in R(res[j]).factor()] if fct: - res1.append(fct) - return res1 - res1 = [] - for J in res: - LJ = J.minimal_associated_primes() + char_var[j] = fct + else: + char_var[j] = [] + strict = False + j += 1 + return char_var + char_var = dict() + strict = True + j = 0 + while strict and j <= bound: + LJ = res[j].minimal_associated_primes() fct = [id.groebner_basis() for id in LJ] - if fct != [(S.one(),)]: - res1.append(fct) - return res1 + char_var[j] = fct + if not fct: + strict = False + j += 1 + return char_var def rewriting_system(self): """ diff --git a/src/sage/groups/perm_gps/permgroup_element.pxd b/src/sage/groups/perm_gps/permgroup_element.pxd index c0cab01c706..2e3f22150e7 100644 --- a/src/sage/groups/perm_gps/permgroup_element.pxd +++ b/src/sage/groups/perm_gps/permgroup_element.pxd @@ -18,6 +18,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): cpdef _set_permutation_group_element(self, PermutationGroupElement p, bint convert) noexcept cpdef _mul_(self, other) noexcept + cpdef PermutationGroupElement _transpose_left(self, j, k) noexcept cpdef PermutationGroupElement _generate_new(self, list new_list) noexcept cpdef PermutationGroupElement _generate_new_GAP(self, old) noexcept cpdef _gap_list(self) noexcept diff --git a/src/sage/groups/perm_gps/permgroup_element.pyx b/src/sage/groups/perm_gps/permgroup_element.pyx index 29eae266c53..a459451bd6d 100644 --- a/src/sage/groups/perm_gps/permgroup_element.pyx +++ b/src/sage/groups/perm_gps/permgroup_element.pyx @@ -1298,6 +1298,39 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): return coercion_model.bin_op(left, right, operator.mul) + cpdef PermutationGroupElement _transpose_left(self, j, k) noexcept: + r""" + Return the product of the transposition `(j, k)` with ``self``. + + EXAMPLES:: + + sage: S = SymmetricGroup(5) + sage: s = S([5, 2, 4, 3, 1]) + sage: s._transpose_left(2, 3) + (1,5)(2,4,3) + sage: S((2, 3)) * s + (1,5)(2,4,3) + + sage: S = SymmetricGroup(["a", "b", "c", "d", "e"]) + sage: s = S(["e", "b", "d", "c", "a"]) + sage: s._transpose_left("b", "c") + ('a','e')('b','d','c') + sage: S(("b", "c")) * s + ('a','e')('b','d','c') + """ + if j == k: + return self + cdef PermutationGroupElement prod = self._new_c() + cdef int i + for i in range(self.n): + prod.perm[i] = self.perm[i] + if not self._parent._has_natural_domain(): + convert_dict = self._parent._domain_to_gap + j = convert_dict[j] + k = convert_dict[k] + prod.perm[j - 1], prod.perm[k - 1] = self.perm[k - 1], self.perm[j - 1] + return prod + cpdef _mul_(left, _right) noexcept: r""" EXAMPLES:: diff --git a/src/sage/interfaces/axiom.py b/src/sage/interfaces/axiom.py index 5df8d2e184a..5933e633d38 100644 --- a/src/sage/interfaces/axiom.py +++ b/src/sage/interfaces/axiom.py @@ -304,12 +304,13 @@ def _commands(self): EXAMPLES:: - sage: cmds = axiom._commands() #optional - axiom - sage: len(cmds) > 100 #optional - axiom + sage: # optional - axiom + sage: cmds = axiom._commands() + sage: len(cmds) > 100 True - sage: '<' in cmds #optional - axiom + sage: '<' in cmds True - sage: 'factor' in cmds #optional - axiom + sage: 'factor' in cmds True """ s = self.eval(")what things") @@ -327,18 +328,19 @@ def _tab_completion(self, verbose=True, use_disk_cache=True): EXAMPLES:: - sage: c = axiom._tab_completion(use_disk_cache=False, verbose=False) #optional - axiom - sage: len(c) > 100 #optional - axiom + sage: # optional - axiom + sage: c = axiom._tab_completion(use_disk_cache=False, verbose=False) + sage: len(c) > 100 True - sage: 'factor' in c #optional - axiom + sage: 'factor' in c True - sage: '**' in c #optional - axiom + sage: '**' in c False - sage: 'upperCase?' in c #optional - axiom + sage: 'upperCase?' in c False - sage: 'upperCase_q' in c #optional - axiom + sage: 'upperCase_q' in c True - sage: 'upperCase_e' in c #optional - axiom + sage: 'upperCase_e' in c True """ try: @@ -396,11 +398,12 @@ def get(self, var): EXAMPLES:: - sage: axiom.set('xx', '2') #optional - axiom - sage: axiom.get('xx') #optional - axiom + sage: # optional - axiom + sage: axiom.set('xx', '2') + sage: axiom.get('xx') '2' - sage: a = axiom('(1 + sqrt(2))^5') #optional - axiom - sage: axiom.get(a.name()) #optional - axiom + sage: a = axiom('(1 + sqrt(2))^5') + sage: axiom.get(a.name()) ' +-+\r\r\n 29\\|2 + 41' """ s = self._eval_line(str(var)) @@ -571,26 +574,28 @@ def _richcmp_(self, other, op): """ EXAMPLES:: - sage: two = axiom(2) #optional - axiom - sage: two == 2 #optional - axiom + sage: # optional - axiom + sage: two = axiom(2) + sage: two == 2 True - sage: two == 3 #optional - axiom + sage: two == 3 False - sage: two < 3 #optional - axiom + sage: two < 3 True - sage: two > 1 #optional - axiom + sage: two > 1 True - sage: a = axiom(1); b = axiom(2) #optional - axiom - sage: a == b #optional - axiom + sage: # optional - axiom + sage: a = axiom(1); b = axiom(2) + sage: a == b False - sage: a < b #optional - axiom + sage: a < b True - sage: a > b #optional - axiom + sage: a > b False - sage: b < a #optional - axiom + sage: b < a False - sage: b > a #optional - axiom + sage: b > a True We can also compare more complicated object such as functions:: @@ -649,15 +654,16 @@ def __getitem__(self, n): EXAMPLES:: - sage: v = axiom('[i*x^i for i in 0..5]'); v # optional - axiom + sage: # optional - axiom + sage: v = axiom('[i*x^i for i in 0..5]'); v 2 3 4 5 [0,x,2x ,3x ,4x ,5x ] - sage: v[4] # optional - axiom + sage: v[4] 3 3x - sage: v[1] # optional - axiom + sage: v[1] 0 - sage: v[10] # optional - axiom + sage: v[10] Traceback (most recent call last): ... IndexError: index out of range @@ -677,12 +683,13 @@ def comma(self, *args): EXAMPLES:: - sage: two = axiom(2) #optional - axiom - sage: two.comma(3) #optional - axiom + sage: # optional - axiom + sage: two = axiom(2) + sage: two.comma(3) [2,3] - sage: two.comma(3,4) #optional - axiom + sage: two.comma(3,4) [2,3,4] - sage: _.type() #optional - axiom + sage: _.type() Tuple PositiveInteger """ P = self._check_valid() @@ -796,12 +803,12 @@ def _sage_(self): 2.12340000000000 sage: _.parent() #optional - axiom Real Field with 53 bits of precision - sage: a = RealField(100)(pi) - sage: axiom(a)._sage_() #optional - axiom + sage: a = RealField(100)(pi) # needs sage.symbolic + sage: axiom(a)._sage_() # optional - axiom # needs sage.symbolic 3.1415926535897932384626433833 - sage: _.parent() #optional - axiom + sage: _.parent() # optional - axiom # needs sage.symbolic Real Field with 100 bits of precision - sage: axiom(a)._sage_() == a #optional - axiom + sage: axiom(a)._sage_() == a # optional - axiom # needs sage.symbolic True sage: axiom(2.0)._sage_() #optional - axiom 2.00000000000000 @@ -810,16 +817,17 @@ def _sage_(self): We can also convert Axiom's polynomials to Sage polynomials. - sage: a = axiom(x^2 + 1) #optional - axiom - sage: a.type() #optional - axiom + sage: # optional - axiom, needs sage.symbolic + sage: a = axiom(x^2 + 1) + sage: a.type() Polynomial Integer - sage: a.sage() #optional - axiom + sage: a.sage() x^2 + 1 - sage: _.parent() #optional - axiom + sage: _.parent() Univariate Polynomial Ring in x over Integer Ring - sage: axiom('x^2 + y^2 + 1/2').sage() #optional - axiom + sage: axiom('x^2 + y^2 + 1/2').sage() y^2 + x^2 + 1/2 - sage: _.parent() #optional - axiom + sage: _.parent() Multivariate Polynomial Ring in y, x over Rational Field @@ -902,12 +910,13 @@ def __init__(self, object, name): """ TESTS:: - sage: a = axiom('"Hello"') #optional - axiom - sage: a.upperCase_q #optional - axiom + sage: # optional - axiom + sage: a = axiom('"Hello"') + sage: a.upperCase_q upperCase? - sage: a.upperCase_e #optional - axiom + sage: a.upperCase_e upperCase! - sage: a.upperCase_e() #optional - axiom + sage: a.upperCase_e() "HELLO" """ if name.endswith("_q"): diff --git a/src/sage/interfaces/expect.py b/src/sage/interfaces/expect.py index 17ad63cfbac..cf331f53fd0 100644 --- a/src/sage/interfaces/expect.py +++ b/src/sage/interfaces/expect.py @@ -1,4 +1,4 @@ -# -*- coding: utf-8 -*- +# sage.doctest: needs sage.libs.gap sage.libs.pari sage.libs.singular sage.symbolic """ Common Interface Functionality through Pexpect @@ -40,6 +40,7 @@ import io import os import re +import shlex import signal import sys import weakref @@ -137,11 +138,10 @@ def __init__(self, name, prompt, command=None, env={}, server=None, server = os.getenv(env_name.format('SERVER')) if server_tmpdir is None: server_tmpdir = os.getenv(env_name.format('TMPDIR')) - if command is None: - command = os.getenv(env_name.format('COMMAND')) if script_subdirectory is None: script_subdirectory = os.getenv(env_name.format('SCRIPT_SUBDIRECTORY')) self.__is_remote = False + self.__remote_ulimit = None self.__remote_cleaner = remote_cleaner self._expect = None self._eval_using_file_cutoff = eval_using_file_cutoff @@ -179,32 +179,38 @@ def __init__(self, name, prompt, command=None, env={}, server=None, def set_server_and_command(self, server=None, command=None, server_tmpdir=None, ulimit=None): """ Changes the server and the command to use for this interface. - This raises a Runtime error if the interface is already started. + + This raises a :class:`RuntimeError` if the interface is already started. + + INPUT: + + - ``server`` -- string or ``None`` (default); name of a remote host to connect to using ``ssh``. + + - ``command`` -- one of: + + - a string; command line passed to the shell + + - a sequence of an :class:`~sage.features.Executable` and strings, arguments to + pass to the executable. EXAMPLES:: - sage: magma.set_server_and_command(server = 'remote', command = 'mymagma') # indirect doctest + sage: magma.set_server_and_command(server='remote', command='mymagma') # indirect doctest No remote temporary directory (option server_tmpdir) specified, using /tmp/ on remote sage: magma.server() 'remote' sage: magma.command() - "ssh -t remote 'mymagma'" + 'ssh -t remote mymagma' """ if self._expect: raise RuntimeError("interface has already started") - if command is None: - command = self.name() self._server = server + self.__remote_ulimit = ulimit if server is not None: - if ulimit: - command = "ssh -t %s 'ulimit %s; %s'" % (server, ulimit, command) - else: - command = "ssh -t %s '%s'" % (server, command) self.__is_remote = True self._eval_using_file_cutoff = 0 # don't allow this! if self.__verbose_start: print("Using remote server") - print(command) if server_tmpdir is None: # TO DO: Why default to /tmp/? Might be better to use the expect process itself to get a tmp folder print("No remote temporary directory (option server_tmpdir) specified, using /tmp/ on " + server) @@ -221,7 +227,7 @@ def server(self): EXAMPLES:: - sage: magma.set_server_and_command(server = 'remote') + sage: magma.set_server_and_command(server='remote') No remote temporary directory (option server_tmpdir) specified, using /tmp/ on remote sage: magma.server() # indirect doctest 'remote' @@ -230,15 +236,33 @@ def server(self): def command(self): """ - Return the command used in this interface. + Return the command used in this interface as a string. EXAMPLES:: - sage: magma.set_server_and_command(command = 'magma-2.19') - sage: magma.command() # indirect doctest + sage: magma.set_server_and_command(command='magma-2.19') + sage: magma.command() # indirect doctest 'magma-2.19' """ - return self.__command + command = self.__command + server = self.server() + if command is None: + env_name = 'SAGE_%s_{}' % self.name().upper() # same as in __init__ + command = os.getenv(env_name.format('COMMAND'), self.name()) + elif not isinstance(command, str): + executable = command[0] + if server: + executable = executable.name + else: + executable = executable.absolute_filename() + command = ' '.join([shlex.quote(executable)] + + [shlex.quote(arg) for arg in command[1:]]) + if server: + if self.__remote_ulimit: + command = f"ulimit {self.__remote_ulimit}; {command}" + command = f"ssh -t {shlex.quote(server)} {shlex.quote(command)}" + + return command def _get(self, wait=0.1, alternate_prompt=None): if self._expect is None: @@ -460,7 +484,7 @@ def _start(self, alt_message=None, block_during_init=True): if self.__logfilename is not None: self.__logfile = open(self.__logfilename, 'wb') - cmd = self.__command + cmd = self.command() if self.__verbose_start: print(cmd) diff --git a/src/sage/interfaces/fricas.py b/src/sage/interfaces/fricas.py index c771aea716c..75a277bcd05 100644 --- a/src/sage/interfaces/fricas.py +++ b/src/sage/interfaces/fricas.py @@ -1,3 +1,4 @@ +# sage.doctest: optional - fricas r""" Interface to FriCAS @@ -21,69 +22,69 @@ EXAMPLES:: - sage: fricas('3 * 5') # optional - fricas + sage: fricas('3 * 5') 15 - sage: a = fricas(3) * fricas(5); a # optional - fricas + sage: a = fricas(3) * fricas(5); a 15 The type of a is :class:`FriCASElement`, i.e., an element of the FriCAS interpreter:: - sage: type(a) # optional - fricas + sage: type(a) - sage: a.parent() # optional - fricas + sage: a.parent() FriCAS The underlying FriCAS type of a is also available, via the type method:: - sage: a.typeOf() # optional - fricas + sage: a.typeOf() PositiveInteger FriCAS objects are normally displayed using "ASCII art":: - sage: fricas(2/3) # optional - fricas + sage: fricas(2/3) 2 - 3 - sage: fricas('x^2 + 3/7') # optional - fricas + sage: fricas('x^2 + 3/7') 2 3 x + - 7 Functions defined in FriCAS are available as methods of the :class:`fricas` object:: - sage: F = fricas.factor('x^5 - y^5'); F # optional - fricas + sage: F = fricas.factor('x^5 - y^5'); F 4 3 2 2 3 4 - (y - x)(y + x y + x y + x y + x ) - sage: type(F) # optional - fricas + sage: type(F) - sage: F.typeOf() # optional - fricas + sage: F.typeOf() Factored(Polynomial(Integer)) We can also create a FriCAS polynomial and apply the function ``factor`` from FriCAS. The notation ``f.factor()`` is consistent with how the rest of SageMath works:: - sage: f = fricas('x^5 - y^5') # optional - fricas - sage: f^2 # optional - fricas + sage: f = fricas('x^5 - y^5') + sage: f^2 10 5 5 10 y - 2 x y + x - sage: f.factor() # optional - fricas + sage: f.factor() 4 3 2 2 3 4 - (y - x)(y + x y + x y + x y + x ) For many FriCAS types, translation to an appropriate SageMath type is available:: - sage: f.factor().sage() # optional - fricas + sage: f.factor().sage() (y - x) * (y^4 + y^3*x + y^2*x^2 + y*x^3 + x^4) Control-C interruption works well with the FriCAS interface. For example, try the following sum but with a much bigger range, and hit control-C:: - sage: f = fricas('(x^5 - y^5)^10000') # not tested - fricas + sage: f = fricas('(x^5 - y^5)^10000') # not tested Interrupting FriCAS... ... KeyboardInterrupt: Ctrl-c pressed while running FriCAS @@ -92,7 +93,7 @@ differential equation for the generating function for integer partitions:: - sage: fricas("guessADE([partition n for n in 0..40], homogeneous==4)") # optional - fricas + sage: fricas("guessADE([partition n for n in 0..40], homogeneous==4)") [ [ n @@ -121,9 +122,9 @@ FriCAS can solve linear ordinary differential equations:: - sage: fricas.set("y", "operator y") # optional - fricas - sage: fricas.set("deq", "x^3*D(y x, x, 3) + x^2*D(y x, x, 2) - 2*x*D(y x, x) + 2*y x - 2*x^4") # optional - fricas - sage: fricas.set("sol", "solve(deq, y, x)"); fricas("sol") # optional - fricas + sage: fricas.set("y", "operator y") + sage: fricas.set("deq", "x^3*D(y x, x, 3) + x^2*D(y x, x, 2) - 2*x*D(y x, x) + 2*y x - 2*x^4") + sage: fricas.set("sol", "solve(deq, y, x)"); fricas("sol") 5 3 2 x - 10 x + 20 x + 4 [particular = ----------------------, @@ -133,36 +134,36 @@ basis = [---------------, ------, -------------]] x x x - sage: fricas("sol.particular").sage() # optional - fricas + sage: fricas("sol.particular").sage() 1/15*(x^5 - 10*x^3 + 20*x^2 + 4)/x - sage: fricas("sol.basis").sage() # optional - fricas + sage: fricas("sol.basis").sage() [(2*x^3 - 3*x^2 + 1)/x, (x^3 - 1)/x, (x^3 - 3*x^2 - 1)/x] - sage: fricas.eval(")clear values y deq sol") # optional - fricas + sage: fricas.eval(")clear values y deq sol") '' FriCAS can expand expressions into series:: - sage: x = var('x'); ex = sqrt(cos(x)); a = fricas(ex).series(x=0); a # optional - fricas + sage: x = var('x'); ex = sqrt(cos(x)); a = fricas(ex).series(x=0); a 1 2 1 4 19 6 559 8 29161 10 11 1 - - x - -- x - ---- x - ------ x - --------- x + O(x ) 4 96 5760 645120 116121600 - sage: a.coefficients()[38].sage() # optional - fricas + sage: a.coefficients()[38].sage() -29472026335337227150423659490832640468979/274214482066329363682430667508979749984665600000000 - sage: ex = sqrt(atan(x)); a = fricas(ex).series(x=0); a # optional - fricas + sage: ex = sqrt(atan(x)); a = fricas(ex).series(x=0); a 1 5 9 - - - 2 1 2 31 2 6 x - - x + --- x + O(x ) 6 360 - sage: a.coefficient(9/2).sage() # optional - fricas + sage: a.coefficient(9/2).sage() 31/360 - sage: x = fricas("x::TaylorSeries Fraction Integer") # optional - fricas - sage: y = fricas("y::TaylorSeries Fraction Integer") # optional - fricas - sage: 2*(1+2*x+sqrt(1-4*x)-2*x*y).recip() # optional - fricas + sage: x = fricas("x::TaylorSeries Fraction Integer") + sage: y = fricas("y::TaylorSeries Fraction Integer") + sage: 2*(1+2*x+sqrt(1-4*x)-2*x*y).recip() 2 3 2 2 3 4 4 5 1 + (x y + x ) + 2 x + (x y + 2 x y + 6 x ) + (4 x y + 18 x ) + @@ -180,7 +181,7 @@ FriCAS does some limits right:: - sage: x = var('x'); ex = x^2*exp(-x)*Ei(x) - x; fricas(ex).limit(x=oo) # optional - fricas + sage: x = var('x'); ex = x^2*exp(-x)*Ei(x) - x; fricas(ex).limit(x=oo) 1 """ @@ -264,7 +265,7 @@ class FriCAS(ExtraTabCompletion, Expect): """ Interface to a FriCAS interpreter. """ - def __init__(self, name='fricas', command='fricas -nosman', + def __init__(self, name='fricas', command=None, script_subdirectory=None, logfile=None, server=None, server_tmpdir=None): """ @@ -272,23 +273,27 @@ def __init__(self, name='fricas', command='fricas -nosman', TESTS:: - sage: fricas == loads(dumps(fricas)) # optional - fricas + sage: fricas == loads(dumps(fricas)) True Check that :trac:`25174` is fixed:: - sage: fricas(I) # optional - fricas + sage: fricas(I) %i - sage: integrate(sin(x)*exp(I*x), x, -pi, 0, algorithm="fricas") # optional - fricas + sage: integrate(sin(x)*exp(I*x), x, -pi, 0, algorithm="fricas") 1/2*I*pi - sage: fricas(I*sin(x)).sage() # optional - fricas + sage: fricas(I*sin(x)).sage() I*sin(x) - sage: fricas(I*x).sage() # optional - fricas + sage: fricas(I*x).sage() I*x """ + if command is None: + from sage.features.fricas import FriCAS + command = [FriCAS(), "-nosman"] + eval_using_file_cutoff = 4096 - 5 # magic number from Expect._eval_line (there might be a bug) assert max(len(c) for c in FRICAS_INIT_CODE) < eval_using_file_cutoff self.__eval_using_file_cutoff = eval_using_file_cutoff @@ -313,13 +318,13 @@ def _start(self): EXAMPLES:: - sage: a = FriCAS() # optional - fricas - sage: a.is_running() # optional - fricas + sage: a = FriCAS() + sage: a.is_running() False - sage: a._start() # optional - fricas - sage: a.is_running() # optional - fricas + sage: a._start() + sage: a.is_running() True - sage: a.quit() # optional - fricas + sage: a.quit() """ # setting the prompt properly is necessary for restarting FriCAS self._prompt = FRICAS_FIRST_PROMPT @@ -356,25 +361,25 @@ def _quit_string(self): EXAMPLES:: - sage: fricas._quit_string() # optional - fricas + sage: fricas._quit_string() ')quit' - sage: a = FriCAS() # optional - fricas - sage: a.is_running() # optional - fricas + sage: a = FriCAS() + sage: a.is_running() False - sage: a._start() # optional - fricas - sage: a.is_running() # optional - fricas + sage: a._start() + sage: a.is_running() True - sage: a.quit() # optional - fricas - sage: a.is_running() # optional - fricas + sage: a.quit() + sage: a.is_running() False TESTS: Ensure that a new process is started after ``quit()``:: - sage: p = fricas.pid() # optional - fricas - sage: fricas.quit() # optional - fricas - sage: fricas.pid() == p # optional - fricas + sage: p = fricas.pid() + sage: fricas.quit() + sage: fricas.pid() == p False """ @@ -387,12 +392,12 @@ def _commands(self): EXAMPLES:: - sage: cmds = fricas._commands() # optional - fricas - sage: len(cmds) > 100 # optional - fricas + sage: cmds = fricas._commands() + sage: len(cmds) > 100 True - sage: '<' in cmds # optional - fricas + sage: '<' in cmds True - sage: 'factor' in cmds # optional - fricas + sage: 'factor' in cmds True """ output = self.eval(")what operations", reformat=False) @@ -408,18 +413,18 @@ def _tab_completion(self, verbose=True, use_disk_cache=True): EXAMPLES:: - sage: c = fricas._tab_completion(use_disk_cache=False, verbose=False) # optional - fricas - sage: len(c) > 100 # optional - fricas + sage: c = fricas._tab_completion(use_disk_cache=False, verbose=False) + sage: len(c) > 100 True - sage: 'factor' in c # optional - fricas + sage: 'factor' in c True - sage: '**' in c # optional - fricas + sage: '**' in c False - sage: 'upperCase?' in c # optional - fricas + sage: 'upperCase?' in c False - sage: 'upperCase_q' in c # optional - fricas + sage: 'upperCase_q' in c True - sage: 'upperCase_e' in c # optional - fricas + sage: 'upperCase_e' in c True """ try: @@ -469,7 +474,7 @@ def _read_in_file_command(self, filename): Evaluate a rather long line:: - sage: len(fricas([i for i in range(600)])) # optional - fricas, indirect doctest + sage: len(fricas([i for i in range(600)])) # indirect doctest 600 """ @@ -521,7 +526,7 @@ def _check_errors(self, line, output): TESTS:: - sage: fricas.set("x", "[i fo83r i in 0..17]") # optional - fricas, indirect doctest + sage: fricas.set("x", "[i fo83r i in 0..17]") # indirect doctest Traceback (most recent call last): ... RuntimeError: An error occurred when FriCAS evaluated '[i fo83r i in 0..17]': @@ -532,7 +537,7 @@ def _check_errors(self, line, output): Error B: Possibly missing a ] 3 error(s) parsing - sage: fricas.set("x", "something stupid") # optional - fricas, indirect doctest + sage: fricas.set("x", "something stupid") # indirect doctest Traceback (most recent call last): ... RuntimeError: An error occurred when FriCAS evaluated 'something stupid': @@ -658,8 +663,8 @@ def set(self, var, value): EXAMPLES:: - sage: fricas.set('xx', '2') # optional - fricas - sage: fricas.get('xx') # optional - fricas + sage: fricas.set('xx', '2') + sage: fricas.get('xx') '2' """ @@ -676,15 +681,15 @@ def get(self, var): EXAMPLES:: - sage: fricas.set('xx', '2') # optional - fricas - sage: fricas.get('xx') # optional - fricas + sage: fricas.set('xx', '2') + sage: fricas.get('xx') '2' - sage: a = fricas('(1 + sqrt(2))^5') # optional - fricas - sage: fricas.get(a.name()) # optional - fricas + sage: a = fricas('(1 + sqrt(2))^5') + sage: fricas.get(a.name()) ' +-+\n29 \\|2 + 41' - sage: fricas.get('(1 + sqrt(2))^5') # optional - fricas + sage: fricas.get('(1 + sqrt(2))^5') ' +-+\n29 \\|2 + 41' - sage: fricas.new('(1 + sqrt(2))^5') # optional - fricas + sage: fricas.new('(1 + sqrt(2))^5') +-+ 29 \|2 + 41 """ @@ -710,37 +715,37 @@ def get_string(self, var): We test that strings are returned properly:: - sage: r = fricas.get_string('concat([concat(string(i)," ") for i in 0..299])') # optional - fricas - sage: r == " ".join(str(i) for i in range(300)) + ' ' # optional - fricas + sage: r = fricas.get_string('concat([concat(string(i)," ") for i in 0..299])') + sage: r == " ".join(str(i) for i in range(300)) + ' ' True - sage: fricas.get_string('concat([string(1) for i in 1..5])') == "1"*5 # optional - fricas + sage: fricas.get_string('concat([string(1) for i in 1..5])') == "1"*5 True - sage: fricas.get_string('concat([string(1) for i in 1..10000])') == "1"*10000 # optional - fricas + sage: fricas.get_string('concat([string(1) for i in 1..10000])') == "1"*10000 True A problem with leading space:: sage: s = "unparse((-1234567890123456789012345678901234567890123456789012345678901234567890*n::EXPR INT)::INFORM)" - sage: fricas.get_string(s) # optional - fricas + sage: fricas.get_string(s) '(-1234567890123456789012345678901234567890123456789012345678901234567890)*n' Check that :trac:`25628` is fixed:: - sage: var("a b"); f = 1/(1+a*cos(x)) # optional - fricas + sage: var("a b"); f = 1/(1+a*cos(x)) (a, b) - sage: lF = integrate(f, x, algorithm="fricas") # optional - fricas - sage: (diff(lF[0], x) - f).simplify_trig() # optional - fricas + sage: lF = integrate(f, x, algorithm="fricas") + sage: (diff(lF[0], x) - f).simplify_trig() 0 - sage: (diff(lF[1], x) - f).simplify_trig() # optional - fricas + sage: (diff(lF[1], x) - f).simplify_trig() 0 - sage: f = 1/(b*x^2+a); lF = integrate(f, x, algorithm="fricas"); lF # optional - fricas + sage: f = 1/(b*x^2+a); lF = integrate(f, x, algorithm="fricas"); lF [1/2*log((2*a*b*x + (b*x^2 - a)*sqrt(-a*b))/(b*x^2 + a))/sqrt(-a*b), arctan(sqrt(a*b)*x/a)/sqrt(a*b)] - sage: (diff(lF[0], x) - f).simplify_trig() # optional - fricas + sage: (diff(lF[0], x) - f).simplify_trig() 0 - sage: (diff(lF[1], x) - f).simplify_trig() # optional - fricas + sage: (diff(lF[1], x) - f).simplify_trig() 0 """ @@ -756,7 +761,7 @@ def get_integer(self, var): TESTS:: - sage: fricas.get_integer('factorial 1111') == factorial(1111) # optional - fricas + sage: fricas.get_integer('factorial 1111') == factorial(1111) True """ @@ -769,10 +774,10 @@ def get_boolean(self, var): TESTS:: - sage: fricas.get_boolean('(1=1)::Boolean') == True # optional - fricas + sage: fricas.get_boolean('(1=1)::Boolean') == True True - sage: fricas.get_boolean('(1=2)::Boolean') == False # optional - fricas + sage: fricas.get_boolean('(1=2)::Boolean') == False True """ return self.get(str(var)).replace("\n", "") == "true" @@ -793,7 +798,7 @@ def get_unparsed_InputForm(self, var): TESTS:: - sage: fricas.get_unparsed_InputForm('1..3') # optional - fricas + sage: fricas.get_unparsed_InputForm('1..3') '(1..3)$Segment(PositiveInteger())' """ @@ -805,7 +810,7 @@ def get_InputForm(self, var): TESTS:: - sage: fricas.get_InputForm('1..3') # optional - fricas + sage: fricas.get_InputForm('1..3') '(($elt (Segment (PositiveInteger)) SEGMENT) 1 3)' """ @@ -817,10 +822,10 @@ def _assign_symbol(self): EXAMPLES:: - sage: fricas.set("x", "1"); # optional - fricas, indirect doctest - sage: fricas.get("x") # optional - fricas + sage: fricas.set("x", "1"); # indirect doctest + sage: fricas.get("x") '1' - sage: fricas.eval(")cl val x") # optional - fricas + sage: fricas.eval(")cl val x") '' """ return ":=" @@ -831,15 +836,15 @@ def _equality_symbol(self): EXAMPLES:: - sage: a = fricas(x==6); a # optional - fricas, indirect doctest + sage: a = fricas(x==6); a # indirect doctest x = 6 A warning:: - sage: fricas.set("x", 2); # optional - fricas - sage: a = fricas(x==6); a # optional - fricas + sage: fricas.set("x", 2); + sage: a = fricas(x==6); a 2 = 6 - sage: fricas.eval(")cl val x") # optional - fricas + sage: fricas.eval(")cl val x") '' """ return "=" @@ -850,7 +855,7 @@ def _true_symbol(self): EXAMPLES:: - sage: str(fricas("(1=1)@Boolean")) == fricas._true_symbol() # optional - fricas + sage: str(fricas("(1=1)@Boolean")) == fricas._true_symbol() True """ return "true" @@ -861,7 +866,7 @@ def _false_symbol(self): EXAMPLES:: - sage: str(fricas("(1~=1)@Boolean")) == fricas._false_symbol() # optional - fricas + sage: str(fricas("(1~=1)@Boolean")) == fricas._false_symbol() True """ return "false" @@ -872,7 +877,7 @@ def _inequality_symbol(self): EXAMPLES:: - sage: fricas(x!=0) # optional - fricas, indirect doctest + sage: fricas(x!=0) # indirect doctest true """ return '~=' @@ -881,7 +886,7 @@ def _repr_(self): """ EXAMPLES:: - sage: fricas # indirect doctest + sage: fricas # indirect doctest FriCAS """ return "FriCAS" @@ -914,11 +919,11 @@ def eval(self, code, strip=True, synchronize=False, locals=None, allow_use_file= EXAMPLES:: - sage: fricas.set("x", "1783"); fricas("x") # optional - fricas + sage: fricas.set("x", "1783"); fricas("x") 1783 - sage: fricas.eval(")cl val x"); # optional - fricas + sage: fricas.eval(")cl val x"); '' - sage: fricas("x") # optional - fricas + sage: fricas("x") x """ @@ -946,9 +951,9 @@ def _function_class(self): EXAMPLES:: - sage: fricas._function_class() # optional - fricas + sage: fricas._function_class() - sage: type(fricas.gcd) # optional - fricas + sage: type(fricas.gcd) """ return FriCASExpectFunction @@ -957,9 +962,9 @@ def _object_class(self): """ EXAMPLES:: - sage: fricas._object_class() # optional - fricas + sage: fricas._object_class() - sage: type(fricas(2)) # optional - fricas + sage: type(fricas(2)) """ return FriCASElement @@ -970,9 +975,9 @@ def _function_element_class(self): EXAMPLES:: - sage: fricas._function_element_class() # optional - fricas + sage: fricas._function_element_class() - sage: type(fricas(2).gcd) # optional - fricas + sage: type(fricas(2).gcd) """ return FriCASFunctionElement @@ -1012,16 +1017,16 @@ def __len__(self): EXAMPLES:: - sage: v = fricas('[x^i for i in 0..5]') # optional - fricas - sage: len(v) # optional - fricas + sage: v = fricas('[x^i for i in 0..5]') + sage: len(v) 6 TESTS: Streams are not handled yet:: - sage: oh = fricas('[i for i in 1..]') # optional - fricas - sage: len(oh) # optional - fricas + sage: oh = fricas('[i for i in 1..]') + sage: len(oh) Traceback (most recent call last): ... TypeError: ... @@ -1036,15 +1041,15 @@ def __iter__(self): EXAMPLES:: - sage: L = fricas([4,5,6]) # optional - fricas - sage: list(L) # optional - fricas + sage: L = fricas([4,5,6]) + sage: list(L) [4, 5, 6] TESTS: Streams are not handled yet:: - sage: oh = fricas('[i for i in 1..]') # optional - fricas + sage: oh = fricas('[i for i in 1..]') sage: next(iter(oh)) # known bug """ for i in range(len(self)): @@ -1059,20 +1064,20 @@ def __getitem__(self, n): TESTS:: - sage: fricas("[1,2,3]")[0] # optional - fricas + sage: fricas("[1,2,3]")[0] 1 Negative indices do work:: - sage: fricas("[1,2,3]")[-1] # optional - fricas + sage: fricas("[1,2,3]")[-1] 3 - sage: fricas("[1,2,3]")[-2] # optional - fricas + sage: fricas("[1,2,3]")[-2] 2 Invalid indices raise exceptions:: - sage: fricas("[1,2,3]")[3] # optional - fricas + sage: fricas("[1,2,3]")[3] Traceback (most recent call last): ... TypeError: An error occurred when FriCAS evaluated 'elt(...,...)': @@ -1082,8 +1087,8 @@ def __getitem__(self, n): And streams are ok too:: - sage: oh = fricas('[i for i in 1..]') # optional - fricas - sage: oh[4] # optional - fricas + sage: oh = fricas('[i for i in 1..]') + sage: oh[4] 5 """ n = int(n) @@ -1107,7 +1112,7 @@ def __int__(self): """ TESTS:: - sage: int(fricas(2)) # optional - fricas + sage: int(fricas(2)) 2 """ return int(self.sage()) @@ -1118,9 +1123,9 @@ def bool(self): EXAMPLES:: - sage: fricas("1=1").bool() # optional - fricas + sage: fricas("1=1").bool() True - sage: fricas("1~=1").bool() # optional - fricas + sage: fricas("1~=1").bool() False """ P = self._check_valid() @@ -1132,7 +1137,7 @@ def __bool__(self): EXAMPLES:: - sage: fricas(0).is_zero() # optional - fricas, indirect doctest + sage: fricas(0).is_zero() # indirect doctest True """ P = self._check_valid() @@ -1142,7 +1147,7 @@ def __float__(self): """ TESTS:: - sage: float(fricas(2)) # optional - fricas + sage: float(fricas(2)) 2.0 """ return float(self.sage()) @@ -1151,7 +1156,7 @@ def _integer_(self, ZZ=None): """ EXAMPLES:: - sage: ZZ(fricas('1')) # optional - fricas + sage: ZZ(fricas('1')) 1 """ return ZZ(self.sage()) @@ -1160,7 +1165,7 @@ def _rational_(self): """ EXAMPLES:: - sage: QQ(fricas('-1/2')) # optional - fricas + sage: QQ(fricas('-1/2')) -1/2 """ return QQ(self.sage()) @@ -1175,13 +1180,13 @@ def _latex_(self): r""" EXAMPLES:: - sage: latex(fricas("sin(x+y)/exp(z)*log(1+%e)")) # optional - fricas + sage: latex(fricas("sin(x+y)/exp(z)*log(1+%e)")) \frac{{{\log \left( {{e+1}} \right)} \ {\sin \left( {{y+x}} \right)}}}{{{e} ^{z}}} - sage: latex(fricas("matrix([[1,2],[3,4]])")) # optional - fricas + sage: latex(fricas("matrix([[1,2],[3,4]])")) \left[ \begin{array}{cc} 1 & 2 \\ 3 & 4\end{array} \right] - sage: latex(fricas("integrate(sin(x+1/x),x)")) # optional - fricas + sage: latex(fricas("integrate(sin(x+1/x),x)")) \int ^{\displaystyle x} {{\sin \left( {{\frac{{{{ \%...} ^{2}}+1}}{ \%...}}} \right)} \ {d \%...}} """ replacements = [(r'\sp ', '^'), @@ -1206,14 +1211,14 @@ def _get_sage_type(self, domain): EXAMPLES:: - sage: m = fricas("dom(1/2)::Any") # optional - fricas - sage: fricas(0)._get_sage_type(m) # optional - fricas + sage: m = fricas("dom(1/2)::Any") + sage: fricas(0)._get_sage_type(m) Rational Field TESTS:: - sage: m = fricas("UP(y, UP(x, AN))::INFORM") # optional - fricas - sage: fricas(0)._get_sage_type(m) # optional - fricas + sage: m = fricas("UP(y, UP(x, AN))::INFORM") + sage: fricas(0)._get_sage_type(m) Univariate Polynomial Ring in y over Univariate Polynomial Ring in x over Algebraic Field """ from sage.rings.qqbar import QQbar @@ -1297,7 +1302,7 @@ def _parse_and_eval(s, start=0): sage: FriCASElement._parse_and_eval("(asin c)") (arcsin(c), 7) - sage: N(FriCASElement._parse_and_eval("(pi)")[0]) # optional - fricas + sage: N(FriCASElement._parse_and_eval("(pi)")[0]) 3.14159265358979 sage: FriCASElement._parse_and_eval('(a "(b c)")') @@ -1401,7 +1406,7 @@ def _parse_other(s, start=0, make_fun=False): sage: var("D") D - sage: integrate(D/x, x, algorithm="fricas") # optional - fricas + sage: integrate(D/x, x, algorithm="fricas") D*log(x) However, it does have to check for constants, for example @@ -1491,7 +1496,7 @@ def _sage_expression(fricas_InputForm): TESTS:: - sage: f = fricas('integrate(sin(x^2), x)'); f # optional - fricas + sage: f = fricas('integrate(sin(x^2), x)'); f +---+ | 2 fresnelS(x |--- ) @@ -1501,16 +1506,16 @@ def _sage_expression(fricas_InputForm): | 2 |--- \|%pi - sage: s = fricas.get_InputForm(f._name); s # optional - fricas + sage: s = fricas.get_InputForm(f._name); s '(/ (fresnelS (* x (^ (/ 2 (pi)) (/ 1 2)))) (^ (/ 2 (pi)) (/ 1 2)))' sage: from sage.interfaces.fricas import FriCASElement - sage: FriCASElement._sage_expression(s) # optional - fricas + sage: FriCASElement._sage_expression(s) 1/2*sqrt(2)*sqrt(pi)*fresnel_sin(sqrt(2)*x/sqrt(pi)) Check that :trac:`22525` is fixed:: sage: l = [sin, cos, sec, csc, cot, tan, asin, acos, atan, acot, acsc, asec, arcsin, arccos, arctan, arccot, arccsc, arcsec] - sage: [f(x)._fricas_().sage().subs(x=0.9) for f in l] # optional - fricas + sage: [f(x)._fricas_().sage().subs(x=0.9) for f in l] [0.783326909627483, 0.621609968270664, 1.60872581046605, @@ -1530,7 +1535,7 @@ def _sage_expression(fricas_InputForm): 1.57079632679490 - 0.467145308103262*I, 0.467145308103262*I] sage: l = [tanh, sinh, cosh, coth, sech, csch, asinh, acosh, atanh, acoth, asech, acsch, arcsinh, arccosh, arctanh, arccoth, arcsech, arccsch] - sage: [f(x)._fricas_().sage().subs(x=0.9) for f in l] # optional - fricas + sage: [f(x)._fricas_().sage().subs(x=0.9) for f in l] [0.716297870199024, 1.02651672570818, 1.43308638544877, @@ -1553,76 +1558,76 @@ def _sage_expression(fricas_InputForm): Check that :trac:`23782` is fixed:: sage: s = '((3*n^10-25*n^9+50*n^8+62*n^7-229*n^6-25*n^5+320*n^4-12*n^3-144*n^2)/11520)::EXPR INT' - sage: fricas(s).sage() # optional - fricas + sage: fricas(s).sage() 1/3840*n^10 - 5/2304*n^9 + 5/1152*n^8 + 31/5760*n^7 - 229/11520*n^6 - 5/2304*n^5 + 1/36*n^4 - 1/960*n^3 - 1/80*n^2 Some checks for digamma and polygamma (:trac:`31853`):: - sage: fricas.digamma(1.0) # optional - fricas + sage: fricas.digamma(1.0) - 0.5772156649_0153286061 sage: psi(1.0) -0.577215664901533 - sage: fricas.polygamma(1, 1.0) # optional - fricas + sage: fricas.polygamma(1, 1.0) 1.644934066848226... sage: psi(1, 1).n() 1.64493406684823 sage: var("w") w - sage: fricas.laplace(log(x), x, w).sage() # optional - fricas + sage: fricas.laplace(log(x), x, w).sage() -(euler_gamma + log(w))/w - sage: fricas(laplace(log(x), x, w)).sage() # optional - fricas + sage: fricas(laplace(log(x), x, w)).sage() -(euler_gamma + log(w))/w Check that :trac:`25224` is fixed:: - sage: integrate(log(x)/(1-x),x,algorithm='fricas') # optional - fricas + sage: integrate(log(x)/(1-x),x,algorithm='fricas') dilog(-x + 1) - sage: fricas(dilog(-x + 1)) # optional - fricas + sage: fricas(dilog(-x + 1)) dilog(x) - sage: dilog._fricas_()(1.0) # optional - fricas + sage: dilog._fricas_()(1.0) 1.6449340668_4822643647_24152 sage: dilog(1.0) 1.64493406684823 Check that :trac:`25987` is fixed:: - sage: integrate(lambert_w(x), x, algorithm="fricas") # optional - fricas + sage: integrate(lambert_w(x), x, algorithm="fricas") (x*lambert_w(x)^2 - x*lambert_w(x) + x)/lambert_w(x) Check that :trac:`25838` is fixed:: sage: F = function('f'); f = SR.var('f') - sage: FF = fricas(F(f)); FF # optional - fricas + sage: FF = fricas(F(f)); FF f(f) - sage: FF.D(f).sage() # optional - fricas + sage: FF.D(f).sage() diff(f(f), f) - sage: bool(FF.D(f).integrate(f).sage() == F(f)) # optional - fricas + sage: bool(FF.D(f).integrate(f).sage() == F(f)) True Check that :trac:`25602` is fixed:: - sage: r = fricas.integrate(72000/(1+x^5),x).sage() # optional - fricas - sage: n(r.subs(x=5)-r.subs(x=3)) # optional - fricas tol 0.1 - 193.020947266210 + sage: r = fricas.integrate(72000/(1+x^5), x).sage() + sage: abs(n(r.subs(x=5) - r.subs(x=3)) - 193.020947266210) <= 0.1 + True - sage: var("a"); r = fricas.integrate(72000*a^8/(a^5+x^5),x).sage() # optional - fricas + sage: var("a"); r = fricas.integrate(72000*a^8/(a^5+x^5), x).sage() a - sage: n(r.subs(a=1, x=5)-r.subs(a=1, x=3)) # optional - fricas tol 0.1 - 193.020947266268 - 8.73114913702011e-11*I + sage: abs(n(r.subs(a=1, x=5) - r.subs(a=1, x=3)) - 193.020947266268) <= 0.1 + True Check conversions of sums and products:: - sage: var("k, m, n") # optional - fricas + sage: var("k, m, n") (k, m, n) - sage: fricas("sum(1/factorial(k), k=1..n)").sage() # optional - fricas + sage: fricas("sum(1/factorial(k), k=1..n)").sage() sum(1/factorial(_...), _..., 1, n) - sage: fricas("eval(sum(x/k, k=1..n), x=k)").sage() # optional - fricas + sage: fricas("eval(sum(x/k, k=1..n), x=k)").sage() k*harmonic_number(n) - sage: fricas("product(1/factorial(k), k=1..n)").sage() # optional - fricas + sage: fricas("product(1/factorial(k), k=1..n)").sage() 1/product(factorial(_...), _..., 1, n) - sage: f = fricas.guess([sum(1/k, k,1,n) for n in range(10)])[0]; f # optional - fricas + sage: f = fricas.guess([sum(1/k, k,1,n) for n in range(10)])[0]; f n - 1 --+ 1 > ------- @@ -1630,10 +1635,10 @@ def _sage_expression(fricas_InputForm): s = 0 10 10 - sage: f.sage() # optional - fricas + sage: f.sage() harmonic_number(n) - sage: f = fricas.guess([0, 1, 3, 9, 33])[0]; f # optional - fricas + sage: f = fricas.guess([0, 1, 3, 9, 33])[0]; f s - 1 n - 1 5 --+ ++-++ @@ -1642,53 +1647,53 @@ def _sage_expression(fricas_InputForm): s = 0 p = 0 5 4 - sage: f.sage() # optional - fricas + sage: f.sage() sum(factorial(_... + 1), _..., 0, n - 1) Check that :trac:`26746` is fixed:: sage: _ = var('x, y, z') sage: f = sin(x^2) + y^z - sage: f.integrate(x, algorithm='fricas') # optional - fricas + sage: f.integrate(x, algorithm='fricas') 1/2*sqrt(2)*sqrt(pi)*(sqrt(2)*x*y^z/sqrt(pi) + fresnel_sin(sqrt(2)*x/sqrt(pi))) - sage: fricas(fresnel_sin(1)) # optional - fricas + sage: fricas(fresnel_sin(1)) fresnelS(1) - sage: fricas("fresnelS(1.0)") # optional - fricas + sage: fricas("fresnelS(1.0)") 0.4382591473_9035476607_676 - sage: fricas(fresnel_cos(1)) # optional - fricas + sage: fricas(fresnel_cos(1)) fresnelC(1) - sage: fricas("fresnelC(1.0)") # optional - fricas + sage: fricas("fresnelC(1.0)") 0.7798934003_7682282947_42 Check that :trac:`17908` is fixed:: - sage: fricas(abs(x)).sage().subs(x=-1783) # optional - fricas + sage: fricas(abs(x)).sage().subs(x=-1783) 1783 Check that :trac:`27310` is fixed:: - sage: fricas.set("F", "operator 'f") # optional - fricas - sage: fricas("eval(D(F(x,y), [x, y], [2, 1]), x=x+y)").sage() # optional - fricas + sage: fricas.set("F", "operator 'f") + sage: fricas("eval(D(F(x,y), [x, y], [2, 1]), x=x+y)").sage() D[0, 0, 1](f)(x + y, y) Conversion of hypergeometric functions (:trac:`31298`):: sage: a,b,c = var("a b c") sage: A = hypergeometric([a, b], [c], x) - sage: fricas(A).sage() - A # optional - fricas + sage: fricas(A).sage() - A 0 - sage: fricas(A).D(x).sage() - diff(A, x) # optional - fricas + sage: fricas(A).D(x).sage() - diff(A, x) 0 Check that :trac:`31858` is fixed:: - sage: fricas.Gamma(3/2).sage() # optional - fricas + sage: fricas.Gamma(3/2).sage() 1/2*sqrt(pi) - sage: fricas.Gamma(3/4).sage() # optional - fricas + sage: fricas.Gamma(3/4).sage() gamma(3/4) - sage: fricas.Gamma(3, 2).sage() # optional - fricas + sage: fricas.Gamma(3, 2).sage() gamma(3, 2) @@ -1696,7 +1701,7 @@ def _sage_expression(fricas_InputForm): sage: var("y") y - sage: f = fricas.zerosOf(y^4 + y + 1, y); f # optional - fricas + sage: f = fricas.zerosOf(y^4 + y + 1, y); f +-----------------------------+ | 2 2 \|- 3 %y1 - 2 %y0 %y1 - 3 %y0 - %y1 - %y0 @@ -1708,7 +1713,7 @@ def _sage_expression(fricas_InputForm): ----------------------------------------------] 2 - sage: f[1].sage() # optional - fricas + sage: f[1].sage() -1/2*sqrt(1/3)*sqrt((3*(1/18*I*sqrt(229)*sqrt(3) + 1/2)^(2/3) + 4)/(1/18*I*sqrt(229)*sqrt(3) + 1/2)^(1/3)) + 1/2*sqrt(-(1/18*I*sqrt(229)*sqrt(3) + 1/2)^(1/3) + 6*sqrt(1/3)/sqrt((3*(1/18*I*sqrt(229)*sqrt(3) + 1/2)^(2/3) + 4)/(1/18*I*sqrt(229)*sqrt(3) + 1/2)^(1/3)) - 4/3/(1/18*I*sqrt(229)*sqrt(3) + 1/2)^(1/3)) """ @@ -1772,101 +1777,101 @@ def _sage_(self): Floats:: - sage: fricas(2.1234).sage() # optional - fricas + sage: fricas(2.1234).sage() 2.12340000000000 - sage: _.parent() # optional - fricas + sage: _.parent() Real Field with 53 bits of precision - sage: a = RealField(100)(pi) # optional - fricas - sage: fricas(a).sage() # optional - fricas + sage: a = RealField(100)(pi) + sage: fricas(a).sage() 3.1415926535897932384626433833 - sage: _.parent() # optional - fricas + sage: _.parent() Real Field with 100 bits of precision - sage: fricas(a).sage() == a # optional - fricas + sage: fricas(a).sage() == a True - sage: fricas(2.0).sage() # optional - fricas + sage: fricas(2.0).sage() 2.00000000000000 - sage: _.parent() # optional - fricas + sage: _.parent() Real Field with 53 bits of precision Algebraic numbers:: - sage: a = fricas('(1 + sqrt(2))^5'); a # optional - fricas + sage: a = fricas('(1 + sqrt(2))^5'); a +-+ 29 \|2 + 41 - sage: b = a.sage(); b # optional - fricas + sage: b = a.sage(); b 82.0121933088198? - sage: b.radical_expression() # optional - fricas + sage: b.radical_expression() 29*sqrt(2) + 41 Integers modulo n:: - sage: fricas("((42^17)^1783)::IntegerMod(5^(5^5))").sage() == Integers(5^(5^5))((42^17)^1783) # optional - fricas + sage: fricas("((42^17)^1783)::IntegerMod(5^(5^5))").sage() == Integers(5^(5^5))((42^17)^1783) True Matrices over a prime field:: - sage: fricas("matrix [[1::PF 3, 2],[2, 0]]").sage().parent() # optional - fricas + sage: fricas("matrix [[1::PF 3, 2],[2, 0]]").sage().parent() Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 3 We can also convert FriCAS's polynomials to Sage polynomials:: - sage: a = fricas("x^2 + 1"); a.typeOf() # optional - fricas + sage: a = fricas("x^2 + 1"); a.typeOf() Polynomial(Integer) - sage: a.sage() # optional - fricas + sage: a.sage() x^2 + 1 - sage: _.parent() # optional - fricas + sage: _.parent() Univariate Polynomial Ring in x over Integer Ring - sage: fricas('x^2 + y^2 + 1/2').sage() # optional - fricas + sage: fricas('x^2 + y^2 + 1/2').sage() y^2 + x^2 + 1/2 - sage: _.parent() # optional - fricas + sage: _.parent() Multivariate Polynomial Ring in y, x over Rational Field - sage: fricas("1$Polynomial Integer").sage() # optional - fricas + sage: fricas("1$Polynomial Integer").sage() 1 - sage: fricas("x^2/2").sage() # optional - fricas + sage: fricas("x^2/2").sage() 1/2*x^2 sage: x = polygen(QQ, 'x') - sage: fricas(x+3).sage() # optional - fricas + sage: fricas(x+3).sage() x + 3 - sage: fricas(x+3).domainOf() # optional - fricas + sage: fricas(x+3).domainOf() Polynomial(Integer()) - sage: fricas(matrix([[2,3],[4,x+5]])).diagonal().sage() # optional - fricas + sage: fricas(matrix([[2,3],[4,x+5]])).diagonal().sage() (2, x + 5) - sage: f = fricas("(y^2+3)::UP(y, INT)").sage(); f # optional - fricas + sage: f = fricas("(y^2+3)::UP(y, INT)").sage(); f y^2 + 3 - sage: f.parent() # optional - fricas + sage: f.parent() Univariate Polynomial Ring in y over Integer Ring - sage: fricas("(y^2+sqrt 3)::UP(y, AN)").sage() # optional - fricas + sage: fricas("(y^2+sqrt 3)::UP(y, AN)").sage() y^2 + 1.732050807568878? Rational functions:: - sage: fricas("x^2 + 1/z").sage() # optional - fricas + sage: fricas("x^2 + 1/z").sage() x^2 + 1/z Expressions:: - sage: fricas(pi).sage() # optional - fricas + sage: fricas(pi).sage() pi - sage: fricas("sin(x+y)/exp(z)*log(1+%e)").sage() # optional - fricas + sage: fricas("sin(x+y)/exp(z)*log(1+%e)").sage() e^(-z)*log(e + 1)*sin(x + y) - sage: fricas("factorial(n)").sage() # optional - fricas + sage: fricas("factorial(n)").sage() factorial(n) - sage: fricas("integrate(sin(x+y), x=0..1)").sage() # optional - fricas + sage: fricas("integrate(sin(x+y), x=0..1)").sage() -cos(y + 1) + cos(y) - sage: fricas("integrate(x*sin(1/x), x=0..1)").sage() # optional - fricas + sage: fricas("integrate(x*sin(1/x), x=0..1)").sage() 'failed' - sage: fricas("integrate(sin((x^2+1)/x),x)").sage() # optional - fricas + sage: fricas("integrate(sin((x^2+1)/x),x)").sage() integral(sin((x^2 + 1)/x), x) .. TODO:: @@ -1875,7 +1880,7 @@ def _sage_(self): Matrices:: - sage: fricas("matrix [[x^n/2^m for n in 0..5] for m in 0..3]").sage() # optional - fricas, long time + sage: fricas("matrix [[x^n/2^m for n in 0..5] for m in 0..3]").sage() # long time [ 1 x x^2 x^3 x^4 x^5] [ 1/2 1/2*x 1/2*x^2 1/2*x^3 1/2*x^4 1/2*x^5] [ 1/4 1/4*x 1/4*x^2 1/4*x^3 1/4*x^4 1/4*x^5] @@ -1883,25 +1888,25 @@ def _sage_(self): Lists:: - sage: fricas("[2^n/x^n for n in 0..5]").sage() # optional - fricas, long time + sage: fricas("[2^n/x^n for n in 0..5]").sage() # long time [1, 2/x, 4/x^2, 8/x^3, 16/x^4, 32/x^5] - sage: fricas("[matrix [[i for i in 1..n]] for n in 0..5]").sage() # optional - fricas, long time + sage: fricas("[matrix [[i for i in 1..n]] for n in 0..5]").sage() # long time [[], [1], [1 2], [1 2 3], [1 2 3 4], [1 2 3 4 5]] Error handling:: - sage: s = fricas.guessPade("[fibonacci i for i in 0..10]"); s # optional - fricas + sage: s = fricas.guessPade("[fibonacci i for i in 0..10]"); s n x [[[x ]- ----------]] 2 x + x - 1 - sage: s.sage() # optional - fricas + sage: s.sage() Traceback (most recent call last): ... NotImplementedError: the translation of the FriCAS Expression 'rootOfADE' to sage is not yet implemented - sage: s = fricas("series(sqrt(1+x), x=0)"); s # optional - fricas + sage: s = fricas("series(sqrt(1+x), x=0)"); s 1 1 2 1 3 5 4 7 5 21 6 33 7 429 8 1 + - x - - x + -- x - --- x + --- x - ---- x + ---- x - ----- x 2 8 16 128 256 1024 2048 32768 @@ -1910,7 +1915,7 @@ def _sage_(self): ----- x - ------ x + O(x ) 65536 262144 - sage: s.sage() # optional - fricas + sage: s.sage() Traceback (most recent call last): ... NotImplementedError: the translation of the FriCAS object @@ -2067,12 +2072,12 @@ def __init__(self, object, name): TESTS:: - sage: a = fricas('"Hello"') # optional - fricas - sage: a.upperCase_q # optional - fricas + sage: a = fricas('"Hello"') + sage: a.upperCase_q upperCase? - sage: a.upperCase_e # optional - fricas + sage: a.upperCase_e upperCase! - sage: a.upperCase_e() # optional - fricas + sage: a.upperCase_e() "HELLO" """ @@ -2092,9 +2097,9 @@ def __init__(self, parent, name): TESTS:: - sage: fricas.upperCase_q # optional - fricas + sage: fricas.upperCase_q upperCase? - sage: fricas.upperCase_e # optional - fricas + sage: fricas.upperCase_e upperCase! """ @@ -2116,7 +2121,7 @@ def is_FriCASElement(x): doctest:...: DeprecationWarning: the function is_FriCASElement is deprecated; use isinstance(x, sage.interfaces.abc.FriCASElement) instead See https://github.com/sagemath/sage/issues/34804 for details. False - sage: is_FriCASElement(fricas(2)) # optional - fricas + sage: is_FriCASElement(fricas(2)) True """ from sage.misc.superseded import deprecation @@ -2167,13 +2172,13 @@ def __doctest_cleanup(): """ EXAMPLES:: - sage: from sage.interfaces.fricas import __doctest_cleanup # optional - fricas - sage: a = FriCAS() # optional - fricas - sage: two = a(2) # optional - fricas - sage: a.is_running() # optional - fricas + sage: from sage.interfaces.fricas import __doctest_cleanup + sage: a = FriCAS() + sage: two = a(2) + sage: a.is_running() True - sage: __doctest_cleanup() # optional - fricas - sage: a.is_running() # optional - fricas + sage: __doctest_cleanup() + sage: a.is_running() False """ import sage.interfaces.quit diff --git a/src/sage/interfaces/frobby.py b/src/sage/interfaces/frobby.py index aab3bd9b58f..7eb5e53becd 100644 --- a/src/sage/interfaces/frobby.py +++ b/src/sage/interfaces/frobby.py @@ -115,20 +115,22 @@ def alexander_dual(self, monomial_ideal): This is a simple example of computing irreducible decomposition. :: - sage: (a, b, c, d) = QQ['a,b,c,d'].gens() # optional - frobby - sage: id = ideal(a * b, b * c, c * d, d * a) # optional - frobby - sage: alexander_dual = frobby.alexander_dual(id) # optional - frobby - sage: true_alexander_dual = ideal(b * d, a * c) # optional - frobby - sage: alexander_dual == true_alexander_dual # use sets to ignore order # optional - frobby + sage: # optional - frobby + sage: (a, b, c, d) = QQ['a,b,c,d'].gens() + sage: id = ideal(a * b, b * c, c * d, d * a) + sage: alexander_dual = frobby.alexander_dual(id) + sage: true_alexander_dual = ideal(b * d, a * c) + sage: alexander_dual == true_alexander_dual # use sets to ignore order True We see how it is much faster to compute this with frobby than the built-in procedure for simplicial complexes:: - sage: t=simplicial_complexes.PoincareHomologyThreeSphere() # optional - frobby - sage: R=PolynomialRing(QQ,16,'x') # optional - frobby - sage: I=R.ideal([prod([R.gen(i-1) for i in a]) for a in t.facets()]) # optional - frobby - sage: len(frobby.alexander_dual(I).gens()) # optional - frobby + sage: # optional - frobby + sage: t=simplicial_complexes.PoincareHomologyThreeSphere() + sage: R=PolynomialRing(QQ,16,'x') + sage: I=R.ideal([prod([R.gen(i-1) for i in a]) for a in t.facets()]) + sage: len(frobby.alexander_dual(I).gens()) 643 @@ -261,11 +263,12 @@ def irreducible_decomposition(self, monomial_ideal): This is a simple example of computing irreducible decomposition. :: - sage: (x, y, z) = QQ['x,y,z'].gens() # optional - frobby - sage: id = ideal(x ** 2, y ** 2, x * z, y * z) # optional - frobby - sage: decom = frobby.irreducible_decomposition(id) # optional - frobby - sage: true_decom = [ideal(x, y), ideal(x ** 2, y ** 2, z)] # optional - frobby - sage: set(decom) == set(true_decom) # use sets to ignore order # optional - frobby + sage: # optional - frobby + sage: (x, y, z) = QQ['x,y,z'].gens() + sage: id = ideal(x ** 2, y ** 2, x * z, y * z) + sage: decom = frobby.irreducible_decomposition(id) + sage: true_decom = [ideal(x, y), ideal(x ** 2, y ** 2, z)] + sage: set(decom) == set(true_decom) # use sets to ignore order True We now try the special case of the zero ideal in different rings. @@ -273,25 +276,27 @@ def irreducible_decomposition(self, monomial_ideal): We should also try PolynomialRing(QQ, names=[]), but it has a bug which makes that impossible (see :trac:`3028`). :: - sage: rings = [ZZ['x'], CC['x,y']] # optional - frobby - sage: allOK = True # optional - frobby - sage: for ring in rings: # optional - frobby + sage: # optional - frobby + sage: rings = [ZZ['x'], CC['x,y']] + sage: allOK = True + sage: for ring in rings: ....: id0 = ring.ideal(0) ....: decom0 = frobby.irreducible_decomposition(id0) ....: allOK = allOK and decom0 == [id0] - sage: allOK # optional - frobby + sage: allOK True Finally, we try the ideal that is all of the ring in different rings. :: - sage: rings = [ZZ['x'], CC['x,y']] # optional - frobby - sage: allOK = True # optional - frobby - sage: for ring in rings: # optional - frobby + sage: # optional - frobby + sage: rings = [ZZ['x'], CC['x,y']] + sage: allOK = True + sage: for ring in rings: ....: id1 = ring.ideal(1) ....: decom1 = frobby.irreducible_decomposition(id1) ....: allOK = allOK and decom1 == [id1] - sage: allOK # optional - frobby + sage: allOK True """ frobby_input = self._ideal_to_string(monomial_ideal) @@ -316,10 +321,11 @@ def _parse_ideals(self, string, ring): EXAMPLES:: - sage: ring = QQ['x,y,z'] # optional - frobby - sage: (x, y, z) = ring.gens() # optional - frobby - sage: string = '2 3\n1 2 3\n0 5 0\n2 3\n1 2 3\n4 5 6' # optional - frobby - sage: frobby._parse_ideals(string, ring) # optional - frobby + sage: # optional - frobby + sage: ring = QQ['x,y,z'] + sage: (x, y, z) = ring.gens() + sage: string = '2 3\n1 2 3\n0 5 0\n2 3\n1 2 3\n4 5 6' + sage: frobby._parse_ideals(string, ring) [Ideal (x*y^2*z^3, y^5) of Multivariate Polynomial Ring in x, y, z over Rational Field, Ideal (x*y^2*z^3, x^4*y^5*z^6) of Multivariate Polynomial Ring in x, y, z over Rational Field] @@ -365,10 +371,11 @@ def _parse_4ti2_matrix(self, string): The format is straight-forward, as this example shows. :: - sage: string = '2 3\n1 2 3\n 0 5 0' # optional - frobby - sage: parsed_matrix = frobby._parse_4ti2_matrix(string) # optional - frobby - sage: reference_matrix = [[1, 2, 3], [0, 5, 0]] # optional - frobby - sage: parsed_matrix == reference_matrix # optional - frobby + sage: # optional - frobby + sage: string = '2 3\n1 2 3\n 0 5 0' + sage: parsed_matrix = frobby._parse_4ti2_matrix(string) + sage: reference_matrix = [[1, 2, 3], [0, 5, 0]] + sage: parsed_matrix == reference_matrix True A number of syntax errors lead to exceptions. :: @@ -414,10 +421,11 @@ def _ideal_to_string(self, monomial_ideal): EXAMPLES:: - sage: ring = QQ['x,y,z'] # optional - frobby - sage: (x, y, z) = ring.gens() # optional - frobby - sage: id = ring.ideal(x ** 2, x * y * z) # optional - frobby - sage: frobby._ideal_to_string(id) == "2 3\n2 0 0\n1 1 1\n" # optional - frobby + sage: # optional - frobby + sage: ring = QQ['x,y,z'] + sage: (x, y, z) = ring.gens() + sage: id = ring.ideal(x ** 2, x * y * z) + sage: frobby._ideal_to_string(id) == "2 3\n2 0 0\n1 1 1\n" True """ # There is no exponent vector that represents zero as a generator, so @@ -447,10 +455,11 @@ def _monomial_to_string(self, monomial): EXAMPLES:: - sage: ring = QQ['x,y,z'] # optional - frobby - sage: (x, y, z) = ring.gens() # optional - frobby - sage: monomial = x * x * z # optional - frobby - sage: frobby._monomial_to_string(monomial) == '2 0 1\n' # optional - frobby + sage: # optional - frobby + sage: ring = QQ['x,y,z'] + sage: (x, y, z) = ring.gens() + sage: monomial = x * x * z + sage: frobby._monomial_to_string(monomial) == '2 0 1\n' True """ exponents = monomial.exponents() diff --git a/src/sage/interfaces/gfan.py b/src/sage/interfaces/gfan.py index ffb75c39b35..01429c5cde6 100644 --- a/src/sage/interfaces/gfan.py +++ b/src/sage/interfaces/gfan.py @@ -63,7 +63,7 @@ def __call__(self, input, cmd='', verbose=False, format=None): EXAMPLES:: - sage: print(gfan('Q[x,y]{x^2-y-1,y^2-xy-2/3}', cmd='bases')) # optional - gfan + sage: print(gfan('Q[x,y]{x^2-y-1,y^2-xy-2/3}', cmd='bases')) # needs gfan Q[x,y] {{ y^4+4/9-7/3*y^2-y^3, @@ -85,7 +85,7 @@ def __call__(self, input, cmd='', verbose=False, format=None): TESTS:: - sage: _ = gfan(I='Q[x,y]{x^2-y-1,y^2-xy-2/3}', cmd='bases') # optional - gfan + sage: _ = gfan(I='Q[x,y]{x^2-y-1,y^2-xy-2/3}', cmd='bases') # needs gfan doctest:...: DeprecationWarning: use the option 'input' instead of 'I' See https://github.com/sagemath/sage/issues/33468 for details. diff --git a/src/sage/interfaces/gp.py b/src/sage/interfaces/gp.py index e5c77833cca..4cff85207e2 100644 --- a/src/sage/interfaces/gp.py +++ b/src/sage/interfaces/gp.py @@ -1,3 +1,5 @@ +# sage_setup: distribution = sagemath-pari +# sage.doctest: needs sage.libs.pari r""" Interface to the GP calculator of PARI/GP @@ -787,6 +789,7 @@ def new_with_bits_prec(self, s, precision=0): EXAMPLES:: + sage: # needs sage.symbolic sage: pi_def = gp(pi); pi_def 3.141592653589793238462643383 # 32-bit 3.1415926535897932384626433832795028842 # 64-bit @@ -877,13 +880,14 @@ def _sage_(self): EXAMPLES:: - sage: gp(SR(I)).sage() + sage: gp(SR(I)).sage() # needs sage.symbolic i - sage: gp(SR(I)).sage().parent() + sage: gp(SR(I)).sage().parent() # needs sage.symbolic Number Field in i with defining polynomial x^2 + 1 with i = 1*I :: + sage: # needs sage.modules sage: M = Matrix(ZZ,2,2,[1,2,3,4]); M [1 2] [3 4] @@ -955,6 +959,7 @@ def _complex_mpfr_field_(self, CC): EXAMPLES:: + sage: # needs sage.symbolic sage: z = gp(SR(1+15*I)); z 1 + 15*I sage: z._complex_mpfr_field_(CC) @@ -977,7 +982,7 @@ def _complex_double_(self, CDF): EXAMPLES:: - sage: CDF(gp(pi+I*e)) + sage: CDF(gp(pi+I*e)) # needs sage.symbolic 3.141592653589793 + 2.718281828459045*I """ # Retrieving values from another computer algebra system is diff --git a/src/sage/interfaces/interface.py b/src/sage/interfaces/interface.py index 78f94269ff4..8e89aa65c1e 100644 --- a/src/sage/interfaces/interface.py +++ b/src/sage/interfaces/interface.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.libs.gap sage.libs.pari sage.libs.singular sage.symbolic r""" Common Interface Functionality @@ -348,14 +349,14 @@ def _coerce_impl(self, x, use_special=True): if isinstance(x, bool): return self(self._true_symbol() if x else self._false_symbol()) elif isinstance(x, int): - import sage.rings.all - return self(sage.rings.all.Integer(x)) + from sage.rings.integer import Integer + return self(Integer(x)) elif isinstance(x, float): - import sage.rings.all - return self(sage.rings.all.RDF(x)) + from sage.rings.real_double import RDF + return self(RDF(x)) elif isinstance(x, complex): - import sage.rings.all - return self(sage.rings.all.CDF(x)) + from sage.rings.complex_double import CDF + return self(CDF(x)) if use_special: try: return self._coerce_from_special_method(x) @@ -881,11 +882,12 @@ def _reduce(self): by the doctests because the original identifier was reused. This test makes sure that does not happen again:: - sage: a = r("'abc'") # optional - rpy2 - sage: b = dumps(a) # optional - rpy2 - sage: r.set(a.name(), 0) # make sure that identifier reuse # optional - rpy2 + sage: # optional - rpy2 + sage: a = r("'abc'") + sage: b = dumps(a) + sage: r.set(a.name(), 0) # make sure that identifier reuse ....: # does not accidentally lead to success - sage: loads(b) # optional - rpy2 + sage: loads(b) [1] "abc" """ @@ -1373,8 +1375,8 @@ def _integer_(self, ZZ=None): sage: QQ(m) 1 """ - import sage.rings.all - return sage.rings.all.Integer(repr(self)) + from sage.rings.integer import Integer + return Integer(repr(self)) def _rational_(self): """ @@ -1388,8 +1390,8 @@ def _rational_(self): sage: QQ(m) 1/2 """ - import sage.rings.all - return sage.rings.all.Rational(repr(self)) + from sage.rings.rational import Rational + return Rational(repr(self)) def name(self, new_name=None): """ @@ -1401,13 +1403,14 @@ def name(self, new_name=None): EXAMPLES:: - sage: x = r([1,2,3]); x # optional - rpy2 + sage: # optional - rpy2 + sage: x = r([1,2,3]); x [1] 1 2 3 - sage: x.name() # optional - rpy2 + sage: x.name() 'sage...' - sage: x = r([1,2,3]).name('x'); x # optional - rpy2 + sage: x = r([1,2,3]).name('x'); x [1] 1 2 3 - sage: x.name() # optional - rpy2 + sage: x.name() 'x' :: diff --git a/src/sage/interfaces/jmoldata.py b/src/sage/interfaces/jmoldata.py index a68e53e2d85..3e83043d747 100644 --- a/src/sage/interfaces/jmoldata.py +++ b/src/sage/interfaces/jmoldata.py @@ -134,10 +134,10 @@ def export_image(self, sage: from sage.interfaces.jmoldata import JmolData sage: JData = JmolData() - sage: D = dodecahedron() + sage: D = dodecahedron() # needs sage.plot sage: from tempfile import NamedTemporaryFile sage: archive = NamedTemporaryFile(suffix=".zip") - sage: D.export_jmol(archive.name) + sage: D.export_jmol(archive.name) # needs sage.plot sage: archive_native = archive.name sage: import sys sage: if sys.platform == 'cygwin': @@ -145,7 +145,7 @@ def export_image(self, ....: archive_native = cygwin.cygpath(archive_native, 'w') sage: script = f'set defaultdirectory "f{archive_native}"\n' sage: script += 'script SCRIPT\n' - sage: with NamedTemporaryFile(suffix=".png") as testfile: # optional -- java + sage: with NamedTemporaryFile(suffix=".png") as testfile: # optional - java, needs sage.plot ....: JData.export_image(targetfile=testfile.name, ....: datafile=script, ....: image_type="PNG") diff --git a/src/sage/interfaces/kash.py b/src/sage/interfaces/kash.py index ebfd9178c70..aecddae452b 100644 --- a/src/sage/interfaces/kash.py +++ b/src/sage/interfaces/kash.py @@ -89,11 +89,12 @@ :: - sage: a = kash(12345) # optional -- kash - sage: b = kash(25) # optional -- kash - sage: a/b # optional -- kash + sage: # optional - kash + sage: a = kash(12345) + sage: b = kash(25) + sage: a/b 2469/5 - sage: a**b # optional -- kash + sage: a**b 1937659030411463935651167391656422626577614411586152317674869233464019922771432158872187137603759765625 Variable assignment @@ -130,12 +131,13 @@ :: - sage: F = kash.Factorization(4352) # optional -- kash - sage: F[1] # optional -- kash + sage: # optional - kash + sage: F = kash.Factorization(4352) + sage: F[1] <2, 8> - sage: F[2] # optional -- kash + sage: F[2] <17, 1> - sage: F # optional -- kash + sage: F [ <2, 8>, <17, 1> ], extended by: ext1 := 1, ext2 := Unassign @@ -147,17 +149,18 @@ :: - sage: kash.GCD(15,25) # optional -- kash + sage: # optional - kash + sage: kash.GCD(15,25) 5 - sage: kash.LCM(15,25) # optional -- kash + sage: kash.LCM(15,25) 75 - sage: kash.Div(25,15) # optional -- kash + sage: kash.Div(25,15) 1 - sage: kash(17) % kash(5) # optional -- kash + sage: kash(17) % kash(5) 2 - sage: kash.IsPrime(10007) # optional -- kash + sage: kash.IsPrime(10007) TRUE - sage: kash.IsPrime(2005) # optional -- kash + sage: kash.IsPrime(2005) FALSE sage: kash.NextPrime(10007) # optional -- kash @@ -168,18 +171,19 @@ :: - sage: kash.Precision() # optional -- kash + sage: # optional - kash + sage: kash.Precision() 30 - sage: kash('R') # optional -- kash + sage: kash('R') Real field of precision 30 - sage: kash.Precision(40) # optional -- kash + sage: kash.Precision(40) 40 - sage: kash('R') # optional -- kash + sage: kash('R') Real field of precision 40 - sage: z = kash('1 + 2*I') # optional -- kash - sage: z # optional -- kash + sage: z = kash('1 + 2*I') + sage: z 1.000000000000000000000000000000000000000 + 2.000000000000000000000000000000000000000*I - sage: z*z # optional -- kash + sage: z*z -3.000000000000000000000000000000000000000 + 4.000000000000000000000000000000000000000*I sage: kash.Cos('1.24') # optional -- kash @@ -222,40 +226,42 @@ :: - sage: v = kash([1,2,3]); v # optional -- kash + sage: # optional - kash + sage: v = kash([1,2,3]); v [ 1, 2, 3 ] - sage: v[1] # optional -- kash + sage: v[1] 1 - sage: v[3] # optional -- kash + sage: v[3] 3 - sage: v.Append([5]) # optional -- kash + sage: v.Append([5]) [ 1, 2, 3, 5 ] - sage: v # optional -- kash + sage: v [ 1, 2, 3 ] - sage: v.Append_([5, 6]) # optional -- kash + sage: v.Append_([5, 6]) SUCCESS - sage: v # optional -- kash + sage: v [ 1, 2, 3, 5, 6 ] - sage: v.Add(5) # optional -- kash + sage: v.Add(5) [ 1, 2, 3, 5, 6, 5 ] - sage: v # optional -- kash + sage: v [ 1, 2, 3, 5, 6 ] - sage: v.Add_(5) # optional -- kash + sage: v.Add_(5) SUCCESS - sage: v # optional -- kash + sage: v [ 1, 2, 3, 5, 6, 5 ] The ``Apply`` command applies a function to each element of a list:: - sage: L = kash([1,2,3,4]) # optional -- kash - sage: L.Apply('i -> 3*i') # optional -- kash + sage: # optional - kash + sage: L = kash([1,2,3,4]) + sage: L.Apply('i -> 3*i') [ 3, 6, 9, 12 ] - sage: L # optional -- kash + sage: L [ 1, 2, 3, 4 ] - sage: L.Apply('IsEven') # optional -- kash + sage: L.Apply('IsEven') [ FALSE, TRUE, FALSE, TRUE ] - sage: L # optional -- kash + sage: L [ 1, 2, 3, 4 ] Ranges @@ -265,11 +271,12 @@ :: - sage: L = kash('[1..10]') # optional -- kash - sage: L # optional -- kash + sage: # optional - kash + sage: L = kash('[1..10]') + sage: L [ 1 .. 10 ] - sage: L = kash('[2,4..100]') # optional -- kash - sage: L # optional -- kash + sage: L = kash('[2,4..100]') + sage: L [ 2, 4 .. 100 ] Sequences @@ -283,15 +290,16 @@ :: - sage: f = kash('X^3 + X + 1') # optional -- kash - sage: f + f # optional -- kash + sage: # optional - kash + sage: f = kash('X^3 + X + 1') + sage: f + f 2*X^3 + 2*X + 2 - sage: f * f # optional -- kash + sage: f * f X^6 + 2*X^4 + 2*X^3 + X^2 + 2*X + 1 - sage: f.Evaluate(10) # optional -- kash + sage: f.Evaluate(10) 1011 - sage: Qx = kash.PolynomialAlgebra('Q') # optional -- kash - sage: Qx.gen(1)**5 + kash('7/3') # sage1 below somewhat random; optional -- kash + sage: Qx = kash.PolynomialAlgebra('Q') + sage: Qx.gen(1)**5 + kash('7/3') sage1.1^5 + 7/3 Number Fields @@ -308,12 +316,13 @@ :: - sage: f = kash('X^5 + 4*X^4 - 56*X^2 -16*X + 192') # optional -- kash - sage: O = f.EquationOrder() # optional -- kash - sage: a = O.gen(2) # optional -- kash - sage: a # optional -- kash + sage: # optional - kash + sage: f = kash('X^5 + 4*X^4 - 56*X^2 -16*X + 192') + sage: O = f.EquationOrder() + sage: a = O.gen(2) + sage: a [0, 1, 0, 0, 0] - sage: O.Basis() # output somewhat random; optional -- kash + sage: O.Basis() [ _NG.1, _NG.2, @@ -321,9 +330,9 @@ _NG.4, _NG.5 ] - sage: O.Discriminant() # optional -- kash + sage: O.Discriminant() 1364202618880 - sage: O.MaximalOrder() # name sage2 below somewhat random; optional -- kash + sage: O.MaximalOrder() Maximal Order of sage2 sage: O = kash.MaximalOrder('X^3 - 77') # optional -- kash @@ -353,10 +362,11 @@ Computation of class groups and unit groups:: - sage: f = kash('X^5 + 4*X^4 - 56*X^2 -16*X + 192') # optional -- kash - sage: O = kash.EquationOrder(f) # optional -- kash - sage: OK = O.MaximalOrder() # optional -- kash - sage: OK.ClassGroup() # name sage32 below random; optional -- kash + sage: # optional - kash + sage: f = kash('X^5 + 4*X^4 - 56*X^2 -16*X + 192') + sage: O = kash.EquationOrder(f) + sage: OK = O.MaximalOrder() + sage: OK.ClassGroup() Abelian Group isomorphic to Z/6 Defined on 1 generator Relations: @@ -381,12 +391,13 @@ :: - sage: k = kash.FiniteField(25) # optional -- kash - sage: kT = k.RationalFunctionField() # optional -- kash - sage: kTy = kT.PolynomialAlgebra() # optional -- kash - sage: T = kT.gen(1) # optional -- kash - sage: y = kTy.gen(1) # optional -- kash - sage: f = y**3 + T**4 + 1 # optional -- kash + sage: # optional - kash + sage: k = kash.FiniteField(25) + sage: kT = k.RationalFunctionField() + sage: kTy = kT.PolynomialAlgebra() + sage: T = kT.gen(1) + sage: y = kTy.gen(1) + sage: f = y**3 + T**4 + 1 Long Input ---------- diff --git a/src/sage/interfaces/kenzo.py b/src/sage/interfaces/kenzo.py index 3607dd7879e..e403b04dab7 100644 --- a/src/sage/interfaces/kenzo.py +++ b/src/sage/interfaces/kenzo.py @@ -193,12 +193,13 @@ def EilenbergMacLaneSpace(G, n): EXAMPLES:: - sage: from sage.interfaces.kenzo import EilenbergMacLaneSpace # optional - kenzo - sage: e3 = EilenbergMacLaneSpace(ZZ, 3) # optional - kenzo - sage: [e3.homology(i) for i in range(8)] # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import EilenbergMacLaneSpace + sage: e3 = EilenbergMacLaneSpace(ZZ, 3) + sage: [e3.homology(i) for i in range(8)] [Z, 0, 0, Z, 0, C2, 0, C3] - sage: f3 = EilenbergMacLaneSpace(AdditiveAbelianGroup([2]), 3) # optional - kenzo - sage: [f3.homology(i) for i in range(8)] # optional - kenzo + sage: f3 = EilenbergMacLaneSpace(AdditiveAbelianGroup([2]), 3) + sage: [f3.homology(i) for i in range(8)] [Z, 0, 0, C2, 0, C2, C2, C2] """ if G == ZZ: @@ -230,15 +231,16 @@ def __init__(self, kenzo_object): TESTS:: - sage: from sage.interfaces.kenzo import KenzoObject # optional -kenzo - sage: from sage.interfaces.kenzo import __sphere__ # optional -kenzo - sage: ks = __sphere__(2) # optional -kenzo - sage: ks # optional -kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import KenzoObject + sage: from sage.interfaces.kenzo import __sphere__ + sage: ks = __sphere__(2) + sage: ks - sage: s2 = KenzoObject(ks) # optional -kenzo - sage: s2 # optional -kenzo + sage: s2 = KenzoObject(ks) + sage: s2 [K1 Simplicial-Set] - sage: TestSuite(s2).run(skip='_test_pickling') # optional -kenzo + sage: TestSuite(s2).run(skip='_test_pickling') """ self._kenzo = kenzo_object @@ -280,12 +282,13 @@ def group(self, p, i, j): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: S2 = Sphere(2) # optional - kenzo - sage: EMS = S2.em_spectral_sequence() # optional - kenzo - sage: EMS.group(0, -1, 2) # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: S2 = Sphere(2) + sage: EMS = S2.em_spectral_sequence() + sage: EMS.group(0, -1, 2) Additive abelian group isomorphic to Z - sage: EMS.group(0, -1, 3) # optional - kenzo + sage: EMS.group(0, -1, 3) Trivial group """ invs = __spectral_sequence_group__(self._kenzo, p, i, j).python() @@ -308,16 +311,17 @@ def matrix(self, p, i, j): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: S3 = Sphere(3) # optional - kenzo - sage: L = S3.loop_space() # optional - kenzo - sage: EMS = L.em_spectral_sequence() # optional - kenzo - sage: EMS.table(1, -5, -2, 5, 8) # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: S3 = Sphere(3) + sage: L = S3.loop_space() + sage: EMS = L.em_spectral_sequence() + sage: EMS.table(1, -5, -2, 5, 8) 0 Z Z + Z + Z Z + Z + Z 0 0 0 0 0 0 Z Z + Z 0 0 0 0 - sage: EMS.matrix(1, -2 ,8) # optional - kenzo + sage: EMS.matrix(1, -2 ,8) [ 3 -2 0] [ 3 0 -3] [ 0 2 -3] @@ -344,18 +348,19 @@ def differential(self, p, i, j): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: S3 = Sphere(3) # optional - kenzo - sage: L = S3.loop_space() # optional - kenzo - sage: EMS = L.em_spectral_sequence() # optional - kenzo - sage: EMS.table(1,-5,-2,5,8) # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: S3 = Sphere(3) + sage: L = S3.loop_space() + sage: EMS = L.em_spectral_sequence() + sage: EMS.table(1,-5,-2,5,8) 0 Z Z + Z + Z Z + Z + Z 0 0 0 0 0 0 Z Z + Z 0 0 0 0 - sage: EMS.matrix(1, -3, 8) # optional - kenzo + sage: EMS.matrix(1, -3, 8) [ 2 -2 2] - sage: EMS.differential(1, -3, 8) # optional - kenzo + sage: EMS.differential(1, -3, 8) Morphism from module over Integer Ring with invariants (0, 0, 0) to module with invariants (0,) that sends the generators to [(2), (-2), (2)] """ domain = self.group(p, i, j) @@ -458,13 +463,14 @@ def tensor_product(self, other): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: s2 = Sphere(2) # optional - kenzo - sage: s3 = Sphere(3) # optional - kenzo - sage: p = s2.tensor_product(s3) # optional - kenzo - sage: type(p) # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: s2 = Sphere(2) + sage: s3 = Sphere(3) + sage: p = s2.tensor_product(s3) + sage: type(p) - sage: [p.homology(i) for i in range(8)] # optional - kenzo + sage: [p.homology(i) for i in range(8)] [Z, 0, Z, Z, 0, Z, 0, 0] """ return KenzoChainComplex(__tnsr_prdc__(self._kenzo, other._kenzo)) @@ -514,11 +520,12 @@ def identity_morphism(self): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: s2 = Sphere(2) # optional - kenzo - sage: tp = s2.tensor_product(s2) # optional - kenzo - sage: idnt = tp.identity_morphism() # optional - kenzo - sage: type(idnt) # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: s2 = Sphere(2) + sage: tp = s2.tensor_product(s2) + sage: idnt = tp.identity_morphism() + sage: type(idnt) """ return KenzoChainComplexMorphism(__idnt_mrph__(self._kenzo)) @@ -542,20 +549,21 @@ def null_morphism(self, target=None, degree=None): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: s2 = Sphere(2) # optional - kenzo - sage: s3 = Sphere(3) # optional - kenzo - sage: tp22 = s2.tensor_product(s2) # optional - kenzo - sage: tp22 # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: s2 = Sphere(2) + sage: s3 = Sphere(3) + sage: tp22 = s2.tensor_product(s2) + sage: tp22 [K... Chain-Complex] - sage: tp23 = s2.tensor_product(s3) # optional - kenzo - sage: tp23 # optional - kenzo + sage: tp23 = s2.tensor_product(s3) + sage: tp23 [K... Chain-Complex] - sage: null1 = tp22.null_morphism() # optional - kenzo - sage: null1 # optional - kenzo + sage: null1 = tp22.null_morphism() + sage: null1 [K... Morphism (degree 0): K... -> K...] - sage: null2 = tp22.null_morphism(target = tp23, degree = -3) # optional - kenzo - sage: null2 # optional - kenzo + sage: null2 = tp22.null_morphism(target = tp23, degree = -3) + sage: null2 [K... Morphism (degree -3): K... -> K...] """ if target is None: @@ -634,13 +642,14 @@ def orgn(self): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: s2 = Sphere(2) # optional - kenzo - sage: l2 = s2.loop_space() # optional - kenzo - sage: l2.orgn() # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: s2 = Sphere(2) + sage: l2 = s2.loop_space() + sage: l2.orgn() '(LOOP-SPACE [K... Simplicial-Set])' - sage: A = l2.cartesian_product(s2) # optional - kenzo - sage: A.orgn() # optional - kenzo + sage: A = l2.cartesian_product(s2) + sage: A.orgn() '(CRTS-PRDC [K... Simplicial-Group] [K... Simplicial-Set])' """ return str(__orgn_aux1__(self._kenzo)) @@ -669,13 +678,14 @@ def loop_space(self, n=1): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: s2 = Sphere(2) # optional - kenzo - sage: l2 = s2.loop_space() # optional - kenzo - sage: type(l2) # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: s2 = Sphere(2) + sage: l2 = s2.loop_space() + sage: type(l2) - sage: l2 = s2.loop_space() # optional - kenzo - sage: [l2.homology(i) for i in range(8)] # optional - kenzo + sage: l2 = s2.loop_space() + sage: [l2.homology(i) for i in range(8)] [Z, Z, Z, Z, Z, Z, Z, Z] """ return KenzoSimplicialGroup(__loop_space__(self._kenzo, n)) @@ -694,13 +704,14 @@ def cartesian_product(self, other): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: s2 = Sphere(2) # optional - kenzo - sage: s3 = Sphere(3) # optional - kenzo - sage: p = s2.cartesian_product(s3) # optional - kenzo - sage: type(p) # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: s2 = Sphere(2) + sage: s3 = Sphere(3) + sage: p = s2.cartesian_product(s3) + sage: type(p) - sage: [p.homology(i) for i in range(6)] # optional - kenzo + sage: [p.homology(i) for i in range(6)] [Z, 0, Z, Z, 0, Z] """ prod_kenzo = __crts_prdc__(self._kenzo, other._kenzo) @@ -716,12 +727,13 @@ def suspension(self): EXAMPLES:: - sage: from sage.interfaces.kenzo import EilenbergMacLaneSpace # optional - kenzo - sage: e3 = EilenbergMacLaneSpace(ZZ, 3) # optional - kenzo - sage: s = e3.suspension() # optional - kenzo - sage: type(s) # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import EilenbergMacLaneSpace + sage: e3 = EilenbergMacLaneSpace(ZZ, 3) + sage: s = e3.suspension() + sage: type(s) - sage: [s.homology(i) for i in range(6)] # optional - kenzo + sage: [s.homology(i) for i in range(6)] [Z, 0, 0, 0, Z, 0] """ return KenzoSimplicialSet(__suspension__(self._kenzo)) @@ -799,11 +811,12 @@ def sw_spectral_sequence(self): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: S3 = Sphere(3) # optional - kenzo - sage: E = S3.sw_spectral_sequence() # optional - kenzo - sage: T = E.table(0, 0, 4, 0, 4) # optional - kenzo - sage: T # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: S3 = Sphere(3) + sage: E = S3.sw_spectral_sequence() + sage: T = E.table(0, 0, 4, 0, 4) + sage: T Z 0 0 Z 0 0 0 0 0 0 Z 0 0 Z 0 @@ -827,12 +840,13 @@ def serre_spectral_sequence(self): EXAMPLES:: + sage: # optional - kenzo sage: from sage.interfaces.kenzo import Sphere - sage: S2 = Sphere(2) # optional - kenzo - sage: S3 = Sphere(3) # optional - kenzo - sage: P = S2.cartesian_product(S3) # optional - kenzo - sage: E = P.serre_spectral_sequence() # optional - kenzo - sage: E.table(0, 0, 2, 0, 3) # optional - kenzo + sage: S2 = Sphere(2) + sage: S3 = Sphere(3) + sage: P = S2.cartesian_product(S3) + sage: E = P.serre_spectral_sequence() + sage: E.table(0, 0, 2, 0, 3) Z 0 Z 0 0 0 0 0 0 @@ -862,13 +876,14 @@ def wedge(self, other): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: s2 = Sphere(2) # optional - kenzo - sage: s3 = Sphere(3) # optional - kenzo - sage: w = s2.wedge(s3) # optional - kenzo - sage: type(w) # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: s2 = Sphere(2) + sage: s3 = Sphere(3) + sage: w = s2.wedge(s3) + sage: type(w) - sage: [w.homology(i) for i in range(6)] # optional - kenzo + sage: [w.homology(i) for i in range(6)] [Z, 0, Z, Z, 0, 0] """ wedge_kenzo = __wedge__(self._kenzo, other._kenzo) @@ -888,13 +903,14 @@ def join(self, other): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: s2 = Sphere(2) # optional - kenzo - sage: s3 = Sphere(3) # optional - kenzo - sage: j = s2.join(s3) # optional - kenzo - sage: type(j) # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: s2 = Sphere(2) + sage: s3 = Sphere(3) + sage: j = s2.join(s3) + sage: type(j) - sage: [j.homology(i) for i in range(6)] # optional - kenzo + sage: [j.homology(i) for i in range(6)] [Z, 0, 0, 0, 0, 0] """ join_kenzo = __join__(self._kenzo, other._kenzo) @@ -914,13 +930,14 @@ def smash_product(self, other): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: s2 = Sphere(2) # optional - kenzo - sage: s3 = Sphere(3) # optional - kenzo - sage: s = s2.smash_product(s3) # optional - kenzo - sage: type(s) # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: s2 = Sphere(2) + sage: s3 = Sphere(3) + sage: s = s2.smash_product(s3) + sage: type(s) - sage: [s.homology(i) for i in range(6)] # optional - kenzo + sage: [s.homology(i) for i in range(6)] [Z, 0, 0, 0, 0, Z] """ smash_kenzo = __smash_product__(self._kenzo, other._kenzo) @@ -942,13 +959,14 @@ def classifying_space(self): EXAMPLES:: - sage: from sage.interfaces.kenzo import MooreSpace # optional - kenzo - sage: m2 = MooreSpace(2,4) # optional - kenzo - sage: l2 = m2.loop_space() # optional - kenzo - sage: c = l2.classifying_space() # optional - kenzo - sage: type(c) # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import MooreSpace + sage: m2 = MooreSpace(2,4) + sage: l2 = m2.loop_space() + sage: c = l2.classifying_space() + sage: type(c) - sage: [c.homology(i) for i in range(8)] # optional - kenzo + sage: [c.homology(i) for i in range(8)] [Z, 0, 0, 0, C2, 0, 0, 0] """ return KenzoSimplicialGroup(__classifying_space__(self._kenzo)) @@ -1118,14 +1136,15 @@ def SChainComplex(kchaincomplex, start=0, end=15): :: - sage: from sage.interfaces.kenzo import SChainComplex, Sphere # optional - kenzo - sage: S4 = Sphere(4) # optional - kenzo - sage: C = SChainComplex(S4) # optional - kenzo - sage: C # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import SChainComplex, Sphere + sage: S4 = Sphere(4) + sage: C = SChainComplex(S4) + sage: C Chain complex with at most 3 nonzero terms over Integer Ring - sage: C._ascii_art_() # optional - kenzo + sage: C._ascii_art_() 0 <-- C_4 <-- 0 ... 0 <-- C_0 <-- 0 - sage: [C.homology(i) for i in range(6)] # optional - kenzo + sage: [C.homology(i) for i in range(6)] [Z, 0, 0, 0, Z, 0] """ matrices = {} @@ -1156,17 +1175,18 @@ def SAbstractSimplex(simplex, dim): EXAMPLES:: + sage: # optional - kenzo sage: from sage.libs.ecl import EclObject, ecl_eval - sage: from sage.interfaces.kenzo import ( # optional - kenzo + sage: from sage.interfaces.kenzo import ( ....: KenzoObject, SAbstractSimplex) - sage: KAbSm = KenzoObject(ecl_eval("(ABSM 15 'K)")) # optional - kenzo - sage: SAbSm1 = SAbstractSimplex(KAbSm, 2) # optional - kenzo - sage: SAbSm2 = SAbstractSimplex(KAbSm, 7) # optional - kenzo - sage: SAbSm1.degeneracies() # optional - kenzo + sage: KAbSm = KenzoObject(ecl_eval("(ABSM 15 'K)")) + sage: SAbSm1 = SAbstractSimplex(KAbSm, 2) + sage: SAbSm2 = SAbstractSimplex(KAbSm, 7) + sage: SAbSm1.degeneracies() [3, 2, 1, 0] - sage: SAbSm1.dimension() # optional - kenzo + sage: SAbSm1.dimension() 6 - sage: SAbSm2.dimension() # optional - kenzo + sage: SAbSm2.dimension() 11 """ degeneracies = __dgop_int_ext__(__dgop__(simplex._kenzo)).python() @@ -1192,15 +1212,16 @@ def KAbstractSimplex(simplex): EXAMPLES:: + sage: # optional - kenzo sage: from sage.topology.simplicial_set import AbstractSimplex - sage: from sage.interfaces.kenzo import ( # optional - kenzo + sage: from sage.interfaces.kenzo import ( ....: KAbstractSimplex, SAbstractSimplex) - sage: SAbSm = AbstractSimplex(1, (2,0,3,2,1), name = 'SAbSm') # optional - kenzo - sage: KAbSm = KAbstractSimplex(SAbSm) # optional - kenzo - sage: SAbSm2 = SAbstractSimplex(KAbSm, 1) # optional - kenzo - sage: SAbSm.degeneracies() == SAbSm2.degeneracies() # optional - kenzo + sage: SAbSm = AbstractSimplex(1, (2,0,3,2,1), name = 'SAbSm') + sage: KAbSm = KAbstractSimplex(SAbSm) + sage: SAbSm2 = SAbstractSimplex(KAbSm, 1) + sage: SAbSm.degeneracies() == SAbSm2.degeneracies() True - sage: SAbSm.dimension() == SAbSm2.dimension() # optional - kenzo + sage: SAbSm.dimension() == SAbSm2.dimension() True """ return KenzoObject(__kabstractsimplex_aux1__(simplex.degeneracies(), @@ -1289,30 +1310,31 @@ def SFiniteSimplicialSet(ksimpset, limit): EXAMPLES:: + sage: # optional - kenzo sage: from sage.topology.simplicial_set import SimplicialSet - sage: from sage.interfaces.kenzo import ( # optional - kenzo + sage: from sage.interfaces.kenzo import ( ....: AbstractSimplex, KFiniteSimplicialSet, ....: SFiniteSimplicialSet, Sphere) - sage: s0 = AbstractSimplex(0, name='s0') # optional - kenzo - sage: s1 = AbstractSimplex(0, name='s1') # optional - kenzo - sage: s2 = AbstractSimplex(0, name='s2') # optional - kenzo - sage: s01 = AbstractSimplex(1, name='s01') # optional - kenzo - sage: s02 = AbstractSimplex(1, name='s02') # optional - kenzo - sage: s12 = AbstractSimplex(1, name='s12') # optional - kenzo - sage: s012 = AbstractSimplex(2, name='s012') # optional - kenzo - sage: Triangle = SimplicialSet({s01: (s1, s0), # optional - kenzo + sage: s0 = AbstractSimplex(0, name='s0') + sage: s1 = AbstractSimplex(0, name='s1') + sage: s2 = AbstractSimplex(0, name='s2') + sage: s01 = AbstractSimplex(1, name='s01') + sage: s02 = AbstractSimplex(1, name='s02') + sage: s12 = AbstractSimplex(1, name='s12') + sage: s012 = AbstractSimplex(2, name='s012') + sage: Triangle = SimplicialSet({s01: (s1, s0), ....: s02: (s2, s0), ....: s12: (s2, s1)}, ....: base_point = s0) - sage: KTriangle = KFiniteSimplicialSet(Triangle) # optional - kenzo - sage: STriangle = SFiniteSimplicialSet(KTriangle, 1) # optional - kenzo - sage: STriangle.homology() # optional - kenzo + sage: KTriangle = KFiniteSimplicialSet(Triangle) + sage: STriangle = SFiniteSimplicialSet(KTriangle, 1) + sage: STriangle.homology() {0: 0, 1: Z} - sage: S1 = simplicial_sets.Sphere(1) # optional - kenzo - sage: S3 = simplicial_sets.Sphere(3) # optional - kenzo - sage: KS1vS3 = KFiniteSimplicialSet(S1.wedge(S3)) # optional - kenzo - sage: SS1vS3 = SFiniteSimplicialSet(KS1vS3, 3) # optional - kenzo - sage: SS1vS3.homology() # optional - kenzo + sage: S1 = simplicial_sets.Sphere(1) + sage: S3 = simplicial_sets.Sphere(3) + sage: KS1vS3 = KFiniteSimplicialSet(S1.wedge(S3)) + sage: SS1vS3 = SFiniteSimplicialSet(KS1vS3, 3) + sage: SS1vS3.homology() {0: 0, 1: Z, 2: 0, 3: Z} """ list_orgn = __orgn_aux1__(ksimpset._kenzo).python() @@ -1587,18 +1609,19 @@ def composite(self, object=None): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere # optional - kenzo - sage: s2 = Sphere(2) # optional - kenzo - sage: s3 = Sphere(3) # optional - kenzo - sage: tp22 = s2.tensor_product(s2) # optional - kenzo - sage: tp23 = s2.tensor_product(s3) # optional - kenzo - sage: idnt = tp22.identity_morphism() # optional - kenzo - sage: idnt # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere + sage: s2 = Sphere(2) + sage: s3 = Sphere(3) + sage: tp22 = s2.tensor_product(s2) + sage: tp23 = s2.tensor_product(s3) + sage: idnt = tp22.identity_morphism() + sage: idnt [K... Morphism (degree 0): K... -> K...] - sage: null = tp23.null_morphism(target = tp22, degree = 4) # optional - kenzo - sage: null # optional - kenzo + sage: null = tp23.null_morphism(target = tp22, degree = 4) + sage: null [K... Morphism (degree 4): K... -> K...] - sage: idnt.composite((tp22, null)) # optional - kenzo + sage: idnt.composite((tp22, null)) [K... Morphism (degree 3): K... -> K...] """ if object is None: @@ -1765,25 +1788,26 @@ def change_source_target_complex(self, source=None, target=None): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere, KenzoChainComplex # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere, KenzoChainComplex sage: from sage.libs.ecl import ecl_eval - sage: ZCC = KenzoChainComplex(ecl_eval("(z-chcm)")) # optional - kenzo - sage: ZCC # optional - kenzo + sage: ZCC = KenzoChainComplex(ecl_eval("(z-chcm)")) + sage: ZCC [K... Chain-Complex] - sage: s2 = Sphere(2) # optional - kenzo - sage: s3 = Sphere(3) # optional - kenzo - sage: tp = s2.tensor_product(s3) # optional - kenzo - sage: tp # optional - kenzo + sage: s2 = Sphere(2) + sage: s3 = Sphere(3) + sage: tp = s2.tensor_product(s3) + sage: tp [K... Filtered-Chain-Complex] - sage: null = ZCC.null_morphism(tp) # optional - kenzo - sage: null # optional - kenzo + sage: null = ZCC.null_morphism(tp) + sage: null [K... Morphism (degree 0): K... -> K...] - sage: null.source_complex() # optional - kenzo + sage: null.source_complex() [K... Chain-Complex] - sage: null2 = null.change_source_target_complex(source = tp) # optional - kenzo - sage: null2 # optional - kenzo + sage: null2 = null.change_source_target_complex(source = tp) + sage: null2 [K... Morphism (degree 0): K... -> K...] - sage: null2.source_complex() # optional - kenzo + sage: null2.source_complex() [K... Filtered-Chain-Complex] """ source = source or self.source_complex() @@ -1810,24 +1834,25 @@ def destructive_change_source_target_complex(self, source=None, target=None): EXAMPLES:: - sage: from sage.interfaces.kenzo import Sphere, KenzoChainComplex # optional - kenzo + sage: # optional - kenzo + sage: from sage.interfaces.kenzo import Sphere, KenzoChainComplex sage: from sage.libs.ecl import ecl_eval - sage: ZCC = KenzoChainComplex(ecl_eval("(z-chcm)")) # optional - kenzo - sage: ZCC # optional - kenzo + sage: ZCC = KenzoChainComplex(ecl_eval("(z-chcm)")) + sage: ZCC [K... Chain-Complex] - sage: s2 = Sphere(2) # optional - kenzo - sage: s3 = Sphere(3) # optional - kenzo - sage: tp = s2.tensor_product(s3) # optional - kenzo - sage: tp # optional - kenzo + sage: s2 = Sphere(2) + sage: s3 = Sphere(3) + sage: tp = s2.tensor_product(s3) + sage: tp [K... Filtered-Chain-Complex] - sage: null = ZCC.null_morphism(tp) # optional - kenzo - sage: null # optional - kenzo + sage: null = ZCC.null_morphism(tp) + sage: null [K... Morphism (degree 0): K... -> K...] - sage: null.target_complex() # optional - kenzo + sage: null.target_complex() [K... Filtered-Chain-Complex] - sage: null.destructive_change_source_target_complex(target = ZCC) # optional - kenzo + sage: null.destructive_change_source_target_complex(target = ZCC) [K... Cohomology-Class on K... of degree 0] - sage: null.target_complex() # optional - kenzo + sage: null.target_complex() [K... Chain-Complex] """ source = source or self.source_complex() @@ -1864,19 +1889,20 @@ def build_morphism(source_complex, target_complex, degree, algorithm, strategy, EXAMPLES:: + sage: # optional - kenzo sage: from sage.interfaces.kenzo import (KenzoChainComplex, ....: build_morphism) sage: from sage.libs.ecl import ecl_eval - sage: ZCC = KenzoChainComplex(ecl_eval("(z-chcm)")) # optional - kenzo - sage: A = build_morphism( # optional - kenzo + sage: ZCC = KenzoChainComplex(ecl_eval("(z-chcm)")) + sage: A = build_morphism( ....: ZCC, ZCC, -1, ....: ecl_eval("#'(lambda (comb) (cmbn (1- (degr comb))))"), ....: "cmbn", ["zero morphism on ZCC"]) - sage: A.target_complex() # optional - kenzo + sage: A.target_complex() [K... Chain-Complex] - sage: A.degree() # optional - kenzo + sage: A.degree() -1 - sage: type(A) # optional - kenzo + sage: type(A) """ return KenzoChainComplexMorphism( diff --git a/src/sage/interfaces/lie.py b/src/sage/interfaces/lie.py index 84aee7d7259..2866dfbb828 100644 --- a/src/sage/interfaces/lie.py +++ b/src/sage/interfaces/lie.py @@ -53,36 +53,38 @@ You can perform basic arithmetic operations in LiE. :: - sage: lie.eval('19+68') # optional - lie + sage: # optional - lie + sage: lie.eval('19+68') '87' - sage: a = lie('1111111111*1111111111') # optional - lie - sage: a # optional - lie + sage: a = lie('1111111111*1111111111') + sage: a 1234567900987654321 - sage: a/1111111111 # optional - lie + sage: a/1111111111 1111111111 - sage: a = lie('345') # optional - lie - sage: a^2+3*a-5 # optional - lie + sage: a = lie('345') + sage: a^2+3*a-5 120055 - sage: _ / 7*a # optional - lie + sage: _ / 7*a 5916750 Vectors in LiE are created using square brackets. Notice that the indexing in LiE is 1-based, unlike Python/Sage which is 0-based. :: - sage: v = lie('[3,2,6873,-38]') # optional - lie - sage: v # optional - lie + sage: # optional - lie + sage: v = lie('[3,2,6873,-38]') + sage: v [3,2,6873,-38] - sage: v[3] # optional - lie + sage: v[3] 6873 - sage: v+v # optional - lie + sage: v+v [6,4,13746,-76] - sage: v*v # optional - lie + sage: v*v 47239586 - sage: v+234786 # optional - lie + sage: v+234786 [3,2,6873,-38,234786] - sage: v-3 # optional - lie + sage: v-3 [3,2,-38] - sage: v^v # optional - lie + sage: v^v [3,2,6873,-38,3,2,6873,-38] You can also work with matrices in LiE. :: @@ -101,19 +103,20 @@ ,[3, 7, 0, 9] ] - sage: m^3 # optional - lie + sage: # optional - lie + sage: m^3 [[ 220, 87, 81, 375] ,[-168,-1089, 13,1013] ,[1550, 357,-55,1593] ,[-854, -652, 98,-170] ] - sage: v*m # optional - lie + sage: v*m [-6960,62055,55061,-319] - sage: m*v # optional - lie + sage: m*v [20508,-27714,54999,-14089] - sage: v*m*v # optional - lie + sage: v*m*v 378549605 - sage: m+v # optional - lie + sage: m+v [[ 1, 0, 3, 3] ,[12, 4, -4, 7] ,[-1, 9, 8, 0] @@ -130,17 +133,18 @@ LiE handles multivariate (Laurent) polynomials. :: - sage: lie('X[1,2]') # optional - lie + sage: # optional - lie + sage: lie('X[1,2]') 1X[1,2] - sage: -3*_ # optional - lie + sage: -3*_ -3X[1,2] - sage: _ + lie('4X[-1,4]') # optional - lie + sage: _ + lie('4X[-1,4]') 4X[-1,4] - 3X[ 1,2] - sage: _^2 # optional - lie + sage: _^2 16X[-2,8] - 24X[ 0,6] + 9X[ 2,4] - sage: lie('(4X[-1,4]-3X[1,2])*(X[2,0]-X[0,-4])') # optional - lie + sage: lie('(4X[-1,4]-3X[1,2])*(X[2,0]-X[0,-4])') -4X[-1, 0] + 3X[ 1,-2] + 4X[ 1, 4] - 3X[ 3, 2] - sage: _ - _ # optional - lie + sage: _ - _ 0X[0,0] @@ -172,15 +176,16 @@ a function (say f), you can call it using lie.f ; however, user-defined functions do not show up when using tab-completion. :: - sage: lie.eval('f(int x) = 2*x') # optional - lie + sage: # optional - lie + sage: lie.eval('f(int x) = 2*x') '' - sage: lie.f(984) # optional - lie + sage: lie.f(984) 1968 - sage: lie.eval('f(int n) = a=3*n-7; if a < 0 then a = -a fi; 7^a+a^3-4*a-57') # optional - lie + sage: lie.eval('f(int n) = a=3*n-7; if a < 0 then a = -a fi; 7^a+a^3-4*a-57') '' - sage: lie.f(2) # optional - lie + sage: lie.f(2) -53 - sage: lie.f(5) # optional - lie + sage: lie.f(5) 5765224 @@ -250,7 +255,8 @@ which evaluates a polynomial at a point. Below is a (roughly) direct translation of that program into Python / Sage. :: - sage: def eval_pol(p, pt): # optional - lie + sage: # optional - lie + sage: def eval_pol(p, pt): ....: s = 0 ....: for i in range(1,p.length().sage()+1): ....: m = 1 @@ -258,12 +264,12 @@ ....: m *= pt[j]^p.expon(i)[j] ....: s += p.coef(i)*m ....: return s - sage: a = lie('X[1,2]') # optional - lie - sage: b1 = lie('[1,2]') # optional - lie - sage: b2 = lie('[2,3]') # optional - lie - sage: eval_pol(a, b1) # optional - lie + sage: a = lie('X[1,2]') + sage: b1 = lie('[1,2]') + sage: b2 = lie('[2,3]') + sage: eval_pol(a, b1) 4 - sage: eval_pol(a, b2) # optional - lie + sage: eval_pol(a, b2) 18 diff --git a/src/sage/interfaces/macaulay2.py b/src/sage/interfaces/macaulay2.py index 4ed5ab46542..9b11f02a85f 100644 --- a/src/sage/interfaces/macaulay2.py +++ b/src/sage/interfaces/macaulay2.py @@ -958,7 +958,7 @@ def _repr_(self): Sequence sage: str(macaulay2('1..25')) (1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25) - sage: macaulay2.options.after_print = False # optional - macaulay2 + sage: macaulay2.options.after_print = False """ from sage.typeset.ascii_art import empty_ascii_art P = self.parent() diff --git a/src/sage/interfaces/magma.py b/src/sage/interfaces/magma.py index 529bfbc349b..7d66375f25f 100644 --- a/src/sage/interfaces/magma.py +++ b/src/sage/interfaces/magma.py @@ -47,23 +47,25 @@ how many you get using the ``nvals`` named parameter to a function call:: - sage: n = magma(100) # optional - magma - sage: n.IsSquare(nvals = 1) # optional - magma + sage: # optional - magma + sage: n = magma(100) + sage: n.IsSquare(nvals = 1) true - sage: n.IsSquare(nvals = 2) # optional - magma + sage: n.IsSquare(nvals = 2) (true, 10) - sage: n = magma(-2006) # optional - magma - sage: n.Factorization() # optional - magma + sage: n = magma(-2006) + sage: n.Factorization() [ <2, 1>, <17, 1>, <59, 1> ] - sage: n.Factorization(nvals=2) # optional - magma + sage: n.Factorization(nvals=2) ([ <2, 1>, <17, 1>, <59, 1> ], -1) We verify that an obviously principal ideal is principal:: - sage: _ = magma.eval('R := PolynomialRing(RationalField())') # optional - magma - sage: O = magma.NumberField('x^2+23').MaximalOrder() # optional - magma - sage: I = magma('ideal<%s|%s.1>'%(O.name(),O.name())) # optional - magma - sage: I.IsPrincipal(nvals=2) # optional - magma + sage: # optional - magma + sage: _ = magma.eval('R := PolynomialRing(RationalField())') + sage: O = magma.NumberField('x^2+23').MaximalOrder() + sage: I = magma('ideal<%s|%s.1>'%(O.name(),O.name())) + sage: I.IsPrincipal(nvals=2) (true, [1, 0]) Long Input @@ -142,14 +144,15 @@ structure S is denoted by S(x). This also works for the Magma interface:: - sage: G = magma.DirichletGroup(20) # optional - magma - sage: G.AssignNames(['a', 'b']) # optional - magma - sage: (G.1).Modulus() # optional - magma + sage: # optional - magma + sage: G = magma.DirichletGroup(20) + sage: G.AssignNames(['a', 'b']) + sage: (G.1).Modulus() 20 - sage: e = magma.DirichletGroup(40)(G.1) # optional - magma - sage: print(e) # optional - magma + sage: e = magma.DirichletGroup(40)(G.1) + sage: print(e) Kronecker character -4 in modulus 40 - sage: print(e.Modulus()) # optional - magma + sage: print(e.Modulus()) 40 We coerce some polynomial rings into Magma:: @@ -713,13 +716,14 @@ def __call__(self, x, gens=None): EXAMPLES:: - sage: magma(EllipticCurve('37a')) # optional - magma + sage: # optional - magma + sage: magma(EllipticCurve('37a')) Elliptic Curve defined by y^2 + y = x^3 - x over Rational Field - sage: magma('EllipticCurve([GF(5)|1,2,3,4,1])') # optional - magma + sage: magma('EllipticCurve([GF(5)|1,2,3,4,1])') Elliptic Curve defined by y^2 + x*y + 3*y = x^3 + 2*x^2 + 4*x + 1 over GF(5) - sage: magma('PowerSeriesRing(Rationals())', 't') # optional - magma + sage: magma('PowerSeriesRing(Rationals())', 't') Power series ring in t over Rational Field - sage: magma('PolynomialRing(RationalField(), 3)', 'x,y,z') # optional - magma + sage: magma('PolynomialRing(RationalField(), 3)', 'x,y,z') Polynomial ring of rank 3 over Rational Field Order: Lexicographical Variables: x, y, z @@ -736,25 +740,27 @@ def __call__(self, x, gens=None): We test caching:: - sage: R. = ZZ[] # optional - magma - sage: magma(R) is magma(R) # optional - magma + sage: # optional - magma + sage: R. = ZZ[] + sage: magma(R) is magma(R) True - sage: m = Magma() # optional - magma - sage: m(R) # optional - magma + sage: m = Magma() + sage: m(R) Univariate Polynomial Ring in x over Integer Ring - sage: m(R) is magma(R) # optional - magma + sage: m(R) is magma(R) False - sage: R._magma_cache # optional - magma + sage: R._magma_cache {Magma: Univariate Polynomial Ring in x over Integer Ring, Magma: Univariate Polynomial Ring in x over Integer Ring} - sage: P. = PolynomialRing(GF(127)) # optional - magma - sage: m = Magma() # optional - magma - sage: m(P) # optional - magma + sage: # optional - magma + sage: P. = PolynomialRing(GF(127)) + sage: m = Magma() + sage: m(P) Polynomial ring of rank 2 over GF(127) Order: Graded Reverse Lexicographical Variables: x, y - sage: P._magma_cache # optional - magma + sage: P._magma_cache {Magma: Polynomial ring of rank 2 over GF(127) Order: Graded Reverse Lexicographical Variables: x, y} @@ -891,16 +897,17 @@ def clear(self, var): :: - sage: magma = Magma() # optional - magma - sage: a = magma('100') # optional - magma - sage: a.name() # optional - magma + sage: # optional - magma + sage: magma = Magma() + sage: a = magma('100') + sage: a.name() '_sage_[1]' - sage: del a # optional - magma - sage: b = magma('257') # optional - magma - sage: b.name() # optional - magma + sage: del a + sage: b = magma('257') + sage: b.name() '_sage_[1]' - sage: del b # optional - magma - sage: magma('_sage_[1]') # optional - magma + sage: del b + sage: magma('_sage_[1]') 0 """ self.__available_var.insert(0, var) # adds var to front of list @@ -931,12 +938,13 @@ def cputime(self, t=None): EXAMPLES:: - sage: type(magma.cputime()) # optional - magma + sage: # optional - magma + sage: type(magma.cputime()) <... 'float'> - sage: magma.cputime() # random, optional - magma + sage: magma.cputime() 1.9399999999999999 - sage: t = magma.cputime() # optional - magma - sage: magma.cputime(t) # random, optional - magma + sage: t = magma.cputime() + sage: magma.cputime(t) 0.02 """ if t: @@ -1251,15 +1259,16 @@ def bar_call(self, left, name, gens, nvals=1): methods of Magma elements. Here we illustrate directly using bar_call to create quotients:: - sage: V = magma.RModule(ZZ,3) # optional - magma - sage: V # optional - magma + sage: # optional - magma + sage: V = magma.RModule(ZZ,3) + sage: V RModule(IntegerRing(), 3) - sage: magma.bar_call(V, 'quo', [[1,2,3]], nvals=1) # optional - magma + sage: magma.bar_call(V, 'quo', [[1,2,3]], nvals=1) RModule(IntegerRing(), 2) - sage: magma.bar_call(V, 'quo', [[1,2,3]], nvals=2) # optional - magma + sage: magma.bar_call(V, 'quo', [[1,2,3]], nvals=2) (RModule(IntegerRing(), 2), Mapping from: RModule(IntegerRing(), 3) to RModule(IntegerRing(), 2)) - sage: magma.bar_call(V, 'quo', V, nvals=2) # optional - magma + sage: magma.bar_call(V, 'quo', V, nvals=2) (RModule(IntegerRing(), 0), Mapping from: RModule(IntegerRing(), 3) to RModule(IntegerRing(), 0)) """ @@ -1644,11 +1653,12 @@ def __call__(self, *args, **kwds): EXAMPLES: We create a MagmaFunctionElement:: - sage: n = magma(-15) # optional - magma - sage: f = n.Factorisation # optional - magma - sage: type(f) # optional - magma + sage: # optional - magma + sage: n = magma(-15) + sage: f = n.Factorisation + sage: type(f) - sage: f() # optional - magma + sage: f() [ <3, 1>, <5, 1> ] We verify that the nvals argument works. @@ -1686,12 +1696,13 @@ def _instancedoc_(self): EXAMPLES:: - sage: n = magma(-15) # optional - magma - sage: f = n.Factorisation # optional - magma - sage: print(f.__doc__) # optional - magma + sage: # optional - magma + sage: n = magma(-15) + sage: f = n.Factorisation + sage: print(f.__doc__) (n::RngIntElt) -> RngIntEltFact, RngIntElt, SeqEnum ... - sage: print(n.Factorisation.__doc__) # optional - magma + sage: print(n.Factorisation.__doc__) (n::RngIntElt) -> RngIntEltFact, RngIntElt, SeqEnum ... """ @@ -1728,13 +1739,14 @@ def _repr_(self): :: - sage: V = magma('VectorSpace(RationalField(),2)') # optional - magma - sage: V.set_magma_attribute('M', 290398) # optional - magma - sage: V.M # optional - magma + sage: # optional - magma + sage: V = magma('VectorSpace(RationalField(),2)') + sage: V.set_magma_attribute('M', 290398) + sage: V.M 290398 - sage: type(V.M) # optional - magma + sage: type(V.M) - sage: type(V.M.__repr__()) # optional - magma + sage: type(V.M.__repr__()) <... 'str'> Displaying a non-attribute function works as above. @@ -1898,13 +1910,14 @@ def __getattr__(self, attrname): EXAMPLES:: - sage: n = magma(-15) # optional - magma - sage: type(n) # optional - magma + sage: # optional - magma + sage: n = magma(-15) + sage: type(n) - sage: f = n.__getattr__('Factorization') # optional - magma - sage: type(f) # optional - magma + sage: f = n.__getattr__('Factorization') + sage: type(f) - sage: f # optional - magma + sage: f Partially evaluated Magma function or intrinsic 'Factorization' ... """ @@ -1921,24 +1934,25 @@ def _sage_(self): EXAMPLES: Enumerated Sets:: - sage: a = magma('{1,2/3,-5/9}') # optional - magma - sage: a.sage() # optional - magma + sage: # optional - magma + sage: a = magma('{1,2/3,-5/9}') + sage: a.sage() {1, -5/9, 2/3} - sage: a._sage_() # optional - magma + sage: a._sage_() {1, -5/9, 2/3} - sage: type(a.sage()) # optional - magma + sage: type(a.sage()) - sage: a = magma('{1,2/3,-5/9}'); a # optional - magma + sage: a = magma('{1,2/3,-5/9}'); a { -5/9, 2/3, 1 } - sage: a.Type() # optional - magma + sage: a.Type() SetEnum - sage: b = a.sage(); b # optional - magma + sage: b = a.sage(); b {1, -5/9, 2/3} - sage: type(b) # optional - magma + sage: type(b) - sage: c = magma(b); c # optional - magma + sage: c = magma(b); c { -5/9, 2/3, 1 } - sage: c.Type() # optional - magma + sage: c.Type() SetEnum Multisets are converted to lists:: @@ -1986,20 +2000,22 @@ def _sage_(self): Multivariate polynomials:: - sage: R. = QQ[] # optional - magma - sage: f = x^2+3*y # optional - magma - sage: g = magma(f).sage(); g # optional - magma + sage: # optional - magma + sage: R. = QQ[] + sage: f = x^2+3*y + sage: g = magma(f).sage(); g x^2 + 3*y - sage: parent(f) == parent(g) # optional - magma + sage: parent(f) == parent(g) True Real and complex numbers:: - sage: m = magma(RealField(200)(1/3)) # optional - magma - sage: m.sage() # indirect doctest, optional - magma + sage: # optional - magma + sage: m = magma(RealField(200)(1/3)) + sage: m.sage() 0.33333333333333333333333333333333333333333333333333333333333 - sage: m = magma(RealField(1000)(1/3)) # optional - magma - sage: m.sage() # indirect doctest, optional - magma + sage: m = magma(RealField(1000)(1/3)) + sage: m.sage() 0.333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333333 sage: m = magma(ComplexField(200)).1; m # optional - magma @@ -2041,14 +2057,15 @@ def _sage_(self): to relative number fields. Conversion of their elements has not yet been implemented.:: - sage: magma.eval('P := PolynomialRing(Rationals());') # optional - magma + sage: # optional - magma + sage: magma.eval('P := PolynomialRing(Rationals());') '' - sage: K = magma('NumberField([x^2-2,x^2-3]:Abs);') # optional - magma - sage: L = K.sage(); L # optional - magma + sage: K = magma('NumberField([x^2-2,x^2-3]:Abs);') + sage: L = K.sage(); L Number Field in K1 with defining polynomial x^2 - 2 over its base field - sage: L.base_field() # optional - magma + sage: L.base_field() Number Field in K2 with defining polynomial x^2 - 3 - sage: K.GeneratorsSequence()[1].sage() # optional - magma + sage: K.GeneratorsSequence()[1].sage() Traceback (most recent call last): ... NameError: name 'K' is not defined @@ -2083,11 +2100,12 @@ def AssignNames(self, names): """ EXAMPLES:: - sage: S = magma.PolynomialRing(magma.Integers(), 2) # optional - magma - sage: S.AssignNames(['a', 'b']) # optional - magma - sage: S.1 # optional - magma + sage: # optional - magma + sage: S = magma.PolynomialRing(magma.Integers(), 2) + sage: S.AssignNames(['a', 'b']) + sage: S.1 a - sage: S.1^2 + S.2 # optional - magma + sage: S.1^2 + S.2 a^2 + b """ P = self._check_valid() @@ -2214,13 +2232,14 @@ def evaluate(self, *args): EXAMPLES:: - sage: f = magma('Factorization') # optional - magma - sage: f.evaluate(15) # optional - magma + sage: # optional - magma + sage: f = magma('Factorization') + sage: f.evaluate(15) [ <3, 1>, <5, 1> ] - sage: f(15) # optional - magma + sage: f(15) [ <3, 1>, <5, 1> ] - sage: f = magma('GCD') # optional - magma - sage: f.evaluate(15,20) # optional - magma + sage: f = magma('GCD') + sage: f.evaluate(15,20) 5 sage: m = matrix(QQ, 2, 2, [2,3,5,7]) # optional - magma @@ -2242,13 +2261,14 @@ def __call__(self, *args): EXAMPLES:: - sage: M = magma.RMatrixSpace(magma.IntegerRing(), 2, 2) # optional - magma - sage: A = M([1,2,3,4]); A # optional - magma + sage: # optional - magma + sage: M = magma.RMatrixSpace(magma.IntegerRing(), 2, 2) + sage: A = M([1,2,3,4]); A [1 2] [3 4] - sage: type(A) # optional - magma + sage: type(A) - sage: A.Type() # optional - magma + sage: A.Type() ModMatRngElt """ if len(args) > 1: @@ -2274,16 +2294,17 @@ def __iter__(self): EXAMPLES:: - sage: V = magma('VectorSpace(GF(3),2)') # optional - magma - sage: V # optional - magma + sage: # optional - magma + sage: V = magma('VectorSpace(GF(3),2)') + sage: V Full Vector space of degree 2 over GF(3) - sage: w = V.__iter__(); w # optional - magma + sage: w = V.__iter__(); w - sage: next(w) # optional - magma + sage: next(w) (0 0) - sage: next(w) # optional - magma + sage: next(w) (1 0) - sage: list(w) # optional - magma + sage: list(w) [(2 0), (0 1), (1 1), (2 1), (0 2), (1 2), (2 2)] """ P = self._check_valid() @@ -2299,12 +2320,13 @@ def __len__(self): EXAMPLES:: - sage: V = magma('VectorSpace(GF(3),2)') # optional - magma - sage: V # optional - magma + sage: # optional - magma + sage: V = magma('VectorSpace(GF(3),2)') + sage: V Full Vector space of degree 2 over GF(3) - sage: len(V) # optional - magma + sage: len(V) 9 - sage: V.__len__() # optional - magma + sage: V.__len__() 9 """ P = self._check_valid() @@ -2431,11 +2453,12 @@ def _latex_(self): Power Series:: - sage: _=magma.eval('R := PowerSeriesRing(RationalField())') # optional - magma - sage: latex(magma('(1/(1+x))')) # optional - magma + sage: # optional - magma + sage: _=magma.eval('R := PowerSeriesRing(RationalField())') + sage: latex(magma('(1/(1+x))')) 1-x+x^{2}-x^{3}+x^{4}-x^{5}+x^{6}-x^{7}+x^{8}-x^{9}+x^{10}-x^{11}+x^{12}-x^{13}+x^{14}-x^{15}+x^{16}-x^{17}+x^{18}-x^{19}+O(x^{20}) - sage: _=magma.eval('R := PowerSeriesRing(RationalField())') # optional - magma - sage: latex(magma('(-1/(2+x + O(x^3)))')) # optional - magma + sage: _=magma.eval('R := PowerSeriesRing(RationalField())') + sage: latex(magma('(-1/(2+x + O(x^3)))')) \frac{-1}{2}+\frac{1}{4}x-\frac{1}{8}x^{2}+O(x^{3}) p-adic Numbers:: @@ -2457,11 +2480,12 @@ def set_magma_attribute(self, attrname, value): EXAMPLES:: - sage: V = magma("VectorSpace(RationalField(),2)") # optional - magma - sage: V.set_magma_attribute('M',10) # optional - magma - sage: V.get_magma_attribute('M') # optional - magma + sage: # optional - magma + sage: V = magma("VectorSpace(RationalField(),2)") + sage: V.set_magma_attribute('M',10) + sage: V.get_magma_attribute('M') 10 - sage: V.M # optional - magma + sage: V.M 10 """ P = self.parent() # instance of Magma that contains this element. @@ -2478,11 +2502,12 @@ def get_magma_attribute(self, attrname): EXAMPLES:: - sage: V = magma("VectorSpace(RationalField(),10)") # optional - magma - sage: V.set_magma_attribute('M','"hello"') # optional - magma - sage: V.get_magma_attribute('M') # optional - magma + sage: # optional - magma + sage: V = magma("VectorSpace(RationalField(),10)") + sage: V.set_magma_attribute('M','"hello"') + sage: V.get_magma_attribute('M') hello - sage: V.M # optional - magma + sage: V.M hello """ P = self.parent() @@ -2620,13 +2645,14 @@ def __bool__(self): Test use in bool conversions of bools:: - sage: bool(magma(False)) # optional - magma + sage: # optional - magma + sage: bool(magma(False)) False - sage: bool(magma(True)) # optional - magma + sage: bool(magma(True)) True - sage: bool(magma(1)) # optional - magma + sage: bool(magma(1)) True - sage: bool(magma(0)) # optional - magma + sage: bool(magma(0)) False TESTS: @@ -2713,12 +2739,13 @@ def quo(self, gens, **args): :: - sage: V = magma.RModule(ZZ,3); V # optional - magma + sage: # optional - magma + sage: V = magma.RModule(ZZ,3); V RModule(IntegerRing(), 3) - sage: W, phi = V.quo([[1,2,3]]) # optional - magma - sage: W # optional - magma + sage: W, phi = V.quo([[1,2,3]]) + sage: W RModule(IntegerRing(), 2) - sage: phi # optional - magma + sage: phi Mapping from: RModule(IntegerRing(), 3) to RModule(IntegerRing(), 2) """ return self.parent().bar_call(self, 'quo', gens, nvals=2) @@ -2741,10 +2768,11 @@ def ideal(self, gens): EXAMPLES:: - sage: R = magma('PolynomialRing(RationalField())') # optional - magma - sage: R.assign_names(['x']) # optional - magma - sage: x = R.1 # optional - magma - sage: R.ideal([x^2 - 1, x^3 - 1]) # optional - magma + sage: # optional - magma + sage: R = magma('PolynomialRing(RationalField())') + sage: R.assign_names(['x']) + sage: x = R.1 + sage: R.ideal([x^2 - 1, x^3 - 1]) Ideal of Univariate Polynomial Ring in x over Rational Field generated by x - 1 """ return self.parent().bar_call(self, 'ideal', gens, nvals=1) diff --git a/src/sage/interfaces/mathematica.py b/src/sage/interfaces/mathematica.py index 9c6e3ca86e9..9c64e9f4286 100644 --- a/src/sage/interfaces/mathematica.py +++ b/src/sage/interfaces/mathematica.py @@ -31,14 +31,15 @@ call the Mathematica wrapper object's ``sage()`` method. This method returns a native Sage object:: - sage: mobj = mathematica(x^2-1) # optional - mathematica - sage: mobj2 = mobj.Factor(); mobj2 # optional - mathematica + sage: # optional - mathematica + sage: mobj = mathematica(x^2-1) + sage: mobj2 = mobj.Factor(); mobj2 (-1 + x)*(1 + x) - sage: mobj2.parent() # optional - mathematica + sage: mobj2.parent() Mathematica - sage: sobj = mobj2.sage(); sobj # optional - mathematica + sage: sobj = mobj2.sage(); sobj (x + 1)*(x - 1) - sage: sobj.parent() # optional - mathematica + sage: sobj.parent() Symbolic Ring @@ -122,16 +123,17 @@ We solve an equation and a system of two equations:: - sage: eqn = mathematica('3x + 5 == 14') # optional - mathematica - sage: eqn # optional - mathematica + sage: # optional - mathematica + sage: eqn = mathematica('3x + 5 == 14') + sage: eqn 5 + 3*x == 14 - sage: eqn.Solve('x') # optional - mathematica + sage: eqn.Solve('x') {{x -> 3}} - sage: sys = mathematica('{x^2 - 3y == 3, 2x - y == 1}') # optional - mathematica - sage: print(sys) # optional - mathematica + sage: sys = mathematica('{x^2 - 3y == 3, 2x - y == 1}') + sage: print(sys) 2 {x - 3 y == 3, 2 x - y == 1} - sage: sys.Solve('{x, y}') # optional - mathematica + sage: sys.Solve('{x, y}') {{x -> 0, y -> -1}, {x -> 6, y -> 11}} Assignments and definitions @@ -227,15 +229,16 @@ We factor an integer:: - sage: n = mathematica(2434500) # optional - mathematica - sage: n.FactorInteger() # optional - mathematica + sage: # optional - mathematica + sage: n = mathematica(2434500) + sage: n.FactorInteger() {{2, 2}, {3, 2}, {5, 3}, {541, 1}} - sage: n = mathematica(2434500) # optional - mathematica - sage: F = n.FactorInteger(); F # optional - mathematica + sage: n = mathematica(2434500) + sage: F = n.FactorInteger(); F {{2, 2}, {3, 2}, {5, 3}, {541, 1}} - sage: F[1] # optional - mathematica + sage: F[1] {2, 2} - sage: F[4] # optional - mathematica + sage: F[4] {541, 1} Mathematica's ECM package is no longer available. @@ -261,17 +264,18 @@ :: - sage: x = mathematica(pi/2) # optional - mathematica - sage: print(x) # optional - mathematica + sage: # optional - mathematica + sage: x = mathematica(pi/2) + sage: print(x) Pi -- 2 - sage: loads(dumps(x)) == x # optional - mathematica + sage: loads(dumps(x)) == x True - sage: n = x.N(50) # optional - mathematica - sage: print(n) # optional - mathematica + sage: n = x.N(50) + sage: print(n) 1.5707963267948966192313216916397514420985846996876 - sage: loads(dumps(n)) == n # optional - mathematica + sage: loads(dumps(n)) == n True Complicated translations @@ -351,13 +355,14 @@ Check that numerical approximations via Mathematica's `N[]` function work correctly (:trac:`18888`, :trac:`28907`):: - sage: mathematica('Pi/2').N(10) # optional -- mathematica + sage: # optional - mathematica + sage: mathematica('Pi/2').N(10) 1.5707963268 - sage: mathematica('Pi').N(10) # optional -- mathematica + sage: mathematica('Pi').N(10) 3.1415926536 - sage: mathematica('Pi').N(50) # optional -- mathematica + sage: mathematica('Pi').N(50) 3.14159265358979323846264338327950288419716939937511 - sage: str(mathematica('Pi*x^2-1/2').N()) # optional -- mathematica + sage: str(mathematica('Pi*x^2-1/2').N()) 2 -0.5 + 3.14159 x @@ -373,13 +378,14 @@ Check that all trig/hyperbolic functions and their reciprocals are correctly translated to Mathematica (:trac:`34087`):: - sage: x=var('x') # optional - mathematica - sage: FL=[sin, cos, tan, csc, sec, cot, # optional - mathematica + sage: # optional - mathematica + sage: x=var('x') + sage: FL=[sin, cos, tan, csc, sec, cot, ....: sinh, cosh, tanh, csch, sech, coth] - sage: IFL=[arcsin, arccos, arctan, arccsc, # optional - mathematica + sage: IFL=[arcsin, arccos, arctan, arccsc, ....: arcsec, arccot, arcsinh, arccosh, ....: arctanh, arccsch, arcsech, arccoth] - sage: [mathematica.TrigToExp(u(x)).sage() # optional - mathematica + sage: [mathematica.TrigToExp(u(x)).sage() ....: for u in FL] [-1/2*I*e^(I*x) + 1/2*I*e^(-I*x), 1/2*e^(I*x) + 1/2*e^(-I*x), @@ -393,7 +399,7 @@ -2/(e^(-x) - e^x), 2/(e^(-x) + e^x), -(e^(-x) + e^x)/(e^(-x) - e^x)] - sage: [mathematica.TrigToExp(u(x)).sage() # optional - mathematica + sage: [mathematica.TrigToExp(u(x)).sage() ....: for u in IFL] [-I*log(I*x + sqrt(-x^2 + 1)), 1/2*pi + I*log(I*x + sqrt(-x^2 + 1)), @@ -789,12 +795,13 @@ def _sage_(self, locals={}): Mathematica lists of numbers/constants become Sage lists of numbers/constants:: - sage: m = mathematica('{{1., 4}, Pi, 3.2e100, I}') # optional - mathematica - sage: s = m.sage(); s # optional - mathematica + sage: # optional - mathematica + sage: m = mathematica('{{1., 4}, Pi, 3.2e100, I}') + sage: s = m.sage(); s [[1.00000000000000, 4], pi, 3.20000000000000*e100, I] - sage: s[1].n() # optional - mathematica + sage: s[1].n() 3.14159265358979 - sage: s[3]^2 # optional - mathematica + sage: s[3]^2 -1 :: @@ -825,11 +832,12 @@ def _sage_(self, locals={}): :: - sage: m = mathematica('bla^2') # optional - mathematica - sage: mb = m.sage() # optional - mathematica - sage: var('bla') # optional - mathematica + sage: # optional - mathematica + sage: m = mathematica('bla^2') + sage: mb = m.sage() + sage: var('bla') bla - sage: bla^2 - mb # optional - mathematica + sage: bla^2 - mb 0 diff --git a/src/sage/interfaces/mathics.py b/src/sage/interfaces/mathics.py index 0bf0bc78829..aec033d3173 100644 --- a/src/sage/interfaces/mathics.py +++ b/src/sage/interfaces/mathics.py @@ -47,14 +47,15 @@ call the Mathics wrapper object's ``sage()`` method. This method returns a native Sage object:: - sage: mobj = mathics(x^2-1) # optional - mathics - sage: mobj2 = mobj.Factor(); mobj2 # optional - mathics + sage: # optional - mathics + sage: mobj = mathics(x^2-1) + sage: mobj2 = mobj.Factor(); mobj2 (-1 + x) (1 + x) - sage: mobj2.parent() # optional - mathics + sage: mobj2.parent() Mathics - sage: sobj = mobj2.sage(); sobj # optional - mathics + sage: sobj = mobj2.sage(); sobj (x + 1)*(x - 1) - sage: sobj.parent() # optional - mathics + sage: sobj.parent() Symbolic Ring @@ -132,15 +133,16 @@ We solve an equation and a system of two equations:: - sage: eqn = mathics('3x + 5 == 14') # optional - mathics - sage: eqn # optional - mathics + sage: # optional - mathics + sage: eqn = mathics('3x + 5 == 14') + sage: eqn 5 + 3 x == 14 - sage: eqn.Solve('x') # optional - mathics + sage: eqn.Solve('x') {{x -> 3}} - sage: sys = mathics('{x^2 - 3y == 3, 2x - y == 1}') # optional - mathics - sage: print(sys) # optional - mathics + sage: sys = mathics('{x^2 - 3y == 3, 2x - y == 1}') + sage: print(sys) {x ^ 2 - 3 y == 3, 2 x - y == 1} - sage: sys.Solve('{x, y}') # optional - mathics + sage: sys.Solve('{x, y}') {{x -> 0, y -> -1}, {x -> 6, y -> 11}} Assignments and definitions @@ -233,15 +235,16 @@ We factor an integer:: - sage: n = mathics(2434500) # optional - mathics - sage: n.FactorInteger() # optional - mathics + sage: # optional - mathics + sage: n = mathics(2434500) + sage: n.FactorInteger() {{2, 2}, {3, 2}, {5, 3}, {541, 1}} - sage: n = mathics(2434500) # optional - mathics - sage: F = n.FactorInteger(); F # optional - mathics + sage: n = mathics(2434500) + sage: F = n.FactorInteger(); F {{2, 2}, {3, 2}, {5, 3}, {541, 1}} - sage: F[1] # optional - mathics + sage: F[1] {2, 2} - sage: F[4] # optional - mathics + sage: F[4] {541, 1} @@ -266,15 +269,16 @@ :: - sage: x = mathics(pi/2) # optional - mathics - sage: print(x) # optional - mathics + sage: # optional - mathics + sage: x = mathics(pi/2) + sage: print(x) Pi / 2 - sage: loads(dumps(x)) == x # optional - mathics + sage: loads(dumps(x)) == x True - sage: n = x.N(50) # optional - mathics - sage: print(n) # optional - mathics + sage: n = x.N(50) + sage: print(n) 1.5707963267948966192313216916397514420985846996876 - sage: loads(dumps(n)) == n # optional - mathics + sage: loads(dumps(n)) == n True Complicated translations @@ -356,13 +360,14 @@ Check that numerical approximations via Mathics's `N[]` function work correctly (:trac:`18888`, :trac:`28907`):: - sage: mathics('Pi/2').N(10) # optional -- mathics + sage: # optional - mathics + sage: mathics('Pi/2').N(10) 1.570796327 - sage: mathics('Pi').N(10) # optional -- mathics + sage: mathics('Pi').N(10) 3.141592654 - sage: mathics('Pi').N(50) # optional -- mathics + sage: mathics('Pi').N(50) 3.1415926535897932384626433832795028841971693993751 - sage: str(mathics('Pi*x^2-1/2').N()) # optional -- mathics + sage: str(mathics('Pi*x^2-1/2').N()) '-0.5 + 3.14159 x ^ 2.' Check that Mathics's `E` exponential symbol is correctly backtranslated @@ -405,15 +410,16 @@ def _mathics_sympysage_symbol(self): EXAMPLES:: + sage: # optional - mathics sage: from sage.interfaces.mathics import _mathics_sympysage_symbol - sage: mt = mathics('t') # optional - mathics - sage: st = mt.to_sympy(); st # optional - mathics + sage: mt = mathics('t') + sage: st = mt.to_sympy(); st _Mathics_User_Global`t - sage: _mathics_sympysage_symbol(st) # optional - mathics + sage: _mathics_sympysage_symbol(st) t - sage: bool(_ == st._sage_()) # optional - mathics + sage: bool(_ == st._sage_()) True - sage: type(st._sage_()) # optional - mathics + sage: type(st._sage_()) """ from sage.symbolic.ring import SR @@ -442,20 +448,21 @@ class Mathics(Interface): EXAMPLES:: - sage: t = mathics('Tan[I + 0.5]') # optional - mathics - sage: t.parent() # optional - mathics + sage: # optional - mathics + sage: t = mathics('Tan[I + 0.5]') + sage: t.parent() Mathics - sage: ts = t.sage() # optional - mathics - sage: ts.parent() # optional - mathics + sage: ts = t.sage() + sage: ts.parent() Complex Field with 53 bits of precision - sage: t == mathics(ts) # optional - mathics + sage: t == mathics(ts) True - sage: mtan = mathics.Tan # optional - mathics - sage: mt = mtan(I+1/2) # optional - mathics - sage: mt == t # optional - mathics + sage: mtan = mathics.Tan + sage: mt = mtan(I+1/2) + sage: mt == t True - sage: u = mathics(I+1/2) # optional - mathics - sage: u.Tan() == mt # optional - mathics + sage: u = mathics(I+1/2) + sage: u.Tan() == mt True @@ -829,34 +836,37 @@ class MathicsElement(ExtraTabCompletion, InterfaceElement): EXAMPLES:: - sage: me=mathics(e); me # optional - mathics + sage: # optional - mathics + sage: me=mathics(e); me E - sage: type(me) # optional - mathics + sage: type(me) - sage: P = me.parent(); P # optional - mathics + sage: P = me.parent(); P Mathics - sage: type(P) # optional - mathics + sage: type(P) Access to the Mathics expression objects:: - sage: res = me._mathics_result # optional - mathics - sage: type(res) # optional - mathics + sage: # optional - mathics + sage: res = me._mathics_result + sage: type(res) - sage: expr = res.last_eval; expr # optional - mathics + sage: expr = res.last_eval; expr - sage: type(expr) # optional - mathics + sage: type(expr) Applying Mathics methods:: - sage: me.to_sympy() # optional - mathics + sage: # optional - mathics + sage: me.to_sympy() E - sage: me.get_name() # optional - mathics + sage: me.get_name() 'System`E' - sage: me.is_inexact() # optional - mathics + sage: me.is_inexact() False - sage: me.is_symbol() # optional - mathics + sage: me.is_symbol() True Conversion to Sage:: @@ -900,12 +910,13 @@ def __getattr__(self, attrname): r""" EXAMPLES:: - sage: a = mathics(5*x) # optional - mathics - sage: res = a._mathics_result # optional - mathics - sage: str(a) == res.result # optional - mathics + sage: # optional - mathics + sage: a = mathics(5*x) + sage: res = a._mathics_result + sage: str(a) == res.result True - sage: t = mathics._eval('5*x') # optional - mathics - sage: t.last_eval == res.last_eval # optional - mathics + sage: t = mathics._eval('5*x') + sage: t.last_eval == res.last_eval True """ P = self._check_valid() @@ -1004,12 +1015,13 @@ def _sage_(self, locals={}): Mathics lists of numbers/constants become Sage lists of numbers/constants:: - sage: m = mathics('{{1., 4}, Pi, 3.2e100, I}') # optional - mathics - sage: s = m.sage(); s # optional - mathics + sage: # optional - mathics + sage: m = mathics('{{1., 4}, Pi, 3.2e100, I}') + sage: s = m.sage(); s [[1.00000000000000, 4], pi, 3.20000000000000*e100, 1.00000000000000*I] - sage: s[1].n() # optional - mathics + sage: s[1].n() 3.14159265358979 - sage: s[3]^2 # optional - mathics + sage: s[3]^2 -1.00000000000000 :: @@ -1040,11 +1052,12 @@ def _sage_(self, locals={}): :: - sage: m = mathics('bla^2') # optional - mathics - sage: mb = m.sage() # optional - mathics - sage: var('bla') # optional - mathics + sage: # optional - mathics + sage: m = mathics('bla^2') + sage: mb = m.sage() + sage: var('bla') bla - sage: bla^2 - mb # optional - mathics + sage: bla^2 - mb 0 """ @@ -1203,14 +1216,15 @@ def _richcmp_(self, other, op): r""" EXAMPLES:: - sage: mobj1 = mathics([x^2-1, 2]) # optional - mathics - sage: mobj2 = mathics('{x^2-1, 2}') # optional - mathics - sage: mobj3 = mathics('5*x + y') # optional - mathics - sage: mobj1 == mobj2 # optional - mathics + sage: # optional - mathics + sage: mobj1 = mathics([x^2-1, 2]) + sage: mobj2 = mathics('{x^2-1, 2}') + sage: mobj3 = mathics('5*x + y') + sage: mobj1 == mobj2 True - sage: mobj1 < mobj2 # optional - mathics + sage: mobj1 < mobj2 False - sage: mobj1 == mobj3 # optional - mathics + sage: mobj1 == mobj3 False """ P = self.parent() diff --git a/src/sage/interfaces/matlab.py b/src/sage/interfaces/matlab.py index 24c40a3647c..74354b77412 100644 --- a/src/sage/interfaces/matlab.py +++ b/src/sage/interfaces/matlab.py @@ -30,53 +30,57 @@ EXAMPLES:: - sage: matlab('4+10') # optional - matlab + sage: # optional - matlab + sage: matlab('4+10') 14 - sage: matlab('date') # optional - matlab; random output + sage: matlab('date') 18-Oct-2006 - sage: matlab('5*10 + 6') # optional - matlab + sage: matlab('5*10 + 6') 56 - sage: matlab('(6+6)/3') # optional - matlab + sage: matlab('(6+6)/3') 4 - sage: matlab('9')^2 # optional - matlab + sage: matlab('9')^2 81 - sage: a = matlab(10); b = matlab(20); c = matlab(30) # optional - matlab - sage: avg = (a+b+c)/3 ; avg # optional - matlab + sage: a = matlab(10); b = matlab(20); c = matlab(30) + sage: avg = (a+b+c)/3 ; avg 20 - sage: parent(avg) # optional - matlab + sage: parent(avg) Matlab :: - sage: my_scalar = matlab('3.1415') # optional - matlab - sage: my_scalar # optional - matlab + sage: # optional - matlab + sage: my_scalar = matlab('3.1415') + sage: my_scalar 3.1415 - sage: my_vector1 = matlab('[1,5,7]') # optional - matlab - sage: my_vector1 # optional - matlab + sage: my_vector1 = matlab('[1,5,7]') + sage: my_vector1 1 5 7 - sage: my_vector2 = matlab('[1;5;7]') # optional - matlab - sage: my_vector2 # optional - matlab + sage: my_vector2 = matlab('[1;5;7]') + sage: my_vector2 1 5 7 - sage: my_vector1 * my_vector2 # optional - matlab + sage: my_vector1 * my_vector2 75 :: - sage: row_vector1 = matlab('[1 2 3]') # optional - matlab - sage: row_vector2 = matlab('[3 2 1]') # optional - matlab - sage: matrix_from_row_vec = matlab('[%s; %s]'%(row_vector1.name(), row_vector2.name())) # optional - matlab - sage: matrix_from_row_vec # optional - matlab + sage: # optional - matlab + sage: row_vector1 = matlab('[1 2 3]') + sage: row_vector2 = matlab('[3 2 1]') + sage: matrix_from_row_vec = matlab('[%s; %s]'%(row_vector1.name(), row_vector2.name())) + sage: matrix_from_row_vec 1 2 3 3 2 1 :: - sage: column_vector1 = matlab('[1;3]') # optional - matlab - sage: column_vector2 = matlab('[2;8]') # optional - matlab - sage: matrix_from_col_vec = matlab('[%s %s]'%(column_vector1.name(), column_vector2.name())) # optional - matlab - sage: matrix_from_col_vec # optional - matlab + sage: # optional - matlab + sage: column_vector1 = matlab('[1;3]') + sage: column_vector2 = matlab('[2;8]') + sage: matrix_from_col_vec = matlab('[%s %s]'%(column_vector1.name(), column_vector2.name())) + sage: matrix_from_col_vec 1 2 3 8 @@ -106,12 +110,13 @@ :: - sage: my_vector1 = matlab('[1,5,7]') # optional - matlab - sage: my_vector1(1) # optional - matlab + sage: # optional - matlab + sage: my_vector1 = matlab('[1,5,7]') + sage: my_vector1(1) 1 - sage: my_vector1(2) # optional - matlab + sage: my_vector1(2) 5 - sage: my_vector1(3) # optional - matlab + sage: my_vector1(3) 7 Matrix indexing works as follows:: @@ -159,10 +164,11 @@ class Matlab(Expect): EXAMPLES:: - sage: a = matlab('[ 1, 1, 2; 3, 5, 8; 13, 21, 33 ]') # optional - matlab - sage: b = matlab('[ 1; 3; 13]') # optional - matlab - sage: c = a * b # optional - matlab - sage: print(c) # optional - matlab + sage: # optional - matlab + sage: a = matlab('[ 1, 1, 2; 3, 5, 8; 13, 21, 33 ]') + sage: b = matlab('[ 1; 3; 13]') + sage: c = a * b + sage: print(c) 30 122 505 @@ -328,12 +334,13 @@ def _matrix_(self, R): EXAMPLES:: - sage: A = matlab('[1,2;3,4]') # optional - matlab - sage: matrix(ZZ, A) # optional - matlab + sage: # optional - matlab + sage: A = matlab('[1,2;3,4]') + sage: matrix(ZZ, A) [1 2] [3 4] - sage: A = matlab('[1,2;3,4.5]') # optional - matlab - sage: matrix(RR, A) # optional - matlab + sage: A = matlab('[1,2;3,4.5]') + sage: matrix(RR, A) [1.00000000000000 2.00000000000000] [3.00000000000000 4.50000000000000] diff --git a/src/sage/interfaces/maxima_abstract.py b/src/sage/interfaces/maxima_abstract.py index 9fe624a7f02..abc43baf127 100644 --- a/src/sage/interfaces/maxima_abstract.py +++ b/src/sage/interfaces/maxima_abstract.py @@ -1020,11 +1020,13 @@ def plot_list(self, ptsx, ptsy, options=None): EXAMPLES:: - sage: zeta_ptsx = [ (pari(1/2 + i*I/10).zeta().real()).precision(1) for i in range(70,150)] - sage: zeta_ptsy = [ (pari(1/2 + i*I/10).zeta().imag()).precision(1) for i in range(70,150)] - sage: maxima.plot_list(zeta_ptsx, zeta_ptsy) # not tested + sage: zeta_ptsx = [(pari(1/2 + i*I/10).zeta().real()).precision(1) # needs sage.libs.pari + ....: for i in range(70,150)] + sage: zeta_ptsy = [(pari(1/2 + i*I/10).zeta().imag()).precision(1) # needs sage.libs.pari + ....: for i in range(70,150)] + sage: maxima.plot_list(zeta_ptsx, zeta_ptsy) # not tested # needs sage.libs.pari sage: opts='[gnuplot_preamble, "set nokey"], [gnuplot_term, ps], [gnuplot_out_file, "zeta.eps"]' - sage: maxima.plot_list(zeta_ptsx, zeta_ptsy, opts) # not tested + sage: maxima.plot_list(zeta_ptsx, zeta_ptsy, opts) # not tested # needs sage.libs.pari """ cmd = 'plot2d([discrete,%s, %s]' % (ptsx, ptsy) if options is None: @@ -1056,18 +1058,23 @@ def plot_multilist(self, pts_list, options=None): EXAMPLES:: - sage: xx = [ i/10.0 for i in range(-10,10)] - sage: yy = [ i/10.0 for i in range(-10,10)] - sage: x0 = [ 0 for i in range(-10,10)] - sage: y0 = [ 0 for i in range(-10,10)] - sage: zeta_ptsx1 = [ (pari(1/2+i*I/10).zeta().real()).precision(1) for i in range(10)] - sage: zeta_ptsy1 = [ (pari(1/2+i*I/10).zeta().imag()).precision(1) for i in range(10)] - sage: maxima.plot_multilist([[zeta_ptsx1,zeta_ptsy1],[xx,y0],[x0,yy]]) # not tested - sage: zeta_ptsx1 = [ (pari(1/2+i*I/10).zeta().real()).precision(1) for i in range(10,150)] - sage: zeta_ptsy1 = [ (pari(1/2+i*I/10).zeta().imag()).precision(1) for i in range(10,150)] - sage: maxima.plot_multilist([[zeta_ptsx1,zeta_ptsy1],[xx,y0],[x0,yy]]) # not tested + sage: xx = [i/10.0 for i in range(-10,10)] + sage: yy = [i/10.0 for i in range(-10,10)] + sage: x0 = [0 for i in range(-10,10)] + sage: y0 = [0 for i in range(-10,10)] + sage: zeta_ptsx1 = [(pari(1/2+i*I/10).zeta().real()).precision(1) # needs sage.libs.pari + ....: for i in range(10)] + sage: zeta_ptsy1 = [(pari(1/2+i*I/10).zeta().imag()).precision(1) # needs sage.libs.pari + ....: for i in range(10)] + sage: maxima.plot_multilist([[zeta_ptsx1,zeta_ptsy1], [xx,y0], [x0,yy]]) # not tested + sage: zeta_ptsx1 = [(pari(1/2+i*I/10).zeta().real()).precision(1) # needs sage.libs.pari + ....: for i in range(10,150)] + sage: zeta_ptsy1 = [(pari(1/2+i*I/10).zeta().imag()).precision(1) # needs sage.libs.pari + ....: for i in range(10,150)] + sage: maxima.plot_multilist([[zeta_ptsx1,zeta_ptsy1], [xx,y0], [x0,yy]]) # not tested sage: opts='[gnuplot_preamble, "set nokey"]' - sage: maxima.plot_multilist([[zeta_ptsx1,zeta_ptsy1],[xx,y0],[x0,yy]],opts) # not tested + sage: maxima.plot_multilist([[zeta_ptsx1,zeta_ptsy1], [xx,y0], [x0,yy]], # not tested + ....: opts) """ n = len(pts_list) cmd = '[' diff --git a/src/sage/interfaces/mupad.py b/src/sage/interfaces/mupad.py index 956de696806..82920a9edaa 100644 --- a/src/sage/interfaces/mupad.py +++ b/src/sage/interfaces/mupad.py @@ -13,23 +13,25 @@ TESTS:: - sage: mupad.package('"MuPAD-Combinat"') # optional - mupad - sage: combinat = mupad.combinat # optional - mupad - sage: examples = mupad.examples # optional - mupad - sage: S = examples.SymmetricFunctions() # optional - mupad - sage: S.s[2,1]^2 # optional - mupad + sage: # optional - mupad + sage: mupad.package('"MuPAD-Combinat"') + sage: combinat = mupad.combinat + sage: examples = mupad.examples + sage: S = examples.SymmetricFunctions() + sage: S.s[2,1]^2 s[3, 3] + s[4, 2] + s[2, 2, 1, 1] + s[2, 2, 2] + 2 s[3, 2, 1] + s[4, 1, 1] + s[3, 1, 1, 1] - sage: S.omega( S.s[3] ) # optional - mupad + sage: S.omega( S.s[3] ) s[1, 1, 1] - sage: s = S.s # optional - mupad - sage: p = S.p # optional - mupad - sage: s(s[2,1] + p[2,1]) # optional - mupad + sage: s = S.s + sage: p = S.p + sage: s(s[2,1] + p[2,1]) s[2, 1] + s[3] - s[1, 1, 1] - sage: s(_) # optional - mupad + sage: s(_) s[2, 1] + s[3] - s[1, 1, 1] - sage: combinat.tableaux.list(3) # optional - mupad # note: the order of the result seems to depend on the version of MuPAD / MuPAD-Combinat + sage: # optional - mupad + sage: combinat.tableaux.list(3) -- +---+ -- | | 3 | | | +---+ +---+ +---+ | @@ -37,8 +39,8 @@ | +---+---+---+ +---+---+ +---+---+ +---+ | | | 1 | 2 | 3 |, | 1 | 2 |, | 1 | 3 |, | 1 | | -- +---+---+---+ +---+---+ +---+---+ +---+ -- - sage: three = mupad(3) # optional - mupad - sage: three.combinat.tableaux.list() # optional - mupad + sage: three = mupad(3) + sage: three.combinat.tableaux.list() -- +---+ -- | | 3 | | | +---+ +---+ +---+ | @@ -46,12 +48,12 @@ | +---+---+---+ +---+---+ +---+---+ +---+ | | | 1 | 2 | 3 |, | 1 | 2 |, | 1 | 3 |, | 1 | | -- +---+---+---+ +---+---+ +---+---+ +---+ -- - sage: t = _[1] # optional - mupad - sage: t # optional - mupad + sage: t = _[1] + sage: t +---+---+---+ | 1 | 2 | 3 | +---+---+---+ - sage: combinat.tableaux.conjugate(t) # optional - mupad + sage: combinat.tableaux.conjugate(t) +---+ | 3 | +---+ @@ -60,21 +62,22 @@ | 1 | +---+ - sage: combinat.ribbonsTableaux.list([2,2],[1,1],2) # optional - mupad + sage: # optional - mupad + sage: combinat.ribbonsTableaux.list([2,2],[1,1],2) -- +---+---+ +---+---+ -- | | | 2 | | 2 | | | + + +, +---+---+ | | | 1 | | | 1 | | -- +---+---+ +---+---+ -- - sage: combinat.tableaux.kAtom([2,1],3) # optional - mupad + sage: combinat.tableaux.kAtom([2,1],3) -- +---+ -- | | 2 | | | +---+---+ | | | 1 | 1 | | -- +---+---+ -- - sage: M = S.Macdonald() # optional - mupad - sage: a = M.P[1]^2 # optional - mupad - sage: mupad.mapcoeffs(a, 'normal') # optional - mupad + sage: M = S.Macdonald() + sage: a = M.P[1]^2 + sage: mupad.mapcoeffs(a, 'normal') q - t + q t - 1 P[2] + --------------- P[1, 1] q t - 1 @@ -491,13 +494,14 @@ def __getattr__(self, attrname): """ EXAMPLES:: - sage: mupad.package('"MuPAD-Combinat"') # optional - mupad-Combinat - sage: combinat = mupad.combinat # optional - mupad-Combinat - sage: three = mupad(3) # optional - mupad-Combinat - sage: type(three.combinat) # optional - mupad-Combinat + sage: # optional - mupad + sage: mupad.package('"MuPAD-Combinat"') + sage: combinat = mupad.combinat + sage: three = mupad(3) + sage: type(three.combinat) - sage: tableaux = three.combinat.tableaux # optional - mupad-Combinat - sage: type(tableaux) # optional - mupad-Combinat + sage: tableaux = three.combinat.tableaux + sage: type(tableaux) """ P = self._obj.parent() @@ -528,13 +532,14 @@ def __call__(self, *args): """ EXAMPLES:: - sage: mupad.package('"MuPAD-Combinat"') # optional - mupad-Combinat - sage: combinat = mupad.combinat # optional - mupad-Combinat - sage: examples = mupad.examples # optional - mupad-Combinat - sage: S = examples.SymmetricFunctions() # optional - mupad-Combinat - sage: type(S.omega) # optional - mupad-Combinat + sage: # optional - mupad + sage: mupad.package('"MuPAD-Combinat"') + sage: combinat = mupad.combinat + sage: examples = mupad.examples + sage: S = examples.SymmetricFunctions() + sage: type(S.omega) - sage: S.omega(S.s[3]) # optional - mupad-Combinat + sage: S.omega(S.s[3]) s[1, 1, 1] """ P = self._obj.parent() @@ -551,11 +556,12 @@ def __getattr__(self, attrname): """ EXAMPLES:: - sage: mupad.package('"MuPAD-Combinat"') # optional - mupad-Combinat - sage: S = mupad.examples.SymmetricFunctions() # optional - mupad-Combinat - sage: type(S) # optional - mupad-Combinat + sage: # optional - mupad + sage: mupad.package('"MuPAD-Combinat"') + sage: S = mupad.examples.SymmetricFunctions() + sage: type(S) - sage: S.s # optional - mupad-Combinat + sage: S.s (examples::SymmetricFunctions(Dom::ExpressionField()))::s sage: x = mupad('x') # optional - mupad-Combinat diff --git a/src/sage/interfaces/octave.py b/src/sage/interfaces/octave.py index d0f5694c8bc..10e8457aa0f 100644 --- a/src/sage/interfaces/octave.py +++ b/src/sage/interfaces/octave.py @@ -60,31 +60,32 @@ :: - sage: octave("airy(3,2)") # optional - octave + sage: # optional - octave + sage: octave("airy(3,2)") 4.10068 - sage: octave("beta(2,2)") # optional - octave + sage: octave("beta(2,2)") 0.166667 - sage: octave("betainc(0.2,2,2)") # optional - octave + sage: octave("betainc(0.2,2,2)") 0.104 - sage: octave("besselh(0,2)") # optional - octave + sage: octave("besselh(0,2)") (0.223891,0.510376) - sage: octave("besselh(0,1)") # optional - octave + sage: octave("besselh(0,1)") (0.765198,0.088257) - sage: octave("besseli(1,2)") # optional - octave + sage: octave("besseli(1,2)") 1.59064 - sage: octave("besselj(1,2)") # optional - octave + sage: octave("besselj(1,2)") 0.576725 - sage: octave("besselk(1,2)") # optional - octave + sage: octave("besselk(1,2)") 0.139866 - sage: octave("erf(0)") # optional - octave + sage: octave("erf(0)") 0 - sage: octave("erf(1)") # optional - octave + sage: octave("erf(1)") 0.842701 - sage: octave("erfinv(0.842)") # optional - octave + sage: octave("erfinv(0.842)") 0.998315 - sage: octave("gamma(1.5)") # optional - octave + sage: octave("gamma(1.5)") 0.886227 - sage: octave("gammainc(1.5,1)") # optional - octave + sage: octave("gammainc(1.5,1)") 0.77687 Tutorial @@ -92,37 +93,39 @@ EXAMPLES:: - sage: octave('4+10') # optional - octave + sage: # optional - octave + sage: octave('4+10') 14 - sage: octave('date') # optional - octave; random output + sage: octave('date') 18-Oct-2007 - sage: octave('5*10 + 6') # optional - octave + sage: octave('5*10 + 6') 56 - sage: octave('(6+6)/3') # optional - octave + sage: octave('(6+6)/3') 4 - sage: octave('9')^2 # optional - octave + sage: octave('9')^2 81 - sage: a = octave(10); b = octave(20); c = octave(30) # optional - octave - sage: avg = (a+b+c)/3 # optional - octave - sage: avg # optional - octave + sage: a = octave(10); b = octave(20); c = octave(30) + sage: avg = (a+b+c)/3 + sage: avg 20 - sage: parent(avg) # optional - octave + sage: parent(avg) Octave :: - sage: my_scalar = octave('3.1415') # optional - octave - sage: my_scalar # optional - octave + sage: # optional - octave + sage: my_scalar = octave('3.1415') + sage: my_scalar 3.1415 - sage: my_vector1 = octave('[1,5,7]') # optional - octave - sage: my_vector1 # optional - octave + sage: my_vector1 = octave('[1,5,7]') + sage: my_vector1 1 5 7 - sage: my_vector2 = octave('[1;5;7]') # optional - octave - sage: my_vector2 # optional - octave + sage: my_vector2 = octave('[1;5;7]') + sage: my_vector2 1 5 7 - sage: my_vector1 * my_vector2 # optional - octave + sage: my_vector1 * my_vector2 75 """ @@ -356,11 +359,12 @@ def _start(self): EXAMPLES:: - sage: o = Octave() # optional - octave - sage: o.is_running() # optional - octave + sage: # optional - octave + sage: o = Octave() + sage: o.is_running() False - sage: o._start() # optional - octave - sage: o.is_running() # optional - octave + sage: o._start() + sage: o.is_running() True """ Expect._start(self) @@ -647,13 +651,14 @@ def __bool__(self): EXAMPLES:: - sage: bool(octave('0')) # optional - octave + sage: # optional - octave + sage: bool(octave('0')) False - sage: bool(octave('[]')) # optional - octave + sage: bool(octave('[]')) False - sage: bool(octave('[0,0]')) # optional - octave + sage: bool(octave('[0,0]')) False - sage: bool(octave('[0,0,0;0,0,0]')) # optional - octave + sage: bool(octave('[0,0,0;0,0,0]')) False sage: bool(octave('0.1')) # optional - octave @@ -685,12 +690,13 @@ def _matrix_(self, R=None): sage: _.base_ring() # optional - octave Complex Double Field - sage: A = octave('[1,2;3,4]') # optional - octave - sage: matrix(ZZ, A) # optional - octave + sage: # optional - octave + sage: A = octave('[1,2;3,4]') + sage: matrix(ZZ, A) [1 2] [3 4] - sage: A = octave('[1,2;3,4.5]') # optional - octave - sage: matrix(RR, A) # optional - octave + sage: A = octave('[1,2;3,4.5]') + sage: matrix(RR, A) [1.00000000000000 2.00000000000000] [3.00000000000000 4.50000000000000] """ @@ -716,14 +722,15 @@ def _vector_(self, R=None): EXAMPLES:: - sage: A = octave('[1,2,3,4]') # optional - octave - sage: vector(ZZ, A) # optional - octave + sage: # optional - octave + sage: A = octave('[1,2,3,4]') + sage: vector(ZZ, A) (1, 2, 3, 4) - sage: A = octave('[1,2.3,4.5]') # optional - octave - sage: vector(A) # optional - octave + sage: A = octave('[1,2.3,4.5]') + sage: vector(A) (1.0, 2.3, 4.5) - sage: A = octave('[1,I]') # optional - octave - sage: vector(A) # optional - octave + sage: A = octave('[1,I]') + sage: vector(A) (1.0, 1.0*I) """ from sage.modules.free_module import FreeModule @@ -780,23 +787,24 @@ def _sage_(self): EXAMPLES:: - sage: A = octave('2833') # optional - octave - sage: A.sage() # optional - octave + sage: # optional - octave + sage: A = octave('2833') + sage: A.sage() 2833.0 - sage: B = sqrt(A) # optional - octave - sage: B.sage() # optional - octave + sage: B = sqrt(A) + sage: B.sage() 53.2259 - sage: C = sqrt(-A) # optional - octave - sage: C.sage() # optional - octave + sage: C = sqrt(-A) + sage: C.sage() 53.2259*I - sage: A = octave('[1,2,3,4]') # optional - octave - sage: A.sage() # optional - octave + sage: A = octave('[1,2,3,4]') + sage: A.sage() (1.0, 2.0, 3.0, 4.0) - sage: A = octave('[1,2.3,4.5]') # optional - octave - sage: A.sage() # optional - octave + sage: A = octave('[1,2.3,4.5]') + sage: A.sage() (1.0, 2.3, 4.5) - sage: A = octave('[1,2.3+I,4.5]') # optional - octave - sage: A.sage() # optional - octave + sage: A = octave('[1,2.3+I,4.5]') + sage: A.sage() (1.0, 2.3 + 1.0*I, 4.5) """ if self.isscalar(): diff --git a/src/sage/interfaces/polymake.py b/src/sage/interfaces/polymake.py index 9161ebd5377..3875ff7962e 100644 --- a/src/sage/interfaces/polymake.py +++ b/src/sage/interfaces/polymake.py @@ -243,15 +243,16 @@ def _function_call_string(self, function, args, kwds): EXAMPLES:: - sage: polymake._function_call_string('cube', ['2','7','3'], ['group=>1']) # optional - jupymake + sage: # optional - jupymake + sage: polymake._function_call_string('cube', ['2','7','3'], ['group=>1']) 'cube(2,7,3, group=>1);' - sage: c = polymake('cube(2,7,3, group=>1)') # optional - jupymake - sage: c.VERTICES # optional - jupymake + sage: c = polymake('cube(2,7,3, group=>1)') + sage: c.VERTICES 1 3 3 1 7 3 1 3 7 1 7 7 - sage: c.GROUP # optional - jupymake + sage: c.GROUP full combinatorial group """ @@ -461,13 +462,14 @@ def clear(self, var): TESTS:: - sage: c = polymake.cube(15) # optional - jupymake - sage: polymake._available_vars = [] # optional - jupymake - sage: old = c._name # optional - jupymake - sage: del c # optional - jupymake # indirect doctest - sage: len(polymake._available_vars) # optional - jupymake + sage: # optional - jupymake + sage: c = polymake.cube(15) + sage: polymake._available_vars = [] + sage: old = c._name + sage: del c + sage: len(polymake._available_vars) 1 - sage: polymake._next_var_name() in old # optional - jupymake + sage: polymake._next_var_name() in old True """ @@ -500,13 +502,14 @@ def _create(self, value, name=None): EXAMPLES:: - sage: polymake._create("('foo', 'bar')", name="my_array") # optional - jupymake + sage: # optional - jupymake + sage: polymake._create("('foo', 'bar')", name="my_array") '@my_array' - sage: print(polymake.eval('print join(", ", @my_array);')) # optional - jupymake + sage: print(polymake.eval('print join(", ", @my_array);')) foo, bar - sage: polymake._create('"foobar"', name="my_string") # optional - jupymake + sage: polymake._create('"foobar"', name="my_string") '$my_string[0]' - sage: print(polymake.eval('print $my_string[0];')) # optional - jupymake + sage: print(polymake.eval('print $my_string[0];')) foobar """ @@ -743,20 +746,22 @@ def application(self, app): terms of inequalities. Polymake knows to compute the f- and h-vector and finds that the polytope is very ample:: - sage: q = polymake.new_object("Polytope", INEQUALITIES=[[5,-4,0,1],[-3,0,-4,1],[-2,1,0,0],[-4,4,4,-1],[0,0,1,0],[8,0,0,-1],[1,0,-1,0],[3,-1,0,0]]) # optional - jupymake - sage: q.H_VECTOR # optional - jupymake + sage: # optional - jupymake + sage: q = polymake.new_object("Polytope", INEQUALITIES=[[5,-4,0,1],[-3,0,-4,1],[-2,1,0,0],[-4,4,4,-1],[0,0,1,0],[8,0,0,-1],[1,0,-1,0],[3,-1,0,0]]) + sage: q.H_VECTOR 1 5 5 1 - sage: q.F_VECTOR # optional - jupymake + sage: q.F_VECTOR 8 14 8 - sage: q.VERY_AMPLE # optional - jupymake + sage: q.VERY_AMPLE true In the application 'fan', polymake can now compute the normal fan of `q` and its (primitive) rays:: - sage: polymake.application('fan') # optional - jupymake - sage: g = q.normal_fan() # optional - jupymake - sage: g.RAYS # optional - jupymake + sage: # optional - jupymake + sage: polymake.application('fan') + sage: g = q.normal_fan() + sage: g.RAYS -1 0 1/4 0 -1 1/4 1 0 0 @@ -765,7 +770,7 @@ def application(self, app): 0 0 -1 0 -1 0 -1 0 0 - sage: g.RAYS.primitive() # optional - jupymake + sage: g.RAYS.primitive() -4 0 1 0 -4 1 1 0 0 @@ -784,14 +789,15 @@ def application(self, app): but only in 'tropical', the following shows the effect of changing the application. :: - sage: polymake.application('polytope') # optional - jupymake - sage: 'trop_witness' in dir(polymake) # optional - jupymake + sage: # optional - jupymake + sage: polymake.application('polytope') + sage: 'trop_witness' in dir(polymake) False - sage: polymake.application('tropical') # optional - jupymake - sage: 'trop_witness' in dir(polymake) # optional - jupymake + sage: polymake.application('tropical') + sage: 'trop_witness' in dir(polymake) True - sage: polymake.application('polytope') # optional - jupymake - sage: 'trop_witness' in dir(polymake) # optional - jupymake + sage: polymake.application('polytope') + sage: 'trop_witness' in dir(polymake) False For completeness, we show what happens when asking for an application @@ -827,17 +833,18 @@ def new_object(self, name, *args, **kwds): EXAMPLES:: - sage: q = polymake.new_object("Polytope", INEQUALITIES=[[4,-4,0,1],[-4,0,-4,1],[-2,1,0,0],[-4,4,4,-1],[0,0,1,0],[8,0,0,-1]]) # optional - jupymake - sage: q.N_VERTICES # optional - jupymake + sage: # optional - jupymake + sage: q = polymake.new_object("Polytope", INEQUALITIES=[[4,-4,0,1],[-4,0,-4,1],[-2,1,0,0],[-4,4,4,-1],[0,0,1,0],[8,0,0,-1]]) + sage: q.N_VERTICES 4 - sage: q.BOUNDED # optional - jupymake + sage: q.BOUNDED true - sage: q.VERTICES # optional - jupymake + sage: q.VERTICES 1 2 0 4 1 3 0 8 1 2 1 8 1 3 1 8 - sage: q.full_typename() # optional - jupymake + sage: q.full_typename() 'Polytope' """ @@ -885,11 +892,12 @@ def _repr_(self): of the object that is not longer than single line, it is used for printing:: - sage: p = polymake.rand_sphere(3, 12, seed=15) # optional - jupymake - sage: p # optional - jupymake + sage: # optional - jupymake + sage: p = polymake.rand_sphere(3, 12, seed=15) + sage: p Random spherical polytope of dimension 3; seed=15... - sage: c = polymake.cube(4) # optional - jupymake - sage: c # optional - jupymake + sage: c = polymake.cube(4) + sage: c cube of dimension 4 We use the print representation of scalars to display scalars:: @@ -924,11 +932,12 @@ def _repr_(self): Similarly, polymake matrices and vectors are explicitly listed:: - sage: c.VERTICES.typename() # optional - jupymake + sage: # optional - jupymake + sage: c.VERTICES.typename() 'Matrix' - sage: c.VERTICES[0].typename() # optional - jupymake + sage: c.VERTICES[0].typename() 'Vector' - sage: c.VERTICES # optional - jupymake # random + sage: c.VERTICES 1 -1 -1 -1 -1 1 1 -1 -1 -1 1 -1 1 -1 -1 @@ -945,7 +954,7 @@ def _repr_(self): 1 1 -1 1 1 1 -1 1 1 1 1 1 1 1 1 - sage: c.VERTICES[0] # optional - jupymake + sage: c.VERTICES[0] 1 -1 -1 -1 -1 For other types, we simply use the print representation offered @@ -1225,34 +1234,37 @@ def __getattr__(self, attrname): A property:: - sage: c = polymake.cube(3) # optional - jupymake - sage: c.H_VECTOR # optional - jupymake + sage: # optional - jupymake + sage: c = polymake.cube(3) + sage: c.H_VECTOR 1 5 5 1 - sage: c.N_VERTICES # optional - jupymake + sage: c.N_VERTICES 8 - sage: d = polymake.cross(3) # optional - jupymake - sage: d.N_VERTICES # optional - jupymake + sage: d = polymake.cross(3) + sage: d.N_VERTICES 6 A function:: - sage: c.minkowski_sum_fukuda # optional - jupymake + sage: # optional - jupymake + sage: c.minkowski_sum_fukuda minkowski_sum_fukuda (bound to Polymake::polytope::Polytope__Rational object) - sage: s = c.minkowski_sum_fukuda(d) # optional - jupymake - sage: s.N_VERTICES # optional - jupymake + sage: s = c.minkowski_sum_fukuda(d) + sage: s.N_VERTICES 24 - sage: s # optional - jupymake + sage: s Polytope[SAGE...] A member function:: - sage: c = polymake.cube(2) # optional - jupymake - sage: V = polymake.new_object('Vector', [1,0,0]) # optional - jupymake - sage: V # optional - jupymake + sage: # optional - jupymake + sage: c = polymake.cube(2) + sage: V = polymake.new_object('Vector', [1,0,0]) + sage: V 1 0 0 - sage: c.contains # optional - jupymake + sage: c.contains Member function 'contains' of Polymake::polytope::Polytope__Rational object - sage: c.contains(V) # optional - jupymake + sage: c.contains(V) true """ @@ -1281,13 +1293,14 @@ def get_member_function(self, attrname): EXAMPLES:: - sage: c = polymake.cube(2) # optional - jupymake - sage: c.contains # optional - jupymake + sage: # optional - jupymake + sage: c = polymake.cube(2) + sage: c.contains Member function 'contains' of Polymake::polytope::Polytope__Rational object - sage: V = polymake.new_object('Vector', [1,0,0]) # optional - jupymake - sage: V # optional - jupymake + sage: V = polymake.new_object('Vector', [1,0,0]) + sage: V 1 0 0 - sage: c.contains(V) # optional - jupymake + sage: c.contains(V) true Whether a member function of the given name actually exists for that @@ -1438,12 +1451,13 @@ def typeof(self): EXAMPLES:: - sage: p = polymake.rand_sphere(3, 13, seed=12) # optional - jupymake - sage: p.typeof() # optional - jupymake + sage: # optional - jupymake + sage: p = polymake.rand_sphere(3, 13, seed=12) + sage: p.typeof() ('Polymake::polytope::Polytope__Rational', 'ARRAY') - sage: p.VERTICES.typeof() # optional - jupymake + sage: p.VERTICES.typeof() ('Polymake::common::Matrix_A_Rational_I_NonSymmetric_Z', 'ARRAY') - sage: p.get_schedule('"F_VECTOR"').typeof() # optional - jupymake + sage: p.get_schedule('"F_VECTOR"').typeof() ('Polymake::Core::Scheduler::RuleChain', 'ARRAY') On "small" objects, it just returns empty strings:: @@ -1666,13 +1680,14 @@ class PolymakeFunctionElement(InterfaceFunctionElement): EXAMPLES:: - sage: c = polymake.cube(2) # optional - jupymake - sage: V = polymake.new_object('Vector', [1,0,0]) # optional - jupymake - sage: V # optional - jupymake + sage: # optional - jupymake + sage: c = polymake.cube(2) + sage: V = polymake.new_object('Vector', [1,0,0]) + sage: V 1 0 0 - sage: c.contains # optional - jupymake + sage: c.contains Member function 'contains' of Polymake::polytope::Polytope__Rational object - sage: c.contains(V) # optional - jupymake + sage: c.contains(V) true """ @@ -1840,16 +1855,17 @@ class PolymakeJuPyMake(PolymakeAbstract): :: - sage: L = polymake.db_query({'"_id"': '"F.4D.0047"'}, # long time, optional - jupymake internet perl_mongodb + sage: # long time, optional - internet jupymake perl_mongodb + sage: L = polymake.db_query({'"_id"': '"F.4D.0047"'}, ....: db='"LatticePolytopes"', ....: collection='"SmoothReflexive"'); L BigObjectArray - sage: len(L) # long time, optional - jupymake internet perl_mongodb + sage: len(L) 1 - sage: P = L[0] # long time, optional - jupymake internet perl_mongodb - sage: sorted(P.list_properties(), key=str) # long time, optional - jupymake internet perl_mongodb + sage: P = L[0] + sage: sorted(P.list_properties(), key=str) [..., LATTICE_POINTS_GENERATORS, ..., POINTED, ...] - sage: P.F_VECTOR # long time, optional - jupymake internet perl_mongodb + sage: P.F_VECTOR 20 40 29 9 """ diff --git a/src/sage/interfaces/qepcad.py b/src/sage/interfaces/qepcad.py index b6b657515bc..5a69861eec8 100644 --- a/src/sage/interfaces/qepcad.py +++ b/src/sage/interfaces/qepcad.py @@ -404,13 +404,14 @@ A :class:`QepcadCell` has accessor methods for the important state held within a cell. For instance:: - sage: c.level() # optional - qepcad + sage: # optional - qepcad + sage: c.level() 2 - sage: c.index() # optional - qepcad + sage: c.index() (3, 4) - sage: qe.cell(3).number_of_children() # optional - qepcad + sage: qe.cell(3).number_of_children() 5 - sage: len(qe.cell(3)) # optional - qepcad + sage: len(qe.cell(3)) 5 One particularly useful thing we can get from a cell is its sample point, @@ -574,19 +575,20 @@ sage: _qepcad_atoms(qepcad(F, solution='extended')) # optional - qepcad {'x > _root_1 2 x^2 - 3', 'x^2 - 3 <= 0'} - sage: qe = qepcad(qf.and_(ellipse == 0, circle == 0), interact=True) # optional - qepcad - sage: qe.go(); qe.go(); qe.go() # optional - qepcad + sage: # optional - qepcad + sage: qe = qepcad(qf.and_(ellipse == 0, circle == 0), interact=True) + sage: qe.go(); qe.go(); qe.go() QEPCAD object has moved to phase 'Before Projection (y)' QEPCAD object has moved to phase 'Before Choice' QEPCAD object has moved to phase 'Before Solution' - sage: for c in qe.cell(): # optional - qepcad + sage: for c in qe.cell(): ....: count_ellipse = 0 ....: count_circle = 0 ....: for c2 in c: ....: count_ellipse += (c2.signs()[1][0] == 0) ....: count_circle += (c2.signs()[1][1] == 0) ....: c.set_truth(count_ellipse == 2 and count_circle == 2) - sage: _qepcad_atoms(qe.solution_extension('G')) # optional - qepcad + sage: _qepcad_atoms(qe.solution_extension('G')) {'8 x^2 - 8 x - 29 < 0', 'x^2 - 3 < 0'} @@ -1044,24 +1046,25 @@ def phase(self): EXAMPLES:: - sage: qe = qepcad(x > 2/3, interact=True) # optional - qepcad - sage: qe.phase() # optional - qepcad + sage: # optional - qepcad + sage: qe = qepcad(x > 2/3, interact=True) + sage: qe.phase() 'Before Normalization' - sage: qe.go() # optional - qepcad + sage: qe.go() QEPCAD object has moved to phase 'At the end of projection phase' - sage: qe.phase() # optional - qepcad + sage: qe.phase() 'At the end of projection phase' - sage: qe.go() # optional - qepcad + sage: qe.go() QEPCAD object has moved to phase 'Before Choice' - sage: qe.phase() # optional - qepcad + sage: qe.phase() 'Before Choice' - sage: qe.go() # optional - qepcad + sage: qe.go() QEPCAD object has moved to phase 'Before Solution' - sage: qe.phase() # optional - qepcad + sage: qe.phase() 'Before Solution' - sage: qe.go() # optional - qepcad + sage: qe.go() 3 x - 2 > 0 - sage: qe.phase() # optional - qepcad + sage: qe.phase() 'EXITED' """ match = self._qex.expect().match @@ -1079,13 +1082,14 @@ def _parse_answer_stats(self): EXAMPLES:: - sage: qe = qepcad(x^2 > 2, interact=True) # optional - qepcad - sage: qe.finish() # optional - qepcad + sage: # optional - qepcad + sage: qe = qepcad(x^2 > 2, interact=True) + sage: qe.finish() x^2 - 2 > 0 - sage: (ans, stats) = qe._parse_answer_stats() # optional - qepcad - sage: ans # optional - qepcad + sage: (ans, stats) = qe._parse_answer_stats() + sage: ans 'x^2 - 2 > 0' - sage: stats # random, optional - qepcad + sage: stats '-----------------------------------------------------------------------------\r\n0 Garbage collections, 0 Cells and 0 Arrays reclaimed, in 0 milliseconds.\r\n492514 Cells in AVAIL, 500000 Cells in SPACE.\r\n\r\nSystem time: 16 milliseconds.\r\nSystem time after the initialization: 4 milliseconds.\r\n-----------------------------------------------------------------------------\r\n' """ if self.phase() != 'EXITED': @@ -1168,14 +1172,15 @@ def cell(self, *index): EXAMPLES:: - sage: qe = qepcad(x + 3 == 42, interact=True) # optional - qepcad - sage: qe.go(); qe.go(); qe.go() # optional - qepcad + sage: # optional - qepcad + sage: qe = qepcad(x + 3 == 42, interact=True) + sage: qe.go(); qe.go(); qe.go() QEPCAD object has moved to phase 'At the end of projection phase' QEPCAD object has moved to phase 'Before Choice' QEPCAD object has moved to phase 'Before Solution' - sage: qe.cell(2) # optional - qepcad + sage: qe.cell(2) QEPCAD cell (2) - sage: qe.cell(2) is qe.cell(2) # optional - qepcad + sage: qe.cell(2) is qe.cell(2) True """ index_str = _format_cell_index(index) @@ -2696,16 +2701,17 @@ def sample_point(self): EXAMPLES:: - sage: qe = qepcad(x^2 - x - 1 == 0, interact=True) # optional - qepcad - sage: qe.go(); qe.go(); qe.go() # optional - qepcad + sage: # optional - qepcad + sage: qe = qepcad(x^2 - x - 1 == 0, interact=True) + sage: qe.go(); qe.go(); qe.go() QEPCAD object has moved to phase 'At the end of projection phase' QEPCAD object has moved to phase 'Before Choice' QEPCAD object has moved to phase 'Before Solution' - sage: v1 = qe.cell(2).sample_point()[0]; v1 # optional - qepcad + sage: v1 = qe.cell(2).sample_point()[0]; v1 -0.618033988749895? - sage: v2 = qe.cell(4).sample_point()[0]; v2 # optional - qepcad + sage: v2 = qe.cell(4).sample_point()[0]; v2 1.618033988749895? - sage: v1 + v2 == 1 # optional - qepcad + sage: v1 + v2 == 1 True """ try: diff --git a/src/sage/interfaces/quit.py b/src/sage/interfaces/quit.py index 575646f2365..c10b1414dde 100644 --- a/src/sage/interfaces/quit.py +++ b/src/sage/interfaces/quit.py @@ -63,14 +63,14 @@ def expect_quitall(verbose=False): EXAMPLES:: sage: sage.interfaces.quit.expect_quitall() - sage: gp.eval('a=10') + sage: gp.eval('a=10') # needs sage.libs.pari '10' - sage: gp('a') + sage: gp('a') # needs sage.libs.pari 10 sage: sage.interfaces.quit.expect_quitall() - sage: gp('a') + sage: gp('a') # needs sage.libs.pari a - sage: sage.interfaces.quit.expect_quitall(verbose=True) + sage: sage.interfaces.quit.expect_quitall(verbose=True) # needs sage.libs.pari Exiting PARI/GP interpreter with PID ... running .../gp --fast --emacs --quiet --stacksize 10000000 """ for P in expect_objects: @@ -87,18 +87,18 @@ def kill_spawned_jobs(verbose=False): """ INPUT: - - ``verbose`` -- bool (default: False); if True, display a - message each time a process is sent a kill signal + - ``verbose`` -- bool (default: ``False``); if ``True``, display a + message each time a process is sent a kill signal EXAMPLES:: - sage: gp.eval('a=10') + sage: gp.eval('a=10') # needs sage.libs.pari '10' sage: sage.interfaces.quit.kill_spawned_jobs(verbose=False) sage: sage.interfaces.quit.expect_quitall() - sage: gp.eval('a=10') + sage: gp.eval('a=10') # needs sage.libs.pari '10' - sage: sage.interfaces.quit.kill_spawned_jobs(verbose=True) + sage: sage.interfaces.quit.kill_spawned_jobs(verbose=True) # needs sage.libs.pari Killing spawned job ... After doing the above, we do the following to avoid confusion in other doctests:: @@ -140,6 +140,7 @@ def invalidate_all(): EXAMPLES:: + sage: # needs sage.libs.pari sage.symbolic sage: a = maxima(2); b = gp(3) sage: a, b (2, 3) @@ -151,8 +152,8 @@ def invalidate_all(): However the maxima and gp sessions should still work out, though with their state reset:: - sage: a = maxima(2); b = gp(3) - sage: a, b + sage: a = maxima(2); b = gp(3) # needs sage.libs.pari sage.symbolic + sage: a, b # needs sage.libs.pari sage.symbolic (2, 3) """ for I in expect_objects: diff --git a/src/sage/interfaces/rubik.py b/src/sage/interfaces/rubik.py index 109a2623c95..767c440715d 100644 --- a/src/sage/interfaces/rubik.py +++ b/src/sage/interfaces/rubik.py @@ -137,19 +137,20 @@ def solve(self, facets): EXAMPLES:: - sage: from sage.interfaces.rubik import * # optional - rubiks - sage: solver = DikSolver() # optional - rubiks - sage: solver = OptimalSolver() # optional - rubiks # long time (28s on sage.math, 2012) + sage: # optional - rubiks + sage: from sage.interfaces.rubik import * + sage: solver = DikSolver() + sage: solver = OptimalSolver() # long time (28s on sage.math, 2012) Initializing tables... Done. - sage: C = RubiksCube("R U") # optional - rubiks - sage: solver.solve(C.facets()) # optional - rubiks + sage: C = RubiksCube("R U") + sage: solver.solve(C.facets()) 'R U' - sage: C = RubiksCube("R U F L B D") # optional - rubiks - sage: solver.solve(C.facets()) # optional - rubiks + sage: C = RubiksCube("R U F L B D") + sage: solver.solve(C.facets()) 'R U F L B D' - sage: C = RubiksCube("R2 D2") # optional - rubiks - sage: solver.solve(C.facets()) # optional - rubiks + sage: C = RubiksCube("R2 D2") + sage: solver.solve(C.facets()) 'R2 D2' """ self.ready() @@ -193,21 +194,22 @@ def solve(self, facets): """ EXAMPLES:: - sage: from sage.interfaces.rubik import * # optional - rubiks - sage: C = RubiksCube("R U") # optional - rubiks - sage: CubexSolver().solve(C.facets()) # optional - rubiks + sage: # optional - rubiks + sage: from sage.interfaces.rubik import * + sage: C = RubiksCube("R U") + sage: CubexSolver().solve(C.facets()) 'R U' - sage: C = RubiksCube("R U F L B D") # optional - rubiks - sage: sol = CubexSolver().solve(C.facets()); sol # optional - rubiks + sage: C = RubiksCube("R U F L B D") + sage: sol = CubexSolver().solve(C.facets()); sol "U' L' L' U L U' L U D L L D' L' D L' D' L D L' U' L D' L' U L' B' U' L' U B L D L D' U' L' U L B L B' L' U L U' L' F' L' F L' F L F' L' D' L' D D L D' B L B' L B' L B F' L F F B' L F' B D' D' L D B' B' L' D' B U' U' L' B' D' F' F' L D F'" - sage: RubiksCube(sol) == C # optional - rubiks + sage: RubiksCube(sol) == C True - sage: C = RubiksCube("R2 F'") # optional - rubiks - sage: CubexSolver().solve(C.facets()) # optional - rubiks + sage: C = RubiksCube("R2 F'") + sage: CubexSolver().solve(C.facets()) "R' R' F'" - sage: C = RubiksCube().scramble() # optional - rubiks - sage: sol = CubexSolver().solve(C.facets()) # optional - rubiks - sage: C == RubiksCube(sol) # optional - rubiks + sage: C = RubiksCube().scramble() + sage: sol = CubexSolver().solve(C.facets()) + sage: C == RubiksCube(sol) True """ s = self.format_cube(facets) @@ -245,15 +247,16 @@ def solve(self, facets, timeout=10, extra_time=2): """ EXAMPLES:: - sage: from sage.interfaces.rubik import * # optional - rubiks - sage: C = RubiksCube().move("R U") # optional - rubiks - sage: DikSolver().solve(C.facets()) # optional - rubiks + sage: # optional - rubiks + sage: from sage.interfaces.rubik import * + sage: C = RubiksCube().move("R U") + sage: DikSolver().solve(C.facets()) 'R U' - sage: C = RubiksCube().move("R U F L B D") # optional - rubiks - sage: DikSolver().solve(C.facets()) # optional - rubiks + sage: C = RubiksCube().move("R U F L B D") + sage: DikSolver().solve(C.facets()) 'R U F L B D' - sage: C = RubiksCube().move("R2 F'") # optional - rubiks - sage: DikSolver().solve(C.facets()) # optional - rubiks + sage: C = RubiksCube().move("R2 F'") + sage: DikSolver().solve(C.facets()) "R2 F'" """ cube_str = self.format_cube(facets) diff --git a/src/sage/interfaces/sage0.py b/src/sage/interfaces/sage0.py index 9eddb7019f7..11ece30ac56 100644 --- a/src/sage/interfaces/sage0.py +++ b/src/sage/interfaces/sage0.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.all r""" Interface to Sage @@ -506,9 +507,9 @@ def _sage_(self): EXAMPLES:: - sage: sr = mq.SR(allow_zero_inversions=True) - sage: F,s = sr.polynomial_system() - sage: F == sage0(F)._sage_() + sage: sr = mq.SR(allow_zero_inversions=True) # needs sage.modules sage.rings.finite_rings + sage: F,s = sr.polynomial_system() # needs sage.modules sage.rings.finite_rings + sage: F == sage0(F)._sage_() # needs sage.modules sage.rings.finite_rings True """ P = self.parent() diff --git a/src/sage/interfaces/sagespawn.pyx b/src/sage/interfaces/sagespawn.pyx index 6bb9b90e580..497efc74bba 100644 --- a/src/sage/interfaces/sagespawn.pyx +++ b/src/sage/interfaces/sagespawn.pyx @@ -1,3 +1,4 @@ +# sage.doctest: optional - ptyprocess """ Sage wrapper around pexpect's ``spawn`` class and the ptyprocess's ``PtyProcess`` class. diff --git a/src/sage/interfaces/scilab.py b/src/sage/interfaces/scilab.py index 54c28f55598..b1fd5c1d983 100644 --- a/src/sage/interfaces/scilab.py +++ b/src/sage/interfaces/scilab.py @@ -15,60 +15,65 @@ EXAMPLES:: - sage: scilab.eval('2+2') # optional - scilab + sage: # optional - scilab + sage: scilab.eval('2+2') 'ans =\n \n 4.' - sage: scilab('2+2') # optional - scilab + sage: scilab('2+2') 4. - sage: a = scilab(10) # optional - scilab - sage: a**10 # optional - scilab + sage: a = scilab(10) + sage: a**10 1.000D+10 Tutorial based the MATLAB interface tutorial: EXAMPLES:: - sage: scilab('4+10') # optional - scilab + sage: # optional - scilab + sage: scilab('4+10') 14. - sage: scilab('date') # optional - scilab; random output + sage: scilab('date') 15-Feb-2010 - sage: scilab('5*10 + 6') # optional - scilab + sage: scilab('5*10 + 6') 56. - sage: scilab('(6+6)/3') # optional - scilab + sage: scilab('(6+6)/3') 4. - sage: scilab('9')^2 # optional - scilab + sage: scilab('9')^2 81. - sage: a = scilab(10); b = scilab(20); c = scilab(30) # optional - scilab - sage: avg = (a+b+c)/3 # optional - scilab - sage: avg # optional - scilab + sage: a = scilab(10); b = scilab(20); c = scilab(30) + sage: avg = (a+b+c)/3 + sage: avg 20. - sage: parent(avg) # optional - scilab + sage: parent(avg) Scilab - sage: my_scalar = scilab('3.1415') # optional - scilab - sage: my_scalar # optional - scilab + sage: # optional - scilab + sage: my_scalar = scilab('3.1415') + sage: my_scalar 3.1415 - sage: my_vector1 = scilab('[1,5,7]') # optional - scilab - sage: my_vector1 # optional - scilab + sage: my_vector1 = scilab('[1,5,7]') + sage: my_vector1 1. 5. 7. - sage: my_vector2 = scilab('[1;5;7]') # optional - scilab - sage: my_vector2 # optional - scilab + sage: my_vector2 = scilab('[1;5;7]') + sage: my_vector2 1. 5. 7. - sage: my_vector1 * my_vector2 # optional - scilab + sage: my_vector1 * my_vector2 75. - sage: row_vector1 = scilab('[1 2 3]') # optional - scilab - sage: row_vector2 = scilab('[3 2 1]') # optional - scilab - sage: matrix_from_row_vec = scilab('[%s; %s]'%(row_vector1.name(), row_vector2.name())) # optional - scilab - sage: matrix_from_row_vec # optional - scilab + sage: # optional - scilab + sage: row_vector1 = scilab('[1 2 3]') + sage: row_vector2 = scilab('[3 2 1]') + sage: matrix_from_row_vec = scilab('[%s; %s]'%(row_vector1.name(), row_vector2.name())) + sage: matrix_from_row_vec 1. 2. 3. 3. 2. 1. - sage: column_vector1 = scilab('[1;3]') # optional - scilab - sage: column_vector2 = scilab('[2;8]') # optional - scilab - sage: matrix_from_col_vec = scilab('[%s %s]'%(column_vector1.name(), column_vector2.name())) # optional - scilab - sage: matrix_from_col_vec # optional - scilab + sage: # optional - scilab + sage: column_vector1 = scilab('[1;3]') + sage: column_vector2 = scilab('[2;8]') + sage: matrix_from_col_vec = scilab('[%s %s]'%(column_vector1.name(), column_vector2.name())) + sage: matrix_from_col_vec 1. 2. 3. 8. @@ -90,12 +95,13 @@ sage: tm # optional - scilab 0.5 2.5 4.5 6.5 8.5 - sage: my_vector1 = scilab('[1,5,7]') # optional - scilab - sage: my_vector1(1) # optional - scilab + sage: # optional - scilab + sage: my_vector1 = scilab('[1,5,7]') + sage: my_vector1(1) 1. - sage: my_vector1(2) # optional - scilab + sage: my_vector1(2) 5. - sage: my_vector1(3) # optional - scilab + sage: my_vector1(3) 7. Matrix indexing works as follows:: @@ -113,15 +119,16 @@ Setting using parenthesis cannot work (because of how the Python language works). Use square brackets or the set function:: - sage: my_matrix = scilab('[8, 12, 19; 7, 3, 2; 12, 4, 23; 8, 1, 1]') # optional - scilab - sage: my_matrix.set(2,3, 1999) # optional - scilab - sage: my_matrix # optional - scilab + sage: # optional - scilab + sage: my_matrix = scilab('[8, 12, 19; 7, 3, 2; 12, 4, 23; 8, 1, 1]') + sage: my_matrix.set(2,3, 1999) + sage: my_matrix 8. 12. 19. 7. 3. 1999. 12. 4. 23. 8. 1. 1. - sage: my_matrix[2,3] = -126 # optional - scilab - sage: my_matrix # optional - scilab + sage: my_matrix[2,3] = -126 + sage: my_matrix 8. 12. 19. 7. 3. - 126. 12. 4. 23. @@ -129,39 +136,40 @@ TESTS:: - sage: M = scilab(x) # optional - scilab + sage: # optional - scilab + sage: M = scilab(x) Traceback (most recent call last): ... TypeError: ..._interface_init_() takes exactly one argument (0 given) - sage: M = scilab(matrix(3,range(9))); M # optional - scilab + sage: M = scilab(matrix(3,range(9))); M 0. 1. 2. 3. 4. 5. 6. 7. 8. - sage: M(10) # optional - scilab + sage: M(10) Traceback (most recent call last): ... TypeError: Error executing code in Scilab ... Invalid index. - sage: M[10] # optional - scilab + sage: M[10] Traceback (most recent call last): ... TypeError: Error executing code in Scilab ... Invalid index. - sage: M(4,2) # optional - scilab + sage: M(4,2) Traceback (most recent call last): ... TypeError: Error executing code in Scilab ... Invalid index. - sage: M[2,4] # optional - scilab + sage: M[2,4] Traceback (most recent call last): ... TypeError: Error executing code in Scilab ... Invalid index. - sage: M(9) = x # optional - scilab + sage: M(9) = x Traceback (most recent call last): ... SyntaxError: can...t assign to function call (..., line 1) @@ -199,10 +207,11 @@ class Scilab(Expect): EXAMPLES:: - sage: a = scilab('[ 1, 1, 2; 3, 5, 8; 13, 21, 33 ]') # optional - scilab - sage: b = scilab('[ 1; 3; 13]') # optional - scilab - sage: c = a * b # optional - scilab - sage: print(c) # optional - scilab + sage: # optional - scilab + sage: a = scilab('[ 1, 1, 2; 3, 5, 8; 13, 21, 33 ]') + sage: b = scilab('[ 1; 3; 13]') + sage: c = a * b + sage: print(c) 30. 122. 505. @@ -433,12 +442,13 @@ def __getitem__(self, n): EXAMPLES:: - sage: M = scilab('[1,2,3;4,5,6;7,8,9]') # optional - scilab - sage: M[1] # optional - scilab + sage: # optional - scilab + sage: M = scilab('[1,2,3;4,5,6;7,8,9]') + sage: M[1] 1. - sage: M[7] # optional - scilab + sage: M[7] 3. - sage: M[3,2] # optional - scilab + sage: M[3,2] 8. """ if isinstance(n, tuple): @@ -453,14 +463,15 @@ def __setitem__(self, n, value): EXAMPLES:: - sage: M = scilab('[1,2,3;4,5,6;7,8,9]') # optional - scilab - sage: M[6] = 0 # optional - scilab - sage: M # optional - scilab + sage: # optional - scilab + sage: M = scilab('[1,2,3;4,5,6;7,8,9]') + sage: M[6] = 0 + sage: M 1. 2. 3. 4. 5. 6. 7. 0. 9. - sage: M[3,2] = 10 # optional - scilab - sage: M # optional - scilab + sage: M[3,2] = 10 + sage: M 1. 2. 3. 4. 5. 6. 7. 10. 9. @@ -477,12 +488,13 @@ def _matrix_(self, R): EXAMPLES:: - sage: A = scilab('[1,2;3,4]') # optional - scilab - sage: matrix(ZZ, A) # optional - scilab + sage: # optional - scilab + sage: A = scilab('[1,2;3,4]') + sage: matrix(ZZ, A) [1 2] [3 4] - sage: A = scilab('[1,2;3,4.5]') # optional - scilab - sage: matrix(RR, A) # optional - scilab + sage: A = scilab('[1,2;3,4.5]') + sage: matrix(RR, A) [1.00000000000000 2.00000000000000] [3.00000000000000 4.50000000000000] """ diff --git a/src/sage/interfaces/sympy.py b/src/sage/interfaces/sympy.py index a334c241127..c380731f8b7 100644 --- a/src/sage/interfaces/sympy.py +++ b/src/sage/interfaces/sympy.py @@ -1,3 +1,4 @@ +# sage.doctest: optional - sympy """ SymPy --> Sage conversion diff --git a/src/sage/interfaces/sympy_wrapper.py b/src/sage/interfaces/sympy_wrapper.py index 7f49cb76923..5ad6095a787 100644 --- a/src/sage/interfaces/sympy_wrapper.py +++ b/src/sage/interfaces/sympy_wrapper.py @@ -1,3 +1,4 @@ +# sage.doctest: optional - sympy """ Wrapper Class for Sage Sets as SymPy Sets """ @@ -96,6 +97,7 @@ def is_finite_set(self): EXAMPLES:: + sage: # needs sage.graphs sage: W = WeylGroup(["A",1,1]) sage: sW = W._sympy_(); sW SageSet(Weyl Group of type ['A', 1, 1] (as a matrix group acting on the root space)) @@ -111,6 +113,7 @@ def is_iterable(self): EXAMPLES:: + sage: # needs sage.graphs sage: W = WeylGroup(["A",1,1]) sage: sW = W._sympy_(); sW SageSet(Weyl Group of type ['A', 1, 1] (as a matrix group acting on the root space)) @@ -167,6 +170,7 @@ def __len__(self): EXAMPLES:: + sage: # needs sage.graphs sage: sB3 = WeylGroup(["B", 3])._sympy_(); sB3 SageSet(Weyl Group of type ['B', 3] (as a matrix group acting on the ambient space)) sage: len(sB3) diff --git a/src/sage/interfaces/tests.py b/src/sage/interfaces/tests.py index 8c760c2a2c0..13f755b4d11 100644 --- a/src/sage/interfaces/tests.py +++ b/src/sage/interfaces/tests.py @@ -13,9 +13,9 @@ 4 sage: parent(a) Gap - sage: a = 2 * maxima('2'); a + sage: a = 2 * maxima('2'); a # needs sage.symbolic 4 - sage: parent(a) + sage: parent(a) # needs sage.symbolic Maxima sage: a = 2 * singular('2'); a 4 diff --git a/src/sage/interfaces/tides.py b/src/sage/interfaces/tides.py index f70a2357cd3..1b00f52df54 100644 --- a/src/sage/interfaces/tides.py +++ b/src/sage/interfaces/tides.py @@ -37,8 +37,10 @@ - [TIDES]_ """ + from sage.rings.real_mpfr import RealField -from sage.calculus.all import symbolic_expression +from sage.misc.lazy_import import lazy_import +lazy_import("sage.calculus.all", "symbolic_expression") from sage.misc.flatten import flatten from sage.ext.fast_callable import fast_callable from sage.rings.semirings.non_negative_integer_semiring import NN diff --git a/src/sage/libs/arb/acb.pxd b/src/sage/libs/arb/acb.pxd index 5148dc43991..851488d803a 100644 --- a/src/sage/libs/arb/acb.pxd +++ b/src/sage/libs/arb/acb.pxd @@ -1,4 +1,4 @@ -# distutils: libraries = gmp flint ARB_LIBRARY +# distutils: libraries = gmp flint # distutils: depends = acb.h from sage.libs.arb.types cimport * @@ -152,10 +152,6 @@ cdef extern from "arb_wrap.h": void acb_sech(acb_t s, const acb_t z, long prec) void acb_csch(acb_t c, const acb_t z, long prec) - void acb_rising_ui_bs(acb_t z, const acb_t x, unsigned long n, long prec) - void acb_rising_ui_rs(acb_t z, const acb_t x, unsigned long n, unsigned long step, long prec) - void acb_rising_ui_rec(acb_t z, const acb_t x, unsigned long n, long prec) - void acb_rising_ui(acb_t z, const acb_t x, unsigned long n, long prec) void acb_rising(acb_t z, const acb_t x, const acb_t n, long prec) void acb_gamma(acb_t y, const acb_t x, long prec) diff --git a/src/sage/libs/arb/acb_calc.pxd b/src/sage/libs/arb/acb_calc.pxd index a5dbf360b5e..67bd2ed57dc 100644 --- a/src/sage/libs/arb/acb_calc.pxd +++ b/src/sage/libs/arb/acb_calc.pxd @@ -1,4 +1,4 @@ -# distutils: libraries = gmp flint ARB_LIBRARY +# distutils: libraries = gmp flint # distutils: depends = acb_calc.h from sage.libs.arb.types cimport * diff --git a/src/sage/libs/arb/acb_elliptic.pxd b/src/sage/libs/arb/acb_elliptic.pxd index 176f68df00e..e3480e9f73b 100644 --- a/src/sage/libs/arb/acb_elliptic.pxd +++ b/src/sage/libs/arb/acb_elliptic.pxd @@ -1,4 +1,4 @@ -# distutils: libraries = gmp flint ARB_LIBRARY +# distutils: libraries = gmp flint # distutils: depends = acb_elliptic.h from sage.libs.arb.types cimport * diff --git a/src/sage/libs/arb/acb_hypgeom.pxd b/src/sage/libs/arb/acb_hypgeom.pxd index 418e766f10d..c43e5c0623b 100644 --- a/src/sage/libs/arb/acb_hypgeom.pxd +++ b/src/sage/libs/arb/acb_hypgeom.pxd @@ -1,4 +1,4 @@ -# distutils: libraries = gmp flint ARB_LIBRARY +# distutils: libraries = gmp flint # distutils: depends = acb_hypgeom.h from sage.libs.arb.types cimport * diff --git a/src/sage/libs/arb/acb_modular.pxd b/src/sage/libs/arb/acb_modular.pxd index c708e9bf97d..cdc413c92da 100644 --- a/src/sage/libs/arb/acb_modular.pxd +++ b/src/sage/libs/arb/acb_modular.pxd @@ -1,4 +1,4 @@ -# distutils: libraries = gmp flint ARB_LIBRARY +# distutils: libraries = gmp flint # distutils: depends = acb_modular.h from sage.libs.arb.types cimport * diff --git a/src/sage/libs/arb/acb_poly.pxd b/src/sage/libs/arb/acb_poly.pxd index 69f4320055b..ae02757ffd9 100644 --- a/src/sage/libs/arb/acb_poly.pxd +++ b/src/sage/libs/arb/acb_poly.pxd @@ -1,4 +1,4 @@ -# distutils: libraries = gmp flint ARB_LIBRARY +# distutils: libraries = gmp flint # distutils: depends = acb_poly.h from sage.libs.arb.types cimport * @@ -79,24 +79,10 @@ cdef extern from "arb_wrap.h": void _acb_poly_divrem(acb_ptr Q, acb_ptr R, acb_srcptr A, long lenA, acb_srcptr B, long lenB, long prec) bint acb_poly_divrem(acb_poly_t Q, acb_poly_t R, const acb_poly_t A, const acb_poly_t B, long prec) void _acb_poly_div_root(acb_ptr Q, acb_t R, acb_srcptr A, long len, const acb_t c, long prec) - void _acb_poly_taylor_shift_horner(acb_ptr g, const acb_t c, long n, long prec) - void acb_poly_taylor_shift_horner(acb_poly_t g, const acb_poly_t f, const acb_t c, long prec) - void _acb_poly_taylor_shift_divconquer(acb_ptr g, const acb_t c, long n, long prec) - void acb_poly_taylor_shift_divconquer(acb_poly_t g, const acb_poly_t f, const acb_t c, long prec) - void _acb_poly_taylor_shift_convolution(acb_ptr g, const acb_t c, long n, long prec) - void acb_poly_taylor_shift_convolution(acb_poly_t g, const acb_poly_t f, const acb_t c, long prec) void _acb_poly_taylor_shift(acb_ptr g, const acb_t c, long n, long prec) void acb_poly_taylor_shift(acb_poly_t g, const acb_poly_t f, const acb_t c, long prec) - void _acb_poly_compose_horner(acb_ptr res, acb_srcptr poly1, long len1, acb_srcptr poly2, long len2, long prec) - void acb_poly_compose_horner(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, long prec) - void _acb_poly_compose_divconquer(acb_ptr res, acb_srcptr poly1, long len1, acb_srcptr poly2, long len2, long prec) - void acb_poly_compose_divconquer(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, long prec) void _acb_poly_compose(acb_ptr res, acb_srcptr poly1, long len1, acb_srcptr poly2, long len2, long prec) void acb_poly_compose(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, long prec) - void _acb_poly_compose_series_horner(acb_ptr res, acb_srcptr poly1, long len1, acb_srcptr poly2, long len2, long n, long prec) - void acb_poly_compose_series_horner(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, long n, long prec) - void _acb_poly_compose_series_brent_kung(acb_ptr res, acb_srcptr poly1, long len1, acb_srcptr poly2, long len2, long n, long prec) - void acb_poly_compose_series_brent_kung(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, long n, long prec) void _acb_poly_compose_series(acb_ptr res, acb_srcptr poly1, long len1, acb_srcptr poly2, long len2, long n, long prec) void acb_poly_compose_series(acb_poly_t res, const acb_poly_t poly1, const acb_poly_t poly2, long n, long prec) void _acb_poly_revert_series_lagrange(acb_ptr h, acb_srcptr f, long flen, long n, long prec) @@ -161,10 +147,6 @@ cdef extern from "arb_wrap.h": void acb_poly_exp_series_basecase(acb_poly_t f, const acb_poly_t h, long n, long prec) void _acb_poly_exp_series(acb_ptr f, acb_srcptr h, long hlen, long n, long prec) void acb_poly_exp_series(acb_poly_t f, const acb_poly_t h, long n, long prec) - void _acb_poly_sin_cos_series_basecase(acb_ptr s, acb_ptr c, acb_srcptr h, long hlen, long n, long prec, int times_pi) - void acb_poly_sin_cos_series_basecase(acb_poly_t s, acb_poly_t c, const acb_poly_t h, long n, long prec, int times_pi) - void _acb_poly_sin_cos_series_tangent(acb_ptr s, acb_ptr c, acb_srcptr h, long hlen, long n, long prec, int times_pi) - void acb_poly_sin_cos_series_tangent(acb_poly_t s, acb_poly_t c, const acb_poly_t h, long n, long prec, int times_pi) void _acb_poly_sin_cos_series(acb_ptr s, acb_ptr c, acb_srcptr h, long hlen, long n, long prec) void acb_poly_sin_cos_series(acb_poly_t s, acb_poly_t c, const acb_poly_t h, long n, long prec) void _acb_poly_sin_series(acb_ptr s, acb_srcptr h, long hlen, long n, long prec) diff --git a/src/sage/libs/arb/arb.pxd b/src/sage/libs/arb/arb.pxd index c82b94de30f..acd232ab816 100644 --- a/src/sage/libs/arb/arb.pxd +++ b/src/sage/libs/arb/arb.pxd @@ -1,4 +1,4 @@ -# distutils: libraries = gmp flint ARB_LIBRARY +# distutils: libraries = gmp flint # distutils: depends = arb.h from sage.libs.arb.types cimport * @@ -224,15 +224,8 @@ cdef extern from "arb_wrap.h": void arb_lambertw(arb_t res, const arb_t x, int flags, long prec) - void arb_rising_ui_bs(arb_t z, const arb_t x, unsigned long n, long prec) - void arb_rising_ui_rs(arb_t z, const arb_t x, unsigned long n, unsigned long step, long prec) - void arb_rising_ui_rec(arb_t z, const arb_t x, unsigned long n, long prec) - void arb_rising_ui(arb_t z, const arb_t x, unsigned long n, long prec) void arb_rising(arb_t z, const arb_t x, const arb_t n, long prec) void arb_rising_fmpq_ui(arb_t z, const fmpq_t x, unsigned long n, long prec) - void arb_rising2_ui_bs(arb_t u, arb_t v, const arb_t x, unsigned long n, long prec) - void arb_rising2_ui_rs(arb_t u, arb_t v, const arb_t x, unsigned long n, unsigned long step, long prec) - void arb_rising2_ui(arb_t u, arb_t v, const arb_t x, unsigned long n, long prec) void arb_fac_ui(arb_t z, unsigned long n, long prec) void arb_bin_ui(arb_t z, const arb_t n, unsigned long k, long prec) void arb_bin_uiui(arb_t z, unsigned long n, unsigned long k, long prec) diff --git a/src/sage/libs/arb/arb_fmpz_poly.pxd b/src/sage/libs/arb/arb_fmpz_poly.pxd index 079f76e9d9e..55daa705238 100644 --- a/src/sage/libs/arb/arb_fmpz_poly.pxd +++ b/src/sage/libs/arb/arb_fmpz_poly.pxd @@ -1,4 +1,4 @@ -# distutils: libraries = gmp flint ARB_LIBRARY +# distutils: libraries = gmp flint # distutils: depends = arb_fmpz_poly.h from sage.libs.arb.types cimport * @@ -22,5 +22,4 @@ cdef extern from "arb_wrap.h": unsigned long arb_fmpz_poly_deflation(const fmpz_poly_t poly) void arb_fmpz_poly_deflate(fmpz_poly_t res, const fmpz_poly_t poly, unsigned long deflation) void arb_fmpz_poly_complex_roots(acb_ptr roots, const fmpz_poly_t poly, int flags, long prec) - void arb_fmpz_poly_cos_minpoly(fmpz_poly_t res, unsigned long n) void arb_fmpz_poly_gauss_period_minpoly(fmpz_poly_t res, unsigned long q, unsigned long n) diff --git a/src/sage/libs/arb/arb_hypgeom.pxd b/src/sage/libs/arb/arb_hypgeom.pxd index fb1c40ddaa8..139b987d669 100644 --- a/src/sage/libs/arb/arb_hypgeom.pxd +++ b/src/sage/libs/arb/arb_hypgeom.pxd @@ -1,4 +1,4 @@ -# distutils: libraries = gmp flint ARB_LIBRARY +# distutils: libraries = gmp flint # distutils: depends = arb_hypgeom.h from sage.libs.flint.types cimport fmpz_t diff --git a/src/sage/libs/arb/arb_wrap.h b/src/sage/libs/arb/arb_wrap.h index 49997075ee5..488bb376d5e 100644 --- a/src/sage/libs/arb/arb_wrap.h +++ b/src/sage/libs/arb/arb_wrap.h @@ -5,25 +5,27 @@ * by arb, most of which rely on flint's ulong and slong defines. */ +#include + #undef ulong #undef slong #define ulong mp_limb_t #define slong mp_limb_signed_t -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #undef ulong #undef slong diff --git a/src/sage/libs/arb/arf.pxd b/src/sage/libs/arb/arf.pxd index b8b83fefcdc..84778fe9f09 100644 --- a/src/sage/libs/arb/arf.pxd +++ b/src/sage/libs/arb/arf.pxd @@ -1,4 +1,4 @@ -# distutils: libraries = gmp flint ARB_LIBRARY +# distutils: libraries = gmp flint # distutils: depends = arf.h from sage.libs.arb.types cimport * @@ -30,7 +30,6 @@ cdef extern from "arb_wrap.h": void arf_set_ui(arf_t y, unsigned long x) void arf_set_si(arf_t y, long x) void arf_set_mpfr(arf_t y, const mpfr_t x) - # void arf_set_fmpr(arf_t y, const fmpr_t x) void arf_set_d(arf_t y, double x) void arf_swap(arf_t y, arf_t x) void arf_init_set_ui(arf_t y, unsigned long x) @@ -46,7 +45,6 @@ cdef extern from "arb_wrap.h": int arf_set_round_fmpz_2exp(arf_t y, const fmpz_t x, const fmpz_t e, long prec, arf_rnd_t rnd) void arf_get_fmpz_2exp(fmpz_t m, fmpz_t e, const arf_t x) double arf_get_d(const arf_t x, arf_rnd_t rnd) - # void arf_get_fmpr(fmpr_t y, const arf_t x) int arf_get_mpfr(mpfr_t y, const arf_t x, mpfr_rnd_t rnd) void arf_get_fmpz(fmpz_t z, const arf_t x, arf_rnd_t rnd) long arf_get_si(const arf_t x, arf_rnd_t rnd) diff --git a/src/sage/libs/arb/bernoulli.pxd b/src/sage/libs/arb/bernoulli.pxd index f859ebfb8d7..95a84dd5179 100644 --- a/src/sage/libs/arb/bernoulli.pxd +++ b/src/sage/libs/arb/bernoulli.pxd @@ -1,4 +1,4 @@ -# distutils: libraries = gmp flint ARB_LIBRARY +# distutils: libraries = gmp flint # distutils: depends = bernoulli.h from sage.libs.flint.types cimport fmpq_t, ulong diff --git a/src/sage/libs/arb/mag.pxd b/src/sage/libs/arb/mag.pxd index d5d8693ea8f..69dfb990ae0 100644 --- a/src/sage/libs/arb/mag.pxd +++ b/src/sage/libs/arb/mag.pxd @@ -1,4 +1,4 @@ -# distutils: libraries = gmp flint ARB_LIBRARY +# distutils: libraries = gmp flint # distutils: depends = mag.h from sage.libs.arb.types cimport * @@ -27,13 +27,11 @@ cdef extern from "arb_wrap.h": # void mag_randtest(mag_t x, flint_rand_t state, long expbits) # void mag_randtest_special(mag_t x, flint_rand_t state, long expbits) void mag_set_d(mag_t y, double x) - # void mag_set_fmpr(mag_t y, const fmpr_t x) void mag_set_ui(mag_t y, unsigned long x) void mag_set_fmpz(mag_t y, const fmpz_t x) void mag_set_d_2exp_fmpz(mag_t z, double x, const fmpz_t y) void mag_set_fmpz_2exp_fmpz(mag_t z, const fmpz_t x, const fmpz_t y) void mag_set_ui_2exp_si(mag_t z, unsigned long x, long y) - # void mag_get_fmpr(fmpr_t y, const mag_t x) void mag_get_fmpq(fmpq_t y, const mag_t x) void mag_set_ui_lower(mag_t z, unsigned long x) void mag_set_fmpz_lower(mag_t z, const fmpz_t x) diff --git a/src/sage/libs/coxeter3/__init__.py b/src/sage/libs/coxeter3/__init__.py index e69de29bb2d..61138b7bc1a 100644 --- a/src/sage/libs/coxeter3/__init__.py +++ b/src/sage/libs/coxeter3/__init__.py @@ -0,0 +1 @@ +# sage_setup: distribution = sagemath-coxeter3 diff --git a/src/sage/libs/coxeter3/all__sagemath_coxeter3.py b/src/sage/libs/coxeter3/all__sagemath_coxeter3.py index e69de29bb2d..61138b7bc1a 100644 --- a/src/sage/libs/coxeter3/all__sagemath_coxeter3.py +++ b/src/sage/libs/coxeter3/all__sagemath_coxeter3.py @@ -0,0 +1 @@ +# sage_setup: distribution = sagemath-coxeter3 diff --git a/src/sage/libs/flint/flint_wrap.h b/src/sage/libs/flint/flint_wrap.h index 266535c3835..4db72b97660 100644 --- a/src/sage/libs/flint/flint_wrap.h +++ b/src/sage/libs/flint/flint_wrap.h @@ -15,6 +15,7 @@ */ #include +#include /* Save previous definition of ulong if any, as pari also uses it */ /* Should work on GCC, clang, MSVC */ @@ -33,6 +34,7 @@ #include #include +#include #include #include #include @@ -47,6 +49,7 @@ #include #include #include +#include #include #include #include diff --git a/src/sage/libs/flint/fmpq.pxd b/src/sage/libs/flint/fmpq.pxd index 5e64c82102f..0616c0a7408 100644 --- a/src/sage/libs/flint/fmpq.pxd +++ b/src/sage/libs/flint/fmpq.pxd @@ -12,6 +12,8 @@ cdef extern from "flint_wrap.h": fmpz * fmpq_denref(fmpq_t) void fmpq_init(fmpq_t) void fmpq_clear(fmpq_t) + void fmpq_init_set_readonly(fmpq_t, const mpq_t) + void fmpq_clear_readonly(fmpq_t) void fmpq_one(fmpq_t) void fmpq_zero(fmpq_t) bint fmpq_is_zero(fmpq_t) diff --git a/src/sage/libs/flint/fmpq_poly.pxd b/src/sage/libs/flint/fmpq_poly.pxd index 6050c487835..afa16e5bbdd 100644 --- a/src/sage/libs/flint/fmpq_poly.pxd +++ b/src/sage/libs/flint/fmpq_poly.pxd @@ -30,6 +30,9 @@ cdef extern from "flint_wrap.h": void fmpq_poly_canonicalise(fmpq_poly_t) int fmpq_poly_is_canonical(const fmpq_poly_t) + void _fmpq_poly_set_length(fmpq_poly_t, slong) + void _fmpq_poly_normalise(fmpq_poly_t) + # Polynomial parameters slong fmpq_poly_degree(const fmpq_poly_t) ulong fmpq_poly_length(const fmpq_poly_t) @@ -46,10 +49,7 @@ cdef extern from "flint_wrap.h": void fmpq_poly_set_ui(fmpq_poly_t, ulong) void fmpq_poly_set_fmpz(fmpq_poly_t, const fmpz_t) void fmpq_poly_set_fmpq(fmpq_poly_t, const fmpq_t) - void fmpq_poly_set_mpz(fmpq_poly_t, const mpz_t) - void fmpq_poly_set_mpq(fmpq_poly_t, const mpq_t) void fmpq_poly_set_fmpz_poly(fmpq_poly_t, const fmpz_poly_t) - void fmpq_poly_set_array_mpq(fmpq_poly_t, const mpq_t *, slong) void fmpq_poly_set_str(fmpq_poly_t, const char *) char *fmpq_poly_get_str(const fmpq_poly_t) @@ -67,7 +67,6 @@ cdef extern from "flint_wrap.h": void fmpq_poly_reverse(fmpq_poly_t, const fmpq_poly_t, slong) void fmpq_poly_get_coeff_fmpq(fmpq_t, const fmpq_poly_t, slong) - void fmpq_poly_get_coeff_mpq(mpq_t, const fmpq_poly_t, slong) void fmpq_poly_get_coeff_si(slong, const fmpq_poly_t, slong) void fmpq_poly_get_coeff_ui(ulong, const fmpq_poly_t, slong) @@ -75,8 +74,6 @@ cdef extern from "flint_wrap.h": void fmpq_poly_set_coeff_ui(fmpq_poly_t, slong, ulong) void fmpq_poly_set_coeff_fmpz(fmpq_poly_t, slong, const fmpz_t) void fmpq_poly_set_coeff_fmpq(fmpq_poly_t, slong, const fmpq_t) - void fmpq_poly_set_coeff_mpz(fmpq_poly_t, slong, const mpz_t) - void fmpq_poly_set_coeff_mpq(fmpq_poly_t, slong, const mpq_t) # Comparison int fmpq_poly_equal(const fmpq_poly_t, const fmpq_poly_t) @@ -100,8 +97,6 @@ cdef extern from "flint_wrap.h": fmpq_poly_t, const fmpq_poly_t, const fmpz_t) void fmpq_poly_scalar_mul_fmpq( fmpq_poly_t, const fmpq_poly_t, const fmpq_t) - void fmpq_poly_scalar_mul_mpz(fmpq_poly_t, const fmpq_poly_t, const mpz_t) - void fmpq_poly_scalar_mul_mpq(fmpq_poly_t, const fmpq_poly_t, const mpq_t) void fmpq_poly_scalar_div_si(fmpq_poly_t, const fmpq_poly_t, slong) void fmpq_poly_scalar_div_ui(fmpq_poly_t, const fmpq_poly_t, ulong) @@ -109,8 +104,6 @@ cdef extern from "flint_wrap.h": fmpq_poly_t, const fmpq_poly_t, const fmpz_t) void fmpq_poly_scalar_div_fmpq( fmpq_poly_t, const fmpq_poly_t, const fmpq_t) - void fmpq_poly_scalar_div_mpz(fmpq_poly_t, const fmpq_poly_t, const mpz_t) - void fmpq_poly_scalar_div_mpq(fmpq_poly_t, const fmpq_poly_t, const mpq_t) # Multiplication void fmpq_poly_mul(fmpq_poly_t, const fmpq_poly_t, const fmpq_poly_t) @@ -155,8 +148,6 @@ cdef extern from "flint_wrap.h": # Evaluation void fmpq_poly_evaluate_fmpz(fmpq_t, const fmpq_poly_t, const fmpz_t) void fmpq_poly_evaluate_fmpq(fmpq_t, const fmpq_poly_t, const fmpq_t) - void fmpq_poly_evaluate_mpz(mpq_t, const fmpq_poly_t, const mpz_t) - void fmpq_poly_evaluate_mpq(mpq_t, const fmpq_poly_t, const mpq_t) # Composition void fmpq_poly_compose(fmpq_poly_t, const fmpq_poly_t, const fmpq_poly_t) @@ -189,3 +180,11 @@ cdef extern from "flint_wrap.h": # since the fmpq_poly header seems to be lacking this inline function cdef inline sage_fmpq_poly_max_limbs(const fmpq_poly_t poly) noexcept: return _fmpz_vec_max_limbs(fmpq_poly_numref(poly), fmpq_poly_length(poly)) + +# functions removed from flint but still needed in sage +cdef void fmpq_poly_scalar_mul_mpz(fmpq_poly_t, const fmpq_poly_t, const mpz_t) +cdef void fmpq_poly_scalar_mul_mpq(fmpq_poly_t, const fmpq_poly_t, const mpq_t) +cdef void fmpq_poly_set_coeff_mpq(fmpq_poly_t, slong, const mpq_t) +cdef void fmpq_poly_get_coeff_mpq(mpq_t, const fmpq_poly_t, slong) +cdef void fmpq_poly_set_mpz(fmpq_poly_t, const mpz_t) +cdef void fmpq_poly_set_mpq(fmpq_poly_t, const mpq_t) diff --git a/src/sage/libs/flint/fmpq_poly.pyx b/src/sage/libs/flint/fmpq_poly.pyx new file mode 100644 index 00000000000..3b8a0cf0c51 --- /dev/null +++ b/src/sage/libs/flint/fmpq_poly.pyx @@ -0,0 +1,45 @@ +# Functions removed from flint but still needed in Sage. Code adapted from +# earlier versions of flint. + +from sage.libs.gmp.mpq cimport * +from sage.libs.flint.fmpz cimport * +from sage.libs.flint.fmpq cimport * + +cdef void fmpq_poly_scalar_mul_mpz(fmpq_poly_t rop, const fmpq_poly_t op, const mpz_t c): + cdef fmpz_t f + fmpz_init_set_readonly(f, c) + fmpq_poly_scalar_mul_fmpz(rop, op, f) + fmpz_clear_readonly(f) + +cdef void fmpq_poly_scalar_mul_mpq(fmpq_poly_t rop, const fmpq_poly_t op, const mpq_t c): + cdef fmpq_t f + fmpq_init_set_readonly(f, c) + fmpq_poly_scalar_mul_fmpq(rop, op, f) + fmpq_clear_readonly(f) + +cdef void fmpq_poly_set_coeff_mpq(fmpq_poly_t poly, slong n, const mpq_t x): + cdef fmpq_t t + fmpq_init_set_readonly(t, x) + fmpq_poly_set_coeff_fmpq(poly, n, t) + fmpq_clear_readonly(t) + +cdef void fmpq_poly_get_coeff_mpq(mpq_t x, const fmpq_poly_t poly, slong n): + cdef fmpq_t t + fmpq_init(t) + fmpq_poly_get_coeff_fmpq(t, poly, n) + fmpq_get_mpq(x, t) + fmpq_clear(t) + +cdef void fmpq_poly_set_mpq(fmpq_poly_t poly, const mpq_t x): + fmpq_poly_fit_length(poly, 1) + fmpz_set_mpz(fmpq_poly_numref(poly), mpq_numref(x)) + fmpz_set_mpz(fmpq_poly_denref(poly), mpq_denref(x)) + _fmpq_poly_set_length(poly, 1) + _fmpq_poly_normalise(poly) + +cdef void fmpq_poly_set_mpz(fmpq_poly_t poly, const mpz_t x): + fmpq_poly_fit_length(poly, 1) + fmpz_set_mpz(fmpq_poly_numref(poly), x) + fmpz_one(fmpq_poly_denref(poly)) + _fmpq_poly_set_length(poly, 1) + _fmpq_poly_normalise(poly) diff --git a/src/sage/libs/flint/fmpz.pxd b/src/sage/libs/flint/fmpz.pxd index 01058d0f130..b97fbe1eae0 100644 --- a/src/sage/libs/flint/fmpz.pxd +++ b/src/sage/libs/flint/fmpz.pxd @@ -16,6 +16,9 @@ cdef extern from "flint_wrap.h": void fmpz_init_set(fmpz_t, fmpz_t) void fmpz_init_set_ui(fmpz_t, ulong) + void fmpz_init_set_readonly(fmpz_t, const mpz_t) + void fmpz_clear_readonly(fmpz_t) + # Conversion void fmpz_set(fmpz_t f, fmpz_t g) void fmpz_set_ui(fmpz_t, ulong) diff --git a/src/sage/libs/flint/fmpz_mod_poly.pxd b/src/sage/libs/flint/fmpz_mod_poly.pxd index 24b653eb3b7..2727246da98 100644 --- a/src/sage/libs/flint/fmpz_mod_poly.pxd +++ b/src/sage/libs/flint/fmpz_mod_poly.pxd @@ -67,13 +67,6 @@ cdef extern from "flint_wrap.h": void fmpz_mod_poly_get_coeff_fmpz(fmpz_t x, const fmpz_mod_poly_t poly, slong n, const fmpz_mod_ctx_t ctx) - void fmpz_mod_poly_set_coeff_mpz(fmpz_mod_poly_t poly, - slong n, const mpz_t x, const fmpz_mod_ctx_t ctx) - - void fmpz_mod_poly_get_coeff_mpz(mpz_t x, - const fmpz_mod_poly_t poly, slong n, const fmpz_mod_ctx_t ctx) - - void _fmpz_mod_poly_shift_left(fmpz * res, const fmpz * poly, slong len, slong n) @@ -194,14 +187,6 @@ cdef extern from "flint_wrap.h": const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) - void fmpz_mod_poly_div_basecase(fmpz_mod_poly_t Q, - const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, - const fmpz_mod_ctx_t ctx) - - void fmpz_mod_poly_div_newton_n_preinv(fmpz_mod_poly_t Q, - const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, - const fmpz_mod_poly_t Binv, const fmpz_mod_ctx_t ctx) - void fmpz_mod_poly_divrem_newton_n_preinv(fmpz_mod_poly_t Q, fmpz_mod_poly_t R, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_poly_t Binv, const fmpz_mod_ctx_t ctx) @@ -213,10 +198,6 @@ cdef extern from "flint_wrap.h": const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) - void fmpz_mod_poly_divrem_divconquer(fmpz_mod_poly_t Q, - fmpz_mod_poly_t R, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, - const fmpz_mod_ctx_t ctx) - void fmpz_mod_poly_divrem(fmpz_mod_poly_t Q, fmpz_mod_poly_t R, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) @@ -254,40 +235,13 @@ cdef extern from "flint_wrap.h": void fmpz_mod_poly_make_monic_f(fmpz_t f, fmpz_mod_poly_t res, const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx) - void fmpz_mod_poly_gcd_euclidean(fmpz_mod_poly_t G, - const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, - const fmpz_mod_ctx_t ctx) - - void fmpz_mod_poly_gcd_euclidean_f(fmpz_t f, fmpz_mod_poly_t G, - const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, - const fmpz_mod_ctx_t ctx) - void fmpz_mod_poly_gcd_f(fmpz_t f, fmpz_mod_poly_t G, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) - void fmpz_mod_poly_gcd_hgcd(fmpz_mod_poly_t G, - const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, - const fmpz_mod_ctx_t ctx) - - void fmpz_mod_poly_gcd(fmpz_mod_poly_t G, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) - void fmpz_mod_poly_xgcd_euclidean(fmpz_mod_poly_t G, - fmpz_mod_poly_t S, fmpz_mod_poly_t T, - const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, - const fmpz_mod_ctx_t ctx) - - void fmpz_mod_poly_xgcd_euclidean_f(fmpz_t f, fmpz_mod_poly_t G, - fmpz_mod_poly_t S, fmpz_mod_poly_t T, - const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, - const fmpz_mod_ctx_t ctx) - - void fmpz_mod_poly_xgcd_hgcd(fmpz_mod_poly_t G, fmpz_mod_poly_t S, - fmpz_mod_poly_t T, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, - const fmpz_mod_ctx_t ctx) - void fmpz_mod_poly_xgcd(fmpz_mod_poly_t G, fmpz_mod_poly_t S, fmpz_mod_poly_t T, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, const fmpz_mod_ctx_t ctx) @@ -361,14 +315,6 @@ cdef extern from "flint_wrap.h": const fmpz_mod_poly_t poly, const fmpz * xs, slong n, const fmpz_mod_ctx_t ctx) - void fmpz_mod_poly_compose_horner(fmpz_mod_poly_t res, - const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, - const fmpz_mod_ctx_t ctx) - - void fmpz_mod_poly_compose_divconquer(fmpz_mod_poly_t res, - const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, - const fmpz_mod_ctx_t ctx) - void fmpz_mod_poly_compose(fmpz_mod_poly_t res, const fmpz_mod_poly_t poly1, const fmpz_mod_poly_t poly2, const fmpz_mod_ctx_t ctx) diff --git a/src/sage/libs/flint/fmpz_poly.pxd b/src/sage/libs/flint/fmpz_poly.pxd index 18b36672d30..c8bc6d3ca0a 100644 --- a/src/sage/libs/flint/fmpz_poly.pxd +++ b/src/sage/libs/flint/fmpz_poly.pxd @@ -28,7 +28,6 @@ cdef extern from "flint_wrap.h": void fmpz_poly_set_ui(fmpz_poly_t, ulong) void fmpz_poly_set_si(fmpz_poly_t, slong) void fmpz_poly_set_fmpz(fmpz_poly_t, const fmpz_t) - void fmpz_poly_set_mpz(fmpz_poly_t, const mpz_t) int fmpz_poly_set_str(fmpz_poly_t, const char *) char *fmpz_poly_get_str(const fmpz_poly_t) @@ -70,7 +69,6 @@ cdef extern from "flint_wrap.h": # Scalar multiplication and division void fmpz_poly_scalar_mul_fmpz( fmpz_poly_t, const fmpz_poly_t, const fmpz_t) - void fmpz_poly_scalar_mul_mpz(fmpz_poly_t, const fmpz_poly_t, const mpz_t) void fmpz_poly_scalar_mul_si(fmpz_poly_t, const fmpz_poly_t, slong) void fmpz_poly_scalar_mul_ui(fmpz_poly_t, const fmpz_poly_t, ulong) void fmpz_poly_scalar_mul_2exp(fmpz_poly_t, const fmpz_poly_t, ulong) @@ -310,12 +308,14 @@ cdef extern from "flint_wrap.h": fmpz_poly_t, const fmpz_poly_t, const fmpz_t, const nmod_poly_t, int) - # Some functions for backwards compatibility - void fmpz_poly_scalar_mul_mpz(fmpz_poly_t, const fmpz_poly_t, const mpz_t) - void fmpz_poly_scalar_divexact_mpz(fmpz_poly_t, const fmpz_poly_t, const mpz_t) - void fmpz_poly_scalar_fdiv_mpz(fmpz_poly_t, const fmpz_poly_t, const mpz_t) - void fmpz_poly_set_coeff_mpz(fmpz_poly_t, slong, const mpz_t) - void fmpz_poly_get_coeff_mpz(mpz_t, const fmpz_poly_t, slong) + +# functions removed from flint but still needed in sage +cdef void fmpz_poly_scalar_mul_mpz(fmpz_poly_t, const fmpz_poly_t, const mpz_t) +cdef void fmpz_poly_scalar_divexact_mpz(fmpz_poly_t, const fmpz_poly_t, const mpz_t) +cdef void fmpz_poly_scalar_fdiv_mpz(fmpz_poly_t, const fmpz_poly_t, const mpz_t) +cdef void fmpz_poly_set_coeff_mpz(fmpz_poly_t, slong, const mpz_t) +cdef void fmpz_poly_get_coeff_mpz(mpz_t, const fmpz_poly_t, slong) +cdef void fmpz_poly_set_mpz(fmpz_poly_t, const mpz_t) # Wrapper Cython class diff --git a/src/sage/libs/flint/fmpz_poly.pyx b/src/sage/libs/flint/fmpz_poly.pyx index 74915b37612..cfcbea9090c 100644 --- a/src/sage/libs/flint/fmpz_poly.pyx +++ b/src/sage/libs/flint/fmpz_poly.pyx @@ -25,10 +25,10 @@ from cysignals.memory cimport sig_free from sage.arith.long cimport pyobject_to_long from sage.cpython.string cimport char_to_str, str_to_bytes +from sage.libs.flint.fmpz cimport * from sage.structure.sage_object cimport SageObject from sage.rings.integer cimport Integer - cdef class Fmpz_poly(SageObject): def __cinit__(self): @@ -455,3 +455,44 @@ cdef class Fmpz_poly(SageObject): """ from sage.rings.integer_ring import ZZ return ZZ[var](self.list()) + + +# Functions removed from flint but still needed in Sage. Code adapted from +# earlier versions of flint. + +cdef void fmpz_poly_scalar_mul_mpz(fmpz_poly_t rop, const fmpz_poly_t op, const mpz_t c): + cdef fmpz_t f + fmpz_init_set_readonly(f, c) + fmpz_poly_scalar_mul_fmpz(rop, op, f) + fmpz_clear_readonly(f) + +cdef void fmpz_poly_scalar_divexact_mpz(fmpz_poly_t rop, const fmpz_poly_t op, const mpz_t c): + cdef fmpz_t f + fmpz_init_set_readonly(f, c) + fmpz_poly_scalar_divexact_fmpz(rop, op, f) + fmpz_clear_readonly(f) + +cdef void fmpz_poly_scalar_fdiv_mpz(fmpz_poly_t rop, const fmpz_poly_t op, const mpz_t c): + cdef fmpz_t f + fmpz_init_set_readonly(f, c) + fmpz_poly_scalar_fdiv_fmpz(rop, op, f) + fmpz_clear_readonly(f) + +cdef void fmpz_poly_set_coeff_mpz(fmpz_poly_t poly, slong n, const mpz_t x): + cdef fmpz_t t + fmpz_init_set_readonly(t, x) + fmpz_poly_set_coeff_fmpz(poly, n, t) + fmpz_clear_readonly(t) + +cdef void fmpz_poly_get_coeff_mpz(mpz_t x, const fmpz_poly_t poly, slong n): + cdef fmpz_t t + fmpz_init(t) + fmpz_poly_get_coeff_fmpz(t, poly, n) + fmpz_get_mpz(x, t) + fmpz_clear(t) + +cdef void fmpz_poly_set_mpz(fmpz_poly_t poly, const mpz_t x): + fmpz_poly_fit_length(poly, 1) + fmpz_set_mpz(poly.coeffs, x) + _fmpz_poly_set_length(poly, 1) + _fmpz_poly_normalise(poly) diff --git a/src/sage/libs/flint/fmpz_poly_q.pxd b/src/sage/libs/flint/fmpz_poly_q.pxd index 846542dc0d8..63c13355bf6 100644 --- a/src/sage/libs/flint/fmpz_poly_q.pxd +++ b/src/sage/libs/flint/fmpz_poly_q.pxd @@ -49,11 +49,7 @@ cdef extern from "flint_wrap.h": #* Scalar multiplication and division ****************************************/ void fmpz_poly_q_scalar_mul_si(fmpz_poly_q_t rop, const fmpz_poly_q_t op, long x) - void fmpz_poly_q_scalar_mul_mpz(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const mpz_t x) - void fmpz_poly_q_scalar_mul_mpq(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const mpq_t x) void fmpz_poly_q_scalar_div_si(fmpz_poly_q_t rop, const fmpz_poly_q_t op, long x) - void fmpz_poly_q_scalar_div_mpz(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const mpz_t x) - void fmpz_poly_q_scalar_div_mpq(fmpz_poly_q_t rop, const fmpz_poly_q_t op, const mpq_t x) #* Multiplication and division ***********************************************/ void fmpz_poly_q_mul(fmpz_poly_q_t rop, @@ -67,9 +63,6 @@ cdef extern from "flint_wrap.h": #* Derivative ****************************************************************/ void fmpz_poly_q_derivative(fmpz_poly_q_t rop, const fmpz_poly_q_t op) - #* Evaluation ****************************************************************/ - int fmpz_poly_q_evaluate(mpq_t rop, const fmpz_poly_q_t f, const mpq_t a) - #* Input and output **********************************************************/ int fmpz_poly_q_set_str(fmpz_poly_q_t rop, const char *s) char * fmpz_poly_q_get_str(const fmpz_poly_q_t op) diff --git a/src/sage/libs/linbox/linbox_flint_interface.pyx b/src/sage/libs/linbox/linbox_flint_interface.pyx index 1979ac0f0a4..37a340c457f 100644 --- a/src/sage/libs/linbox/linbox_flint_interface.pyx +++ b/src/sage/libs/linbox/linbox_flint_interface.pyx @@ -33,6 +33,7 @@ and C. Pernet. The functions available are: # https://www.gnu.org/licenses/ # **************************************************************************** +from sage.libs.gmp.types cimport mpz_t from sage.libs.flint.types cimport fmpz_t from sage.libs.flint.fmpz cimport fmpz_get_mpz, fmpz_set_mpz from sage.libs.flint.fmpz_mat cimport fmpz_mat_entry, fmpz_mat_nrows, fmpz_mat_ncols @@ -80,11 +81,13 @@ cdef void fmpz_poly_set_linbox(fmpz_poly_t p, PolynomialRing_integer.Element& q) (the .pxd file) in order to keep the header C-compatible """ cdef size_t i + cdef mpz_t tmp fmpz_poly_fit_length(p, q.size()) for i in range(q.size()): - fmpz_poly_set_coeff_mpz(p, i, q[i].get_mpz_const()) + tmp = q[i].get_mpz_const() + fmpz_poly_set_coeff_mpz(p, i, tmp) _fmpz_poly_set_length(p, q.size()) diff --git a/src/sage/matrix/matrix_complex_ball_dense.pyx b/src/sage/matrix/matrix_complex_ball_dense.pyx index e5414abdd9e..2f0131f4064 100644 --- a/src/sage/matrix/matrix_complex_ball_dense.pyx +++ b/src/sage/matrix/matrix_complex_ball_dense.pyx @@ -1,4 +1,4 @@ -# distutils: libraries = ARB_LIBRARY +# distutils: libraries = flint r""" Arbitrary precision complex ball matrices using Arb diff --git a/src/sage/matrix/matrix_integer_sparse.pyx b/src/sage/matrix/matrix_integer_sparse.pyx index 27f5cdfac0f..6c5c20dbc6b 100644 --- a/src/sage/matrix/matrix_integer_sparse.pyx +++ b/src/sage/matrix/matrix_integer_sparse.pyx @@ -847,6 +847,7 @@ cdef class Matrix_integer_sparse(Matrix_sparse): sage: matrix(ZZ, 1, 1, sparse=True)._charpoly_linbox() x """ + cdef mpz_t tmp if self._nrows != self._ncols: raise ArithmeticError('only valid for square matrix') @@ -869,7 +870,8 @@ cdef class Matrix_integer_sparse(Matrix_sparse): cdef size_t i fmpz_poly_fit_length(g._poly, p.size()) for i in range(p.size()): - fmpz_poly_set_coeff_mpz(g._poly, i, p[0][i].get_mpz_const()) + tmp = p[0][i].get_mpz_const() + fmpz_poly_set_coeff_mpz(g._poly, i, tmp) _fmpz_poly_set_length(g._poly, p.size()) del M @@ -966,9 +968,11 @@ cdef class Matrix_integer_sparse(Matrix_sparse): sig_off() cdef size_t i + cdef mpz_t tmp fmpz_poly_fit_length(g._poly, p.size()) for i in range(p.size()): - fmpz_poly_set_coeff_mpz(g._poly, i, p[0][i].get_mpz_const()) + tmp = p[0][i].get_mpz_const() + fmpz_poly_set_coeff_mpz(g._poly, i, tmp) _fmpz_poly_set_length(g._poly, p.size()) del M diff --git a/src/sage/matrix/matrix_laurent_mpolynomial_dense.pxd b/src/sage/matrix/matrix_laurent_mpolynomial_dense.pxd new file mode 100644 index 00000000000..2a1170d0bc5 --- /dev/null +++ b/src/sage/matrix/matrix_laurent_mpolynomial_dense.pxd @@ -0,0 +1,4 @@ +from sage.matrix.matrix_generic_dense cimport Matrix_generic_dense + +cdef class Matrix_Laurent_mpolynomial_dense(Matrix_generic_dense): + pass diff --git a/src/sage/matrix/matrix_laurent_mpolynomial_dense.pyx b/src/sage/matrix/matrix_laurent_mpolynomial_dense.pyx new file mode 100644 index 00000000000..1f345a68ba6 --- /dev/null +++ b/src/sage/matrix/matrix_laurent_mpolynomial_dense.pyx @@ -0,0 +1,114 @@ +""" +Dense matrices over multivariate polynomials over fields. + +AUTHOR: + +- Enrique Artal (2023-??): initial version +""" + +# ***************************************************************************** +# Copyright (C) 2023 Enrique Artal +# +# Distributed under the terms of the GNU General Public License (GPL) +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# https://www.gnu.org/licenses/ +# ***************************************************************************** +from sage.matrix.constructor import identity_matrix +from sage.rings.polynomial.laurent_polynomial_ring_base import LaurentPolynomialRing_generic + +cdef class Matrix_laurent_mpolynomial_dense(Matrix_generic_dense): + """ + Dense matrix over a Laurent multivariate polynomial ring over a field. + """ + def laurent_matrix_reduction(self): + """ + From a matrix `self` of Laurent polynomials, apply elementary operations + to obtain a matrix `P` of polynomials such that the variables do not divide + no column and no row. + + OUTPUT: + + Three matrices `L`, `P`, `R` such that ``self` equals `L P R`, where `L` and + `R` are diagonal with monomial entries. + + EXAMPLES: + + sage: R. = LaurentPolynomialRing(QQ) + sage: L = [1/3*x^-1*y - 6*x^-2*y^2 - 1/2*x^-2*y, 1/5*x + 1/2*y + 1/6] + sage: L += [1/2 - 5*x^-1*y - 2*x^-1, -1/3*y^-2 - 4*x^-1*y^-1 + 11*x^-1*y^-2] + sage: A = matrix(R, 2, L) + sage: lf, P, rg = A.laurent_matrix_reduction() + sage: lf + [ x^-2 0] + [ 0 x^-1*y^-2] + sage: P + [ 1/3*x - 6*y - 1/2 1/5*x^3 + 1/2*x^2*y + 1/6*x^2] + [ 1/2*x*y - 5*y^2 - 2*y -1/3*x - 4*y + 11] + sage: rg + [y 0] + [0 1] + """ + R = self.base_ring() + n_rows, n_cols = self.dimensions() + mat_l = identity_matrix(R, n_rows) + mat_r = identity_matrix(R, n_cols) + res = self.__copy__() + for j, rw in enumerate(res.rows()): + for t in R.gens(): + n = min(mon.degree(t) for a in rw for cf, mon in a) + res.rescale_row(j, t ** -n) + mat_l.rescale_col(j, t ** n) + for j, cl in enumerate(res.columns()): + for t in R.gens(): + n = min(mon.degree(t) for a in cl for cf, mon in a) + res.rescale_col(j, t ** -n) + mat_r.rescale_row(j, t ** n) + res = res.change_ring(R.polynomial_ring()) + return mat_l, res, mat_r + + def _fitting_ideal(self, i): + r""" + Return the `i`-th Fitting ideal of the matrix. This is the ideal generated + by the `n - i` minors, where `n` is the number of columns. + + INPUT: + + ``i`` -- an integer + + OUTPUT: + + An ideal on the base ring. + + EXAMPLES:: + + sage: R. = LaurentPolynomialRing(QQ) + sage: M = matrix(R, [[2*x^-1-z, 0, y-z^-2, 0], [0, z - y^-1, z - x, 0],[z - y, x^-2 - y, 0, z]]) + sage: M + [-z + 2*x^-1 0 y - z^-2 0] + [ 0 z - y^-1 -x + z 0] + [ -y + z -y + x^-2 0 z] + sage: M.fitting_ideal(0) + Ideal (0) of Multivariate Laurent Polynomial Ring in x, y, z over Rational Field + sage: M.fitting_ideal(1) == M._fitting_ideal(1) + True + sage: M.fitting_ideal(1).groebner_basis() + (x^4 - 2*x^3*y - x*z^3 - 4*x^2*y + 8*x*y^2 + 4*x*y*z + 2*z^2 - 8*y, + x*y*z^2 - x*z - 2*y*z + 2, + x^2*z - x*z^2 - 2*x + 2*z, + y^2*z + 1/4*x^2 - 1/2*x*y - 1/4*x*z - y + 1/2) + sage: M.fitting_ideal(2).groebner_basis() + (1,) + sage: M.fitting_ideal(3).groebner_basis() + (1,) + sage: M.fitting_ideal(4).groebner_basis() + (1,) + sage: [R.ideal(M.minors(i)) == M._fitting_ideal(4 - i) for i in range(5)] + [True, True, True, True, True] + + """ + R = self.base_ring() + S = R.polynomial_ring() + A = self.laurent_matrix_reduction()[1].change_ring(S) + J = A._fitting_ideal(i) + return J.change_ring(R) diff --git a/src/sage/matrix/matrix_space.py b/src/sage/matrix/matrix_space.py index 3795ff4b0fa..940358b2c81 100644 --- a/src/sage/matrix/matrix_space.py +++ b/src/sage/matrix/matrix_space.py @@ -306,6 +306,13 @@ def get_matrix_class(R, nrows, ncols, sparse, implementation): pass else: return matrix_mpolynomial_dense.Matrix_mpolynomial_dense + elif isinstance(R, sage.rings.polynomial.laurent_polynomial_ring.LaurentPolynomialRing_mpair) and R.base_ring() in _Fields: + try: + from . import matrix_laurent_mpolynomial_dense + except ImportError: + pass + else: + return matrix_laurent_mpolynomial_dense.Matrix_laurent_mpolynomial_dense # The fallback from sage.matrix.matrix_generic_dense import Matrix_generic_dense diff --git a/src/sage/misc/all.py b/src/sage/misc/all.py index e5a6418043a..5876ef9484d 100644 --- a/src/sage/misc/all.py +++ b/src/sage/misc/all.py @@ -1,11 +1,11 @@ -from .lazy_attribute import lazy_attribute, lazy_class_attribute -from .lazy_import import lazy_import +from sage.misc.lazy_attribute import lazy_attribute, lazy_class_attribute +from sage.misc.lazy_import import lazy_import -from .all__sagemath_objects import * -from .all__sagemath_environment import * -from .all__sagemath_repl import * +from sage.misc.all__sagemath_objects import * +from sage.misc.all__sagemath_environment import * +from sage.misc.all__sagemath_repl import * -from .misc import (BackslashOperator, +from sage.misc.misc import (BackslashOperator, exists, forall, is_iterator, random_sublist, pad_zeros, @@ -15,27 +15,27 @@ lazy_import('sage.misc.misc', 'union', deprecation=32096) -from .banner import version +from sage.misc.banner import version -from .dev_tools import import_statements +from sage.misc.dev_tools import import_statements -from .html import html, pretty_print_default +from sage.misc.html import html, pretty_print_default -from .table import table +from sage.misc.table import table -from .sage_timeit_class import timeit +from sage.misc.sage_timeit_class import timeit -from .edit_module import edit +from sage.misc.edit_module import edit -from .map_threaded import map_threaded +from sage.misc.map_threaded import map_threaded -from .session import load_session, save_session, show_identifiers +from sage.misc.session import load_session, save_session, show_identifiers -from .remote_file import get_remote_file +from sage.misc.remote_file import get_remote_file -from .mrange import xmrange, mrange, xmrange_iter, mrange_iter, cartesian_product_iterator +from sage.misc.mrange import xmrange, mrange, xmrange_iter, mrange_iter, cartesian_product_iterator -from .fpickle import pickle_function, unpickle_function +from sage.misc.fpickle import pickle_function, unpickle_function lazy_import('sage.misc.pager', 'pager') @@ -45,21 +45,21 @@ 'constructions', 'help']) lazy_import('pydoc', 'help', 'python_help') -from .classgraph import class_graph +from sage.misc.classgraph import class_graph -from .reset import reset, restore +from sage.misc.reset import reset, restore -from .mathml import mathml +from sage.misc.mathml import mathml -from .defaults import (set_default_variable_name, +from sage.misc.defaults import (set_default_variable_name, series_precision, set_series_precision) lazy_import("sage.misc.cython", "cython_lambda") lazy_import("sage.misc.cython", "cython_compile", "cython") -from .func_persist import func_persist +from sage.misc.func_persist import func_persist -from .functional import (additive_order, +from sage.misc.functional import (additive_order, base_ring, base_field, basis, @@ -118,15 +118,15 @@ transpose) -from .latex import LatexExpr, latex, view +from sage.misc.latex import LatexExpr, latex, view -from .randstate import seed, set_random_seed, initial_seed, current_randstate +from sage.misc.randstate import seed, set_random_seed, initial_seed, current_randstate -from .prandom import * +from sage.misc.prandom import * -from .timing import walltime, cputime +from sage.misc.timing import walltime, cputime -from .explain_pickle import explain_pickle, unpickle_newobj, unpickle_global, unpickle_build, unpickle_instantiate, unpickle_persistent, unpickle_extension, unpickle_appends +from sage.misc.explain_pickle import explain_pickle, unpickle_newobj, unpickle_global, unpickle_build, unpickle_instantiate, unpickle_persistent, unpickle_extension, unpickle_appends lazy_import('sage.misc.inline_fortran', 'fortran') diff --git a/src/sage/misc/all__sagemath_environment.py b/src/sage/misc/all__sagemath_environment.py index f25faa1289d..9ebcc85870b 100644 --- a/src/sage/misc/all__sagemath_environment.py +++ b/src/sage/misc/all__sagemath_environment.py @@ -1 +1 @@ -from .temporary_file import tmp_dir, tmp_filename +from sage.misc.temporary_file import tmp_dir, tmp_filename diff --git a/src/sage/misc/all__sagemath_objects.py b/src/sage/misc/all__sagemath_objects.py index 43a9c1c06d5..30a76f38fab 100644 --- a/src/sage/misc/all__sagemath_objects.py +++ b/src/sage/misc/all__sagemath_objects.py @@ -2,35 +2,35 @@ import sage.structure.all # to break a cyclic import -from .lazy_attribute import lazy_attribute, lazy_class_attribute -from .lazy_import import lazy_import +from sage.misc.lazy_attribute import lazy_attribute, lazy_class_attribute +from sage.misc.lazy_import import lazy_import -from .verbose import (set_verbose, set_verbose_files, +from sage.misc.verbose import (set_verbose, set_verbose_files, get_verbose_files, unset_verbose_files, get_verbose) lazy_import('sage.misc.verbose', 'verbose', deprecation=17815) -from .call import attrcall +from sage.misc.call import attrcall -from .misc_c import prod, running_total, balanced_sum +from sage.misc.misc_c import prod, running_total, balanced_sum mul = prod add = sum -from .repr import repr_lincomb +from sage.misc.repr import repr_lincomb -from .flatten import flatten +from sage.misc.flatten import flatten -from .persist import save, load, dumps, loads, db, db_save +from sage.misc.persist import save, load, dumps, loads, db, db_save -from .constant_function import ConstantFunction +from sage.misc.constant_function import ConstantFunction -from .sage_unittest import TestSuite +from sage.misc.sage_unittest import TestSuite -from .decorators import specialize, sage_wraps, infix_operator +from sage.misc.decorators import specialize, sage_wraps, infix_operator -from .unknown import Unknown, UnknownError +from sage.misc.unknown import Unknown, UnknownError -from .cachefunc import CachedFunction, cached_function, cached_method, cached_in_parent_method, disk_cached_function +from sage.misc.cachefunc import CachedFunction, cached_function, cached_method, cached_in_parent_method, disk_cached_function -from .abstract_method import abstract_method +from sage.misc.abstract_method import abstract_method -from .timing import walltime, cputime +from sage.misc.timing import walltime, cputime diff --git a/src/sage/misc/all__sagemath_repl.py b/src/sage/misc/all__sagemath_repl.py index f5891ff1242..c7acba4ab07 100644 --- a/src/sage/misc/all__sagemath_repl.py +++ b/src/sage/misc/all__sagemath_repl.py @@ -1,3 +1,3 @@ -from .sage_eval import sage_eval, sageobj +from sage.misc.sage_eval import sage_eval, sageobj -from .sage_input import sage_input +from sage.misc.sage_input import sage_input diff --git a/src/sage/misc/benchmark.py b/src/sage/misc/benchmark.py index 2a6ee53a0c1..0309571905d 100644 --- a/src/sage/misc/benchmark.py +++ b/src/sage/misc/benchmark.py @@ -1,6 +1,6 @@ "Benchmarks" -from .misc import cputime +from sage.misc.misc import cputime from sage.all import * diff --git a/src/sage/misc/copying.py b/src/sage/misc/copying.py index bcd6c9c3646..cec1a5189cd 100644 --- a/src/sage/misc/copying.py +++ b/src/sage/misc/copying.py @@ -1,7 +1,7 @@ "License" import os -from . import pager +from sage.misc import pager from sage.env import SAGE_ROOT diff --git a/src/sage/misc/cython.py b/src/sage/misc/cython.py index c0c803bf943..268593e557d 100644 --- a/src/sage/misc/cython.py +++ b/src/sage/misc/cython.py @@ -27,7 +27,7 @@ from sage.env import (SAGE_LOCAL, cython_aliases, sage_include_directories) -from .temporary_file import spyx_tmp, tmp_filename +from sage.misc.temporary_file import spyx_tmp, tmp_filename from sage.repl.user_globals import get_globals from sage.misc.sage_ostools import restore_cwd, redirection from sage.cpython.string import str_to_bytes diff --git a/src/sage/misc/explain_pickle.py b/src/sage/misc/explain_pickle.py index 30c3988850b..2fb34a2234e 100644 --- a/src/sage/misc/explain_pickle.py +++ b/src/sage/misc/explain_pickle.py @@ -5,9 +5,9 @@ - Carl Witty (2009-03) -The explain_pickle function takes a pickle and produces Sage code that +The :func:`explain_pickle` function takes a pickle and produces Sage code that will evaluate to the contents of the pickle. Ideally, the combination -of explain_pickle to produce Sage code and sage_eval to evaluate the code +of :func:`explain_pickle` to produce Sage code and :func:`sage_eval` to evaluate the code would be a 100% compatible implementation of cPickle's unpickler; this is almost the case now. @@ -27,9 +27,9 @@ True By default (as above) the code produced contains calls to several -utility functions (unpickle_global, etc.); this is done so that the +utility functions (:func:`unpickle_global`, etc.); this is done so that the code is truly equivalent to the pickle. If the pickle can be loaded -into a future version of Sage, then the code that explain_pickle +into a future version of Sage, then the code that :func:`explain_pickle` produces today should work in that future Sage as well. It is also possible to produce simpler code, that is tied to the current @@ -44,11 +44,11 @@ from sage.rings.rational import make_rational Polynomial_rational_flint(unpickle_PolynomialRing(RationalField(), ('x',), None, False), [make_rational('0'), make_rational('1')], False, True) -The explain_pickle function has several use cases. +The :func:`explain_pickle` function has several use cases. - Write pickling support for your classes - You can use explain_pickle to see what will happen when a pickle + You can use :func:`explain_pickle` to see what will happen when a pickle is unpickled. Consider: is this sequence of commands something that can be easily supported in all future Sage versions, or does it expose internal design decisions that are subject to change? @@ -56,55 +56,55 @@ - Debug old pickles If you have a pickle from an old version of Sage that no longer - unpickles, you can use explain_pickle to see what it is trying to + unpickles, you can use :func:`explain_pickle` to see what it is trying to do, to figure out how to fix it. - - Use explain_pickle in doctests to help maintenance + - Use :func:`explain_pickle` in doctests to help maintenance If you have a ``loads(dumps(S))`` doctest, you could also add an ``explain_pickle(dumps(S))`` doctest. Then if something changes in a way that would invalidate old pickles, the output of - ``explain_pickle`` will also change. At that point, you can add + :func:`explain_pickle` will also change. At that point, you can add the previous output of :obj:`explain_pickle` as a new set of doctests (and then update the :obj:`explain_pickle` doctest to use the new output), to ensure that old pickles will continue to work. -As mentioned above, there are several output modes for :obj:`explain_pickle`, +As mentioned above, there are several output modes for :func:`explain_pickle`, that control fidelity versus simplicity of the output. For example, the GLOBAL instruction takes a module name and a class name and produces the corresponding class. So GLOBAL of ``sage.rings.integer``, ``Integer`` is approximately equivalent to ``sage.rings.integer.Integer``. However, this class lookup process can be customized (using -sage.misc.persist.register_unpickle_override). For instance, +:func:`sage.misc.persist.register_unpickle_override`). For instance, if some future version of Sage renamed ``sage/rings/integer.pyx`` to ``sage/rings/knuth_was_here.pyx``, old pickles would no longer work unless register_unpickle_override was used; in that case, GLOBAL of -'sage.rings.integer', 'integer' would mean +``sage.rings.integer``, ``integer`` would mean ``sage.rings.knuth_was_here.integer``. -By default, ``explain_pickle`` will map this GLOBAL instruction to +By default, :func:`explain_pickle` will map this GLOBAL instruction to ``unpickle_global('sage.rings.integer', 'integer')``. Then when this code -is evaluated, unpickle_global will look up the current mapping in the -register_unpickle_override table, so the generated code will continue -to work even in hypothetical future versions of Sage where integer.pyx +is evaluated, :func:`unpickle_global` will look up the current mapping in the +:func:`register_unpickle_override` table, so the generated code will continue +to work even in hypothetical future versions of Sage where ``integer.pyx`` has been renamed. If you pass the flag ``in_current_sage=True``, then -:obj:`explain_pickle` will generate code that may only work in the +:func:`explain_pickle` will generate code that may only work in the current version of Sage, not in future versions. In this case, it would generate:: from sage.rings.integer import integer -and if you ran explain_pickle in hypothetical future sage, it would generate: +and if you ran :func:`explain_pickle` in hypothetical future sage, it would generate: from sage.rings.knuth_was_here import integer but the current code wouldn't work in the future sage. If you pass the flag ``default_assumptions=True``, then -:obj:`explain_pickle` will generate code that would work in the +:func:`explain_pickle` will generate code that would work in the absence of any special unpickling information. That is, in either current Sage or hypothetical future Sage, it would generate:: @@ -114,32 +114,32 @@ human-readable), but may not actually work; so it is only intended for human reading. -There are several functions used in the output of :obj:`explain_pickle`. +There are several functions used in the output of :func:`explain_pickle`. Here I give a brief description of what they usually do, as well as how to modify their operation (for instance, if you're trying to get old pickles to work). - ``unpickle_global(module, classname)``: - unpickle_global('sage.foo.bar', 'baz') is usually equivalent to - sage.foo.bar.baz, but this can be customized with - register_unpickle_override. + ``unpickle_global('sage.foo.bar', 'baz')`` is usually equivalent to + ``sage.foo.bar.baz``, but this can be customized with + :func:`register_unpickle_override`. - ``unpickle_newobj(klass, args)``: Usually equivalent to ``klass.__new__(klass, *args)``. If ``klass`` is a Python class, then you can define :meth:`__new__` to control the result (this result actually need not be an - instance of klass). (This doesn't work for Cython classes.) + instance of ``klass``). (This doesn't work for Cython classes.) - ``unpickle_build(obj, state)``: If ``obj`` has a :meth:`__setstate__` method, then this is equivalent to - ``obj.__setstate__(state)``. Otherwise uses state to set the attributes + ``obj.__setstate__(state)``. Otherwise uses ``state`` to set the attributes of ``obj``. Customize by defining :meth:`__setstate__`. - ``unpickle_instantiate(klass, args)``: Usually equivalent to ``klass(*args)``. Cannot be customized. - - unpickle_appends(lst, vals): - Appends the values in vals to lst. If not ``isinstance(lst, list)``, + - ``unpickle_appends(lst, vals)``: + Appends the values in ``vals`` to ``lst``. If not ``isinstance(lst, list)``, can be customized by defining a :meth:`append` method. """ @@ -165,7 +165,6 @@ from pickletools import genops -import sage.all from sage.misc.sage_input import SageInputBuilder, SageInputExpression from sage.misc.sage_eval import sage_eval from sage.misc.persist import (unpickle_override, unpickle_global, dumps, @@ -181,30 +180,30 @@ def explain_pickle(pickle=None, file=None, compress=True, **kwargs): r""" Explain a pickle. That is, produce source code such that evaluating the code is equivalent to loading the pickle. Feeding the result - of ``explain_pickle`` to ``sage_eval`` should be totally equivalent to loading + of :func:`explain_pickle` to :func:`sage_eval` should be totally equivalent to loading the ``pickle`` with ``cPickle``. INPUT: - - ``pickle`` -- the pickle to explain, as a string (default: None) - - ``file`` -- a filename of a pickle (default: None) - - ``compress`` -- if False, don't attempt to decompress the pickle - (default: True) - - ``in_current_sage`` -- if True, produce potentially simpler code that is - tied to the current version of Sage. (default: False) - - ``default_assumptions`` -- if True, produce potentially simpler code that - assumes that generic unpickling code will be - used. This code may not actually work. - (default: False) - - ``eval`` -- if True, then evaluate the resulting code and return the - evaluated result. (default: False) - - ``preparse`` -- if True, then produce code to be evaluated with - Sage's preparser; if False, then produce standard - Python code; if None, then produce code that will work - either with or without the preparser. (default: True) - - ``pedantic`` -- if True, then carefully ensures that the result has - at least as much sharing as the result of cPickle - (it may have more, for immutable objects). (default: False) + - ``pickle`` -- the pickle to explain, as a string (default: ``None``) + - ``file`` -- a filename of a pickle (default: ``None``) + - ``compress`` -- if ``False``, don't attempt to decompress the pickle + (default: ``True``) + - ``in_current_sage`` -- if ``True``, produce potentially simpler code that is + tied to the current version of Sage. (default: ``False``) + - ``default_assumptions`` -- if ``True``, produce potentially simpler code that + assumes that generic unpickling code will be + used. This code may not actually work. + (default: ``False``) + - ``eval`` -- if ``True``, then evaluate the resulting code and return the + evaluated result. (default: ``False``) + - ``preparse`` -- if ``True``, then produce code to be evaluated with + Sage's preparser; if ``False``, then produce standard + Python code; if ``None``, then produce code that will work + either with or without the preparser. (default: ``True``) + - ``pedantic`` -- if ``True``, then carefully ensures that the result has + at least as much sharing as the result of cPickle + (it may have more, for immutable objects). (default: ``False``) Exactly one of ``pickle`` (a string containing a pickle) or ``file`` (the filename of a pickle) must be provided. @@ -263,16 +262,16 @@ def explain_pickle_string(pickle, in_current_sage=False, default_assumptions=False, eval=False, preparse=True, pedantic=False): r""" - This is a helper function for explain_pickle. It takes a decompressed + This is a helper function for :func:`explain_pickle`. It takes a decompressed pickle string as input; other than that, its options are all the same - as explain_pickle. + as :func:`explain_pickle`. EXAMPLES:: sage: sage.misc.explain_pickle.explain_pickle_string(dumps("Hello, world", compress=False)) 'Hello, world' - (See the documentation for ``explain_pickle`` for many more examples.) + (See the documentation for :func:`explain_pickle` for many more examples.) """ sib = SageInputBuilder(preparse=preparse) @@ -321,17 +320,19 @@ def name_is_valid(name): class PickleObject(): r""" - Pickles have a stack-based virtual machine. The explain_pickle - pickle interpreter mostly uses SageInputExpressions, from sage_input, + Pickles have a stack-based virtual machine. The :func:`explain_pickle` + pickle interpreter mostly uses :class:`sage.misc.sage_input.SageInputExpression` objects as the stack values. However, sometimes we want some more information about the value on the stack, so that we can generate better (prettier, less confusing) code. In such cases, we push - a PickleObject instead of a SageInputExpression. A PickleObject + a :class:`PickleObject` instead of a :class:`~sage.misc.sage_input.SageInputExpression`. + A :class:`PickleObject` contains a value (which may be a standard Python value, or a - PickleDict or PickleInstance), an expression (a SageInputExpression), + :class:`PickleDict` or :class:`PickleInstance`), an expression + (a :class:`~sage.misc.sage_input.SageInputExpression`), and an "immutable" flag (which checks whether this object - has been converted to a SageInputExpression; if it has, then we - must not mutate the object, since the SageInputExpression would not + has been converted to a :class:`SageInputExpression`; if it has, then we + must not mutate the object, since the :class:`SageInputExpression` would not reflect the changes). """ @@ -375,9 +376,9 @@ def _sage_input_(self, sib, coerced): class PickleDict(): r""" - An object which can be used as the value of a PickleObject. The items + An object which can be used as the value of a :class:`PickleObject`. The items is a list of key-value pairs, where the keys and values are - SageInputExpressions. We use this to help construct dictionary literals, + :class:`SageInputExpression` objects. We use this to help construct dictionary literals, instead of always starting with an empty dictionary and assigning to it. """ @@ -395,8 +396,8 @@ def __init__(self, items): class PickleInstance(): r""" - An object which can be used as the value of a PickleObject. Unlike - other possible values of a PickleObject, a PickleInstance doesn't represent + An object which can be used as the value of a :class:`PickleObject`. Unlike + other possible values of a :class:`PickleObject`, a :class:`PickleInstance` doesn't represent an exact value; instead, it gives the class (type) of the object. """ def __init__(self, klass): @@ -414,7 +415,7 @@ def __init__(self, klass): class PickleExplainer(): r""" An interpreter for the pickle virtual machine, that executes - symbolically and constructs SageInputExpressions instead of + symbolically and constructs :class:`SageInputExpression` objects instead of directly constructing values. """ def __init__(self, sib, in_current_sage=False, default_assumptions=False, @@ -448,7 +449,7 @@ def run_pickle(self, p): r""" Given an (uncompressed) pickle as a string, run the pickle in this virtual machine. Once a STOP has been executed, return - the result (a SageInputExpression representing code which, when + the result (a :class:`SageInputExpression` representing code which, when evaluated, will give the value of the pickle). EXAMPLES:: @@ -477,8 +478,8 @@ def run_pickle(self, p): def check_value(self, v): r""" - Check that the given value is either a SageInputExpression or a - PickleObject. Used for internal sanity checking. + Check that the given value is either a :class:`SageInputExpression` or a + :class:`PickleObject`. Used for internal sanity checking. EXAMPLES:: @@ -514,7 +515,7 @@ def push(self, v): def push_and_share(self, v): r""" Push a value onto the virtual machine's stack; also mark it as shared - for sage_input if we are in pedantic mode. + for :func:`sage_input` if we are in pedantic mode. EXAMPLES:: @@ -595,14 +596,15 @@ def pop_to_mark(self): def share(self, v): r""" - Mark a sage_input value as shared, if we are in pedantic mode. + Mark a :func:`sage_input` value as shared, if we are in pedantic mode. EXAMPLES:: sage: from sage.misc.explain_pickle import * sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() - sage: pe = PickleExplainer(sib, in_current_sage=True, default_assumptions=False, pedantic=True) + sage: pe = PickleExplainer(sib, in_current_sage=True, + ....: default_assumptions=False, pedantic=True) sage: v = sib(7) sage: v._sie_share False @@ -617,15 +619,16 @@ def share(self, v): def is_mutable_pickle_object(self, v): r""" - Test whether a PickleObject is mutable (has never been converted - to a SageInputExpression). + Test whether a :class:`PickleObject` is mutable (has never been converted + to a :class:`SageInputExpression`). EXAMPLES:: sage: from sage.misc.explain_pickle import * sage: from sage.misc.sage_input import SageInputBuilder sage: sib = SageInputBuilder() - sage: pe = PickleExplainer(sib, in_current_sage=True, default_assumptions=False, pedantic=True) + sage: pe = PickleExplainer(sib, in_current_sage=True, + ....: default_assumptions=False, pedantic=True) sage: v = PickleObject(1, sib(1)) sage: pe.is_mutable_pickle_object(v) True @@ -1394,7 +1397,12 @@ def GLOBAL(self, name): # OK, we know what module and function name will actually # be used, as well as the actual function. # Is this already available at the command line? - cmdline_f = getattr(sage.all, func, None) + try: + import sage.all + except ImportError: + cmdline_f = None + else: + cmdline_f = getattr(sage.all, func, None) if cmdline_f is f: self.push(PickleObject(f, self.sib.name(func))) return @@ -2368,7 +2376,7 @@ def UNICODE(self, s): def unpickle_newobj(klass, args): r""" Create a new object; this corresponds to the C code - klass->tp_new(klass, args, NULL). Used by ``explain_pickle``. + ``klass->tp_new(klass, args, NULL)``. Used by :func:`explain_pickle`. EXAMPLES:: @@ -2413,7 +2421,7 @@ def pers_load(id): def unpickle_build(obj, state): r""" - Set the state of an object. Used by ``explain_pickle``. + Set the state of an object. Used by :func:`explain_pickle`. EXAMPLES:: @@ -2447,8 +2455,8 @@ def unpickle_build(obj, state): def unpickle_instantiate(fn, args): r""" - Instantiate a new object of class fn with arguments args. Almost always - equivalent to ``fn(*args)``. Used by ``explain_pickle``. + Instantiate a new object of class ``fn`` with arguments ``args``. Almost always + equivalent to ``fn(*args)``. Used by :func:`explain_pickle`. EXAMPLES:: @@ -2469,7 +2477,7 @@ def unpickle_persistent(s): r""" Takes an integer index and returns the persistent object with that index; works by calling whatever callable is stored in - unpickle_persistent_loader. Used by ``explain_pickle``. + ``unpickle_persistent_loader``. Used by :func:`explain_pickle`. EXAMPLES:: @@ -2484,7 +2492,7 @@ def unpickle_persistent(s): def unpickle_extension(code): r""" Takes an integer index and returns the extension object with that - index. Used by ``explain_pickle``. + index. Used by :func:`explain_pickle`. EXAMPLES:: @@ -2512,7 +2520,7 @@ def unpickle_appends(lst, vals): r""" Given a list (or list-like object) and a sequence of values, appends the values to the end of the list. This is careful to do so using the - exact same technique that cPickle would use. Used by ``explain_pickle``. + exact same technique that cPickle would use. Used by :func:`explain_pickle`. EXAMPLES:: @@ -2532,7 +2540,9 @@ def unpickle_appends(lst, vals): def test_pickle(p, verbose_eval=False, pedantic=False, args=()): r""" - Tests explain_pickle on a given pickle p. p can be: + Test :func:`explain_pickle` on a given pickle ``p``. + + ``p`` can be: - a string containing an uncompressed pickle (which will always end with a '.') @@ -2542,14 +2552,14 @@ def test_pickle(p, verbose_eval=False, pedantic=False, args=()): the stack (using persistent IDs), run the pickle fragment, and then STOP (if the string 'mark' occurs in args, then a mark will be pushed) - - an arbitrary object; test_pickle will pickle the object + - an arbitrary object; :func:`test_pickle` will pickle the object - Once it has a pickle, test_pickle will print the pickle's - disassembly, run explain_pickle with in_current_sage=True and - False, print the results, evaluate the results, unpickle the + Once it has a pickle, :func:`test_pickle` will print the pickle's + disassembly, run :func:`explain_pickle` with ``in_current_sage=True`` and + ``False``, print the results, evaluate the results, unpickle the object with cPickle, and compare all three results. - If verbose_eval is True, then test_pickle will print messages + If ``verbose_eval`` is ``True``, then :func:`test_pickle` will print messages before evaluating the pickles; this is to allow for tests where the unpickling prints messages (to verify that the same operations occur in all cases). @@ -2636,7 +2646,7 @@ def pers_load(s): class EmptyOldstyleClass: r""" A featureless old-style class (does not inherit from object); used for - testing explain_pickle. + testing :func:`explain_pickle`. """ def __repr__(self): r""" @@ -2674,7 +2684,7 @@ def __hash__(self): class EmptyNewstyleClass(): r""" A featureless new-style class (inherits from object); used for - testing explain_pickle. + testing :func:`explain_pickle`. """ def __repr__(self): r""" @@ -2696,8 +2706,8 @@ def __repr__(self): class TestReduceGetinitargs: r""" - An old-style class with a __getinitargs__ method. Used for testing - explain_pickle. + An old-style class with a :func:`__getinitargs__` method. Used for testing + :func:`explain_pickle`. """ def __init__(self): r""" @@ -2748,8 +2758,8 @@ def __repr__(self): class TestReduceNoGetinitargs: r""" - An old-style class with no __getinitargs__ method. Used for testing - explain_pickle. + An old-style class with no :meth:`__getinitargs__` method. Used for testing + :func:`explain_pickle`. """ def __init__(self): r""" @@ -2786,8 +2796,8 @@ def __repr__(self): class TestAppendList(list): r""" - A subclass of list, with deliberately-broken append and extend methods. - Used for testing explain_pickle. + A subclass of :class:`list`, with deliberately-broken append and extend methods. + Used for testing :func:`explain_pickle`. """ def append(self): r""" @@ -2835,7 +2845,7 @@ def extend(self): class TestAppendNonlist(): r""" A list-like class, carefully designed to test exact unpickling - behavior. Used for testing explain_pickle. + behavior. Used for testing :func:`explain_pickle`. """ def __init__(self): r""" @@ -2918,8 +2928,8 @@ def __repr__(self): class TestBuild(): r""" - A simple class with a __getstate__ but no __setstate__. Used for testing - explain_pickle. + A simple class with a :meth:`__getstate__` but no :meth:`__setstate__`. Used for testing + :func:`explain_pickle`. """ def __getstate__(self): r""" @@ -2955,8 +2965,8 @@ def __repr__(self): class TestBuildSetstate(TestBuild): r""" - A simple class with a __getstate__ and a __setstate__. Used for testing - explain_pickle. + A simple class with a :meth:`__getstate__` and a :meth:`__setstate__`. Used for testing + :func:`explain_pickle`. """ def __setstate__(self, state): r""" @@ -2978,8 +2988,8 @@ def __setstate__(self, state): class TestGlobalOldName(): r""" A featureless new-style class. When you try to unpickle an instance - of this class, it is redirected to create a TestGlobalNewName instead. - Used for testing explain_pickle. + of this class, it is redirected to create a :class:`TestGlobalNewName` instead. + Used for testing :func:`explain_pickle`. EXAMPLES:: @@ -2993,8 +3003,8 @@ class TestGlobalOldName(): class TestGlobalNewName(): r""" A featureless new-style class. When you try to unpickle an instance - of TestGlobalOldName, it is redirected to create an instance of this - class instead. Used for testing explain_pickle. + of :class:`TestGlobalOldName`, it is redirected to create an instance of this + class instead. Used for testing :func:`explain_pickle`. EXAMPLES:: diff --git a/src/sage/misc/func_persist.py b/src/sage/misc/func_persist.py index cf020479440..65b6d536d79 100644 --- a/src/sage/misc/func_persist.py +++ b/src/sage/misc/func_persist.py @@ -43,7 +43,7 @@ def bern(n): import inspect import os -from . import persist +from sage.misc import persist class func_persist: r""" diff --git a/src/sage/misc/lazy_import_cache.py b/src/sage/misc/lazy_import_cache.py index e34c0ca6942..191a2058e2b 100644 --- a/src/sage/misc/lazy_import_cache.py +++ b/src/sage/misc/lazy_import_cache.py @@ -6,7 +6,7 @@ import os import hashlib -from ..env import SAGE_LIB, DOT_SAGE +from sage.env import SAGE_LIB, DOT_SAGE def get_cache_file(): diff --git a/src/sage/misc/misc.py b/src/sage/misc/misc.py index 936f279a690..4f60a11b780 100644 --- a/src/sage/misc/misc.py +++ b/src/sage/misc/misc.py @@ -45,7 +45,7 @@ import sys import warnings -from .lazy_string import lazy_string +from sage.misc.lazy_string import lazy_string from sage.env import DOT_SAGE, HOSTNAME from sage.misc.lazy_import import lazy_import diff --git a/src/sage/misc/package_dir.py b/src/sage/misc/package_dir.py index 9f075b16c31..3749a4f2a91 100644 --- a/src/sage/misc/package_dir.py +++ b/src/sage/misc/package_dir.py @@ -14,7 +14,10 @@ import os import glob +import re import sys + +from collections import defaultdict from contextlib import contextmanager @@ -26,12 +29,12 @@ class SourceDistributionFilter: - ``include_distributions`` -- (default: ``None``) if not ``None``, should be a sequence or set of strings: include files whose - ``distribution`` (from a ``# sage_setup: distribution = PACKAGE`` + ``distribution`` (from a ``# sage_setup:`` ``distribution = PACKAGE`` directive in the source file) is an element of ``distributions``. - ``exclude_distributions`` -- (default: ``None``) if not ``None``, should be a sequence or set of strings: exclude files whose - ``distribution`` (from a ``# sage_setup: distribution = PACKAGE`` + ``distribution`` (from a ``# sage_setup:`` ``distribution = PACKAGE`` directive in the module source file) is in ``exclude_distributions``. EXAMPLES:: @@ -90,9 +93,12 @@ def __contains__(self, filename): return distribution not in self._exclude_distributions +distribution_directive = re.compile(r"(\s*#?\s*)(sage_setup:\s*distribution\s*=\s*([-_A-Za-z0-9]*))") + + def read_distribution(src_file): - """ - Parse ``src_file`` for a ``# sage_setup: distribution = PKG`` directive. + r""" + Parse ``src_file`` for a ``# sage_setup:`` ``distribution = PKG`` directive. INPUT: @@ -119,9 +125,12 @@ def read_distribution(src_file): line = line.lstrip() if not line: continue - if line[0] != '#': + if line.startswith('#') or line.startswith(';'): + line = line[1:].lstrip() + elif line.startswith('/*') or line.startswith('//') or line.startswith(';;'): + line = line[2:].lstrip() + else: break - line = line[1:].lstrip() kind = "sage_setup:" if line.startswith(kind): key, _, value = (s.strip() for s in line[len(kind):].partition('=')) @@ -130,6 +139,105 @@ def read_distribution(src_file): return '' +def update_distribution(src_file, distribution, *, verbose=False): + r""" + Add or update a ``# sage_setup:`` ``distribution = PKG`` directive in ``src_file``. + + For a Python or Cython file, if a ``distribution`` directive + is not already present, it is added. + + For any other file, if a ``distribution`` directive is not already + present, no action is taken. + + INPUT: + + - ``src_file`` -- file name of a source file + + EXAMPLES:: + + sage: from sage.misc.package_dir import read_distribution, update_distribution + sage: import tempfile + sage: def test(filename, file_contents): + ....: with tempfile.TemporaryDirectory() as d: + ....: fname = os.path.join(d, filename) + ....: with open(fname, 'w') as f: + ....: f.write(file_contents) + ....: with open(fname, 'r') as f: + ....: print(f.read() + "====") + ....: update_distribution(fname, 'sagemath-categories') + ....: with open(fname, 'r') as f: + ....: print(f.read() + "====") + ....: update_distribution(fname, '') + ....: with open(fname, 'r') as f: + ....: print(f.read(), end="") + sage: test('module.py', '# Python file\n') + # Python file + ==== + # sage_setup: distribution...= sagemath-categories + # Python file + ==== + # sage_setup: distribution...= + # Python file + sage: test('file.cpp', '// sage_setup: ' 'distribution=sagemath-modules\n' + ....: '// C++ file with existing directive\n') + // sage_setup: distribution...=sagemath-modules + // C++ file with existing directive + ==== + // sage_setup: distribution...= sagemath-categories + // C++ file with existing directive + ==== + // sage_setup: distribution...= + // C++ file with existing directive + sage: test('file.cpp', '// C++ file without existing directive\n') + // C++ file without existing directive + ==== + // C++ file without existing directive + ==== + // C++ file without existing directive + """ + if not distribution: + distribution = '' + directive = 'sage_setup: ' f'distribution = {distribution}'.rstrip() + try: + with open(src_file, 'r') as f: + src_lines = f.read().splitlines() + except UnicodeDecodeError: + # Silently skip binary files + return + any_found = False + any_change = False + for i, line in enumerate(src_lines): + if m := distribution_directive.search(line): + old_distribution = m.group(3) + if any_found: + # Found a second distribution directive; remove it. + if not (line := distribution_directive.sub(r'', line)): + line = None + else: + line = distribution_directive.sub(fr'\1{directive}', line) + if line != src_lines[i]: + src_lines[i] = line + any_change = True + if verbose: + print(f"{src_file}: changed 'sage_setup: " f"distribution' " + f"from {old_distribution!r} to {distribution!r}") + any_found = True + if not any_found: + if any(src_file.endswith(ext) + for ext in [".pxd", ".pxi", ".py", ".pyx", ".sage"]): + src_lines.insert(0, f'# {directive}') + any_change = True + if verbose: + print(f"{src_file}: added 'sage_setup: " + f"distribution = {distribution}' directive") + if not any_change: + return + with open(src_file, 'w') as f: + for line in src_lines: + if line is not None: + f.write(line + '\n') + + def is_package_or_sage_namespace_package_dir(path, *, distribution_filter=None): r""" Return whether ``path`` is a directory that contains a Python package. @@ -147,7 +255,7 @@ def is_package_or_sage_namespace_package_dir(path, *, distribution_filter=None): - ``distribution_filter`` -- (optional, default: ``None``) only consider ``all*.py`` files whose distribution (from a - ``# sage_setup: distribution = PACKAGE`` directive in the source file) + ``# sage_setup:`` ``distribution = PACKAGE`` directive in the source file) is an element of ``distribution_filter``. EXAMPLES: @@ -333,3 +441,181 @@ def seen(p, m={}): path = [p for p in path if not seen(p)] yield from walk_packages(path, info.name + '.', onerror) + + +def _all_filename(distribution): + if not distribution: + return 'all.py' + return f"all__{distribution.replace('-', '_')}.py" + + +def _distribution_from_all_filename(filename): + if m := re.match('all(__(.*?))?[.]py', filename): + if distribution_per_all_filename := m.group(2): + return distribution_per_all_filename.replace('_', '-') + return '' + return False + + +if __name__ == '__main__': + + from argparse import ArgumentParser + + parser = ArgumentParser(prog="sage --fixdistributions", + description="Maintenance tool for distribution packages of the Sage library", + epilog="By default, '%(prog)s' shows the distribution of each file.") + parser.add_argument('--add', metavar='DISTRIBUTION', type=str, default=None, + help=("add a 'sage_setup: DISTRIBUTION' directive to FILES; " + "do not change files that already have a nonempty directive")) + parser.add_argument('--set', metavar='DISTRIBUTION', type=str, default=None, + help="add or update the 'sage_setup: DISTRIBUTION' directive in FILES") + parser.add_argument('--from-egg-info', action="store_true", default=False, + help="take FILES from pkgs/DISTRIBUTION/DISTRIBUTION.egg-info/SOURCES.txt") + parser.add_argument("filename", metavar='FILES', nargs='*', type=str, + help=("source files or directories (default: all files from SAGE_SRC, " + "unless --from-egg-info, --add, or --set are used)")) + + args = parser.parse_args() + + distribution = args.set or args.add or '' + + if distribution == 'all': + distributions = ["sagemath-bliss", + "sagemath-coxeter3", + "sagemath-mcqd", + "sagemath-meataxe", + "sagemath-sirocco", + "sagemath-tdlib", + "sagemath-environment", + "sagemath-categories", + "sagemath-repl", + "sagemath-objects"] + else: + distributions = [distribution.replace('_', '-')] + + if args.from_egg_info: + if not distribution: + print("Switch '--from-egg-info' must be used with either " + "'--add DISTRIBUTION' or '--set DISTRIBUTION'") + sys.exit(1) + elif not args.filename: + if distribution: + print("Switches '--add' and '--set' require the switch '--from-egg-info' " + "or one or more file or directory names") + sys.exit(1) + from sage.env import SAGE_SRC + if (not SAGE_SRC + or not os.path.exists(os.path.join(SAGE_SRC, 'sage')) + or not os.path.exists(os.path.join(SAGE_SRC, 'conftest_test.py'))): + print(f'{SAGE_SRC=} does not seem to contain a copy of the Sage source tree') + sys.exit(1) + args.filename = [os.path.join(SAGE_SRC, 'sage')] + + ordinary_packages = set() + package_distributions_per_directives = defaultdict(set) # path -> set of strings (distributions) + package_distributions_per_all_files = defaultdict(set) # path -> set of strings (distributions) + + def handle_file(root, file): + path = os.path.join(root, file) + if args.set is not None: + update_distribution(path, distribution, verbose=True) + file_distribution = distribution + elif args.add is not None: + if not (file_distribution := read_distribution(path)): + update_distribution(path, distribution, verbose=True) + file_distribution = distribution + else: + file_distribution = read_distribution(path) + print(f'{path}: file in distribution {file_distribution!r}') + package_distributions_per_directives[root].add(file_distribution) + if file.startswith('__init__.'): + ordinary_packages.add(root) + elif (distribution_per_all_filename := _distribution_from_all_filename(file)) is False: + # Not an all*.py file. + pass + elif not distribution_per_all_filename: + # An all.py file. + if file_distribution: + # The all.py is declared to belong to a named distribution, that's OK + package_distributions_per_all_files[root].add(file_distribution) + else: + pass + else: + # An all__*.py file + if distribution_per_all_filename != file_distribution: + print(f'{path}: file should go in distribution {distribution_per_all_filename!r}, not {file_distribution!r}') + package_distributions_per_all_files[root].add(distribution_per_all_filename) + + for distribution in distributions: + + paths = list(args.filename) + + if args.from_egg_info: + from sage.env import SAGE_ROOT + if not distribution: + print("Switch '--from-egg-info' must be used with either " + "'--add DISTRIBUTION' or '--set DISTRIBUTION'") + sys.exit(1) + if not SAGE_ROOT: + print(f'{SAGE_ROOT=} does not seem to contain a copy of the Sage source root') + sys.exit(1) + distribution_dir = os.path.join(SAGE_ROOT, 'pkgs', distribution) + if not os.path.exists(distribution_dir): + print(f'{distribution_dir} does not exist') + sys.exit(1) + distribution_underscore = distribution.replace('-', '_') + try: + with open(os.path.join(distribution_dir, + f'{distribution_underscore}.egg-info', 'SOURCES.txt'), "r") as f: + paths.extend(os.path.join(SAGE_ROOT, 'src', line.strip()) + for line in f + if line.startswith('sage/')) + print(f"sage --fixdistributions: found egg-info of distribution {distribution!r}") + except FileNotFoundError: + if len(distributions) > 1: + print(f"sage --fixdistributions: distribution {distribution!r} does not have egg-info, skipping it; " + f"run 'make {distribution_underscore}-sdist' or 'make {distribution_underscore}' to create it") + continue + else: + print(f"sage --fixdistributions: distribution {distribution!r} does not have egg-info; " + f"run 'make {distribution_underscore}-sdist' or 'make {distribution_underscore}' to create it") + sys.exit(1) + + for path in paths: + path = os.path.relpath(path) + if os.path.isdir(path): + if not is_package_or_sage_namespace_package_dir(path): + print(f'{path}: non-package directory') + else: + for root, dirs, files in os.walk(path): + for dir in sorted(dirs): + path = os.path.join(root, dir) + if any(dir.startswith(prefix) for prefix in ['.', 'build', 'dist', '__pycache__', '_vendor', '.tox']): + # Silently skip + dirs.remove(dir) + elif not is_package_or_sage_namespace_package_dir(path): + print(f'{path}: non-package directory') + dirs.remove(dir) + for file in sorted(files): + if any(file.endswith(ext) for ext in [".pyc", ".pyo", ".bak", ".so", "~"]): + continue + handle_file(root, file) + else: + handle_file(*os.path.split(path)) + + print(f"sage --fixdistributions: checking consistency") + + for package in ordinary_packages: + if len(package_distributions_per_directives[package]) > 1: + print(f'{package}: ordinary packages (with __init__.py) cannot be split in several distributions (' + + ', '.join(f'{dist!r}' + for dist in sorted(package_distributions_per_directives[package])) + ')') + + for package, distributions_per_directives in package_distributions_per_directives.items(): + if package in ordinary_packages: + pass + elif ((missing_all_files := distributions_per_directives - package_distributions_per_all_files[package]) + and not(missing_all_files == set(['']) and len(distributions_per_directives) < 2)): + s = '' if len(missing_all_files) == 1 else 's' + print(f'{package}: missing file{s} ' + ', '.join(_all_filename(distribution) + for distribution in missing_all_files)) diff --git a/src/sage/misc/sagedoc.py b/src/sage/misc/sagedoc.py index fb11088dac9..2632d0c4359 100644 --- a/src/sage/misc/sagedoc.py +++ b/src/sage/misc/sagedoc.py @@ -45,8 +45,8 @@ import sys import pydoc from sage.misc.temporary_file import tmp_dir -from .viewer import browser -from . import sageinspect +from sage.misc.viewer import browser +from sage.misc import sageinspect import sage.version from sage.env import SAGE_DOC, SAGE_SRC diff --git a/src/sage/misc/superseded.py b/src/sage/misc/superseded.py index 6e93d8e5a51..87352e4f361 100644 --- a/src/sage/misc/superseded.py +++ b/src/sage/misc/superseded.py @@ -363,10 +363,10 @@ def __init__(self, issue_number, func, module, instance=None, unbound=None): try: self.__dict__.update(func.__dict__) except AttributeError: - pass # Cython classes don't have __dict__ + pass # Cython classes don't have __dict__ self.func = func - self.issue_number = issue_number - self.instance = instance # for use with methods + self.issue_number = issue_number + self.instance = instance # for use with methods self.unbound = unbound self.__module__ = module if isinstance(func, type(deprecation)): diff --git a/src/sage/modular/abvar/abvar.py b/src/sage/modular/abvar/abvar.py index 4f23ab768fd..f47e1fc7448 100644 --- a/src/sage/modular/abvar/abvar.py +++ b/src/sage/modular/abvar/abvar.py @@ -2060,8 +2060,8 @@ def newform_level(self, none_if_not_known=False): if none_if_not_known: return None level = LCM([f.level() for f in self.newform_decomposition('a')]) - groups = sorted(set([f.group() for f in - self.newform_decomposition('a')])) + groups = sorted({f.group() for f in + self.newform_decomposition('a')}) if len(groups) == 1: groups = groups[0] self.__newform_level = level, groups @@ -3870,7 +3870,7 @@ def _factors_with_same_label(self, other): if not isinstance(other, ModularAbelianVariety_abstract): raise TypeError("other must be an abelian variety") D = self.decomposition() - C = set([A.newform_label() for A in other.decomposition()]) + C = {A.newform_label() for A in other.decomposition()} Z = [] for X in D: lbl = X.newform_label() @@ -4899,7 +4899,7 @@ def tamagawa_number_bounds(self, p): else: raise NotImplementedError("Atkin-Lehner at p must act as a scalar") else: - mul_primes = sorted(set([p] + [q for q in prime_range(2, 2 * self.dimension() + 2)])) + mul_primes = sorted(set([p] + list(prime_range(2, 2 * self.dimension() + 2)))) div = Integer(div) mul = Integer(mul) mul_primes = tuple(mul_primes) diff --git a/src/sage/modular/abvar/homspace.py b/src/sage/modular/abvar/homspace.py index 964df397a93..d0e192d2808 100644 --- a/src/sage/modular/abvar/homspace.py +++ b/src/sage/modular/abvar/homspace.py @@ -168,15 +168,15 @@ - Craig Citro, Robert Bradshaw (2008-03): Rewrote with modabvar overhaul """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2007 William Stein # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** from copy import copy @@ -188,7 +188,6 @@ from . import morphism -import sage.rings.integer_ring from sage.rings.infinity import Infinity from sage.rings.ring import Ring @@ -276,7 +275,7 @@ def _matrix_space(self): sage: Hom(J0(11), J0(22))._matrix_space Full MatrixSpace of 2 by 4 dense matrices over Integer Ring """ - return MatrixSpace(ZZ,2*self.domain().dimension(), 2*self.codomain().dimension()) + return MatrixSpace(ZZ, 2*self.domain().dimension(), 2*self.codomain().dimension()) def _element_constructor_from_element_class(self, *args, **keywords): """ @@ -479,7 +478,7 @@ def free_module(self): """ self.calculate_generators() V = ZZ**(4*self.domain().dimension() * self.codomain().dimension()) - return V.submodule([ V(m.matrix().list()) for m in self.gens() ]) + return V.submodule([V(m.matrix().list()) for m in self.gens()]) def gen(self, i=0): """ @@ -570,7 +569,7 @@ def calculate_generators(self): return if (self.domain() == self.codomain()) and (self.domain().dimension() == 1): - self._gens = tuple([ identity_matrix(ZZ,2) ]) + self._gens = (identity_matrix(ZZ, 2),) return phi = self.domain()._isogeny_to_product_of_powers() @@ -583,9 +582,9 @@ def calculate_generators(self): Mt = psi.complementary_isogeny().matrix() R = ZZ**(4*self.domain().dimension()*self.codomain().dimension()) - gens = R.submodule([ (M*self._get_matrix(g)*Mt).list() - for g in im_gens ]).saturation().basis() - self._gens = tuple([ self._get_matrix(g) for g in gens ]) + gens = R.submodule([(M*self._get_matrix(g)*Mt).list() + for g in im_gens]).saturation().basis() + self._gens = tuple([self._get_matrix(g) for g in gens]) def _calculate_product_gens(self): """ @@ -746,7 +745,8 @@ def _calculate_simple_gens(self): Mf = f.matrix() Mg = g.matrix() - return [ Mf * self._get_matrix(e) * Mg for e in ls ] + return [Mf * self._get_matrix(e) * Mg for e in ls] + # NOTE/WARNING/TODO: Below in the __init__, etc. we do *not* check # that the input gens are give something that spans a sub*ring*, as apposed @@ -820,7 +820,7 @@ def __init__(self, A, gens=None, category=None): if gens is None: self._gens = None else: - self._gens = tuple([ self._get_matrix(g) for g in gens ]) + self._gens = tuple([self._get_matrix(g) for g in gens]) self._is_full_ring = gens is None def _repr_(self): @@ -903,7 +903,7 @@ def index_in_saturation(self): A = self.abelian_variety() d = A.dimension() M = ZZ**(4*d**2) - gens = [ x.matrix().list() for x in self.gens() ] + gens = [x.matrix().list() for x in self.gens()] R = M.submodule(gens) return R.index_in_saturation() @@ -934,8 +934,8 @@ def discriminant(self): 2 """ g = self.gens() - M = Matrix(ZZ,len(g), [ (g[i]*g[j]).trace() - for i in range(len(g)) for j in range(len(g)) ]) + M = Matrix(ZZ, len(g), [(g[i]*g[j]).trace() + for i in range(len(g)) for j in range(len(g))]) return M.determinant() def image_of_hecke_algebra(self, check_every=1): @@ -1002,18 +1002,18 @@ def image_of_hecke_algebra(self, check_every=1): EndVecZ = ZZ**(4*d**2) if d == 1: - self.__hecke_algebra_image = EndomorphismSubring(A, [[1,0,0,1]]) + self.__hecke_algebra_image = EndomorphismSubring(A, [[1, 0, 0, 1]]) return self.__hecke_algebra_image V = EndVecZ.submodule([A.hecke_operator(1).matrix().list()]) - for n in range(2,M.sturm_bound()+1): + for n in range(2, M.sturm_bound()+1): if (check_every > 0 and n % check_every == 0 and V.dimension() == d and V.index_in_saturation() == 1): break - V += EndVecZ.submodule([ A.hecke_operator(n).matrix().list() ]) + V += EndVecZ.submodule([A.hecke_operator(n).matrix().list()]) self.__hecke_algebra_image = EndomorphismSubring(A, V.basis()) return self.__hecke_algebra_image diff --git a/src/sage/modular/arithgroup/arithgroup_perm.py b/src/sage/modular/arithgroup/arithgroup_perm.py index eb0e645559a..8204995e1d1 100644 --- a/src/sage/modular/arithgroup/arithgroup_perm.py +++ b/src/sage/modular/arithgroup/arithgroup_perm.py @@ -1798,7 +1798,7 @@ def cusp_widths(self,exp=False): """ inv = self.S2()**2 L = self.L() - cusps = set(c[0] for c in L.cycle_tuples(singletons=True)) + cusps = {c[0] for c in L.cycle_tuples(singletons=True)} if exp: widths = {} else: @@ -2603,7 +2603,7 @@ def odd_subgroups(self): s3 = PermutationConstructor([x + tuple(y + n for y in x) for x in s3cycs]) H = ArithmeticSubgroup_Permutation(S2=s2,S3=s3) - bucket = set([H]) + bucket = {H} res = [H] # We use a set *and* a list since checking whether an element is in a # set is very fast, but on the other hand we want the order the results diff --git a/src/sage/modular/arithgroup/congroup_gammaH.py b/src/sage/modular/arithgroup/congroup_gammaH.py index c9e53fdf3a8..60df7b2add9 100644 --- a/src/sage/modular/arithgroup/congroup_gammaH.py +++ b/src/sage/modular/arithgroup/congroup_gammaH.py @@ -146,7 +146,7 @@ def _normalize_H(H, level): for h in H: if gcd(h, level) > 1: raise ArithmeticError('The generators %s must be units modulo %s' % (H, level)) - H = set(u for u in H if u > 1) + H = {u for u in H if u > 1} final_H = set() for h in H: inv_h = h.inverse_mod(level) @@ -1140,7 +1140,7 @@ def ncusps(self): c = ZZ(0) for d in (d for d in N.divisors() if d**2 <= N): Nd = lcm(d, N // d) - Hd = set([x % Nd for x in H]) + Hd = {x % Nd for x in H} lenHd = len(Hd) if Nd - 1 not in Hd: lenHd *= 2 @@ -1182,7 +1182,7 @@ def nregcusps(self): c = ZZ(0) for d in (d for d in divisors(N) if d**2 <= N): Nd = lcm(d, N // d) - Hd = set([x % Nd for x in H]) + Hd = {x % Nd for x in H} if Nd - 1 not in Hd: summand = euler_phi(d) * euler_phi(N // d) // (2 * len(Hd)) if d**2 == N: @@ -1395,7 +1395,7 @@ def _list_subgroup(N, gens): sage: sage.modular.arithgroup.congroup_gammaH._list_subgroup(11, [3]) [1, 3, 4, 5, 9] """ - H = set([1]) + H = {1} N = int(N) for g in gens: if gcd(g, N) != 1: @@ -1405,7 +1405,7 @@ def _list_subgroup(N, gens): while not (gk in H): gk = (gk * g) % N sbgrp.append(gk) - H = set([(x * h) % N for x in sbgrp for h in H]) + H = {(x * h) % N for x in sbgrp for h in H} return sorted(H) diff --git a/src/sage/modular/btquotients/btquotient.py b/src/sage/modular/btquotients/btquotient.py index 3c7bceb0aa3..acb47da55e7 100644 --- a/src/sage/modular/btquotients/btquotient.py +++ b/src/sage/modular/btquotients/btquotient.py @@ -3710,7 +3710,7 @@ def _compute_quotient(self, check=True): 'from expected.') self._nontorsion_generators = nontorsion_generators - self._boundary = dict([(vv.rep, vv) for vv in vertex_list]) + self._boundary = {vv.rep: vv for vv in vertex_list} self._edge_list = edge_list self._vertex_list = vertex_list self._num_edges = num_edges diff --git a/src/sage/modular/dirichlet.py b/src/sage/modular/dirichlet.py index e752cc36b59..568e7c678f0 100644 --- a/src/sage/modular/dirichlet.py +++ b/src/sage/modular/dirichlet.py @@ -1282,7 +1282,7 @@ def galois_orbit(self, sort=True): P = self.parent() z = self.element() o = int(z.additive_order()) - Auts = set([m % o for m in P._automorphisms()]) + Auts = {m % o for m in P._automorphisms()} v = [P.element_class(P, m * z, check=False) for m in Auts] if sort: v.sort() diff --git a/src/sage/modular/etaproducts.py b/src/sage/modular/etaproducts.py index b17a99068a8..700b369b5df 100644 --- a/src/sage/modular/etaproducts.py +++ b/src/sage/modular/etaproducts.py @@ -558,7 +558,7 @@ def basis(self, reduce=True): nf = (i < S.ncols() and S[i, i]) or 0 # ? good_vects.append((vect * 24 / gcd(nf, 24)).list()) for v in good_vects: - v.append(-sum([r for r in v])) + v.append(-sum(list(v))) dicts = [] for v in good_vects: dicts.append({}) diff --git a/src/sage/modular/hypergeometric_motive.py b/src/sage/modular/hypergeometric_motive.py index 0db87ac9f66..b26e5c39be5 100644 --- a/src/sage/modular/hypergeometric_motive.py +++ b/src/sage/modular/hypergeometric_motive.py @@ -661,7 +661,7 @@ def wild_primes(self): [2, 3, 5] """ gamma = self.gamma_array() - return sorted(set([p for n in gamma.keys() for (p, _) in n.factor()])) + return sorted({p for n in gamma.keys() for (p, _) in n.factor()}) def zigzag(self, x, flip_beta=False): r""" diff --git a/src/sage/modular/local_comp/smoothchar.py b/src/sage/modular/local_comp/smoothchar.py index 62d80dc560a..1e4c25fe096 100644 --- a/src/sage/modular/local_comp/smoothchar.py +++ b/src/sage/modular/local_comp/smoothchar.py @@ -1103,7 +1103,7 @@ def quadratic_chars(self): q = 1 ram = [self.from_dirichlet(chi) for chi in DirichletGroup(self.prime() ** q, QQ) if not chi.is_trivial()] nr = self.character(0, [-1]) - return sorted([nr] + [f for f in ram] + [f*nr for f in ram]) + return sorted([nr] + list(ram) + [f*nr for f in ram]) class SmoothCharacterGroupQuadratic(SmoothCharacterGroupGeneric): r""" @@ -1793,12 +1793,12 @@ def exponents(self, c): c = ZZ(c) p = self.prime() if c == 0: - return tuple([0]) + return (0,) elif c == 1: - return tuple([p - 1, 0]) + return (p - 1, 0) elif p > 3 or self._unif_sqr == 3 or c <= 3: d = (c + 1) // 2 - return tuple([p**(d - 1) * (p - 1), p**(c // 2), 0]) + return (p**(d - 1) * (p - 1), p**(c // 2), 0) else: # awkward case, see above return self.ideal(c).idealstar(2).gens_orders() + (0,) diff --git a/src/sage/modular/modform_hecketriangle/abstract_space.py b/src/sage/modular/modform_hecketriangle/abstract_space.py index e0c4506122d..d1c52cc3b8f 100644 --- a/src/sage/modular/modform_hecketriangle/abstract_space.py +++ b/src/sage/modular/modform_hecketriangle/abstract_space.py @@ -761,7 +761,7 @@ def aut_factor(self, gamma, t): elif (gamma.is_reflection()): return self._ep * (t/QQbar(I))**self._weight else: - L = [v for v in gamma.word_S_T()[0]] + L = list(gamma.word_S_T()[0]) aut_f = ZZ(1) while (len(L) > 0): M = L.pop(-1) @@ -1857,7 +1857,7 @@ def _quasi_form_matrix(self, min_exp=0, order_1=ZZ(0), incr_prec_by=0): return A B = A - A = A.delete_rows([r for r in range(column_size + (row_size-column_size)//2 - 1, row_size)]) + A = A.delete_rows(list(range(column_size + (row_size-column_size)//2 - 1, row_size))) # Next we simply delete row by row. Note that A is still modified here... while (B.rank() == column_size): diff --git a/src/sage/modular/modform_hecketriangle/analytic_type.py b/src/sage/modular/modform_hecketriangle/analytic_type.py index bdbc34a778a..e5fc53abb25 100644 --- a/src/sage/modular/modform_hecketriangle/analytic_type.py +++ b/src/sage/modular/modform_hecketriangle/analytic_type.py @@ -445,7 +445,7 @@ def __init__(self): linear_extension=True, facade=False) L = self._base_poset.order_ideals_lattice() - H = L._hasse_diagram.relabel({i: x for i, x in enumerate(L._elements)}, + H = L._hasse_diagram.relabel(dict(enumerate(L._elements)), inplace=False) FiniteLatticePoset.__init__(self, hasse_diagram=H, elements=L._elements, category=L.category(), @@ -485,7 +485,7 @@ def __call__(self, *args, **kwargs): True """ if len(args) > 1: - return super().__call__([arg for arg in args], **kwargs) + return super().__call__(list(args), **kwargs) else: return super().__call__(*args, **kwargs) diff --git a/src/sage/modular/modform_hecketriangle/constructor.py b/src/sage/modular/modform_hecketriangle/constructor.py index 3a9e21fa852..040aa01add7 100644 --- a/src/sage/modular/modform_hecketriangle/constructor.py +++ b/src/sage/modular/modform_hecketriangle/constructor.py @@ -129,8 +129,8 @@ def rational_type(f, n=ZZ(3), base_ring=ZZ): num = R(f.numerator()) denom = R(f.denominator()) - ep_num = set([ZZ.one() - 2*((sum([g.exponents()[0][m] for m in [1, 2]])) % 2) for g in dhom(num).monomials()]) - ep_denom = set([ZZ.one() - 2*((sum([g.exponents()[0][m] for m in [1, 2]])) % 2) for g in dhom(denom).monomials()]) + ep_num = {ZZ.one() - 2*((sum([g.exponents()[0][m] for m in [1, 2]])) % 2) for g in dhom(num).monomials()} + ep_denom = {ZZ.one() - 2*((sum([g.exponents()[0][m] for m in [1, 2]])) % 2) for g in dhom(denom).monomials()} if (n == infinity): hom_num = R( num.subs(x=x**4, y=y**2, z=z**2) ) diff --git a/src/sage/modular/modform_hecketriangle/element.py b/src/sage/modular/modform_hecketriangle/element.py index b8cac1e9f52..4f58baafff5 100644 --- a/src/sage/modular/modform_hecketriangle/element.py +++ b/src/sage/modular/modform_hecketriangle/element.py @@ -337,7 +337,7 @@ def lseries(self, num_prec=None, max_imaginary_part=0, max_asymp_coeffs=40): # num_coeffs = L.num_coeffs() num_coeffs = L.num_coeffs(1.2) - coeff_vector = [coeff for coeff in self.q_expansion_vector(min_exp=0, max_exp=num_coeffs + 1, fix_d=True)] + coeff_vector = list(self.q_expansion_vector(min_exp=0, max_exp=num_coeffs + 1, fix_d=True)) pari_precode = "coeff = {};".format(coeff_vector) L.init_coeffs(v="coeff[k+1]", pari_precode=pari_precode, diff --git a/src/sage/modular/modform_hecketriangle/hecke_triangle_groups.py b/src/sage/modular/modform_hecketriangle/hecke_triangle_groups.py index 6c73cc50d40..b37898fc024 100644 --- a/src/sage/modular/modform_hecketriangle/hecke_triangle_groups.py +++ b/src/sage/modular/modform_hecketriangle/hecke_triangle_groups.py @@ -803,7 +803,7 @@ def root_extension_embedding(self, D, K=None): else: K = AlgebraicField() - L = [emb for emb in F.embeddings(K)] + L = list(F.embeddings(K)) # Three possibilities up to numerical artefacts: # (1) emb = e, purely imaginary diff --git a/src/sage/modular/modform_hecketriangle/space.py b/src/sage/modular/modform_hecketriangle/space.py index 9df1e2d60ba..e897808ef23 100644 --- a/src/sage/modular/modform_hecketriangle/space.py +++ b/src/sage/modular/modform_hecketriangle/space.py @@ -327,7 +327,7 @@ def coordinate_vector(self, v): ambient_space = self.graded_ring().reduce_type("holo", degree=(gens[0].weight(), gens[0].ep())) subspace = ambient_space.subspace(gens) vector_part_in_subspace = subspace(parts[r]) - coord_part = [v for v in vector_part_in_subspace.coordinate_vector()] + coord_part = list(vector_part_in_subspace.coordinate_vector()) coord_vector += coord_part return self._module(vector(self.coeff_ring(), coord_vector)) @@ -499,7 +499,7 @@ def coordinate_vector(self, v): ambient_space = self.graded_ring().reduce_type("cusp", degree=(gens[0].weight(), gens[0].ep())) subspace = ambient_space.subspace(gens) vector_part_in_subspace = subspace(parts[r]) - coord_part = [v for v in vector_part_in_subspace.coordinate_vector()] + coord_part = list(vector_part_in_subspace.coordinate_vector()) coord_vector += coord_part return self._module(vector(self.coeff_ring(), coord_vector)) diff --git a/src/sage/modular/modform_hecketriangle/subspace.py b/src/sage/modular/modform_hecketriangle/subspace.py index 4475f71530a..504c5fc1936 100644 --- a/src/sage/modular/modform_hecketriangle/subspace.py +++ b/src/sage/modular/modform_hecketriangle/subspace.py @@ -208,7 +208,7 @@ def __init__(self, ambient_space, basis, check): Module.__init__(self, base=ambient_space.base_ring()) self._ambient_space = ambient_space - self._basis = [v for v in basis] + self._basis = list(basis) # self(v) instead would somehow mess up the coercion model self._gens = [self._element_constructor_(v) for v in basis] self._module = ambient_space._module.submodule([ambient_space.coordinate_vector(v) for v in basis]) diff --git a/src/sage/modular/modsym/ambient.py b/src/sage/modular/modsym/ambient.py index a0e40c27785..89ba2741eac 100644 --- a/src/sage/modular/modsym/ambient.py +++ b/src/sage/modular/modsym/ambient.py @@ -2260,7 +2260,7 @@ def integral_structure(self, algorithm='default'): # The attribute _mod2term is set by self.compute_presentation(). # It is a list of pairs (n, c), such that the ith element of the list # is equivalent to c times the n-th basis Manin symbol. - G = set([i for i, _ in self._mod2term]) + G = {i for i, _ in self._mod2term} # Now G is a set of integer i such that these integers gives # indices of Manin symbols that together generate the integral diff --git a/src/sage/modular/modsym/boundary.py b/src/sage/modular/modsym/boundary.py index e90a5d165f6..903c57e9b96 100644 --- a/src/sage/modular/modsym/boundary.py +++ b/src/sage/modular/modsym/boundary.py @@ -567,7 +567,7 @@ def __call__(self, x): return sum([c * self._coerce_in_manin_symbol(v) for c, v in S]) elif is_FreeModuleElement(x): - y = {i: xi for i, xi in enumerate(x)} + y = dict(enumerate(x)) return BoundarySpaceElement(self, y) raise TypeError("Coercion of %s (of type %s) into %s not (yet) defined." % (x, type(x), self)) diff --git a/src/sage/modular/modsym/ghlist.py b/src/sage/modular/modsym/ghlist.py index 5df29f52af9..2e74217f851 100644 --- a/src/sage/modular/modsym/ghlist.py +++ b/src/sage/modular/modsym/ghlist.py @@ -48,7 +48,7 @@ def __init__(self, group): N = group.level() v = group._coset_reduction_data()[0] N = group.level() - coset_reps = set([a for a, b, _ in v if b == 1]) + coset_reps = {a for a, b, _ in v if b == 1} w = [group._reduce_coset(x*u, x*v) for x in coset_reps for u,v in p1list.P1List(N).list()] w = sorted(set(w)) self.__list = w diff --git a/src/sage/modular/modsym/relation_matrix.py b/src/sage/modular/modsym/relation_matrix.py index 5885812d36c..0533ea36f09 100644 --- a/src/sage/modular/modsym/relation_matrix.py +++ b/src/sage/modular/modsym/relation_matrix.py @@ -320,7 +320,7 @@ def gens_to_basis_matrix(syms, relation_matrix, mod, field, sparse): basis_set = set(A.nonpivots()) pivots = A.pivots() - basis_mod2 = set([j for j, c in mod if c != 0]) + basis_mod2 = {j for j, c in mod if c != 0} basis_set = basis_set.intersection(basis_mod2) basis = sorted(basis_set) @@ -333,7 +333,7 @@ def gens_to_basis_matrix(syms, relation_matrix, mod, field, sparse): M = MatrixSpace(field, len(syms), len(basis), sparse=sparse) B = M(0) - cols_index = dict([(basis[i], i) for i in range(len(basis))]) + cols_index = {basis[i]: i for i in range(len(basis))} for i in basis_mod2: t, l = search(basis, i) diff --git a/src/sage/modular/multiple_zeta.py b/src/sage/modular/multiple_zeta.py index 494d183e805..cefcb3b3c65 100644 --- a/src/sage/modular/multiple_zeta.py +++ b/src/sage/modular/multiple_zeta.py @@ -277,7 +277,7 @@ def composition_to_iterated(w, reverse=False) -> tuple[int, ...]: sage: composition_to_iterated((1,2), True) (1, 0, 1) """ - word = tuple() + word = () loop_over = reversed(w) if reverse else w for letter in loop_over: word += (1,) + (0,) * (letter - 1) @@ -1175,7 +1175,7 @@ def simplify_full(self, basis=None): """ if basis is None: basis = self.parent().basis_brown - support = set(sum(d) for d in self.support()) + support = {sum(d) for d in self.support()} result = self.parent().zero() for d in sorted(support): h = self.homogeneous_component(d) @@ -1994,7 +1994,7 @@ def __bool__(self) -> bool: P = self.parent() deg = P.degree_on_basis phi = P.phi - for d in sorted(set(deg(w) for w in self.support())): + for d in sorted({deg(w) for w in self.support()}): z = self.homogeneous_component(d) if not phi(z).is_zero(): return True diff --git a/src/sage/modular/multiple_zeta_F_algebra.py b/src/sage/modular/multiple_zeta_F_algebra.py index 251310de6b8..89ac3436cb2 100644 --- a/src/sage/modular/multiple_zeta_F_algebra.py +++ b/src/sage/modular/multiple_zeta_F_algebra.py @@ -121,7 +121,7 @@ def basis_f_odd_iterator(n, start=3) -> Iterator[tuple]: (3, 11)] """ if n == 0: - yield tuple() + yield () return if n % 2 and n >= start: yield (n,) diff --git a/src/sage/modules/all.py b/src/sage/modules/all.py index 87621e61b29..660f1ef3807 100644 --- a/src/sage/modules/all.py +++ b/src/sage/modules/all.py @@ -1,4 +1,4 @@ -#***************************************************************************** +# ***************************************************************************** # Copyright (C) 2005 William Stein # # Distributed under the terms of the GNU General Public License (GPL) @@ -11,23 +11,30 @@ # The full text of the GPL is available at: # # http://www.gnu.org/licenses/ -#***************************************************************************** +# ***************************************************************************** -from .free_module import FreeModule, VectorSpace, span +from sage.modules.free_module import FreeModule, VectorSpace, span -from .free_quadratic_module import (FreeQuadraticModule, QuadraticSpace, - InnerProductSpace) +from sage.modules.free_quadratic_module import ( + FreeQuadraticModule, + QuadraticSpace, + InnerProductSpace, +) -from .free_module_element import (vector, free_module_element, zero_vector, - random_vector) +from sage.modules.free_module_element import ( + vector, + free_module_element, + zero_vector, + random_vector, +) -from .vector_space_morphism import linear_transformation +from sage.modules.vector_space_morphism import linear_transformation -from .with_basis.all import * +from sage.modules.with_basis.all import * from sage.misc.lazy_import import lazy_import -lazy_import('sage.modules.filtered_vector_space', 'FilteredVectorSpace') -lazy_import('sage.modules.multi_filtered_vector_space', 'MultiFilteredVectorSpace') -lazy_import('sage.modules.free_quadratic_module_integer_symmetric', 'IntegralLattice') -lazy_import('sage.modules.torsion_quadratic_module', 'TorsionQuadraticForm') +lazy_import("sage.modules.filtered_vector_space", "FilteredVectorSpace") +lazy_import("sage.modules.multi_filtered_vector_space", "MultiFilteredVectorSpace") +lazy_import("sage.modules.free_quadratic_module_integer_symmetric", "IntegralLattice") +lazy_import("sage.modules.torsion_quadratic_module", "TorsionQuadraticForm") diff --git a/src/sage/modules/complex_double_vector.py b/src/sage/modules/complex_double_vector.py index 88ad6bb6d67..728d862e8fc 100644 --- a/src/sage/modules/complex_double_vector.py +++ b/src/sage/modules/complex_double_vector.py @@ -19,6 +19,6 @@ # http://www.gnu.org/licenses/ ############################################################################### -from .vector_complex_double_dense import Vector_complex_double_dense +from sage.modules.vector_complex_double_dense import Vector_complex_double_dense ComplexDoubleVectorSpaceElement = Vector_complex_double_dense diff --git a/src/sage/modules/free_module.py b/src/sage/modules/free_module.py index 5a65b4260f0..00b28b26620 100644 --- a/src/sage/modules/free_module.py +++ b/src/sage/modules/free_module.py @@ -177,33 +177,41 @@ ########################################################################### import itertools +from warnings import warn -from . import free_module_element import sage.matrix.matrix_space import sage.misc.latex as latex - -from sage.modules.module import Module -import sage.rings.ring as ring import sage.rings.abc -import sage.rings.integer_ring -import sage.rings.rational_field import sage.rings.infinity import sage.rings.integer -from sage.categories.principal_ideal_domains import PrincipalIdealDomains -from sage.categories.integral_domains import IntegralDomains +import sage.rings.integer_ring +import sage.rings.rational_field +import sage.rings.ring as ring from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets +from sage.categories.integral_domains import IntegralDomains +from sage.categories.principal_ideal_domains import PrincipalIdealDomains +from sage.misc.cachefunc import cached_method from sage.misc.lazy_attribute import lazy_attribute +from sage.misc.lazy_import import LazyImport from sage.misc.randstate import current_randstate +from sage.modules import free_module_element +from sage.modules.module import Module from sage.rings.finite_rings.finite_field_base import FiniteField from sage.structure.factory import UniqueFactory +from sage.structure.richcmp import ( + op_EQ, + op_GE, + op_GT, + op_LE, + op_LT, + op_NE, + revop, + rich_to_bool, + richcmp, + richcmp_method, + richcmp_not_equal, +) from sage.structure.sequence import Sequence -from sage.structure.richcmp import (richcmp_method, rich_to_bool, richcmp, - richcmp_not_equal, revop, - op_LT,op_LE,op_EQ,op_NE,op_GT,op_GE) -from sage.misc.cachefunc import cached_method -from sage.misc.lazy_import import LazyImport - -from warnings import warn ############################################################################### # @@ -226,7 +234,7 @@ def create_key(self, base_ring, rank, sparse=False, inner_product_matrix=None): """ rank = int(sage.rings.integer.Integer(rank)) - if not (inner_product_matrix is None): + if inner_product_matrix is not None: inner_product_matrix = sage.matrix.matrix_space.MatrixSpace(base_ring, rank)(inner_product_matrix) inner_product_matrix.set_immutable() @@ -253,7 +261,7 @@ def create_object(self, version, key): base_ring, rank, sparse, inner_product_matrix = key if inner_product_matrix is not None: - from .free_quadratic_module import FreeQuadraticModule + from sage.modules.free_quadratic_module import FreeQuadraticModule return FreeQuadraticModule(base_ring, rank, inner_product_matrix=inner_product_matrix, sparse=sparse) if not isinstance(sparse,bool): @@ -1784,7 +1792,7 @@ def quotient_module(self, sub, check=True): sub = self.submodule(sub) except (TypeError, ArithmeticError): raise ArithmeticError("sub must be a subspace of self") - from .quotient_module import QuotientModule_free_ambient + from sage.modules.quotient_module import QuotientModule_free_ambient return QuotientModule_free_ambient(self, sub) def __truediv__(self, sub): @@ -1821,7 +1829,9 @@ def free_resolution(self, *args, **kwds): [ z x*z] 0 <-- C_0 <-------------- C_1 <-- 0 """ - from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular + from sage.rings.polynomial.multi_polynomial_libsingular import ( + MPolynomialRing_libsingular, + ) if isinstance(self.base_ring(), MPolynomialRing_libsingular): from sage.homology.free_resolution import FiniteFreeResolution_singular return FiniteFreeResolution_singular(self, *args, **kwds) @@ -1854,13 +1864,19 @@ def graded_free_resolution(self, *args, **kwds): sage: N.graded_free_resolution(degrees=[2, 1, 3], shifts=[2, 3]) # needs sage.libs.singular S(-2)⊕S(-3) <-- S(-6)⊕S(-8) <-- 0 """ - from sage.rings.polynomial.multi_polynomial_libsingular import MPolynomialRing_libsingular + from sage.rings.polynomial.multi_polynomial_libsingular import ( + MPolynomialRing_libsingular, + ) if isinstance(self.base_ring(), MPolynomialRing_libsingular): - from sage.homology.graded_resolution import GradedFiniteFreeResolution_singular + from sage.homology.graded_resolution import ( + GradedFiniteFreeResolution_singular, + ) return GradedFiniteFreeResolution_singular(self, *args, **kwds) if isinstance(self, FreeModule_generic): - from sage.homology.graded_resolution import GradedFiniteFreeResolution_free_module + from sage.homology.graded_resolution import ( + GradedFiniteFreeResolution_free_module, + ) return GradedFiniteFreeResolution_free_module(self, *args, **kwds) raise NotImplementedError("the module must be a free module or " @@ -1991,7 +2007,7 @@ def construction(self): # Should there be a category for free modules accepting it as hom space? # See similar method for FreeModule_generic_field class def _Hom_(self, Y, category): - from .free_module_homspace import FreeModuleHomspace + from sage.modules.free_module_homspace import FreeModuleHomspace return FreeModuleHomspace(self, Y, category) def dense_module(self): @@ -2443,7 +2459,7 @@ def aux(length, norm, max_): iters = [iter(R) for _ in range(len(G))] for x in iters: next(x) # put at 0 - zero = R(0) + zero = R.zero() v = [zero for _ in range(len(G))] n = 0 z = self(0) @@ -3873,11 +3889,11 @@ def intersection(self, other): V2 = self A1 = V1.basis_matrix() A2 = V2.basis_matrix() - S = A1.stack(A2) - K = S.integer_kernel(self.base_ring()).basis_matrix() - n = int(V1.dimension()) + S = A1.stack(A2) + K = S.integer_kernel(self.base_ring()).basis_matrix() + n = int(V1.dimension()) K = K.matrix_from_columns(range(n)) - B = K*A1 + B = K * A1 return self.span(B) def __and__(self, other): @@ -4084,7 +4100,9 @@ def span_of_basis(self, basis, base_ring=None, check=True, already_echelonized=F if base_ring is None or base_ring == self.base_ring(): try: if self.is_dense(): - from .free_module_integer import FreeModule_submodule_with_basis_integer + from sage.modules.free_module_integer import ( + FreeModule_submodule_with_basis_integer, + ) return FreeModule_submodule_with_basis_integer(self.ambient_module(), basis=basis, check=check, already_echelonized=already_echelonized, @@ -4299,7 +4317,7 @@ def quotient_module(self, sub, check=True, **kwds): except (TypeError, ArithmeticError): raise ArithmeticError("sub must be a subspace of self") if self.base_ring() == sage.rings.integer_ring.ZZ: - from .fg_pid.fgp_module import FGP_Module + from sage.modules.fg_pid.fgp_module import FGP_Module return FGP_Module(self, sub, check=False, **kwds) raise NotImplementedError("quotients of modules over rings other than fields or ZZ is not fully implemented") @@ -4376,9 +4394,9 @@ def _Hom_(self, Y, category): (number fields and quotient fields and metric spaces) """ if Y.base_ring().is_field(): - from . import vector_space_homspace + from sage.modules import vector_space_homspace return vector_space_homspace.VectorSpaceHomspace(self, Y, category) - from . import free_module_homspace + from sage.modules import free_module_homspace return free_module_homspace.FreeModuleHomspace(self, Y, category) def scale(self, other): @@ -5127,7 +5145,7 @@ def quotient_module(self, sub, check=True): except (TypeError, ArithmeticError): raise ArithmeticError("sub must be a subspace of self") A, L = self.__quotient_matrices(sub) - from . import quotient_module + from sage.modules import quotient_module return quotient_module.FreeModule_ambient_field_quotient(self, sub, A, L) def __quotient_matrices(self, sub): @@ -5201,10 +5219,10 @@ def __quotient_matrices(self, sub): # Our algorithm is to note that D is determined if we just # replace both A and S by the submatrix got from their pivot # columns. - P = A.pivots() + P = A.pivots() AA = A.matrix_from_columns(P) SS = S.matrix_from_columns(P) - D = SS * AA**(-1) + D = SS * AA**(-1) # Compute the image of each basis vector for ``self`` under the # map "write an element of ``self`` in terms of the basis A" then @@ -5370,8 +5388,8 @@ def _coerce_map_from_(self, M): sage: V = QQ^2 sage: V.coerce_map_from(M) """ - from sage.modules.submodule import Submodule_free_ambient from sage.modules.quotient_module import FreeModule_ambient_field_quotient + from sage.modules.submodule import Submodule_free_ambient if isinstance(M, FreeModule_ambient_field_quotient): # No forgetful map. @@ -5732,7 +5750,7 @@ def change_ring(self, R): """ if self.base_ring() is R: return self - from .free_quadratic_module import is_FreeQuadraticModule + from sage.modules.free_quadratic_module import is_FreeQuadraticModule if is_FreeQuadraticModule(self): return FreeModule(R, self.rank(), inner_product_matrix=self.inner_product_matrix(), @@ -5989,8 +6007,8 @@ def _sympy_(self): sage: (1, 2, 3) in sZZ3 # needs sympy True """ - from sympy import ProductSet from sage.interfaces.sympy import sympy_init + from sympy import ProductSet sympy_init() return ProductSet(*([self.coordinate_ring()] * self.rank())) @@ -8180,21 +8198,21 @@ def element_class(R, is_sparse): """ import sage.rings.integer_ring if sage.rings.integer_ring.is_IntegerRing(R) and not is_sparse: - from .vector_integer_dense import Vector_integer_dense + from sage.modules.vector_integer_dense import Vector_integer_dense return Vector_integer_dense elif sage.rings.rational_field.is_RationalField(R) and not is_sparse: - from .vector_rational_dense import Vector_rational_dense + from sage.modules.vector_rational_dense import Vector_rational_dense return Vector_rational_dense elif isinstance(R, sage.rings.abc.IntegerModRing) and not is_sparse: if R.order() == 2: try: - from .vector_mod2_dense import Vector_mod2_dense + from sage.modules.vector_mod2_dense import Vector_mod2_dense except ImportError: pass else: return Vector_mod2_dense try: - from .vector_modn_dense import Vector_modn_dense, MAX_MODULUS + from sage.modules.vector_modn_dense import MAX_MODULUS, Vector_modn_dense except ImportError: pass else: @@ -8210,7 +8228,9 @@ def element_class(R, is_sparse): return Vector_real_double_dense elif isinstance(R, sage.rings.abc.ComplexDoubleField) and not is_sparse: try: - from sage.modules.vector_complex_double_dense import Vector_complex_double_dense + from sage.modules.vector_complex_double_dense import ( + Vector_complex_double_dense, + ) except ImportError: pass else: diff --git a/src/sage/modules/free_module_morphism.py b/src/sage/modules/free_module_morphism.py index cdc933f23d0..6cf1add1f75 100644 --- a/src/sage/modules/free_module_morphism.py +++ b/src/sage/modules/free_module_morphism.py @@ -41,12 +41,10 @@ # be coercible into vector space of appropriate dimension. import sage.modules.free_module as free_module -from . import matrix_morphism from sage.categories.morphism import Morphism +from sage.modules import free_module_homspace, matrix_morphism +from sage.structure.richcmp import rich_to_bool, richcmp from sage.structure.sequence import Sequence -from sage.structure.richcmp import richcmp, rich_to_bool - -from . import free_module_homspace def is_FreeModuleMorphism(x): diff --git a/src/sage/modules/free_quadratic_module.py b/src/sage/modules/free_quadratic_module.py index ff112b9a5c2..df0f90a4fb6 100644 --- a/src/sage/modules/free_quadratic_module.py +++ b/src/sage/modules/free_quadratic_module.py @@ -71,7 +71,7 @@ import sage.misc.latex as latex import sage.rings.ring as ring from sage.categories.principal_ideal_domains import PrincipalIdealDomains -from . import free_module +from sage.modules import free_module # ############################################################################# # @@ -154,7 +154,7 @@ def FreeQuadraticModule(base_ring, rank, inner_product_matrix, if key in _cache: M = _cache[key]() - if not (M is None): + if M is not None: return M if not base_ring.is_commutative(): diff --git a/src/sage/modules/quotient_module.py b/src/sage/modules/quotient_module.py index c50c1d044fc..09c8b313c91 100644 --- a/src/sage/modules/quotient_module.py +++ b/src/sage/modules/quotient_module.py @@ -19,10 +19,11 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from .free_module import (Module_free_ambient, - FreeModule_ambient, - FreeModule_ambient_field) - +from sage.modules.free_module import ( + FreeModule_ambient, + FreeModule_ambient_field, + Module_free_ambient, +) ############################################################################### # diff --git a/src/sage/modules/real_double_vector.py b/src/sage/modules/real_double_vector.py index 1ceb320078e..5430e175f11 100644 --- a/src/sage/modules/real_double_vector.py +++ b/src/sage/modules/real_double_vector.py @@ -16,6 +16,6 @@ # Distributed under the terms of the GNU General Public License (GPL) # http://www.gnu.org/licenses/ ############################################################################### -from .vector_real_double_dense import Vector_real_double_dense +from sage.modules.vector_real_double_dense import Vector_real_double_dense RealDoubleVectorSpaceElement = Vector_real_double_dense diff --git a/src/sage/modules/submodule.py b/src/sage/modules/submodule.py index 3ab5a195f49..8d00d4f4553 100644 --- a/src/sage/modules/submodule.py +++ b/src/sage/modules/submodule.py @@ -34,10 +34,12 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.modules.free_module import (basis_seq, - Module_free_ambient, - FreeModule_ambient_domain) -from .quotient_module import QuotientModule_free_ambient +from sage.modules.free_module import ( + FreeModule_ambient_domain, + Module_free_ambient, + basis_seq, +) +from sage.modules.quotient_module import QuotientModule_free_ambient class Submodule_free_ambient(Module_free_ambient): diff --git a/src/sage/modules/vector_callable_symbolic_dense.py b/src/sage/modules/vector_callable_symbolic_dense.py index 1929eabcf46..70b05d98b66 100644 --- a/src/sage/modules/vector_callable_symbolic_dense.py +++ b/src/sage/modules/vector_callable_symbolic_dense.py @@ -49,7 +49,7 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from . import free_module_element +from sage.modules import free_module_element from sage.symbolic.ring import SR diff --git a/src/sage/modules/vector_mod2_dense.pxd b/src/sage/modules/vector_mod2_dense.pxd index 98a77624019..1292762a76e 100644 --- a/src/sage/modules/vector_mod2_dense.pxd +++ b/src/sage/modules/vector_mod2_dense.pxd @@ -1,4 +1,4 @@ -from .free_module_element cimport FreeModuleElement +from sage.modules.free_module_element cimport FreeModuleElement from sage.libs.m4ri cimport mzd_t diff --git a/src/sage/modules/vector_space_morphism.py b/src/sage/modules/vector_space_morphism.py index 91f8f6f64b2..1102d15968e 100644 --- a/src/sage/modules/vector_space_morphism.py +++ b/src/sage/modules/vector_space_morphism.py @@ -329,11 +329,12 @@ #################################################################################### -import sage.modules.matrix_morphism as matrix_morphism import sage.modules.free_module_morphism as free_module_morphism -from . import vector_space_homspace +import sage.modules.matrix_morphism as matrix_morphism +from sage.modules import vector_space_homspace from sage.structure.element import is_Matrix + def linear_transformation(arg0, arg1=None, arg2=None, side='left'): r""" Create a linear transformation from a variety of possible inputs. @@ -692,12 +693,14 @@ def linear_transformation(arg0, arg1=None, arg2=None, side='left'): ArithmeticError: some image of the function is not in the codomain, because element [1, 0] is not in free module """ + from sage.categories.homset import Hom from sage.matrix.constructor import matrix - from sage.modules.module import is_VectorSpace from sage.modules.free_module import VectorSpace - from sage.categories.homset import Hom + from sage.modules.module import is_VectorSpace try: - from sage.modules.vector_callable_symbolic_dense import Vector_callable_symbolic_dense + from sage.modules.vector_callable_symbolic_dense import ( + Vector_callable_symbolic_dense, + ) except ImportError: Vector_callable_symbolic_dense = () diff --git a/src/sage/modules/vector_symbolic_dense.py b/src/sage/modules/vector_symbolic_dense.py index ce134c0462e..46ea21be585 100644 --- a/src/sage/modules/vector_symbolic_dense.py +++ b/src/sage/modules/vector_symbolic_dense.py @@ -54,7 +54,7 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from . import free_module_element +from sage.modules import free_module_element from sage.symbolic.expression import Expression diff --git a/src/sage/modules/vector_symbolic_sparse.py b/src/sage/modules/vector_symbolic_sparse.py index 73cb41ae611..ff53995021c 100644 --- a/src/sage/modules/vector_symbolic_sparse.py +++ b/src/sage/modules/vector_symbolic_sparse.py @@ -56,7 +56,7 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from . import free_module_element +from sage.modules import free_module_element from sage.symbolic.expression import Expression diff --git a/src/sage/modules/with_basis/morphism.py b/src/sage/modules/with_basis/morphism.py index b94629a8dfe..30b4041f0cb 100644 --- a/src/sage/modules/with_basis/morphism.py +++ b/src/sage/modules/with_basis/morphism.py @@ -1055,7 +1055,7 @@ def coreduced(self, y): on_basis = self.on_basis() assert y in G - result = G.zero() + result = G.zero() remainder = y while not remainder.is_zero(): @@ -1447,7 +1447,7 @@ def __init__(self, domain, diagonal, codomain=None, category=None): if codomain is None: raise ValueError("The codomain should be specified") if not (domain.basis().keys() == codomain.basis().keys() and - domain.base_ring() == codomain.base_ring()): + domain.base_ring() == codomain.base_ring()): raise ValueError("The domain and codomain should have the same base ring " "and the same basis indexing") from collections.abc import Callable diff --git a/src/sage/plot/plot3d/platonic.py b/src/sage/plot/plot3d/platonic.py index be590739c3e..94d15ab16ad 100644 --- a/src/sage/plot/plot3d/platonic.py +++ b/src/sage/plot/plot3d/platonic.py @@ -152,6 +152,7 @@ def prep(G, center, size, kwds): G = G.translate(center) return G + @rename_keyword(alpha='opacity') def tetrahedron(center=(0, 0, 0), size=1, **kwds): """ @@ -255,15 +256,16 @@ def tetrahedron(center=(0, 0, 0), size=1, **kwds): one = RR.one() sqrt2 = RR(2).sqrt() sqrt6 = RR(6).sqrt() - point_list = [(0,0,1), - (2*sqrt2/3, 0, -one/3), - ( -sqrt2/3, sqrt6/3, -one/3), - ( -sqrt2/3, -sqrt6/3, -one/3)] + point_list = [(0, 0, 1), + (2*sqrt2/3, 0, -one/3), + (-sqrt2/3, sqrt6/3, -one/3), + (-sqrt2/3, -sqrt6/3, -one/3)] face_list = [[0,1,2],[1,3,2],[0,2,3],[0,3,1]] if 'aspect_ratio' not in kwds: kwds['aspect_ratio'] = [1, 1, 1] return index_face_set(face_list, point_list, enclosed=True, center=center, size=size, **kwds) + @rename_keyword(alpha='opacity') def cube(center=(0, 0, 0), size=1, color=None, frame_thickness=0, frame_color=None, **kwds): @@ -405,6 +407,7 @@ def cube(center=(0, 0, 0), size=1, color=None, frame_thickness=0, B += frame3d((-0.5,-0.5,-0.5),(0.5,0.5,0.5), thickness=frame_thickness, color=frame_color) return prep(B, center, size, kwds) + @rename_keyword(alpha='opacity') def octahedron(center=(0, 0, 0), size=1, **kwds): r""" @@ -440,7 +443,8 @@ def octahedron(center=(0, 0, 0), size=1, **kwds): kwds['enclosed'] = True if 'aspect_ratio' not in kwds: kwds['aspect_ratio'] = [1, 1, 1] - return prep(Box(1,1,1).dual(**kwds), center, size, kwds) + return prep(Box(1, 1, 1).dual(**kwds), center, size, kwds) + @rename_keyword(alpha='opacity') def dodecahedron(center=(0, 0, 0), size=1, **kwds): @@ -514,21 +518,21 @@ def dodecahedron(center=(0, 0, 0), size=1, **kwds): - Robert Bradshaw, William Stein """ RR = RDF - one = RR(1) + one = RR.one() sqrt3 = RR(3).sqrt() sqrt5 = RR(5).sqrt() R3 = RR**3 - rot = matrix(RR, [[ -one/2,-sqrt3/2, 0], - [ sqrt3/2, -one/2, 0], - [ 0, 0, 1]]) - rot2 = rot*rot + rot = matrix(RR, [[-one / 2, -sqrt3 / 2, 0], + [sqrt3 / 2, -one / 2, 0], + [0, 0, 1]]) + rot2 = rot * rot # The top - Q = R3([0,0,1]) + Q = R3([0, 0, 1]) # The first ring P1 = R3([2*one/3, 0, sqrt5/3]) # The second ring - R1 = R3([sqrt5/3, 1/sqrt3, one/3]) + R1 = R3([sqrt5/3, 1/sqrt3, one/3]) R2 = R3([sqrt5/3, -1/sqrt3, one/3]) top = [Q, P1, rot*P1, rot2*P1, R1, rot*R2, rot*R1, rot2*R2, rot2*R1, R2] @@ -555,6 +559,7 @@ def dodecahedron(center=(0, 0, 0), size=1, **kwds): # vertex_spheres += [faces.stickers(['red','yellow','blue','purple','black','orange'], .1, .1)] # [faces] # return Graphics3dGroup(vertex_spheres) + @rename_keyword(alpha='opacity') def icosahedron(center=(0, 0, 0), size=1, **kwds): r""" diff --git a/src/sage/plot/plot3d/tri_plot.py b/src/sage/plot/plot3d/tri_plot.py index da719020117..256b0d348c3 100644 --- a/src/sage/plot/plot3d/tri_plot.py +++ b/src/sage/plot/plot3d/tri_plot.py @@ -412,38 +412,38 @@ def plot_block(self, min_x, mid_x, max_x, min_y, mid_y, max_y, sw_z, nw_z, se_z, self.interface(0, sw.top, sw.top_c, nw.bottom, nw.bottom_c) self.interface(0, se.top, se.top_c, ne.bottom, ne.bottom_c) - #get the boundary information about the subsquares - left = sw.left + nw.left[1:] - left_c = sw.left_c + nw.left_c - right = se.right + ne.right[1:] - right_c = se.right_c + ne.right_c - top = nw.top + ne.top[1:] - top_c = nw.top_c + ne.top_c - bottom = sw.bottom + se.bottom[1:] + # get the boundary information about the subsquares + left = sw.left + nw.left[1:] + left_c = sw.left_c + nw.left_c + right = se.right + ne.right[1:] + right_c = se.right_c + ne.right_c + top = nw.top + ne.top[1:] + top_c = nw.top_c + ne.top_c + bottom = sw.bottom + se.bottom[1:] bottom_c = sw.bottom_c + se.bottom_c else: # just build the square we're in if self._g is None: - sw = [(min_x,min_y,sw_z[0])] - nw = [(min_x,max_y,nw_z[0])] - se = [(max_x,min_y,se_z[0])] - ne = [(max_x,max_y,ne_z[0])] - c = [[(mid_x,mid_y,mid_z[0])]] + sw = [(min_x, min_y, sw_z[0])] + nw = [(min_x, max_y, nw_z[0])] + se = [(max_x, min_y, se_z[0])] + ne = [(max_x, max_y, ne_z[0])] + c = [[(mid_x, mid_y, mid_z[0])]] else: - sw = [(min_x,min_y,sw_z[0]),sw_z[1]] - nw = [(min_x,max_y,nw_z[0]),nw_z[1]] - se = [(max_x,min_y,se_z[0]),se_z[1]] - ne = [(max_x,max_y,ne_z[0]),ne_z[1]] - c = [[(mid_x,mid_y,mid_z[0]),mid_z[1]]] - - left = [sw,nw] - left_c = c - top = [nw,ne] - top_c = c - right = [se,ne] - right_c = c - bottom = [sw,se] + sw = [(min_x, min_y, sw_z[0]), sw_z[1]] + nw = [(min_x, max_y, nw_z[0]), nw_z[1]] + se = [(max_x, min_y, se_z[0]), se_z[1]] + ne = [(max_x, max_y, ne_z[0]), ne_z[1]] + c = [[(mid_x, mid_y, mid_z[0]), mid_z[1]]] + + left = [sw, nw] + left_c = c + top = [nw, ne] + top_c = c + right = [se, ne] + right_c = c + bottom = [sw, se] bottom_c = c return PlotBlock(left, left_c, top, top_c, right, right_c, bottom, bottom_c) @@ -465,9 +465,9 @@ def interface(self, n, p, p_c, q, q_c): sage: t._objects[-1].get_vertices() ((-1/4, 0, 1/16), (-1/4, 1/4, 1/8), (-3/8, 1/8, 3/16)) """ - m = [p[0]] # a sorted union of p and q - mpc = [p_c[0]] # centers from p_c corresponding to m - mqc = [q_c[0]] # centers from q_c corresponding to m + m = [p[0]] # a sorted union of p and q + mpc = [p_c[0]] # centers from p_c corresponding to m + mqc = [q_c[0]] # centers from q_c corresponding to m i = 1 j = 1 diff --git a/src/sage/quadratic_forms/all.py b/src/sage/quadratic_forms/all.py index 3445705978a..81d395f375c 100644 --- a/src/sage/quadratic_forms/all.py +++ b/src/sage/quadratic_forms/all.py @@ -1,5 +1,7 @@ from .binary_qf import BinaryQF, BinaryQF_reduced_representatives +from .bqf_class_group import BQFClassGroup + from .ternary_qf import TernaryQF, find_all_ternary_qf_by_level_disc, find_a_ternary_qf_by_level_disc from .quadratic_form import QuadraticForm, DiagonalQuadraticForm, quadratic_form_from_invariants diff --git a/src/sage/quadratic_forms/binary_qf.py b/src/sage/quadratic_forms/binary_qf.py index 0f32bba92ba..880452d9430 100755 --- a/src/sage/quadratic_forms/binary_qf.py +++ b/src/sage/quadratic_forms/binary_qf.py @@ -179,6 +179,49 @@ def _pari_init_(self): """ return 'Qfb(%s,%s,%s)' % (self._a, self._b, self._c) + @staticmethod + def principal(D): + r""" + Return the principal binary quadratic form of the given discriminant. + + EXAMPLES:: + + sage: BinaryQF.principal(8) + x^2 - 2*y^2 + sage: BinaryQF.principal(5) + x^2 + x*y - y^2 + sage: BinaryQF.principal(4) + x^2 - y^2 + sage: BinaryQF.principal(1) + x^2 + x*y + sage: BinaryQF.principal(-3) + x^2 + x*y + y^2 + sage: BinaryQF.principal(-4) + x^2 + y^2 + sage: BinaryQF.principal(-7) + x^2 + x*y + 2*y^2 + sage: BinaryQF.principal(-8) + x^2 + 2*y^2 + + TESTS: + + Some randomized testing:: + + sage: D = 1 + sage: while D.is_square(): + ....: D = choice((-4,+4)) * randrange(9999) + randrange(2) + sage: Q = BinaryQF.principal(D) + sage: Q.discriminant() == D # correct discriminant + True + sage: (Q*Q).is_equivalent(Q) # idempotent (hence identity) + True + """ + D = ZZ(D) + D4 = D % 4 + if D4 not in (0,1): + raise ValueError('discriminant must be congruent to 0 or 1 modulo 4') + return BinaryQF([1, D4, (D4-D)//4]) + def __mul__(self, right): """ Gauss composition or right action by a 2x2 integer matrix. @@ -1581,9 +1624,10 @@ def solve_integer(self, n, *, algorithm="general"): sage: Q.solve_integer(773187972) # needs sage.libs.pari (4919, 1337) - If `Q` is of the form `[1,0,c]` as above and `n` is a prime or - four times a prime, Cornacchia's algorithm can be used, which is - typically much faster than the general method:: + If `Q` is of the form `[1,0,c]` as above and `n` is a prime + (or four times a prime whenever `c \equiv 3 \pmod 4`), then + Cornacchia's algorithm can be used, which is typically much + faster than the general method:: sage: Q = BinaryQF([1, 0, 12345]) sage: n = 2^99 + 5273 @@ -1622,16 +1666,30 @@ def solve_integer(self, n, *, algorithm="general"): Also when using the ``"cornacchia"`` algorithm:: sage: # needs sage.libs.pari - sage: abc = [1, 0, randrange(1,10^3)] - sage: Q = BinaryQF(abc) sage: n = random_prime(10^9) - sage: if randrange(2): - ....: n *= 4 - sage: xy1 = Q.solve_integer(n, algorithm='cornacchia') - sage: xy1 is None or Q(*xy1) == n + sage: c = randrange(1, 10^3) + + sage: # needs sage.libs.pari + sage: Q1 = BinaryQF(1, 0, c) + sage: xy = Q1.solve_integer(n, algorithm='cornacchia') + sage: xy is None or Q1(*xy) == n True - sage: xy2 = Q.solve_integer(n) - sage: (xy1 is None) == (xy2 is None) + sage: (xy is None) == (Q1.solve_integer(n) is None) + True + + sage: # needs sage.libs.pari + sage: Q3 = BinaryQF(1, 0, 4*c+3) + sage: xy = Q3.solve_integer(n, algorithm='cornacchia') + sage: xy is None or Q3(*xy) == n + True + sage: (xy is None) == (Q3.solve_integer(n) is None) + True + + sage: # needs sage.libs.pari + sage: xy = Q3.solve_integer(4*n, algorithm='cornacchia') + sage: xy is None or Q3(*xy) == 4*n + True + sage: (xy is None) == (Q3.solve_integer(4*n) is None) True Test for square discriminants specifically (:trac:`33026`):: @@ -1706,6 +1764,23 @@ def solve_integer(self, n, *, algorithm="general"): sol = self.__pari__().qfbsolve(n, flag) return tuple(map(ZZ, sol)) if sol else None + def form_class(self): + r""" + Return the class of this form modulo equivalence. + + EXAMPLES:: + + sage: F = BinaryQF([3, -16, 161]) + sage: cl = F.form_class(); cl + Class of 3*x^2 + 2*x*y + 140*y^2 + sage: cl.parent() + Form Class Group of Discriminant -1676 + sage: cl.parent() is BQFClassGroup(-4*419) + True + """ + from sage.quadratic_forms.bqf_class_group import BQFClassGroup + return BQFClassGroup(self.discriminant())(self) + def BinaryQF_reduced_representatives(D, primitive_only=False, proper=True): r""" diff --git a/src/sage/quadratic_forms/bqf_class_group.py b/src/sage/quadratic_forms/bqf_class_group.py new file mode 100644 index 00000000000..30c9bd7782a --- /dev/null +++ b/src/sage/quadratic_forms/bqf_class_group.py @@ -0,0 +1,613 @@ +r""" +Class groups of binary quadratic forms + +EXAMPLES: + +Constructing the class of a given binary quadratic form is straightforward:: + + sage: F1 = BinaryQF([22, 91, 99]) + sage: cl1 = F1.form_class(); cl1 + Class of 5*x^2 - 3*x*y + 22*y^2 + +Every class is represented by a reduced form in it:: + + sage: cl1.form() + 5*x^2 - 3*x*y + 22*y^2 + sage: cl1.form() == F1.reduced_form() + True + +Addition of form classes and derived operations are defined by composition +of binary quadratic forms:: + + sage: F2 = BinaryQF([4, 1, 27]) + sage: cl2 = F2.form_class(); cl2 + Class of 4*x^2 + x*y + 27*y^2 + sage: cl1 + cl2 + Class of 9*x^2 + x*y + 12*y^2 + sage: cl1 + cl2 == (F1 * F2).form_class() + True + sage: -cl1 + Class of 5*x^2 + 3*x*y + 22*y^2 + sage: cl1 - cl1 + Class of x^2 + x*y + 108*y^2 + +The form class group can be constructed as an explicit parent object:: + + sage: F1.discriminant() + -431 + sage: Cl = BQFClassGroup(-431); Cl + Form Class Group of Discriminant -431 + sage: cl1.parent() is Cl + True + sage: Cl(F1) == cl1 + True + +Structural properties of the form class group, such as the class number, +the group invariants, and element orders, can be computed:: + + sage: Cl.order() + 21 + sage: cl1 * Cl.order() == Cl.zero() + True + sage: cl2 * Cl.order() == Cl.zero() + True + sage: cl2.order() + 7 + sage: cl2 * cl2.order() == Cl.zero() + True + sage: Cl.abelian_group() + Additive abelian group isomorphic to Z/21 embedded in Form Class Group of Discriminant -431 + sage: Cl.gens() # random + [Class of 5*x^2 + 3*x*y + 22*y^2] + sage: Cl.gens()[0].order() + 21 + +AUTHORS: + +- Lorenz Panny (2023) +""" + +# **************************************************************************** +# Copyright (C) 2023 Lorenz Panny +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# https://www.gnu.org/licenses/ +# **************************************************************************** + +from sage.misc.cachefunc import cached_method + +from sage.structure.parent import Parent +from sage.structure.unique_representation import UniqueRepresentation +from sage.structure.element import AdditiveGroupElement + +from sage.misc.prandom import randrange +from sage.rings.integer_ring import ZZ +from sage.rings.finite_rings.integer_mod import Mod +from sage.arith.misc import random_prime +from sage.groups.generic import order_from_multiple, multiple +from sage.groups.additive_abelian.additive_abelian_wrapper import AdditiveAbelianGroupWrapper +from sage.quadratic_forms.binary_qf import BinaryQF + +from sage.libs.pari import pari + + +class BQFClassGroup(Parent, UniqueRepresentation): + r""" + This type represents the class group for a given discriminant `D`. + + - For `D < 0`, the group is the class group of *positive definite* + binary quadratic forms. The "full" form class group is the direct + sum of two isomorphic copies of this group (one for positive + definite forms and one for negative definite forms). + + - For `D > 0`, this functionality is currently not implemented. + + EXAMPLES:: + + sage: BQFClassGroup(-4) + Form Class Group of Discriminant -4 + sage: BQFClassGroup(-6) + Traceback (most recent call last): + ... + ValueError: not a discriminant + + The discriminant need not be fundamental:: + + sage: BQFClassGroup(-22^2) + Form Class Group of Discriminant -484 + """ + + def __init__(self, D, *, check=True): + r""" + Construct the class group for a given discriminant `D`. + + TESTS: + + Check that positive discriminants are rejected until code is + written for them:: + + sage: BQFClassGroup(101) + Traceback (most recent call last): + ... + NotImplementedError: positive discriminants are not yet supported + """ + self._disc = ZZ(D) + if check: + if not self._disc or self._disc % 4 not in (0,1): + raise ValueError('not a discriminant') + if self._disc > 0: + raise NotImplementedError('positive discriminants are not yet supported') + super().__init__() + + def _element_constructor_(self, F, *, check=True): + r""" + Construct an element of this form class group as a :class:`BQFClassGroup_element`. + + EXAMPLES:: + + sage: Cl = BQFClassGroup(-999) + sage: Cl(0) # indirect doctest + Class of x^2 + x*y + 250*y^2 + sage: Cl(BinaryQF([16, 5, 16])) # indirect doctest + Class of 16*x^2 + 5*x*y + 16*y^2 + """ + if isinstance(F, BQFClassGroup_element): + if check and F.parent() is not self: # class group is unique parent + raise ValueError('quadratic form has incorrect discriminant') + return F + if F == 0: + return self.zero() + if check and not isinstance(F, BinaryQF): + raise TypeError('not a binary quadratic form') + return BQFClassGroup_element(F, parent=self, check=check) + + def zero(self): + r""" + Return the neutral element of this group, i.e., the class of the + principal binary quadratic form of the respective discriminant. + + EXAMPLES:: + + sage: Cl = BQFClassGroup(-999) + sage: cl = Cl.zero(); cl + Class of x^2 + x*y + 250*y^2 + sage: cl + cl == cl + True + """ + return self(BinaryQF.principal(self._disc)) + + def random_element(self): + r""" + Return a somewhat random element of this form class group. + + ALGORITHM: + + Sample random odd primes `a` until `b^2 = D \pmod{4a}` has a + solution `b \in \ZZ` and set `c = (b^2-D)/(4a)`. Flip a coin + to choose the sign of `b`. Then return the class of `[a,b,c]`. + + .. NOTE:: + + No strict guarantees are being made about the distribution of + classes sampled by this function. Heuristically, however, it + should be fairly close to uniform. + + EXAMPLES:: + + sage: Cl = BQFClassGroup(-999); Cl + Form Class Group of Discriminant -999 + sage: cl = Cl.random_element(); cl # random + Class of 10*x^2 + x*y + 25*y^2 + sage: cl.form().discriminant() + -999 + """ + B = self._disc.abs() * 100 + 9999 + while True: + a = random_prime(B, proof=False, lbound=3) + if self._disc.kronecker(a) == 1: + break + b = ZZ(Mod(self._disc, 4*a).sqrt()) + c = (b**2 - self._disc) // (4*a) + if randrange(2): + b = -b + return self(BinaryQF([a,b,c])) + + def __hash__(self): + r""" + Return a hash value for this form class group. + + EXAMPLES:: + + sage: hash(BQFClassGroup(-999)) # random + -4246560339810542104 + """ + return hash(('BQFClassGroup', self._disc)) + + def _repr_(self): + r""" + Return a string describing this form class group. + + EXAMPLES:: + + sage: BQFClassGroup(-999) # indirect doctest + Form Class Group of Discriminant -999 + """ + return f'Form Class Group of Discriminant {self._disc}' + + def discriminant(self): + r""" + Return the discriminant of the forms in this form class group. + + EXAMPLES:: + + sage: BQFClassGroup(-999).discriminant() + -999 + """ + return self._disc + + @cached_method + def order(self): + r""" + Return the order of this form class group (the *class number*). + + ALGORITHM: :func:`sage.rings.number_field.order.quadratic_order_class_number`. + + EXAMPLES:: + + sage: BQFClassGroup(-4).order() + 1 + sage: BQFClassGroup(-11).order() + 1 + sage: BQFClassGroup(-67).order() + 1 + sage: BQFClassGroup(-163).order() + 1 + sage: BQFClassGroup(-999).order() + 24 + sage: BQFClassGroup(-9999).order() + 88 + sage: BQFClassGroup(-99999).order() + 224 + """ + # Beware: If this code is ever generalized to positive + # discriminants, care must be taken to use the correct + # notion of class number. We may need the *narrow* class + # number here; see PARI's documentation for qfbclassno(). + from sage.rings.number_field.order import quadratic_order_class_number + return quadratic_order_class_number(self._disc) + + cardinality = order + + @cached_method + def abelian_group(self): + r""" + Return the structure of this form class group as an + :class:`AdditiveAbelianGroupWrapper` object. + + ALGORITHM: :pari:`quadclassunit` + + EXAMPLES:: + + sage: Cl = BQFClassGroup(-4*777) + sage: Cl.order() + 16 + sage: G = Cl.abelian_group(); G + Additive abelian group isomorphic to Z/4 + Z/2 + Z/2 embedded in Form Class Group of Discriminant -3108 + sage: G.gens() # random + (Class of 11*x^2 + 4*x*y + 71*y^2, + Class of 6*x^2 + 6*x*y + 131*y^2, + Class of 2*x^2 + 2*x*y + 389*y^2) + sage: [g.order() for g in G.gens()] + [4, 2, 2] + sage: G.discrete_log(Cl.random_element()) # random + (3, 0, 1) + """ + h, ords, gens, reg = pari.quadclassunit(self._disc) + ords = [ZZ(o) for o in ords] + gens = [BinaryQF(g) for g in gens] + return AdditiveAbelianGroupWrapper(self, gens, ords) + + def gens(self): + r""" + Return a generating set of this form class group. + + EXAMPLES:: + + sage: Cl = BQFClassGroup(-4*419) + sage: Cl.gens() + [Class of 3*x^2 + 2*x*y + 140*y^2] + + :: + + sage: Cl = BQFClassGroup(-4*777) + sage: Cl.gens() # random + [Class of 11*x^2 + 4*x*y + 71*y^2, + Class of 6*x^2 + 6*x*y + 131*y^2, + Class of 2*x^2 + 2*x*y + 389*y^2] + """ + return [g.element() for g in self.abelian_group().gens()] + + +class BQFClassGroup_element(AdditiveGroupElement): + r""" + This type represents elements of class groups of binary quadratic forms. + + Users should not need to construct objects of this type directly; it can + be accessed via either the :class:`BQFClassGroup` parent object or the + :meth:`~BinaryQF.form_class` method associated to binary quadratic forms. + + Currently only classes of positive definite forms are supported. + + EXAMPLES:: + + sage: F = BinaryQF([22, 91, 99]) + sage: F.form_class() # implicit doctest + Class of 5*x^2 - 3*x*y + 22*y^2 + + :: + + sage: Cl = BQFClassGroup(-4*419) + sage: Cl.zero() + Class of x^2 + 419*y^2 + sage: Cl.gens()[0] # implicit doctest + Class of 3*x^2 + 2*x*y + 140*y^2 + """ + + def __init__(self, F, parent, *, check=True, reduce=True): + r""" + Constructor for classes of binary quadratic forms. + + EXAMPLES:: + + sage: Cl = BQFClassGroup(-431) + sage: F = BinaryQF([22, 91, 99]) + sage: from sage.quadratic_forms.bqf_class_group import BQFClassGroup_element + sage: BQFClassGroup_element(F, parent=Cl) + Class of 5*x^2 - 3*x*y + 22*y^2 + """ + if check: + if not isinstance(F, BinaryQF): + raise TypeError('not a binary quadratic form') + if F.discriminant() != parent.discriminant(): + raise ValueError('given quadratic form has wrong discriminant') + if not F.is_primitive(): + raise ValueError('given quadratic form is not primitive') + if not F.is_positive_definite(): + raise NotImplemented('only positive definite forms are currently supported') + if reduce: + F = F.reduced_form() + self._form = F + super().__init__(parent=parent) + + def form(self): + r""" + Return a reduced quadratic form in this class. + + (For `D < 0`, each class contains a *unique* reduced form.) + + EXAMPLES:: + + sage: F = BinaryQF([3221, 2114, 350]) + sage: cl = F.form_class() + sage: cl.form() + 29*x^2 + 14*x*y + 350*y^2 + sage: cl.form() == F.reduced_form() + True + """ + return self._form + + def _neg_(self): + r""" + Return the inverse of this form class. + + The inverse class of a form `[a,b,c]` is represented by `[a,-b,c]`. + + EXAMPLES:: + + sage: F = BinaryQF([11,21,31]) + sage: cl = F.form_class(); cl + Class of 11*x^2 - x*y + 21*y^2 + sage: -cl # indirect doctest + Class of 11*x^2 + x*y + 21*y^2 + sage: cl + (-cl) == cl.parent().zero() # indirect doctest + True + """ + a,b,c = self._form + F = BinaryQF([a,-b,c]) + return BQFClassGroup_element(F, parent=self.parent()) + + def _add_(self, other): + r""" + Return the composition of two form classes. + + EXAMPLES:: + + sage: cl1 = BinaryQF([11,21,31]).form_class(); cl1 + Class of 11*x^2 - x*y + 21*y^2 + sage: cl2 = BinaryQF([7,55,141]).form_class(); cl2 + Class of 7*x^2 - x*y + 33*y^2 + sage: cl1 + cl2 # indirect doctest + Class of 3*x^2 + x*y + 77*y^2 + """ + F = self._form * other._form + return BQFClassGroup_element(F, parent=self.parent()) + + def _sub_(self, other): + r""" + Return the composition of a form class with the inverse of another. + + EXAMPLES:: + + sage: cl1 = BinaryQF([11,21,31]).form_class(); cl1 + Class of 11*x^2 - x*y + 21*y^2 + sage: cl2 = BinaryQF([7,55,141]).form_class(); cl2 + Class of 7*x^2 - x*y + 33*y^2 + sage: cl1 - cl2 # indirect doctest + Class of 9*x^2 - 7*x*y + 27*y^2 + sage: cl1 - cl2 == cl1 + (-cl2) # indirect doctest + True + """ + return self + (-other) + + def __mul__(self, other): + r""" + Return an integer multiple of this form class with respect to + repeated composition. + + ALGORITHM: :func:`multiple` + + EXAMPLES:: + + sage: F = BinaryQF([11,21,31]) + sage: cl = F.form_class(); cl + Class of 11*x^2 - x*y + 21*y^2 + sage: cl*0 == cl.parent().zero() # indirect doctest + True + sage: cl*1 == cl # indirect doctest + True + sage: cl*(-1) == -cl # indirect doctest + True + sage: cl*2 == cl + cl # indirect doctest + True + sage: cl*5 == cl + cl + cl + cl + cl # indirect doctest + True + sage: 5*cl == cl*5 # indirect doctest + True + sage: cl*(-5) == -(5*cl) # indirect doctest + True + """ + return multiple(self, other, operation='+') + + __rmul__ = __mul__ + + def __eq__(self, other): + r""" + Test two form classes for equality. + + EXAMPLES:: + + sage: F = BinaryQF([11,21,31]) + sage: cl = F.form_class(); cl + Class of 11*x^2 - x*y + 21*y^2 + sage: cl == cl # indirect doctest + True + sage: -cl == cl # indirect doctest + False + """ + # When generalizing to positive discriminants in the future, keep + # in mind that for indefinite forms there can be multiple reduced + # forms per class. This also affects the other comparison methods + # as well as hashing. + return self._form == other._form + + def __ne__(self, other): + r""" + Test two form classes for inequality. + + EXAMPLES:: + + sage: F = BinaryQF([11,21,31]) + sage: cl = F.form_class(); cl + Class of 11*x^2 - x*y + 21*y^2 + sage: cl != cl # indirect doctest + False + sage: -cl != cl # indirect doctest + True + """ + return self._form != other._form + + def __lt__(self, other): + r""" + Compare two form classes according to the lexicographic ordering + on their coefficient lists. + + EXAMPLES:: + + sage: cl1 = BinaryQF([7,55,141]).form_class(); cl1 + Class of 7*x^2 - x*y + 33*y^2 + sage: cl2 = BinaryQF([11,21,31]).form_class(); cl2 + Class of 11*x^2 - x*y + 21*y^2 + sage: cl1 < cl2 # indirect doctest + True + sage: cl1 > cl2 # indirect doctest + False + """ + return self._form < other._form + + def __bool__(self): + r""" + Return ``True`` if this form class is *not* the principal class + and ``False`` otherwise. + + EXAMPLES:: + + sage: cl = BinaryQF([11,21,31]).form_class() + sage: bool(cl) + True + sage: bool(0*cl) + False + """ + return self != self.parent().zero() + + def is_zero(self): + r""" + Return ``True`` if this form class is the principal class and + ``False`` otherwise. + + EXAMPLES:: + + sage: cl = BinaryQF([11,21,31]).form_class() + sage: cl.is_zero() + False + sage: (0*cl).is_zero() + True + """ + return not self + + def __repr__(self): + r""" + Return a string representation of this form class. + + EXAMPLES:: + + sage: F = BinaryQF([11,21,31]) + sage: F.form_class() # indirect doctest + Class of 11*x^2 - x*y + 21*y^2 + """ + return f'Class of {self._form}' + + def __hash__(self): + r""" + Return a hash value for this form class. + + EXAMPLES:: + + sage: cl = BinaryQF([11,21,31]).form_class() + sage: hash(cl) # random + -7760578299759721732 + """ + return hash(('BQFClassGroup_element', self._form)) + + @cached_method + def order(self): + r""" + Return the order of this form class in its class group. + + ALGORITHM: :meth:`BQFClassGroup.order` and :func:`order_from_multiple` + + EXAMPLES:: + + sage: cl = BinaryQF([11,21,31]).form_class() + sage: cl.order() + 10 + sage: (cl+cl).order() + 5 + sage: (cl+cl+cl).order() + 10 + sage: (5*cl).order() + 2 + """ + return order_from_multiple(self, self.parent().cardinality()) diff --git a/src/sage/repl/attach.py b/src/sage/repl/attach.py index 3ae3e7ad0cf..689759d50a8 100644 --- a/src/sage/repl/attach.py +++ b/src/sage/repl/attach.py @@ -70,7 +70,7 @@ import os import time -from IPython import get_ipython +from IPython.core.getipython import get_ipython from sage.repl.load import load, load_wrap import sage.repl.inputhook diff --git a/src/sage/repl/inputhook.py b/src/sage/repl/inputhook.py index 7f7894f6dcf..d49a7ee9060 100644 --- a/src/sage/repl/inputhook.py +++ b/src/sage/repl/inputhook.py @@ -20,7 +20,7 @@ import contextlib import io -from IPython import get_ipython +from IPython.core.getipython import get_ipython from IPython.terminal.pt_inputhooks import register import sage.repl.attach diff --git a/src/sage/repl/interpreter.py b/src/sage/repl/interpreter.py index b9a222c12ef..4ddb8aa94a3 100644 --- a/src/sage/repl/interpreter.py +++ b/src/sage/repl/interpreter.py @@ -153,6 +153,18 @@ from IPython.terminal.ipapp import TerminalIPythonApp, IPAppCrashHandler from IPython.core.crashhandler import CrashHandler +from ctypes import pythonapi, c_int, c_void_p +# The following functions are part of the stable ABI since python 3.2 +# See: https://docs.python.org/3/c-api/sys.html#c.PyOS_getsig + +# PyOS_sighandler_t PyOS_getsig(int i) +pythonapi.PyOS_getsig.restype = c_void_p +pythonapi.PyOS_getsig.argtypes = c_int, + +# PyOS_sighandler_t PyOS_setsig(int i, PyOS_sighandler_t h) +pythonapi.PyOS_setsig.restype = c_void_p +pythonapi.PyOS_setsig.argtypes = c_int, c_void_p, + # TODO: This global variable _do_preparse should be associated with an # IPython InteractiveShell as opposed to a global variable in this @@ -287,6 +299,18 @@ def init_display_formatter(self): backend = BackendIPythonCommandline() backend.get_display_manager().switch_backend(backend, shell=self) + def prompt_for_code(self): + # save sigint handlers (python and os level) + # https://github.com/prompt-toolkit/python-prompt-toolkit/issues/1576 + # https://github.com/sagemath/sage/issues/33428 + # https://github.com/sagemath/sage/pull/35251 + import signal + sigint = signal.getsignal(signal.SIGINT) + sigint_os = pythonapi.PyOS_getsig(signal.SIGINT) + text = TerminalInteractiveShell.prompt_for_code(self) + signal.signal(signal.SIGINT, sigint) + pythonapi.PyOS_setsig(signal.SIGINT, sigint_os) + return text class SageTestShell(SageShellOverride, TerminalInteractiveShell): """ diff --git a/src/sage/rings/abc.pxd b/src/sage/rings/abc.pxd index a53b512d62f..a2d2e3f0ce4 100644 --- a/src/sage/rings/abc.pxd +++ b/src/sage/rings/abc.pxd @@ -1,4 +1,4 @@ -from .ring cimport CommutativeRing, Field +from sage.rings.ring cimport CommutativeRing, Field cdef class RealField(Field): diff --git a/src/sage/rings/all.py b/src/sage/rings/all.py index 1d7b89601f5..2c2f6a0523e 100644 --- a/src/sage/rings/all.py +++ b/src/sage/rings/all.py @@ -12,10 +12,10 @@ # **************************************************************************** from sage.misc.lazy_import import lazy_import -from .all__sagemath_categories import * +from sage.rings.all__sagemath_categories import * # Ring base classes -from .ring import (Ring, Field, CommutativeRing, IntegralDomain, +from sage.rings.ring import (Ring, Field, CommutativeRing, IntegralDomain, DedekindDomain, PrincipalIdealDomain, EuclideanDomain) # Ring element base classes @@ -25,22 +25,22 @@ EuclideanDomainElement, FieldElement) # Ideals -from .ideal import Ideal +from sage.rings.ideal import Ideal ideal = Ideal # Quotient -from .quotient_ring import QuotientRing +from sage.rings.quotient_ring import QuotientRing # Infinities -from .infinity import infinity, Infinity, InfinityRing, unsigned_infinity, UnsignedInfinityRing +from sage.rings.infinity import infinity, Infinity, InfinityRing, unsigned_infinity, UnsignedInfinityRing # Rational integers. -from .integer_ring import IntegerRing, ZZ, crt_basis -from .integer import Integer +from sage.rings.integer_ring import IntegerRing, ZZ, crt_basis +from sage.rings.integer import Integer # Rational numbers -from .rational_field import RationalField, QQ -from .rational import Rational +from sage.rings.rational_field import RationalField, QQ +from sage.rings.rational import Rational Rationals = RationalField # Integers modulo n. @@ -49,120 +49,120 @@ Integers = IntegerModRing # Finite fields -from .finite_rings.all import * +from sage.rings.finite_rings.all import * # Number field -from .number_field.all import * +from sage.rings.number_field.all import * # Function field -from .function_field.all import * +from sage.rings.function_field.all import * # Finite residue fields -from .finite_rings.residue_field import ResidueField +from sage.rings.finite_rings.residue_field import ResidueField # p-adic field -from .padics.all import * -from .padics.padic_printing import _printer_defaults as padic_printing +from sage.rings.padics.all import * +from sage.rings.padics.padic_printing import _printer_defaults as padic_printing # valuations -from .valuation.all import * +from sage.rings.valuation.all import * # Semirings -from .semirings.all import * +from sage.rings.semirings.all import * # Real numbers -from .real_mpfr import (RealField, RR, +from sage.rings.real_mpfr import (RealField, RR, create_RealNumber as RealNumber) # this is used by the preparser to wrap real literals -- very important. Reals = RealField -from .real_double import RealDoubleField, RDF, RealDoubleElement +from sage.rings.real_double import RealDoubleField, RDF, RealDoubleElement -from .real_lazy import RealLazyField, RLF, ComplexLazyField, CLF +from sage.rings.real_lazy import RealLazyField, RLF, ComplexLazyField, CLF from sage.rings.real_arb import RealBallField, RBF # Polynomial Rings and Polynomial Quotient Rings -from .polynomial.all import * +from sage.rings.polynomial.all import * # Algebraic numbers -from .qqbar import (AlgebraicRealField, AA, +from sage.rings.qqbar import (AlgebraicRealField, AA, AlgebraicReal, AlgebraicField, QQbar, AlgebraicNumber, number_field_elements_from_algebraics) -from .universal_cyclotomic_field import UniversalCyclotomicField, E +from sage.rings.universal_cyclotomic_field import UniversalCyclotomicField, E # Intervals -from .real_mpfi import (RealIntervalField, +from sage.rings.real_mpfi import (RealIntervalField, RIF, RealInterval) # Complex numbers -from .complex_mpfr import ComplexField -from .complex_mpfr import create_ComplexNumber as ComplexNumber +from sage.rings.complex_mpfr import ComplexField +from sage.rings.complex_mpfr import create_ComplexNumber as ComplexNumber Complexes = ComplexField -from .complex_interval_field import ComplexIntervalField -from .complex_interval import (create_ComplexIntervalFieldElement as ComplexIntervalFieldElement) +from sage.rings.complex_interval_field import ComplexIntervalField +from sage.rings.complex_interval import (create_ComplexIntervalFieldElement as ComplexIntervalFieldElement) -from .complex_double import ComplexDoubleField, ComplexDoubleElement, CDF +from sage.rings.complex_double import ComplexDoubleField, ComplexDoubleElement, CDF -from .complex_mpc import MPComplexField +from sage.rings.complex_mpc import MPComplexField from sage.rings.complex_arb import ComplexBallField, CBF lazy_import("sage.rings.imaginary_unit", "I") # Power series rings -from .power_series_ring import PowerSeriesRing +from sage.rings.power_series_ring import PowerSeriesRing # Laurent series ring in one variable -from .laurent_series_ring import LaurentSeriesRing +from sage.rings.laurent_series_ring import LaurentSeriesRing # Lazy Laurent series ring lazy_import('sage.rings.lazy_series_ring', ['LazyLaurentSeriesRing', 'LazyPowerSeriesRing', 'LazySymmetricFunctions', 'LazyDirichletSeriesRing']) # Tate algebras -from .tate_algebra import TateAlgebra +from sage.rings.tate_algebra import TateAlgebra # Puiseux series ring -from .puiseux_series_ring import PuiseuxSeriesRing +from sage.rings.puiseux_series_ring import PuiseuxSeriesRing # Pseudo-ring of PARI objects. -from .pari_ring import PariRing, Pari +from sage.rings.pari_ring import PariRing, Pari # Big-oh notation -from .big_oh import O +from sage.rings.big_oh import O # Fraction field -from .fraction_field import FractionField +from sage.rings.fraction_field import FractionField Frac = FractionField # Localization -from .localization import Localization +from sage.rings.localization import Localization # c-finite sequences -from .cfinite_sequence import CFiniteSequence, CFiniteSequences +from sage.rings.cfinite_sequence import CFiniteSequence, CFiniteSequences -from .bernoulli_mod_p import bernoulli_mod_p, bernoulli_mod_p_single +from sage.rings.bernoulli_mod_p import bernoulli_mod_p, bernoulli_mod_p_single -from .monomials import monomials +from sage.rings.monomials import monomials -from .cc import CC -from .cif import CIF +from sage.rings.cc import CC +from sage.rings.cif import CIF # invariant theory -from .invariants.all import * +from sage.rings.invariants.all import * -from .fast_arith import prime_range +from sage.rings.fast_arith import prime_range # continued fractions from sage.rings.continued_fraction import (continued_fraction, continued_fraction_list) # asymptotic ring -from .asymptotic.all import * +from sage.rings.asymptotic.all import * # Register classes in numbers abc -from . import numbers_abc +from sage.rings import numbers_abc diff --git a/src/sage/rings/all__sagemath_categories.py b/src/sage/rings/all__sagemath_categories.py index 8d14e7afcda..d03d1c6b483 100644 --- a/src/sage/rings/all__sagemath_categories.py +++ b/src/sage/rings/all__sagemath_categories.py @@ -1,6 +1,6 @@ # Ring base classes -from .ring import Ring - +from sage.rings.ring import Ring # Ideals -from .ideal import Ideal +from sage.rings.ideal import Ideal + ideal = Ideal diff --git a/src/sage/rings/big_oh.py b/src/sage/rings/big_oh.py index e9b22e77b37..917c81e0a3d 100644 --- a/src/sage/rings/big_oh.py +++ b/src/sage/rings/big_oh.py @@ -11,6 +11,7 @@ from sage.arith.misc import factor from sage.misc.lazy_import import lazy_import + lazy_import('sage.rings.padics.factory', ['Qp', 'Zp']) lazy_import('sage.rings.padics.padic_generic_element', 'pAdicGenericElement') from sage.rings.polynomial.polynomial_element import Polynomial @@ -25,10 +26,12 @@ except ImportError: PuiseuxSeries = () -from . import power_series_ring_element -from . import integer -from . import rational -from . import multi_power_series_ring_element +from sage.rings import ( + integer, + multi_power_series_ring_element, + power_series_ring_element, + rational, +) def O(*x, **kwds): diff --git a/src/sage/rings/cc.py b/src/sage/rings/cc.py index 6db89579029..94e3093488b 100644 --- a/src/sage/rings/cc.py +++ b/src/sage/rings/cc.py @@ -1,3 +1,3 @@ -from .complex_mpfr import ComplexField +from sage.rings.complex_mpfr import ComplexField CC = ComplexField() diff --git a/src/sage/rings/cif.py b/src/sage/rings/cif.py index 91924f4d26c..900c635e87b 100644 --- a/src/sage/rings/cif.py +++ b/src/sage/rings/cif.py @@ -1,3 +1,3 @@ -from .complex_interval_field import ComplexIntervalField +from sage.rings.complex_interval_field import ComplexIntervalField CIF = ComplexIntervalField() diff --git a/src/sage/rings/complex_arb.pyx b/src/sage/rings/complex_arb.pyx index 1e3085c9215..0786de7fc81 100644 --- a/src/sage/rings/complex_arb.pyx +++ b/src/sage/rings/complex_arb.pyx @@ -1360,12 +1360,13 @@ cdef class ComplexBall(RingElement): sage: CBF100(-3r) -3.000000000000000000000000000000 - sage: ComplexBall(CBF100, 10^100) - 1.000000000000000000000000000000e+100 sage: ComplexBall(CBF100, CIF(1, 2)) 1.000000000000000000000000000000 + 2.000000000000000000000000000000*I sage: ComplexBall(CBF100, RBF(1/3), RBF(1)) [0.3333333333333333 +/- ...e-17] + 1.000000000000000000000000000000*I + sage: ComplexBall(CBF100, 10^100) + [1.000000000000000000000000000000e+100 +/- ...] + sage: NF. = QuadraticField(-1, embedding=CC(0, -1)) sage: CBF(a) -1.000000000000000*I @@ -3009,7 +3010,7 @@ cdef class ComplexBall(RingElement): sage: CBF(1).rising_factorial(2**64) [+/- ...e+347382171326740403407] sage: ComplexBallField(128)(1).rising_factorial(2**64) - [2.343691126796861348e+347382171305201285713 +/- ...e+347382171305201285694] + [2.34369112679686134...e+347382171305201285713 +/- ...] sage: CBF(1/2).rising_factorial(CBF(2,3)) # abs tol 1e-15 [-0.123060451458124 +/- 3.06e-16] + [0.0406412631676552 +/- 7.57e-17]*I diff --git a/src/sage/rings/complex_conversion.pyx b/src/sage/rings/complex_conversion.pyx index e7e53724f9c..39c8b63eb55 100644 --- a/src/sage/rings/complex_conversion.pyx +++ b/src/sage/rings/complex_conversion.pyx @@ -1,5 +1,5 @@ -from .complex_double cimport ComplexDoubleElement -from .complex_mpfr cimport ComplexNumber +from sage.rings.complex_double cimport ComplexDoubleElement +from sage.rings.complex_mpfr cimport ComplexNumber from sage.libs.mpfr cimport mpfr_get_d, MPFR_RNDN from sage.libs.gsl.complex cimport GSL_SET_COMPLEX diff --git a/src/sage/rings/complex_double.pyx b/src/sage/rings/complex_double.pyx index 8f1e8205817..944bcc5aa27 100644 --- a/src/sage/rings/complex_double.pyx +++ b/src/sage/rings/complex_double.pyx @@ -105,10 +105,10 @@ complex_double_element_gamma = None complex_double_element_gamma_inc = None complex_double_element_zeta = None -from .complex_conversion cimport CCtoCDF +from sage.rings.complex_conversion cimport CCtoCDF -from .real_double cimport RealDoubleElement, double_repr -from .real_double import RDF +from sage.rings.real_double cimport RealDoubleElement, double_repr +from sage.rings.real_double import RDF from sage.rings.integer_ring import ZZ from sage.structure.richcmp cimport rich_to_bool diff --git a/src/sage/rings/complex_interval.pxd b/src/sage/rings/complex_interval.pxd index 56513b65747..60d8c010cd8 100644 --- a/src/sage/rings/complex_interval.pxd +++ b/src/sage/rings/complex_interval.pxd @@ -2,7 +2,7 @@ from sage.libs.mpfr.types cimport mpfr_prec_t from sage.libs.mpfi.types cimport mpfi_t cimport sage.structure.element -from .real_mpfi cimport RealIntervalFieldElement, RealIntervalField_class +from sage.rings.real_mpfi cimport RealIntervalFieldElement, RealIntervalField_class cdef class ComplexIntervalFieldElement(sage.structure.element.FieldElement): diff --git a/src/sage/rings/complex_interval.pyx b/src/sage/rings/complex_interval.pyx index c38261d136d..5b7a04fef10 100644 --- a/src/sage/rings/complex_interval.pyx +++ b/src/sage/rings/complex_interval.pyx @@ -66,12 +66,12 @@ from sage.arith.constants cimport LOG_TEN_TWO_PLUS_EPSILON from sage.structure.element cimport FieldElement from sage.structure.parent cimport Parent -from .complex_mpfr cimport ComplexNumber +from sage.rings.complex_mpfr cimport ComplexNumber from sage.rings.integer cimport Integer cimport sage.rings.real_mpfi as real_mpfi -from .real_mpfr cimport RealNumber -from .convert.mpfi cimport mpfi_set_sage -from .infinity import infinity +from sage.rings.real_mpfr cimport RealNumber +from sage.rings.convert.mpfi cimport mpfi_set_sage +from sage.rings.infinity import infinity def is_ComplexIntervalFieldElement(x): diff --git a/src/sage/rings/complex_interval_field.py b/src/sage/rings/complex_interval_field.py index 7903ab42bae..c2524923459 100644 --- a/src/sage/rings/complex_interval_field.py +++ b/src/sage/rings/complex_interval_field.py @@ -36,18 +36,17 @@ # **************************************************************************** -from sage.structure.parent import Parent -from .integer_ring import ZZ -from .rational_field import QQ -from .ring import Field -import sage.rings.abc -from . import integer -from . import complex_interval import weakref -from .real_mpfi import RealIntervalField, RealIntervalField_class -from .complex_mpfr import ComplexField -from sage.misc.cachefunc import cached_method +import sage.rings.abc +from sage.misc.cachefunc import cached_method +from sage.rings import complex_interval, integer +from sage.rings.complex_mpfr import ComplexField +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ +from sage.rings.real_mpfi import RealIntervalField, RealIntervalField_class +from sage.rings.ring import Field +from sage.structure.parent import Parent cache = {} def ComplexIntervalField(prec=53, names=None): diff --git a/src/sage/rings/complex_mpc.pyx b/src/sage/rings/complex_mpc.pyx index 562286db44e..7a9ab37e268 100644 --- a/src/sage/rings/complex_mpc.pyx +++ b/src/sage/rings/complex_mpc.pyx @@ -59,7 +59,7 @@ EXAMPLES:: # **************************************************************************** import re -from . import real_mpfr +from sage.rings import real_mpfr import weakref from cpython.object cimport Py_NE @@ -74,13 +74,13 @@ from sage.structure.richcmp cimport rich_to_bool from sage.categories.map cimport Map from sage.libs.pari.all import pari -from .integer cimport Integer -from .complex_mpfr cimport ComplexNumber -from .complex_mpfr import ComplexField_class +from sage.rings.integer cimport Integer +from sage.rings.complex_mpfr cimport ComplexNumber +from sage.rings.complex_mpfr import ComplexField_class from sage.misc.randstate cimport randstate, current_randstate -from .real_mpfr cimport RealField_class, RealNumber -from .real_mpfr import mpfr_prec_min, mpfr_prec_max +from sage.rings.real_mpfr cimport RealField_class, RealNumber +from sage.rings.real_mpfr import mpfr_prec_min, mpfr_prec_max from sage.structure.richcmp cimport rich_to_bool, richcmp from sage.categories.fields import Fields diff --git a/src/sage/rings/complex_mpfr.pxd b/src/sage/rings/complex_mpfr.pxd index 4aa6de62a69..95972c52bb5 100644 --- a/src/sage/rings/complex_mpfr.pxd +++ b/src/sage/rings/complex_mpfr.pxd @@ -1,7 +1,7 @@ from sage.libs.mpfr.types cimport mpfr_t, mpfr_prec_t cimport sage.structure.element -from .real_mpfr cimport RealNumber +from sage.rings.real_mpfr cimport RealNumber cdef class ComplexNumber(sage.structure.element.FieldElement): cdef mpfr_t __re diff --git a/src/sage/rings/complex_mpfr.pyx b/src/sage/rings/complex_mpfr.pyx index d6f92bb2fee..c8a27ac7aec 100644 --- a/src/sage/rings/complex_mpfr.pyx +++ b/src/sage/rings/complex_mpfr.pyx @@ -46,11 +46,11 @@ from sage.misc.sage_eval import sage_eval import sage.rings.abc from sage.arith.constants cimport LOG_TEN_TWO_PLUS_EPSILON -from . import infinity -from .integer cimport Integer +from sage.rings import infinity +from sage.rings.integer cimport Integer -from .complex_double cimport ComplexDoubleElement -from .real_mpfr cimport RealNumber +from sage.rings.complex_double cimport ComplexDoubleElement +from sage.rings.real_mpfr cimport RealNumber from sage.libs.gsl.complex cimport * from sage.libs.mpmath.utils cimport mpfr_to_mpfval diff --git a/src/sage/rings/continued_fraction.py b/src/sage/rings/continued_fraction.py index 1980d55b27c..a813816ac50 100644 --- a/src/sage/rings/continued_fraction.py +++ b/src/sage/rings/continued_fraction.py @@ -207,12 +207,12 @@ import numbers -from sage.structure.sage_object import SageObject -from sage.structure.richcmp import richcmp_method, rich_to_bool import sage.rings.abc -from .integer import Integer -from .integer_ring import ZZ -from .infinity import Infinity +from sage.rings.infinity import Infinity +from sage.rings.integer import Integer +from sage.rings.integer_ring import ZZ +from sage.structure.richcmp import rich_to_bool, richcmp_method +from sage.structure.sage_object import SageObject ZZ_0 = Integer(0) ZZ_1 = Integer(1) @@ -849,8 +849,9 @@ def convergents(self): Add an example with infinite list. """ if self.length() == Infinity: - from sage.misc.lazy_list import lazy_list from itertools import count + + from sage.misc.lazy_list import lazy_list return lazy_list(self.numerator(n) / self.denominator(n) for n in count()) return [self.numerator(n) / self.denominator(n) @@ -876,8 +877,9 @@ def quotients(self): Add an example with infinite list. """ if self.length() == Infinity: - from sage.misc.lazy_list import lazy_list from itertools import count + + from sage.misc.lazy_list import lazy_list return lazy_list(self.quotient(n) for n in count()) return [self.quotient(n) for n in range(len(self))] @@ -1147,8 +1149,7 @@ def numerical_approx(self, prec=None, digits=None, algorithm=None): sage: cf.n(digits=33) # needs sage.combinat 1.28102513329556981555293038097590 """ - from sage.arith.numerical_approx import (digits_to_bits, - numerical_approx_generic) + from sage.arith.numerical_approx import digits_to_bits, numerical_approx_generic if prec is None: prec = digits_to_bits(digits) return numerical_approx_generic(self, prec) @@ -1564,8 +1565,8 @@ def value(self): # now x is one of the root of the equation # q1 x^2 + (q0 - p1) x - p0 = 0 - from sage.rings.number_field.number_field import QuadraticField from sage.misc.functional import squarefree_part + from sage.rings.number_field.number_field import QuadraticField D = (q0-p1)**2 + 4*q1*p0 DD = squarefree_part(D) Q = QuadraticField(DD, 'sqrt%d' % DD) @@ -2674,8 +2675,8 @@ def continued_fraction(x, value=None): return ContinuedFraction_periodic(x1, x2) # input for infinite partial quotient expansion - from sage.misc.lazy_list import lazy_list_generic from sage.combinat.words.infinite_word import InfiniteWord_class + from sage.misc.lazy_list import lazy_list_generic if isinstance(x, (lazy_list_generic, InfiniteWord_class)): return ContinuedFraction_infinite(x, value) diff --git a/src/sage/rings/convert/mpfi.pyx b/src/sage/rings/convert/mpfi.pyx index abef4963bcf..0d42927740a 100644 --- a/src/sage/rings/convert/mpfi.pyx +++ b/src/sage/rings/convert/mpfi.pyx @@ -23,14 +23,14 @@ from sage.cpython.string cimport bytes_to_str from sage.structure.element cimport Element import sage.rings.abc -from ..integer cimport Integer -from ..rational cimport Rational -from ..real_mpfi cimport RealIntervalFieldElement, RealIntervalField_class -from ..real_mpfr cimport RealNumber -from ..real_double cimport RealDoubleElement -from ..complex_mpfr cimport ComplexNumber -from ..complex_interval cimport ComplexIntervalFieldElement -from ..complex_double cimport ComplexDoubleElement +from sage.rings.integer cimport Integer +from sage.rings.rational cimport Rational +from sage.rings.real_mpfi cimport RealIntervalFieldElement, RealIntervalField_class +from sage.rings.real_mpfr cimport RealNumber +from sage.rings.real_double cimport RealDoubleElement +from sage.rings.complex_mpfr cimport ComplexNumber +from sage.rings.complex_interval cimport ComplexIntervalFieldElement +from sage.rings.complex_double cimport ComplexDoubleElement from cypari2.gen cimport Gen diff --git a/src/sage/rings/finite_rings/element_givaro.pyx b/src/sage/rings/finite_rings/element_givaro.pyx index 0483b4949e7..7619ec7185f 100644 --- a/src/sage/rings/finite_rings/element_givaro.pyx +++ b/src/sage/rings/finite_rings/element_givaro.pyx @@ -57,7 +57,7 @@ from cysignals.signals cimport sig_on, sig_off from cypari2.paridecl cimport * from sage.misc.randstate cimport current_randstate -from .element_pari_ffelt cimport FiniteFieldElement_pari_ffelt +from sage.rings.finite_rings.element_pari_ffelt cimport FiniteFieldElement_pari_ffelt from sage.structure.richcmp cimport richcmp import sage.arith.all diff --git a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx index 61e7b05048c..60d275ea5ae 100644 --- a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx +++ b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx @@ -44,8 +44,8 @@ from sage.libs.pari.all import pari from cypari2.gen cimport Gen from cypari2.stack cimport clear_stack -from .element_pari_ffelt import FiniteFieldElement_pari_ffelt -from .finite_field_ntl_gf2e import FiniteField_ntl_gf2e +from sage.rings.finite_rings.element_pari_ffelt import FiniteFieldElement_pari_ffelt +from sage.rings.finite_rings.finite_field_ntl_gf2e import FiniteField_ntl_gf2e from sage.interfaces.abc import GapElement diff --git a/src/sage/rings/finite_rings/element_pari_ffelt.pyx b/src/sage/rings/finite_rings/element_pari_ffelt.pyx index 9beb505cae3..ca262f6f668 100644 --- a/src/sage/rings/finite_rings/element_pari_ffelt.pyx +++ b/src/sage/rings/finite_rings/element_pari_ffelt.pyx @@ -24,8 +24,8 @@ from sage.libs.pari.convert_gmp cimport _new_GEN_from_mpz_t from cypari2.stack cimport new_gen, new_gen_noclear, clear_stack from cypari2.gen cimport Gen as pari_gen, objtogen -from .element_base cimport FinitePolyExtElement -from .integer_mod import IntegerMod_abstract +from sage.rings.finite_rings.element_base cimport FinitePolyExtElement +from sage.rings.finite_rings.integer_mod import IntegerMod_abstract import sage.rings.integer from sage.rings.integer cimport Integer diff --git a/src/sage/rings/finite_rings/hom_finite_field_givaro.pxd b/src/sage/rings/finite_rings/hom_finite_field_givaro.pxd index 62898386212..f5a70c975f9 100644 --- a/src/sage/rings/finite_rings/hom_finite_field_givaro.pxd +++ b/src/sage/rings/finite_rings/hom_finite_field_givaro.pxd @@ -1,8 +1,8 @@ -from .hom_finite_field cimport (SectionFiniteFieldHomomorphism_generic, +from sage.rings.finite_rings.hom_finite_field cimport (SectionFiniteFieldHomomorphism_generic, FiniteFieldHomomorphism_generic, FrobeniusEndomorphism_finite_field) from sage.structure.element cimport Element -from .element_givaro cimport Cache_givaro +from sage.rings.finite_rings.element_givaro cimport Cache_givaro cdef class SectionFiniteFieldHomomorphism_givaro(SectionFiniteFieldHomomorphism_generic): diff --git a/src/sage/rings/finite_rings/hom_finite_field_givaro.pyx b/src/sage/rings/finite_rings/hom_finite_field_givaro.pyx index 21036266df1..bc685731610 100644 --- a/src/sage/rings/finite_rings/hom_finite_field_givaro.pyx +++ b/src/sage/rings/finite_rings/hom_finite_field_givaro.pyx @@ -33,21 +33,21 @@ AUTHOR: from sage.rings.finite_rings.finite_field_constructor import FiniteField -from .hom_finite_field cimport SectionFiniteFieldHomomorphism_generic -from .hom_finite_field cimport FiniteFieldHomomorphism_generic -from .hom_finite_field cimport FrobeniusEndomorphism_finite_field +from sage.rings.finite_rings.hom_finite_field cimport SectionFiniteFieldHomomorphism_generic +from sage.rings.finite_rings.hom_finite_field cimport FiniteFieldHomomorphism_generic +from sage.rings.finite_rings.hom_finite_field cimport FrobeniusEndomorphism_finite_field -from .hom_prime_finite_field cimport FiniteFieldHomomorphism_prime +from sage.rings.finite_rings.hom_prime_finite_field cimport FiniteFieldHomomorphism_prime from sage.categories.homset import Hom from sage.structure.element cimport Element from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro -from .element_givaro cimport FiniteField_givaroElement +from sage.rings.finite_rings.element_givaro cimport FiniteField_givaroElement #from element_givaro cimport make_FiniteField_givaroElement from sage.structure.parent cimport Parent -from .element_givaro cimport Cache_givaro +from sage.rings.finite_rings.element_givaro cimport Cache_givaro cdef class SectionFiniteFieldHomomorphism_givaro(SectionFiniteFieldHomomorphism_generic): diff --git a/src/sage/rings/finite_rings/hom_prime_finite_field.pxd b/src/sage/rings/finite_rings/hom_prime_finite_field.pxd index c0da361fb42..b146b0c9169 100644 --- a/src/sage/rings/finite_rings/hom_prime_finite_field.pxd +++ b/src/sage/rings/finite_rings/hom_prime_finite_field.pxd @@ -1,4 +1,4 @@ -from .hom_finite_field cimport (SectionFiniteFieldHomomorphism_generic, +from sage.rings.finite_rings.hom_finite_field cimport (SectionFiniteFieldHomomorphism_generic, FiniteFieldHomomorphism_generic, FrobeniusEndomorphism_finite_field) diff --git a/src/sage/rings/finite_rings/hom_prime_finite_field.pyx b/src/sage/rings/finite_rings/hom_prime_finite_field.pyx index 6bc38546612..2ff550aa1b1 100644 --- a/src/sage/rings/finite_rings/hom_prime_finite_field.pyx +++ b/src/sage/rings/finite_rings/hom_prime_finite_field.pyx @@ -27,9 +27,9 @@ AUTHOR: from sage.categories.homset import Hom from sage.structure.element cimport Element -from .hom_finite_field cimport SectionFiniteFieldHomomorphism_generic -from .hom_finite_field cimport FiniteFieldHomomorphism_generic -from .hom_finite_field cimport FrobeniusEndomorphism_finite_field +from sage.rings.finite_rings.hom_finite_field cimport SectionFiniteFieldHomomorphism_generic +from sage.rings.finite_rings.hom_finite_field cimport FiniteFieldHomomorphism_generic +from sage.rings.finite_rings.hom_finite_field cimport FrobeniusEndomorphism_finite_field from sage.rings.finite_rings.finite_field_base import FiniteField diff --git a/src/sage/rings/finite_rings/integer_mod_ring.py b/src/sage/rings/finite_rings/integer_mod_ring.py index a448046f137..0bb4ce21f4b 100644 --- a/src/sage/rings/finite_rings/integer_mod_ring.py +++ b/src/sage/rings/finite_rings/integer_mod_ring.py @@ -67,7 +67,7 @@ from sage.arith.misc import CRT_basis import sage.rings.ring as ring import sage.rings.abc -from . import integer_mod +from sage.rings.finite_rings import integer_mod import sage.rings.integer as integer import sage.rings.integer_ring as integer_ring import sage.rings.quotient_ring as quotient_ring diff --git a/src/sage/rings/fraction_field.py b/src/sage/rings/fraction_field.py index 5d298720a90..bfa690cec0e 100644 --- a/src/sage/rings/fraction_field.py +++ b/src/sage/rings/fraction_field.py @@ -83,19 +83,17 @@ # http://www.gnu.org/licenses/ # **************************************************************************** -from . import ring -from . import fraction_field_element import sage.misc.latex as latex +from sage.categories.basic import QuotientFields, Rings +from sage.categories.map import Section from sage.misc.cachefunc import cached_method - +from sage.rings import fraction_field_element, ring from sage.rings.integer_ring import ZZ -from sage.structure.richcmp import richcmp -from sage.structure.parent import Parent -from sage.structure.element import parent from sage.structure.coerce import py_scalar_to_element from sage.structure.coerce_maps import CallableConvertMap, DefaultConvertMap_unique -from sage.categories.basic import QuotientFields, Rings -from sage.categories.map import Section +from sage.structure.element import parent +from sage.structure.parent import Parent +from sage.structure.richcmp import richcmp def FractionField(R, names=None): @@ -327,10 +325,11 @@ def _coerce_map_from_(self, S): sage: f(L(1/7)) == 1/7 True """ - from sage.rings.rational_field import QQ from sage.rings.number_field.number_field_base import NumberField - from sage.rings.polynomial.laurent_polynomial_ring_base import \ - LaurentPolynomialRing_generic + from sage.rings.polynomial.laurent_polynomial_ring_base import ( + LaurentPolynomialRing_generic, + ) + from sage.rings.rational_field import QQ if S is self._R: parent = self._R.Hom(self) @@ -1079,7 +1078,9 @@ def _coerce_map_from_(self, R): 1/t """ - from sage.rings.function_field.function_field_rational import RationalFunctionField + from sage.rings.function_field.function_field_rational import ( + RationalFunctionField, + ) if isinstance(R, RationalFunctionField) and self.variable_name() == R.variable_name() and self.base_ring() is R.constant_base_field(): from sage.categories.homset import Hom parent = Hom(R, self) @@ -1160,8 +1161,8 @@ def section(self): To: Univariate Polynomial Ring in x over Rational Field """ - from sage.categories.sets_with_partial_maps import SetsWithPartialMaps from sage.categories.homset import Hom + from sage.categories.sets_with_partial_maps import SetsWithPartialMaps parent = Hom(self.codomain(), self.domain(), SetsWithPartialMaps()) return parent.__make_element_class__(FractionFieldEmbeddingSection)(self) diff --git a/src/sage/rings/fraction_field_element.pyx b/src/sage/rings/fraction_field_element.pyx index cb0bbce912f..5b6cfa2e29f 100644 --- a/src/sage/rings/fraction_field_element.pyx +++ b/src/sage/rings/fraction_field_element.pyx @@ -22,7 +22,7 @@ AUTHORS: from sage.structure.element cimport FieldElement, parent from sage.structure.richcmp cimport richcmp -from .rational_field import QQ +from sage.rings.rational_field import QQ import sage.misc.latex as latex diff --git a/src/sage/rings/homset.py b/src/sage/rings/homset.py index 0e500de2608..b2f24a3800a 100644 --- a/src/sage/rings/homset.py +++ b/src/sage/rings/homset.py @@ -12,10 +12,11 @@ from sage.categories.homset import HomsetWithBase from sage.categories.rings import Rings + _Rings = Rings() -from . import morphism -from . import quotient_ring +from sage.rings import morphism, quotient_ring + def is_RingHomset(H): """ diff --git a/src/sage/rings/ideal_monoid.py b/src/sage/rings/ideal_monoid.py index 0988ffc72e5..019348a6afe 100644 --- a/src/sage/rings/ideal_monoid.py +++ b/src/sage/rings/ideal_monoid.py @@ -8,10 +8,10 @@ """ -from sage.structure.parent import Parent import sage.rings.integer_ring -from . import ideal from sage.categories.monoids import Monoids +from sage.rings import ideal +from sage.structure.parent import Parent def IdealMonoid(R): diff --git a/src/sage/rings/imaginary_unit.py b/src/sage/rings/imaginary_unit.py index 09349e66e8b..bb29cd32630 100644 --- a/src/sage/rings/imaginary_unit.py +++ b/src/sage/rings/imaginary_unit.py @@ -1,5 +1,5 @@ # coding: utf-8 -from .number_field.number_field import GaussianField +from sage.rings.number_field.number_field import GaussianField I = GaussianField().gen() diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index 3ecd0bd986d..bd31ccbb31d 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -183,7 +183,7 @@ from sage.structure.element import coerce_binop from sage.structure.richcmp cimport rich_to_bool_sgn -from . import integer_ring +from sage.rings import integer_ring cimport gmpy2 gmpy2.import_gmpy2() @@ -207,7 +207,7 @@ new_gen_from_integer = None cdef extern from *: int unlikely(int) nogil # Defined by Cython -cdef object numpy_long_interface = {'typestr': '=i4' if sizeof(long) == 4 else '=i8' } +cdef object numpy_long_interface = {'typestr': '=i4' if sizeof(long) == 4 else '=i8'} cdef object numpy_int64_interface = {'typestr': '=i8'} cdef object numpy_object_interface = {'typestr': '|O'} @@ -288,7 +288,6 @@ cdef _digits_internal(mpz_t v,l,int offset,int power_index,power_list,digits) no cdef mpz_t mpz_res cdef mpz_t mpz_quot cdef Integer temp - cdef int v_int if power_index < 5: # It turns out that simple repeated division is very fast for # relatively few digits. I don't think this is a real algorithmic @@ -318,6 +317,7 @@ cdef mpz_t PARI_PSEUDOPRIME_LIMIT mpz_init(PARI_PSEUDOPRIME_LIMIT) mpz_ui_pow_ui(PARI_PSEUDOPRIME_LIMIT, 2, 64) + def is_Integer(x): """ Return ``True`` if ``x`` is of the Sage :class:`Integer` type. @@ -336,12 +336,14 @@ def is_Integer(x): """ return isinstance(x, Integer) + cdef inline Integer as_Integer(x) noexcept: if isinstance(x, Integer): return x else: return Integer(x) + cdef class IntegerWrapper(Integer): r""" Rationale for the :class:`IntegerWrapper` class: @@ -612,8 +614,6 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): # mpz_init_set_sage(self.value, x) cdef Integer tmp - cdef char* xs - cdef int paritype cdef Py_ssize_t j cdef object otmp @@ -675,8 +675,8 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): elif (isinstance(x, list) or isinstance(x, tuple)) and base > 1: b = the_integer_ring(base) - if b == 2: # we use a faster method - for j from 0 <= j < len(x): + if b == 2: # we use a faster method + for j in range(len(x)): otmp = x[j] if isinstance(otmp, int): if ( otmp) == 1: @@ -968,7 +968,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): sage: m.list() [5] """ - return [ self ] + return [self] def __dealloc__(self): mpz_clear(self.value) @@ -1037,7 +1037,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): sage: (-45)._mathml_() '-45' """ - return '%s'%self + return '%s' % self def __mpz__(self): """ @@ -1098,7 +1098,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): '1000000000' """ if base < 2 or base > 36: - raise ValueError("base (=%s) must be between 2 and 36" % base) + raise ValueError(f"base (={base}) must be between 2 and 36") cdef size_t n cdef char *s n = mpz_sizeinbase(self.value, base) + 2 @@ -1157,16 +1157,15 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): '112th' sage: ZZ(111).ordinal_str() '111th' - """ - if self<0: + if self < 0: raise ValueError("Negative integers are not ordinals.") n = self.abs() - if ((n%100)!=11 and n%10==1): + if (n % 100) != 11 and n % 10 == 1: th = 'st' - elif ((n%100)!=12 and n%10==2): + elif (n % 100) != 12 and n % 10 == 2: th = 'nd' - elif ((n%100)!=13 and n%10==3): + elif (n % 100) != 13 and n % 10 == 3: th = 'rd' else: th = 'th' @@ -1513,7 +1512,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): o = -one z = zero l = [z]*(s if s >= padto else padto) - for i from 0<= i < s: + for i in range(s): # mpz_tstbit seems to return 0 for the high-order bit of # negative numbers?! if mpz_tstbit(self_abs.value,i): @@ -1521,7 +1520,8 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): else: s = mpz_sizeinbase(self.value, 2) do_sig_on = (s > 256) - if do_sig_on: sig_on() + if do_sig_on: + sig_on() # We use a divide and conquer approach (suggested by the prior # author, malb?, of the digits method) here: for base b, compute @@ -1577,7 +1577,8 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): # assigning zero. _digits_internal(self.value,l,0,i-1,power_list,digits) - if do_sig_on: sig_off() + if do_sig_on: + sig_off() # padding should be taken care of with-in the function # all we need to do is return @@ -1908,7 +1909,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): if mpz_fits_slong_p(self.value): return s * mpz_get_si(self.value) else: - return s * int(self) # will raise the appropriate exception + return s * int(self) # will raise the appropriate exception cdef _mul_long(self, long n) noexcept: """ @@ -2024,9 +2025,9 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): # left * den(right) / num(right) y = Rational.__new__(Rational) mpq_div_zz(y.value, (left).value, - mpq_numref((right).value)) + mpq_numref((right).value)) mpz_mul(mpq_numref(y.value), mpq_numref(y.value), - mpq_denref((right).value)) + mpq_denref((right).value)) return y return coercion_model.bin_op(left, right, operator.truediv) @@ -2460,7 +2461,6 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): cdef size_t l_min cdef size_t l_max cdef size_t l - cdef Integer result cdef mpz_t accum cdef mpz_t temp_exp @@ -2578,7 +2578,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): if (1 << (pow_2-1)) == upper-lower: pow_2 -= 1 pow_2_things = [rif_m]*pow_2 - for i from 1<=ii>=0: middle = lower + int(2)**i @@ -2683,13 +2683,12 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): cdef Integer result cdef size_t n_log2 cdef size_t m_log2 - cdef size_t guess # this will contain the final answer + cdef size_t guess # this will contain the final answer cdef bint guess_filled = 0 # this variable is only used in one branch below - cdef mpz_t z if isinstance(m, Integer): - _m=m + _m = m else: - _m=Integer(m) + _m = Integer(m) self_sgn = mpz_sgn(self.value) if self_sgn == 0: @@ -2717,7 +2716,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): # we've already excluded the case when m is an exact power of 2 - if n_log2/m_log2 > 8000: + if n_log2 / m_log2 > 8000: # If we have a very large number of digits, it can be a nice # shortcut to test the guess using interval arithmetic. # (suggested by David Harvey and Carl Witty) @@ -2729,7 +2728,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): guess_filled = 1 elif self < approx_compare: guess_filled = 1 - guess = guess - 1 + guess = guess - 1 if not guess_filled: # At this point, either # 1) self is close enough to a perfect power of m that we @@ -2864,15 +2863,14 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): if elog == -sage.rings.infinity.infinity or m**elog == self: return elog - if (isinstance(m, Rational) - and m.numer() == 1): + if isinstance(m, Rational) and m.numer() == 1: elog = -self.exact_log(m.denom()) if m**elog == self: return elog from sage.functions.log import function_log - return function_log(self,dont_call_method_on_arg=True)/\ - function_log(m,dont_call_method_on_arg=True) + return function_log(self, dont_call_method_on_arg=True)/\ + function_log(m, dont_call_method_on_arg=True) def exp(self, prec=None): r""" @@ -3113,7 +3111,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): cdef list all, prev, sorted cdef Py_ssize_t tip, top - cdef Py_ssize_t i, j, e, ee + cdef Py_ssize_t i, e, ee cdef Integer apn, p, pn, z, all_tip f = self.factor() @@ -3124,7 +3122,6 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): cdef unsigned long p_c, pn_c, apn_c cdef Py_ssize_t all_len, sorted_len, prev_len cdef unsigned long* ptr - cdef unsigned long* empty_c cdef unsigned long* swap_tmp cdef unsigned long* all_c cdef unsigned long* sorted_c @@ -3222,7 +3219,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): sorted = [] tip = 0 top = len(all) - mpz_mul(pn.value, pn.value, p.value) # pn *= p + mpz_mul(pn.value, pn.value, p.value) # pn *= p for a in prev: # apn = a*pn apn = PY_NEW(Integer) @@ -3510,7 +3507,8 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): ZeroDivisionError: cannot raise to a power modulo 0 """ cdef Integer x, _exp, _mod - _exp = Integer(exp); _mod = Integer(mod) + _exp = Integer(exp) + _mod = Integer(mod) if mpz_cmp_si(_mod.value,0) == 0: raise ZeroDivisionError("cannot raise to a power modulo 0") @@ -3763,51 +3761,75 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): # We need to find i. m = start % 30 if 0 <= m <= 1: - i = 0; m = start + (1-m) + i = 0 + m = start + (1-m) elif 1 < m <= 7: - i = 1; m = start + (7-m) + i = 1 + m = start + (7-m) elif 7 < m <= 11: - i = 2; m = start + (11-m) + i = 2 + m = start + (11-m) elif 11 < m <= 13: - i = 3; m = start + (13-m) + i = 3 + m = start + (13-m) elif 13 < m <= 17: - i = 4; m = start + (17-m) + i = 4 + m = start + (17-m) elif 17 < m <= 19: - i = 5; m = start + (19-m) + i = 5 + m = start + (19-m) elif 19 < m <= 23: - i = 6; m = start + (23-m) + i = 6 + m = start + (23-m) elif 23 < m <= 29: - i = 7; m = start + (29-m) - dif[0]=6;dif[1]=4;dif[2]=2;dif[3]=4;dif[4]=2;dif[5]=4;dif[6]=6;dif[7]=2 + i = 7 + m = start + (29-m) + dif[0] = 6 + dif[1] = 4 + dif[2] = 2 + dif[3] = 4 + dif[4] = 2 + dif[5] = 4 + dif[6] = 6 + dif[7] = 2 cdef Integer x = PY_NEW(Integer) if mpz_fits_ulong_p(self.value): n = mpz_get_ui(self.value) # ignores the sign automatically - if n == 1: return one - if start <= 2 and n%2==0: - mpz_set_ui(x.value,2); return x - if start <= 3 and n%3==0: - mpz_set_ui(x.value,3); return x - if start <= 5 and n%5==0: - mpz_set_ui(x.value,5); return x + if n == 1: + return one + if start <= 2 and n % 2 == 0: + mpz_set_ui(x.value,2) + return x + if start <= 3 and n % 3 == 0: + mpz_set_ui(x.value,3) + return x + if start <= 5 and n % 5 == 0: + mpz_set_ui(x.value,5) + return x limit = sqrt_double( n) - if bound < limit: limit = bound + if bound < limit: + limit = bound # Algorithm: only trial divide by numbers that # are congruent to 1,7,11,13,17,19,23,29 mod 30=2*3*5. while m <= limit: - if n%m == 0: - mpz_set_ui(x.value, m); return x - m += dif[i%8] + if n % m == 0: + mpz_set_ui(x.value, m) + return x + m += dif[i % 8] i += 1 mpz_abs(x.value, self.value) return x else: # self is big -- it doesn't fit in unsigned long. if start <= 2 and mpz_even_p(self.value): - mpz_set_ui(x.value,2); return x - if start <= 3 and mpz_divisible_ui_p(self.value,3): - mpz_set_ui(x.value,3); return x - if start <= 5 and mpz_divisible_ui_p(self.value,5): - mpz_set_ui(x.value,5); return x + mpz_set_ui(x.value, 2) + return x + if start <= 3 and mpz_divisible_ui_p(self.value, 3): + mpz_set_ui(x.value, 3) + return x + if start <= 5 and mpz_divisible_ui_p(self.value, 5): + mpz_set_ui(x.value, 5) + return x # x.value = floor(sqrt(self.value)) sig_on() @@ -3829,7 +3851,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): return x def factor(self, algorithm='pari', proof=None, limit=None, int_=False, - verbose=0): + verbose=0): """ Return the prime factorization of this integer as a formal Factorization object. @@ -3949,23 +3971,22 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): raise ValueError("Algorithm is not known") cdef Integer n, p, unit - cdef int i if mpz_sgn(self.value) == 0: raise ArithmeticError("factorization of 0 is not defined") if mpz_sgn(self.value) > 0: - n = self + n = self unit = one else: - n = PY_NEW(Integer) + n = PY_NEW(Integer) unit = PY_NEW(Integer) mpz_neg(n.value, self.value) mpz_set_si(unit.value, -1) if mpz_cmpabs_ui(n.value, 1) == 0: return IntegerFactorization([], unit=unit, unsafe=True, - sort=False, simplify=False) + sort=False, simplify=False) if limit is not None: from sage.rings.factorint import factor_trial_division @@ -3986,7 +4007,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): F = [(smallInteger(a), smallInteger(b)) for a, b in F] F.sort() return IntegerFactorization(F, unit=unit, unsafe=True, - sort=False, simplify=False) + sort=False, simplify=False) if mpz_sizeinbase(n.value, 2) < 40: from sage.rings.factorint import factor_trial_division @@ -3997,20 +4018,20 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): F = factor_using_pari(n, int_=int_, debug_level=verbose, proof=proof) F.sort() return IntegerFactorization(F, unit=unit, unsafe=True, - sort=False, simplify=False) + sort=False, simplify=False) elif algorithm == 'flint': from sage.rings.factorint_flint import factor_using_flint F = factor_using_flint(n) F.sort() return IntegerFactorization(F, unit=unit, unsafe=True, - sort=False, simplify=False) + sort=False, simplify=False) elif algorithm in ['kash', 'magma']: if algorithm == 'kash': from sage.interfaces.kash import kash as I else: from sage.interfaces.magma import magma as I - str_res = I.eval('Factorization(%s)'%n) + str_res = I.eval('Factorization(%s)' % n) # The result looks like "[ , , ... ] str_res = str_res.replace(']', '').replace('[', '').replace('>', '').replace('<', '').split(',') res = [int(s.strip()) for s in str_res] @@ -4025,7 +4046,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): F = qsieve(n) F.sort() return IntegerFactorization(F, unit=unit, unsafe=True, - sort=False, simplify=False) + sort=False, simplify=False) else: from sage.interfaces.ecm import ecm res = [(p, 1) for p in ecm.factor(n, proof=proof)] @@ -4051,10 +4072,10 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): sage: 0.support() Traceback (most recent call last): ... - ArithmeticError: Support of 0 not defined. + ArithmeticError: support of 0 not defined """ if self.is_zero(): - raise ArithmeticError("Support of 0 not defined.") + raise ArithmeticError("support of 0 not defined") return sage.arith.all.prime_factors(self) def coprime_integers(self, m): @@ -4345,7 +4366,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): if mpz_cmpabs_ui(self.value, 1) <= 0: return self - odd = PY_NEW(Integer) + odd = PY_NEW(Integer) bits = mpz_scan1(self.value, 0) mpz_tdiv_q_2exp(odd.value, self.value, bits) return odd @@ -4918,100 +4939,100 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): cdef unsigned long b, c cdef mpz_t u, sabs, nabs a = mpz_cmp_ui(n.value, 2) - if a <= 0: # n <= 2 - if a == 0: # n == 2 - if mpz_popcount(self.value) == 1: #number of bits set in self == 1 + if a <= 0: # n <= 2 + if a == 0: # n == 2 + if mpz_popcount(self.value) == 1: # number of bits set in self == 1 return 1 else: return 0 a = mpz_cmp_si(n.value, -2) - if a >= 0: # -2 <= n < 2: + if a >= 0: # -2 <= n < 2: a = mpz_get_si(n.value) - if a == 1: # n == 1 - if mpz_cmp_ui(self.value, 1) == 0: # Only 1 is a power of 1 + if a == 1: # n == 1 + if mpz_cmp_ui(self.value, 1) == 0: # Only 1 is a power of 1 return 1 else: return 0 - elif a == 0: # n == 0 - if mpz_cmp_ui(self.value, 0) == 0 or mpz_cmp_ui(self.value, 1) == 0: # 0^0 = 1, 0^x = 0 + elif a == 0: # n == 0 + if mpz_cmp_ui(self.value, 0) == 0 or mpz_cmp_ui(self.value, 1) == 0: # 0^0 = 1, 0^x = 0 return 1 else: return 0 - elif a == -1: # n == -1 - if mpz_cmp_ui(self.value, 1) == 0 or mpz_cmp_si(self.value, -1) == 0: # 1 and -1 are powers of -1 + elif a == -1: # n == -1 + if mpz_cmp_ui(self.value, 1) == 0 or mpz_cmp_si(self.value, -1) == 0: # 1 and -1 are powers of -1 return 1 else: return 0 - elif a == -2: # n == -2 + elif a == -2: # n == -2 mpz_init(sabs) mpz_abs(sabs, self.value) - if mpz_popcount(sabs) == 1: # number of bits set in |self| == 1 - b = mpz_scan1(sabs, 0) % 2 # b == 1 if |self| is an odd power of 2, 0 if |self| is an even power + if mpz_popcount(sabs) == 1: # number of bits set in |self| == 1 + b = mpz_scan1(sabs, 0) % 2 # b == 1 if |self| is an odd power of 2, 0 if |self| is an even power mpz_clear(sabs) if (b == 1 and mpz_cmp_ui(self.value, 0) < 0) or (b == 0 and mpz_cmp_ui(self.value, 0) > 0): # An odd power of -2 is negative, an even power must be positive. return 1 - else: # number of bits set in |self| is not 1, so self cannot be a power of -2 + else: # number of bits set in |self| is not 1, so self cannot be a power of -2 return 0 - else: # |self| is not a power of 2, so self cannot be a power of -2 + else: # |self| is not a power of 2, so self cannot be a power of -2 return 0 - else: # n < -2 + else: # n < -2 mpz_init(nabs) mpz_neg(nabs, n.value) - if mpz_popcount(nabs) == 1: # |n| = 2^k for k >= 2. We special case this for speed + if mpz_popcount(nabs) == 1: # |n| = 2^k for k >= 2. We special case this for speed mpz_init(sabs) mpz_abs(sabs, self.value) - if mpz_popcount(sabs) == 1: # |self| = 2^L for some L >= 0. - b = mpz_scan1(sabs, 0) # the bit that self is set at - c = mpz_scan1(nabs, 0) # the bit that n is set at + if mpz_popcount(sabs) == 1: # |self| = 2^L for some L >= 0. + b = mpz_scan1(sabs, 0) # the bit that self is set at + c = mpz_scan1(nabs, 0) # the bit that n is set at # Having obtained b and c, we're done with nabs and sabs (on this branch anyway) mpz_clear(nabs) mpz_clear(sabs) - if b % c == 0: # Now we know that |self| is a power of |n| - b = (b // c) % 2 # Whether b // c is even or odd determines whether (-2^c)^(b // c) is positive or negative + if b % c == 0: # Now we know that |self| is a power of |n| + b = (b // c) % 2 # Whether b // c is even or odd determines whether (-2^c)^(b // c) is positive or negative a = mpz_cmp_ui(self.value, 0) if b == 0 and a > 0 or b == 1 and a < 0: # These two cases are that b // c is even and self positive, or b // c is odd and self negative return 1 - else: # The sign of self is wrong + else: # The sign of self is wrong return 0 - else: # Since |self| is not a power of |n|, self cannot be a power of n + else: # Since |self| is not a power of |n|, self cannot be a power of n return 0 - else: # self is not a power of 2, and thus cannot be a power of n, which is a power of 2. + else: # self is not a power of 2, and thus cannot be a power of n, which is a power of 2. mpz_clear(nabs) mpz_clear(sabs) return 0 - else: # |n| is not a power of 2, so we use mpz_remove + else: # |n| is not a power of 2, so we use mpz_remove mpz_init(u) sig_on() b = mpz_remove(u, self.value, nabs) sig_off() # Having obtained b and u, we're done with nabs mpz_clear(nabs) - if mpz_cmp_ui(u, 1) == 0: # self is a power of |n| + if mpz_cmp_ui(u, 1) == 0: # self is a power of |n| mpz_clear(u) - if b % 2 == 0: # an even power of |n|, and since self > 0, this means that self is a power of n + if b % 2 == 0: # an even power of |n|, and since self > 0, this means that self is a power of n return 1 else: return 0 - elif mpz_cmp_si(u, -1) == 0: # -self is a power of |n| + elif mpz_cmp_si(u, -1) == 0: # -self is a power of |n| mpz_clear(u) - if b % 2 == 1: # an odd power of |n|, and thus self is a power of n + if b % 2 == 1: # an odd power of |n|, and thus self is a power of n return 1 else: return 0 - else: # |self| is not a power of |n|, so self cannot be a power of n + else: # |self| is not a power of |n|, so self cannot be a power of n mpz_clear(u) return 0 - elif mpz_popcount(n.value) == 1: # n > 2 and in fact n = 2^k for k >= 2 - if mpz_popcount(self.value) == 1: # since n is a power of 2, so must self be. - if mpz_scan1(self.value, 0) % mpz_scan1(n.value, 0) == 0: # log_2(self) is divisible by log_2(n) + elif mpz_popcount(n.value) == 1: # n > 2 and in fact n = 2^k for k >= 2 + if mpz_popcount(self.value) == 1: # since n is a power of 2, so must self be. + if mpz_scan1(self.value, 0) % mpz_scan1(n.value, 0) == 0: # log_2(self) is divisible by log_2(n) return 1 else: return 0 - else: # self is not a power of 2, and thus not a power of n + else: # self is not a power of 2, and thus not a power of n return 0 - else: # n > 2, but not a power of 2, so we use mpz_remove + else: # n > 2, but not a power of 2, so we use mpz_remove mpz_init(u) sig_on() mpz_remove(u, self.value, n.value) @@ -5252,8 +5273,8 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): return (self, zero) if get_data else False _small_primes_table[:] = [ - 0,1,1,1,0,1,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0, # 1, 3,..., 49 - 0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0, # 51, 53,..., 99 + 0,1,1,1,0,1,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0, # 1,3,...,49 + 0,1,0,0,1,1,0,0,1,0,1,1,0,0,1,0,1,0,0,1,0,0,0,1,0, # 51,53,...,99 1,1,0,1,1,0,1,0,0,0,0,0,0,1,0,1,0,0,1,1,0,0,0,0,1, # 101,103,...,149 1,0,0,1,0,0,1,0,1,0,0,1,0,0,1,1,0,0,0,0,1,1,0,1,1, # 151,153,...,199 0,0,0,0,0,1,0,0,0,0,0,1,0,1,1,0,1,0,0,1,1,0,0,0,0, # 201,203,...,249 @@ -5725,7 +5746,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): global objtogen if objtogen is None: from cypari2.gen import objtogen - flag = self < 0 and proof + flag = self < 0 and proof return objtogen(self).qfbclassno(flag).sage() def squarefree_part(self, long bound=-1): @@ -5829,7 +5850,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): sage: 144168.next_probable_prime() 144169 """ - return Integer( self.__pari__().nextprime(True) ) + return Integer(self.__pari__().nextprime(True)) def next_prime(self, proof=None): r""" @@ -6138,7 +6159,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): sage: len([D for D in srange(-100,100) if D.is_discriminant()]) 100 """ - return self%4 in [0,1] + return self % 4 in [0, 1] def is_fundamental_discriminant(self): """ @@ -6166,17 +6187,16 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): sage: len([D for D in srange(-100,100) # needs sage.libs.pari ....: if D.is_fundamental_discriminant()]) 61 - """ - if self in [0,1]: + if self in [0, 1]: return False - Dmod4 = self%4 - if Dmod4 in [2,3]: + Dmod4 = self % 4 + if Dmod4 in [2, 3]: return False if Dmod4 == 1: return self.is_squarefree() - d = self//4 - return d%4 in [2,3] and d.is_squarefree() + d = self // 4 + return d % 4 in [2, 3] and d.is_squarefree() cpdef __pari__(self) noexcept: """ @@ -6274,9 +6294,8 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): True """ if self.ndigits(2) > 10000: - return 'StringToInteger("%s",16)'%self.str(16) - else: - return str(self) + return 'StringToInteger("%s",16)' % self.str(16) + return str(self) def _sage_input_(self, sib, coerced): r""" @@ -6339,13 +6358,13 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): sage: Integer(-102).sqrtrem() Traceback (most recent call last): ... - ValueError: square root of negative integer not defined. + ValueError: square root of negative integer not defined """ if mpz_sgn(self.value) < 0: - raise ValueError("square root of negative integer not defined.") + raise ValueError("square root of negative integer not defined") cdef Integer s = PY_NEW(Integer) - cdef Integer r = PY_NEW(Integer) + cdef Integer r = PY_NEW(Integer) mpz_sqrtrem(s.value, r.value, self.value) return s, r @@ -6365,10 +6384,10 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): sage: Integer(-102).isqrt() Traceback (most recent call last): ... - ValueError: square root of negative integer not defined. + ValueError: square root of negative integer not defined """ if mpz_sgn(self.value) < 0: - raise ValueError("square root of negative integer not defined.") + raise ValueError("square root of negative integer not defined") cdef Integer x = PY_NEW(Integer) @@ -6696,7 +6715,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): try: y = Integer(y) except TypeError: - raise TypeError("unsupported operands for %s: %s, %s"%(("<<" if sign == 1 else ">>"), self, y)) + raise TypeError("unsupported operands for %s: %s, %s" % (("<<" if sign == 1 else ">>"), self, y)) except ValueError: return coercion_model.bin_op(self, y, operator.lshift if sign == 1 else operator.rshift) @@ -6945,8 +6964,9 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): def crt(self, y, m, n): """ Return the unique integer between `0` and `mn` that is congruent to - the integer modulo `m` and to `y` modulo `n`. We assume that `m` and - `n` are coprime. + the integer modulo `m` and to `y` modulo `n`. + + We assume that `m` and `n` are coprime. EXAMPLES:: @@ -6958,10 +6978,12 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): sage: m%11 5 """ - cdef object g, s, t + cdef object g, s cdef Integer _y, _m, _n - _y = Integer(y); _m = Integer(m); _n = Integer(n) - g, s, t = _m.xgcd(_n) + _y = Integer(y) + _m = Integer(m) + _n = Integer(n) + g, s, _ = _m.xgcd(_n) if not g.is_one(): raise ArithmeticError("CRT requires that gcd of moduli is 1.") # Now s*m + t*n = 1, so the answer is x + (y-x)*s*m, where x=self. @@ -7023,7 +7045,6 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): return sage.rings.infinity.Infinity return smallInteger(mpz_popcount(self.value)) - def conjugate(self): """ Return the complex conjugate of this integer, which is the @@ -7323,7 +7344,7 @@ def GCD_list(v): cdef int i, n = len(v) cdef Integer z = PY_NEW(Integer) - for i from 0 <= i < n: + for i in range(n): if not isinstance(v[i], Integer): if not isinstance(v, list): v = list(v) @@ -7336,7 +7357,7 @@ def GCD_list(v): sig_on() mpz_gcd(z.value, (v[0]).value, (v[1]).value) - for i from 2 <= i < n: + for i in range(2, n): if mpz_cmp_ui(z.value, 1) == 0: break mpz_gcd(z.value, z.value, (v[i]).value) @@ -7480,7 +7501,7 @@ cdef class long_to_Z(Morphism): def _repr_type(self): return "Native" -############### INTEGER CREATION CODE ##################### +# ############## INTEGER CREATION CODE ##################### # This variable holds the size of any Integer object in bytes. cdef int sizeof_Integer @@ -7492,6 +7513,7 @@ global_dummy_Integer = Integer() # Reallocate to one limb to fix :trac:`31340` and :trac:`33081` _mpz_realloc(global_dummy_Integer.value, 1) + def _check_global_dummy_Integer(): """ Return ``True`` if the global dummy :class:`Integer` is ok. @@ -7560,13 +7582,13 @@ cdef PyObject* fast_tp_new(type t, args, kwds) except NULL: # they do not possess references to other Python # objects (as indicated by the Py_TPFLAGS_HAVE_GC flag). # See below for a more detailed description. - new = PyObject_Malloc( sizeof_Integer ) + new = PyObject_Malloc(sizeof_Integer) if unlikely(new == NULL): raise MemoryError # Now set every member as set in z, the global dummy Integer # created before this tp_new started to operate. - memcpy(new, (global_dummy_Integer), sizeof_Integer ) + memcpy(new, (global_dummy_Integer), sizeof_Integer) # We allocate memory for the _mp_d element of the value of this # new Integer. We allocate one limb. Normally, one would use @@ -7670,15 +7692,16 @@ cdef integer(x) noexcept: return x return Integer(x) + def free_integer_pool(): cdef int i cdef PyObject *o global integer_pool_count, integer_pool_size - for i from 0 <= i < integer_pool_count: + for i in range(integer_pool_count): o = integer_pool[i] - mpz_clear( (o).value ) + mpz_clear((o).value) # Free the object. This assumes that Py_TPFLAGS_HAVE_GC is not # set. If it was set another free function would need to be # called. @@ -7688,6 +7711,7 @@ def free_integer_pool(): integer_pool_count = 0 sig_free(integer_pool) + # Replace default allocation and deletion with faster custom ones hook_fast_tp_functions() @@ -7695,7 +7719,8 @@ hook_fast_tp_functions() initialized = False cdef set_zero_one_elements() noexcept: global the_integer_ring, initialized - if initialized: return + if initialized: + return the_integer_ring._zero_element = Integer(0) the_integer_ring._one_element = Integer(1) initialized = True diff --git a/src/sage/rings/integer_ring.pxd b/src/sage/rings/integer_ring.pxd index 41afccaa514..d0af1bc068f 100644 --- a/src/sage/rings/integer_ring.pxd +++ b/src/sage/rings/integer_ring.pxd @@ -1,5 +1,5 @@ -from .ring cimport PrincipalIdealDomain -from .integer cimport Integer +from sage.rings.ring cimport PrincipalIdealDomain +from sage.rings.integer cimport Integer from sage.libs.gmp.types cimport mpz_t cdef class IntegerRing_class(PrincipalIdealDomain): diff --git a/src/sage/rings/integer_ring.pyx b/src/sage/rings/integer_ring.pyx index b510c4ba992..1ee45b99a59 100644 --- a/src/sage/rings/integer_ring.pyx +++ b/src/sage/rings/integer_ring.pyx @@ -69,7 +69,7 @@ from sage.misc.randstate cimport randstate, current_randstate, SAGE_RAND_MAX cimport sage.rings.integer as integer -from . import ring +from sage.rings import ring arith = None cdef void late_import() noexcept: diff --git a/src/sage/rings/laurent_series_ring.py b/src/sage/rings/laurent_series_ring.py index 565e5d12f4c..187ac847522 100644 --- a/src/sage/rings/laurent_series_ring.py +++ b/src/sage/rings/laurent_series_ring.py @@ -32,20 +32,17 @@ # **************************************************************************** -from sage.categories.rings import Rings -from sage.rings.infinity import infinity from sage.categories.algebras import Algebras -from sage.categories.integral_domains import IntegralDomains -from sage.categories.fields import Fields from sage.categories.complete_discrete_valuation import CompleteDiscreteValuationFields - -from .laurent_series_ring_element import LaurentSeries -from .ring import CommutativeRing - -from sage.structure.unique_representation import UniqueRepresentation +from sage.categories.fields import Fields +from sage.categories.integral_domains import IntegralDomains +from sage.categories.rings import Rings from sage.misc.cachefunc import cached_method - +from sage.rings.infinity import infinity from sage.rings.integer_ring import ZZ +from sage.rings.laurent_series_ring_element import LaurentSeries +from sage.rings.ring import CommutativeRing +from sage.structure.unique_representation import UniqueRepresentation try: from sage.libs.pari.all import pari_gen @@ -315,8 +312,8 @@ def fraction_field(self): ... ValueError: must be an integral domain """ - from sage.categories.integral_domains import IntegralDomains from sage.categories.fields import Fields + from sage.categories.integral_domains import IntegralDomains if self in Fields(): return self elif self in IntegralDomains(): @@ -489,8 +486,8 @@ def _element_constructor_(self, x, n=0, prec=infinity): x^-3 """ from sage.rings.fraction_field_element import is_FractionFieldElement - from sage.rings.polynomial.polynomial_element import Polynomial from sage.rings.polynomial.multi_polynomial import MPolynomial + from sage.rings.polynomial.polynomial_element import Polynomial from sage.structure.element import parent P = parent(x) @@ -643,9 +640,11 @@ def _coerce_map_from_(self, P): True """ A = self.base_ring() + from sage.rings.polynomial.laurent_polynomial_ring_base import ( + LaurentPolynomialRing_generic, + ) from sage.rings.polynomial.polynomial_ring import is_PolynomialRing from sage.rings.power_series_ring import is_PowerSeriesRing - from sage.rings.polynomial.laurent_polynomial_ring_base import LaurentPolynomialRing_generic if ((is_LaurentSeriesRing(P) or isinstance(P, LaurentPolynomialRing_generic) or diff --git a/src/sage/rings/laurent_series_ring_element.pyx b/src/sage/rings/laurent_series_ring_element.pyx index b15e6cbdcf0..cac7acd812c 100644 --- a/src/sage/rings/laurent_series_ring_element.pyx +++ b/src/sage/rings/laurent_series_ring_element.pyx @@ -66,12 +66,12 @@ AUTHORS: # https://www.gnu.org/licenses/ # **************************************************************************** -from .infinity import infinity +from sage.rings.infinity import infinity from sage.rings.rational_field import QQ import sage.misc.latex from sage.rings.polynomial.laurent_polynomial import LaurentPolynomial_univariate -from .power_series_ring_element cimport PowerSeries +from sage.rings.power_series_ring_element cimport PowerSeries from sage.structure.element cimport Element, AlgebraElement from sage.structure.richcmp cimport richcmp_not_equal, rich_to_bool from sage.misc.derivative import multi_derivative diff --git a/src/sage/rings/morphism.pyx b/src/sage/rings/morphism.pyx index 9901eff95a3..f8e32bd8c62 100644 --- a/src/sage/rings/morphism.pyx +++ b/src/sage/rings/morphism.pyx @@ -406,7 +406,7 @@ compare equal:: # https://www.gnu.org/licenses/ # **************************************************************************** -from . import ideal +from sage.rings import ideal import sage.structure.all from sage.structure.richcmp cimport (richcmp, rich_to_bool) from sage.misc.cachefunc import cached_method diff --git a/src/sage/rings/number_field/number_field_element_quadratic.pxd b/src/sage/rings/number_field/number_field_element_quadratic.pxd index 76661971848..b9fbb294a54 100644 --- a/src/sage/rings/number_field/number_field_element_quadratic.pxd +++ b/src/sage/rings/number_field/number_field_element_quadratic.pxd @@ -2,7 +2,7 @@ from sage.libs.gmp.types cimport mpz_t from sage.libs.arb.types cimport arb_t from sage.rings.integer cimport Integer from sage.rings.rational cimport Rational -from .number_field_element cimport NumberFieldElement, NumberFieldElement_absolute +from sage.rings.number_field.number_field_element cimport NumberFieldElement, NumberFieldElement_absolute cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute): diff --git a/src/sage/rings/number_field/order.py b/src/sage/rings/number_field/order.py index 896132b4e56..e3ddebd7e69 100644 --- a/src/sage/rings/number_field/order.py +++ b/src/sage/rings/number_field/order.py @@ -93,6 +93,29 @@ from sage.libs.pari.all import pari +def quadratic_order_class_number(disc): + r""" + Return the class number of the quadratic order of given discriminant. + + EXAMPLES:: + + sage: from sage.rings.number_field.order import quadratic_order_class_number + sage: quadratic_order_class_number(-419) + 9 + sage: quadratic_order_class_number(60) + 2 + + ALGORITHM: Either :pari:`qfbclassno` or :pari:`quadclassunit`, + depending on the size of the discriminant. + """ + # cutoffs from PARI documentation + if disc < -10**25 or disc > 10**10: + h = pari.quadclassunit(disc)[0] + else: + h = pari.qfbclassno(disc) + return ZZ(h) + + class OrderFactory(UniqueFactory): r""" Abstract base class for factories creating orders, such as @@ -1097,7 +1120,7 @@ def class_number(self, proof=None): K = self.number_field() if K.degree() != 2: raise NotImplementedError("computation of class numbers of non-maximal orders not in quadratic fields is not implemented") - return ZZ(pari.qfbclassno(self.discriminant())) + return quadratic_order_class_number(self.discriminant()) return self.number_field().class_number(proof=proof) def class_group(self, proof=None, names='c'): diff --git a/src/sage/rings/polynomial/ideal.py b/src/sage/rings/polynomial/ideal.py index 1ab86736d5b..9719c81ba41 100644 --- a/src/sage/rings/polynomial/ideal.py +++ b/src/sage/rings/polynomial/ideal.py @@ -85,3 +85,16 @@ def groebner_basis(self, algorithm=None): gb = self.gens_reduced() from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence_generic return PolynomialSequence_generic([gb], self.ring(), immutable=True) + + def change_ring(self, R): + """ + Coerce an ideal into a new ring. + + EXAMPLES:: + + sage: R. = QQ[] + sage: I = R.ideal([q^2+q-1]) + sage: I.change_ring(RR['q']) + Principal ideal (q^2 + q - 1.00000000000000) of Univariate Polynomial Ring in q over Real Field with 53 bits of precision + """ + return R.ideal(self.gens()) diff --git a/src/sage/rings/polynomial/laurent_polynomial.pyx b/src/sage/rings/polynomial/laurent_polynomial.pyx index 32dfa655ea7..8e5bd127993 100644 --- a/src/sage/rings/polynomial/laurent_polynomial.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial.pyx @@ -1317,6 +1317,63 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): return ~self raise ArithmeticError("element is not a unit") + def xgcd(self, other): + """ + Extended `gcd` for univariate Laurent polynomial rings over a field. + + EXAMPLES:: + + sage: S. = LaurentPolynomialRing(QQ) + sage: (t^-2 + 1).xgcd(t^-3 + 1) + (1, 1/2*t^2 - 1/2*t^3 - 1/2*t^4, 1/2*t^3 + 1/2*t^4) + """ + R = self.parent() + S = R.polynomial_ring() + f, df = self.monomial_reduction() + g, dg = other.monomial_reduction() + h, p, q = f.xgcd(g) + return R(h), p / df, q / dg + + def inverse_mod(a, m): + """ + Invert the polynomial ``a`` with respect to ``m``, or raise a :class:`ValueError` + if no such inverse exists. + + The parameter ``m`` may be either a single polynomial or an ideal + (for consistency with :meth:`inverse_mod` in other rings). + + ALGORITHM: Solve the system `as + mt = 1`, returning `s` as the inverse + of `a` mod `m`. + + EXAMPLES:: + + sage: S. = LaurentPolynomialRing(QQ) + sage: f = inverse_mod(t^-2 + 1, t^-3 + 1); f + 1/2*t^2 - 1/2*t^3 - 1/2*t^4 + sage: f * (t^-2 + 1) + (1/2*t^4 + 1/2*t^3) * (t^-3 + 1) + 1 + """ + from sage.rings.ideal import is_Ideal + if is_Ideal(m): + v = m.gens_reduced() + if len(v) > 1: + raise NotImplementedError("only inversion modulo principal ideals implemented") + m = v[0] + if m.degree() == 1 and m[1].is_unit(): + # a(x) mod (x-r) = a(r) + r = -m[0] + if not m[1].is_one(): + r *= m.base_ring()(~m[1]) + u = a(r) + if u.is_unit(): + return a.parent()(~u) + g, s, _ = a.xgcd(m) + if g == 1: + return s + elif g.is_unit(): + return g.inverse_of_unit() * s + raise ValueError("impossible inverse modulo") + def _fraction_pair(self): """ Return one representation of ``self`` as a pair @@ -1989,3 +2046,38 @@ cdef class LaurentPolynomial_univariate(LaurentPolynomial): 0 """ return self.__u[-self.__n] + + @coerce_binop + def divides(self, other): + r""" + Return ``True`` if ``self`` divides ``other``. + + EXAMPLES:: + + sage: R. = LaurentPolynomialRing(ZZ) + sage: (2*x**-1 + 1).divides(4*x**-2 - 1) + True + sage: (2*x + 1).divides(4*x**2 + 1) + False + sage: (2*x + x**-1).divides(R(0)) + True + sage: R(0).divides(2*x ** -1 + 1) + False + sage: R(0).divides(R(0)) + True + sage: R. = LaurentPolynomialRing(Zmod(6)) + sage: p = 4*x + 3*x^-1 + sage: q = 5*x^2 + x + 2*x^-2 + sage: p.divides(q) + False + + sage: R. = GF(2)[] + sage: S. = LaurentPolynomialRing(R) + sage: p = (x+y+1) * z**-1 + x*y + sage: q = (y^2-x^2) * z**-2 + z + x-y + sage: p.divides(q), p.divides(p*q) # needs sage.libs.singular + (False, True) + """ + p = self.polynomial_construction()[0] + q = other.polynomial_construction()[0] + return p.divides(q) diff --git a/src/sage/rings/polynomial/laurent_polynomial_ideal.py b/src/sage/rings/polynomial/laurent_polynomial_ideal.py index aa18314e523..d569dc06101 100644 --- a/src/sage/rings/polynomial/laurent_polynomial_ideal.py +++ b/src/sage/rings/polynomial/laurent_polynomial_ideal.py @@ -23,7 +23,9 @@ # **************************************************************************** from sage.rings.ideal import Ideal_generic +from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing_univariate from sage.structure.richcmp import op_EQ, op_NE, op_LT, op_LE, op_GT, op_GE +from sage.arith.misc import GCD class LaurentPolynomialIdeal( Ideal_generic ): def __init__(self, ring, gens, coerce=True, hint=None): @@ -91,7 +93,7 @@ def __init__(self, ring, gens, coerce=True, hint=None): """ Ideal_generic.__init__(self, ring, gens, coerce=coerce) self._poly_ring = ring.polynomial_ring() - self._poly_ideal = None # Create only as needed + self._poly_ideal = None # Create only as needed self._saturated = False if hint is None: self._hint = self._poly_ring.zero_ideal() @@ -192,13 +194,38 @@ def __contains__(self, f): sage: I = P.ideal([x^2*y + 3*x*y^2]) sage: x + 3*y in I True + + This also works in the univariate case:: + + sage: P. = LaurentPolynomialRing(QQ) + sage: I = P.ideal([x^2 + 3*x]) + sage: 1 + 3*x^-1 in I + True """ if not f or f in self.gens(): return True f = self.ring()(f) - g = f.__reduce__()[1][0] + if isinstance(self.ring(), LaurentPolynomialRing_univariate): + g = f.__reduce__()[1][1] + else: + g = f.__reduce__()[1][0] return (g in self.polynomial_ideal()) + def gens_reduced(self): + """ + Return a reduced system of generators. + + EXAMPLES:: + + sage: P. = LaurentPolynomialRing(QQ) + sage: J = P.ideal([x^2 - y^-2, x * y^3 + 2 * y^2+ y]) + sage: J.gens_reduced() + (x + 6*y + 5, 3*y^2 + 4*y + 1) + """ + R = self.ring() + J = self.polynomial_ideal() + return tuple([R(p) for p in J.gens()]) + # Operations on ideals def change_ring(self, R, hint=None): @@ -323,7 +350,7 @@ def toric_coordinate_change(self, M, forward_hint=True): """ if forward_hint: R = self.ring() - apply_to_hint = lambda x, M=M, R=R: R(x).toric_coordinate_change(M).__reduce__()[1][0] + apply_to_hint = lambda x, M=M, R=R: R(x).toric_coordinate_change(M).monomial_reduction()[0] else: apply_to_hint = None return self.apply_map(lambda x, M=M: x.toric_coordinate_change(M), @@ -396,20 +423,34 @@ def polynomial_ideal(self, saturate=True): sage: P. = LaurentPolynomialRing(QQ, 2) sage: I = P.ideal([x^2*y + 3*x*y^2]) sage: I.polynomial_ideal() - Ideal (x + 3*y) of Multivariate Polynomial Ring in x, y - over Rational Field + Ideal (x + 3*y) of Multivariate Polynomial Ring in x, y over Rational Field + sage: P. = LaurentPolynomialRing(QQ) + sage: J = P.ideal(t^2 - t^-1) + sage: J.polynomial_ideal() + Principal ideal (t^3 - 1) of Univariate Polynomial Ring in t over Rational Field + sage: J = P.ideal([t^2 - t^-1, t + t^-1]) + sage: J.polynomial_ideal() + Principal ideal (1) of Univariate Polynomial Ring in t over Rational Field + sage: J = P.ideal([t^2 - t^-1, t - t^-1]) + sage: J.polynomial_ideal() + Principal ideal (t - 1) of Univariate Polynomial Ring in t over Rational Field """ - if self._poly_ideal is not None and (self._saturated or not saturate): - return self._poly_ideal P = self.ring() Q = self._poly_ring + if isinstance(self.ring(), LaurentPolynomialRing_univariate): + a = [Q(p.polynomial_construction()[0]) for p in self.gens()] + if P.base_ring().is_field(): + a = GCD(a) + return Q.ideal(a) + if self._poly_ideal is not None and (self._saturated or not saturate): + return self._poly_ideal gens = self.gens() if len(gens) == 0: - I = Q.ideal([]) - self._poly_ideal = I - self._hint = I + id = Q.ideal([]) + self._poly_ideal = id + self._hint = id self._saturated = True - return I + return id l2 = [f.__reduce__()[1][0] for f in gens] hint = self._hint l2 += list(hint.groebner_basis()) diff --git a/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx b/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx index 9c118a97a0f..c0fd659591f 100644 --- a/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial_mpair.pyx @@ -1534,17 +1534,17 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): sage: R. = LaurentPolynomialRing(QQ) sage: f = y / x + x^2 / y + 3 * x^4 * y^-2 sage: f.monomial_reduction() - (3*x^5 + x^3*y + y^3, 1/(x*y^2)) + (3*x^5 + x^3*y + y^3, x^-1*y^-2) sage: f = y * x + x^2 / y + 3 * x^4 * y^-2 sage: f.monomial_reduction() - (3*x^3 + y^3 + x*y, x/y^2) + (3*x^3 + y^3 + x*y, x*y^-2) sage: x.monomial_reduction() (1, x) sage: (y^-1).monomial_reduction() - (1, 1/y) + (1, y^-1) """ self._normalize() - ring = self._parent._R + ring = self._parent g = ring.gens() mon = ring.prod(g[i] ** j for i, j in enumerate(self._mon)) return (self._poly, mon) @@ -1854,3 +1854,26 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): if new_ring is not None: return new_ring(ans) return ans + + @coerce_binop + def divides(self, other): + """ + Check if ``self`` divides ``other``. + + EXAMPLES:: + + sage: R. = LaurentPolynomialRing(QQ) + sage: f1 = x^-2*y^3 - 9 - 1/14*x^-1*y - 1/3*x^-1 + sage: h = 3*x^-1 - 3*x^-2*y - 1/2*x^-3*y^2 - x^-3*y + x^-3 + sage: f2 = f1 * h + sage: f3 = f2 + x * y + sage: f1.divides(f2) + True + sage: f1.divides(f3) + False + sage: f1.divides(3) + False + """ + p = self.monomial_reduction()[0] + q = other.monomial_reduction()[0] + return p.divides(q) diff --git a/src/sage/rings/polynomial/laurent_polynomial_ring.py b/src/sage/rings/polynomial/laurent_polynomial_ring.py index ac40e815724..812a4b3a351 100644 --- a/src/sage/rings/polynomial/laurent_polynomial_ring.py +++ b/src/sage/rings/polynomial/laurent_polynomial_ring.py @@ -442,8 +442,10 @@ def __init__(self, R): TESTS:: + sage: TestSuite(LaurentPolynomialRing(Zmod(2), 'y')).run() sage: TestSuite(LaurentPolynomialRing(Zmod(4), 'y')).run() sage: TestSuite(LaurentPolynomialRing(ZZ, 'u')).run() + sage: TestSuite(LaurentPolynomialRing(Zmod(2)['T'], 'u')).run() sage: TestSuite(LaurentPolynomialRing(Zmod(4)['T'], 'u')).run() """ if R.ngens() != 1: diff --git a/src/sage/rings/polynomial/laurent_polynomial_ring_base.py b/src/sage/rings/polynomial/laurent_polynomial_ring_base.py index 0c9022c492c..c10cbb219b0 100644 --- a/src/sage/rings/polynomial/laurent_polynomial_ring_base.py +++ b/src/sage/rings/polynomial/laurent_polynomial_ring_base.py @@ -162,11 +162,9 @@ def is_noetherian(self): EXAMPLES:: sage: LaurentPolynomialRing(QQ, 2, 'x').is_noetherian() - Traceback (most recent call last): - ... - NotImplementedError + True """ - raise NotImplementedError + return self.base_ring().is_noetherian() def construction(self): """ diff --git a/src/sage/rings/polynomial/multi_polynomial.pxd b/src/sage/rings/polynomial/multi_polynomial.pxd index 73bde26ab51..3f4fe16888c 100644 --- a/src/sage/rings/polynomial/multi_polynomial.pxd +++ b/src/sage/rings/polynomial/multi_polynomial.pxd @@ -1,4 +1,4 @@ -from .commutative_polynomial cimport CommutativePolynomial +from sage.rings.polynomial.commutative_polynomial cimport CommutativePolynomial cdef class MPolynomial(CommutativePolynomial): diff --git a/src/sage/rings/polynomial/polynomial_element.pxd b/src/sage/rings/polynomial/polynomial_element.pxd index b337919a807..9b8bf41fa06 100644 --- a/src/sage/rings/polynomial/polynomial_element.pxd +++ b/src/sage/rings/polynomial/polynomial_element.pxd @@ -2,8 +2,8 @@ from sage.structure.element import Element from sage.structure.element cimport Element, CommutativeAlgebraElement, ModuleElement from sage.structure.parent cimport Parent from sage.rings.integer cimport Integer -from .commutative_polynomial cimport CommutativePolynomial -from .polynomial_compiled cimport CompiledPolynomialFunction +from sage.rings.polynomial.commutative_polynomial cimport CommutativePolynomial +from sage.rings.polynomial.polynomial_compiled cimport CompiledPolynomialFunction cdef class Polynomial(CommutativePolynomial): diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index 8e9c4822a7b..5a480feae26 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -118,7 +118,7 @@ from sage.misc.derivative import multi_derivative from sage.arith.misc import sort_complex_numbers_for_display, power_mod, is_prime from sage.arith.functions import lcm -from . import polynomial_fateman +from sage.rings.polynomial import polynomial_fateman from sage.rings.ideal import is_Ideal from sage.rings.polynomial.polynomial_ring import is_PolynomialRing @@ -182,7 +182,7 @@ cpdef is_Polynomial(f) noexcept: return isinstance(f, Polynomial) -from .polynomial_compiled cimport CompiledPolynomialFunction +from sage.rings.polynomial.polynomial_compiled cimport CompiledPolynomialFunction from sage.rings.polynomial.polydict cimport ETuple @@ -11055,10 +11055,10 @@ cdef class Polynomial(CommutativePolynomial): sage: R. = Zmod(6)[] sage: p = 4*x + 3 sage: q = 5*x**2 + x + 2 + sage: q.divides(p) + False sage: p.divides(q) - Traceback (most recent call last): - ... - NotImplementedError: divisibility test only implemented for polynomials over an integral domain + False TESTS:: @@ -11081,16 +11081,24 @@ cdef class Polynomial(CommutativePolynomial): sage: q = (y^2-x^2) * z^2 + z + x-y sage: p.divides(q), p.divides(p*q) # needs sage.libs.singular (False, True) + sage: R. = Zmod(6)[] + sage: p = 4*x + 3 + sage: q = 2*x**2 + x + 2 + sage: p.divides(q) + Traceback (most recent call last): + ... + NotImplementedError: divisibility test only implemented for polynomials over an integral domain unless obvious non divisibility of leading terms """ - if not self.base_ring().is_integral_domain(): - raise NotImplementedError("divisibility test only implemented for polynomials over an integral domain") - - if p.is_zero(): return True # everything divides 0 - if self.is_zero(): return False # 0 only divides 0 + if p.is_zero(): + return True # everything divides 0 + if self.is_zero(): + return False # 0 only divides 0 try: - if self.is_unit(): return True # units divide everything + if self.is_unit(): + return True # units divide everything except NotImplementedError: - if self.is_one(): return True # if is_unit is not implemented + if self.is_one(): + return True # if is_unit is not implemented if self.degree() > p.degree(): return False @@ -11098,10 +11106,13 @@ cdef class Polynomial(CommutativePolynomial): if not self.leading_coefficient().divides(p.leading_coefficient()): return False + if not self.base_ring().is_integral_domain(): + raise NotImplementedError("divisibility test only implemented for polynomials over an integral domain unless obvious non divisibility of leading terms") + try: return (p % self).is_zero() # if quo_rem is defined except ArithmeticError: - return False # if division is not exact + return False def specialization(self, D=None, phi=None): r""" diff --git a/src/sage/rings/polynomial/polynomial_rational_flint.pyx b/src/sage/rings/polynomial/polynomial_rational_flint.pyx index 04eaefc9fed..d99f0d3b98c 100644 --- a/src/sage/rings/polynomial/polynomial_rational_flint.pyx +++ b/src/sage/rings/polynomial/polynomial_rational_flint.pyx @@ -222,7 +222,7 @@ cdef class Polynomial_rational_flint(Polynomial): cdef unsigned long n cdef Rational c cdef list L1 - cdef mpq_t * L2 + cdef fmpq_t q Polynomial.__init__(self, parent, is_gen=is_gen) @@ -253,14 +253,11 @@ cdef class Polynomial_rational_flint(Polynomial): L1 = [e if isinstance(e, Rational) else Rational(e) for e in x] n = len(x) sig_on() - L2 = check_allocarray(n, sizeof(mpq_t)) + fmpq_poly_fit_length(self._poly, n) for deg from 0 <= deg < n: - mpq_init(L2[deg]) - mpq_set(L2[deg], ( L1[deg]).value) - fmpq_poly_set_array_mpq(self._poly, L2, n) - for deg from 0 <= deg < n: - mpq_clear(L2[deg]) - sig_free(L2) + fmpq_init_set_readonly(q, ( L1[deg]).value) + fmpq_poly_set_coeff_fmpq(self._poly, deg, q) + fmpq_clear_readonly(q) sig_off() # deg = 0 @@ -435,6 +432,7 @@ cdef class Polynomial_rational_flint(Polynomial): utmost care. """ cdef bint do_sig = _do_sig(self._poly) + cdef fmpz_t tmpfz if isinstance(value, int): if do_sig: sig_str("FLINT exception") @@ -442,7 +440,9 @@ cdef class Polynomial_rational_flint(Polynomial): if do_sig: sig_off() elif isinstance(value, Integer): if do_sig: sig_str("FLINT exception") - fmpq_poly_set_coeff_mpz(self._poly, n, ( value).value) + fmpz_init_set_readonly(tmpfz, ( value).value) + fmpq_poly_set_coeff_fmpz(self._poly, n, tmpfz) + fmpz_clear_readonly(tmpfz) if do_sig: sig_off() elif isinstance(value, Rational): if do_sig: sig_str("FLINT exception") @@ -492,7 +492,7 @@ cdef class Polynomial_rational_flint(Polynomial): cdef Polynomial_rational_flint f cdef Rational r cdef fmpz_t tmpfz - cdef fmpq_t tmpfq + cdef fmpq_t tmpfq, tmpfq1 cdef RealBall arb_a, arb_z cdef ComplexBall acb_a, acb_z @@ -508,13 +508,23 @@ cdef class Polynomial_rational_flint(Polynomial): elif isinstance(a, Rational): r = Rational.__new__(Rational) sig_str("FLINT exception") - fmpq_poly_evaluate_mpq(r.value, self._poly, ( a).value) + fmpq_init_set_readonly(tmpfq, ( a).value) + fmpq_init(tmpfq1) + fmpq_poly_evaluate_fmpq(tmpfq1, self._poly, tmpfq) + fmpq_get_mpq(r.value, tmpfq1) + fmpq_clear(tmpfq1) + fmpq_clear_readonly(tmpfq) sig_off() return r elif isinstance(a, Integer): r = Rational.__new__(Rational) sig_str("FLINT exception") - fmpq_poly_evaluate_mpz(r.value, self._poly, ( a).value) + fmpz_init_set_readonly(tmpfz, ( a).value) + fmpq_init(tmpfq) + fmpq_poly_evaluate_fmpz(tmpfq, self._poly, tmpfz) + fmpq_get_mpq(r.value, tmpfq) + fmpq_clear(tmpfq) + fmpz_clear_readonly(tmpfz) sig_off() return r elif isinstance(a, int): @@ -1321,6 +1331,7 @@ cdef class Polynomial_rational_flint(Polynomial): """ cdef Polynomial_rational_flint res cdef bint do_sig + cdef fmpq_t tmpfq if right == 0: raise ZeroDivisionError("division by zero polynomial") @@ -1331,8 +1342,9 @@ cdef class Polynomial_rational_flint(Polynomial): do_sig = _do_sig(self._poly) if do_sig: sig_str("FLINT exception") - fmpq_poly_scalar_div_mpq(res._poly, self._poly, - ( QQ(right)).value) + fmpq_init_set_readonly(tmpfq, ( QQ(right)).value) + fmpq_poly_scalar_div_fmpq(res._poly, self._poly, tmpfq) + fmpq_clear_readonly(tmpfq) if do_sig: sig_off() return res diff --git a/src/sage/rings/polynomial/polynomial_real_mpfr_dense.pyx b/src/sage/rings/polynomial/polynomial_real_mpfr_dense.pyx index 15c65081cd9..8bd5bd00a67 100644 --- a/src/sage/rings/polynomial/polynomial_real_mpfr_dense.pyx +++ b/src/sage/rings/polynomial/polynomial_real_mpfr_dense.pyx @@ -30,7 +30,7 @@ from cpython.long cimport PyLong_AsLong from cpython.float cimport PyFloat_AS_DOUBLE from sage.structure.parent cimport Parent -from .polynomial_element cimport Polynomial, _dict_to_list +from sage.rings.polynomial.polynomial_element cimport Polynomial, _dict_to_list from sage.rings.real_mpfr cimport RealField_class, RealNumber from sage.rings.integer cimport Integer, smallInteger from sage.rings.rational cimport Rational diff --git a/src/sage/rings/polynomial/polynomial_zmod_flint.pyx b/src/sage/rings/polynomial/polynomial_zmod_flint.pyx index 6e7f7498329..3a66198d568 100644 --- a/src/sage/rings/polynomial/polynomial_zmod_flint.pyx +++ b/src/sage/rings/polynomial/polynomial_zmod_flint.pyx @@ -658,6 +658,11 @@ cdef class Polynomial_zmod_flint(Polynomial_template): ... NotImplementedError: square free factorization of polynomials over rings with composite characteristic is not implemented + :trac:`20003`:: + + sage: P. = GF(7)[] + sage: (6*x+3).squarefree_decomposition() + (6) * (x + 4) """ if not self.base_ring().is_field(): raise NotImplementedError("square free factorization of polynomials over rings with composite characteristic is not implemented") diff --git a/src/sage/rings/power_series_mpoly.pxd b/src/sage/rings/power_series_mpoly.pxd index d358ada1356..d8816e694b7 100644 --- a/src/sage/rings/power_series_mpoly.pxd +++ b/src/sage/rings/power_series_mpoly.pxd @@ -1,5 +1,5 @@ from sage.structure.element cimport ModuleElement -from .power_series_ring_element cimport PowerSeries +from sage.rings.power_series_ring_element cimport PowerSeries cdef class PowerSeries_mpoly(PowerSeries): cdef ModuleElement __f diff --git a/src/sage/rings/power_series_mpoly.pyx b/src/sage/rings/power_series_mpoly.pyx index fa62a7ef6d6..d11eec97269 100644 --- a/src/sage/rings/power_series_mpoly.pyx +++ b/src/sage/rings/power_series_mpoly.pyx @@ -1,10 +1,10 @@ # NOT ready to be used -- possibly should be deleted. -from .power_series_ring_element cimport PowerSeries +from sage.rings.power_series_ring_element cimport PowerSeries from sage.structure.element cimport Element -from .infinity import infinity -from .polynomial.multi_polynomial_ring_base import is_MPolynomialRing -from . import power_series_poly +from sage.rings.infinity import infinity +from sage.rings.polynomial.multi_polynomial_ring_base import is_MPolynomialRing +from sage.rings import power_series_poly cdef class PowerSeries_mpoly(PowerSeries): diff --git a/src/sage/rings/power_series_pari.pxd b/src/sage/rings/power_series_pari.pxd index fadf7f0fd08..35b37929c33 100644 --- a/src/sage/rings/power_series_pari.pxd +++ b/src/sage/rings/power_series_pari.pxd @@ -1,5 +1,5 @@ from cypari2.gen cimport Gen as pari_gen -from .power_series_ring_element cimport PowerSeries +from sage.rings.power_series_ring_element cimport PowerSeries cdef class PowerSeries_pari(PowerSeries): cdef pari_gen g diff --git a/src/sage/rings/power_series_poly.pxd b/src/sage/rings/power_series_poly.pxd index 80c441798a1..e37e1fb26cf 100644 --- a/src/sage/rings/power_series_poly.pxd +++ b/src/sage/rings/power_series_poly.pxd @@ -1,4 +1,4 @@ -from .power_series_ring_element cimport PowerSeries +from sage.rings.power_series_ring_element cimport PowerSeries from sage.rings.polynomial.polynomial_element cimport Polynomial from sage.categories.action cimport Action diff --git a/src/sage/rings/power_series_poly.pyx b/src/sage/rings/power_series_poly.pyx index 519e13c1226..c651fe03d02 100644 --- a/src/sage/rings/power_series_poly.pyx +++ b/src/sage/rings/power_series_poly.pyx @@ -4,9 +4,9 @@ Power Series Methods The class ``PowerSeries_poly`` provides additional methods for univariate power series. """ -from .power_series_ring_element cimport PowerSeries +from sage.rings.power_series_ring_element cimport PowerSeries from sage.structure.element cimport Element -from .infinity import infinity +from sage.rings.infinity import infinity from sage.libs.pari.all import pari_gen, PariError diff --git a/src/sage/rings/power_series_ring.py b/src/sage/rings/power_series_ring.py index b43306adb36..0349bfbe373 100644 --- a/src/sage/rings/power_series_ring.py +++ b/src/sage/rings/power_series_ring.py @@ -134,34 +134,36 @@ """ -from . import power_series_poly -from . import power_series_mpoly -from .power_series_pari import PowerSeries_pari -from . import power_series_ring_element - -from sage.rings.polynomial.polynomial_ring import is_PolynomialRing -from sage.rings.polynomial.multi_polynomial_ring_base import is_MPolynomialRing -from .polynomial.polynomial_ring_constructor import PolynomialRing -from . import laurent_series_ring -from . import laurent_series_ring_element -from . import integer -from . import ring -from .infinity import infinity +import sage.categories.commutative_rings as commutative_rings import sage.misc.latex as latex -from sage.structure.nonexact import Nonexact - from sage.interfaces.abc import MagmaElement -from sage.rings.fraction_field_element import FractionFieldElement from sage.misc.sage_eval import sage_eval - -from sage.structure.unique_representation import UniqueRepresentation +from sage.rings import ( + integer, + laurent_series_ring, + laurent_series_ring_element, + power_series_mpoly, + power_series_poly, + power_series_ring_element, + ring, +) +from sage.rings.fraction_field_element import FractionFieldElement +from sage.rings.infinity import infinity +from sage.rings.polynomial.multi_polynomial_ring_base import is_MPolynomialRing +from sage.rings.polynomial.polynomial_ring import is_PolynomialRing +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing +from sage.rings.power_series_pari import PowerSeries_pari from sage.structure.category_object import normalize_names -from sage.structure.element import parent, Expression -import sage.categories.commutative_rings as commutative_rings +from sage.structure.element import Expression, parent +from sage.structure.nonexact import Nonexact +from sage.structure.unique_representation import UniqueRepresentation + _CommutativeRings = commutative_rings.CommutativeRings() import sage.categories.integral_domains as integral_domains + _IntegralDomains = integral_domains.IntegralDomains() import sage.categories.fields as fields + _Fields = fields.Fields() from sage.categories.complete_discrete_valuation import CompleteDiscreteValuationRings @@ -535,7 +537,9 @@ def __init__(self, base_ring, name=None, default_prec=None, sparse=False, ValueError: default_prec (= -5) must be non-negative """ - from sage.rings.finite_rings.finite_field_pari_ffelt import FiniteField_pari_ffelt + from sage.rings.finite_rings.finite_field_pari_ffelt import ( + FiniteField_pari_ffelt, + ) if implementation is None: if isinstance(base_ring, FiniteField_pari_ffelt): diff --git a/src/sage/rings/power_series_ring_element.pyx b/src/sage/rings/power_series_ring_element.pyx index b2ce51e09b3..8f570db774a 100644 --- a/src/sage/rings/power_series_ring_element.pyx +++ b/src/sage/rings/power_series_ring_element.pyx @@ -96,7 +96,7 @@ With power series the behavior is the same. # **************************************************************************** from cpython.object cimport Py_EQ, Py_NE -from .infinity import infinity, is_Infinite +from sage.rings.infinity import infinity, is_Infinite from sage.rings.rational_field import QQ @@ -104,7 +104,7 @@ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing import sage.misc.misc import sage.arith.all as arith import sage.misc.latex -from .integer import Integer +from sage.rings.integer import Integer from sage.rings.finite_rings.integer_mod_ring import IntegerModRing from sage.categories.fields import Fields diff --git a/src/sage/rings/qqbar.py b/src/sage/rings/qqbar.py index 50f0fb393b8..ad0bf1478d9 100644 --- a/src/sage/rings/qqbar.py +++ b/src/sage/rings/qqbar.py @@ -557,36 +557,52 @@ import itertools import operator -import sage.rings.ring import sage.rings.abc import sage.rings.number_field.number_field_base -from sage.misc.fast_methods import Singleton +import sage.rings.ring +from sage.arith.misc import factor +from sage.categories.action import Action from sage.misc.cachefunc import cached_method +from sage.misc.fast_methods import Singleton from sage.misc.lazy_string import lazy_string from sage.misc.misc import increase_recursion_limit -from sage.structure.coerce import parent_is_numerical, parent_is_real_numerical -from sage.structure.sage_object import SageObject -from sage.structure.richcmp import (richcmp, richcmp_method, - rich_to_bool, richcmp_not_equal, - op_EQ, op_NE, op_GT) -from sage.rings.real_arb import RealBallField -from sage.rings.real_mpfr import RR -from sage.rings.real_mpfi import RealIntervalField, RIF, is_RealIntervalFieldElement, RealIntervalField_class +from sage.rings import infinity from sage.rings.cc import CC from sage.rings.cif import CIF -from sage.rings.complex_interval_field import ComplexIntervalField from sage.rings.complex_interval import is_ComplexIntervalFieldElement -from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing -from sage.rings.polynomial.polynomial_element import Polynomial +from sage.rings.complex_interval_field import ComplexIntervalField from sage.rings.integer_ring import ZZ +from sage.rings.number_field.number_field import ( + CyclotomicField, + GaussianField, + NumberField, +) +from sage.rings.number_field.number_field_element_quadratic import ( + NumberFieldElement_gaussian, +) +from sage.rings.polynomial.polynomial_element import Polynomial +from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.rational_field import QQ -from sage.rings.number_field.number_field import NumberField, GaussianField, CyclotomicField -from sage.rings.number_field.number_field_element_quadratic import NumberFieldElement_gaussian -from sage.arith.misc import factor -from . import infinity -from sage.categories.action import Action - +from sage.rings.real_arb import RealBallField +from sage.rings.real_mpfi import ( + RIF, + RealIntervalField, + RealIntervalField_class, + is_RealIntervalFieldElement, +) +from sage.rings.real_mpfr import RR +from sage.structure.coerce import parent_is_numerical, parent_is_real_numerical from sage.structure.global_options import GlobalOptions +from sage.structure.richcmp import ( + op_EQ, + op_GT, + op_NE, + rich_to_bool, + richcmp, + richcmp_method, + richcmp_not_equal, +) +from sage.structure.sage_object import SageObject class AlgebraicField_common(sage.rings.abc.AlgebraicField_common): @@ -888,8 +904,8 @@ def _factor_multivariate_polynomial(self, f, proof=True): 1 """ - from sage.structure.factorization import Factorization from sage.interfaces.singular import singular + from sage.structure.factorization import Factorization if f.degree() == 0: return Factorization([], f.lc()) @@ -1973,8 +1989,8 @@ def random_element(self, poly_degree=2, *args, **kwds): sage: v # random (0.4694381338921299?, -0.500000000000000? + 0.866025403784439?*I) """ - from sage.rings.integer_ring import ZZ import sage.misc.prandom + from sage.rings.integer_ring import ZZ try: poly_degree = ZZ(poly_degree) except TypeError: @@ -3448,7 +3464,7 @@ def __call__(self, elt): return elt.field_element_value() gen = elt.generator() sp = gen.super_poly(self) - assert (not (sp is None)) + assert (sp is not None) return self._field(elt.field_element_value().polynomial()(sp)) @@ -5324,7 +5340,7 @@ def multiplicative_order(self): sage: QQbar(3/5 + 4/5*I).multiplicative_order() +Infinity """ - if not (1 in CIF(self).norm()): + if 1 not in CIF(self).norm(): return infinity.infinity if self.norm() != 1: return infinity.infinity @@ -5808,7 +5824,7 @@ def multiplicative_order(self): sage: AA(5).sqrt().multiplicative_order() +Infinity """ - if not (1 in RIF(self).abs()): + if 1 not in RIF(self).abs(): return infinity.infinity if self == 1: return 1 @@ -7395,7 +7411,7 @@ def _complex_refine_interval(self, interval, prec): # Give up and fall back on root isolation. return self._complex_isolate_interval(interval, prec) - if not (zero in slope): + if zero not in slope: new_range = center - val / slope interval = interval.intersection(new_range) @@ -8596,7 +8612,6 @@ def exactify(self): 1000 sage: sys.setrecursionlimit(old_recursion_limit) """ - import sys with increase_recursion_limit(10): left = self._left right = self._right @@ -8825,5 +8840,6 @@ def get_AA_golden_ratio(): # Support Python's numbers abstract base class import numbers + numbers.Real.register(AlgebraicReal) numbers.Complex.register(AlgebraicNumber) diff --git a/src/sage/rings/quotient_ring.py b/src/sage/rings/quotient_ring.py index 7dc4e0803c8..a6a0a8ce7f8 100644 --- a/src/sage/rings/quotient_ring.py +++ b/src/sage/rings/quotient_ring.py @@ -112,16 +112,15 @@ # (at your option) any later version. # http://www.gnu.org/licenses/ # **************************************************************************** +import sage.interfaces.abc import sage.misc.latex as latex -from . import ring, ideal, quotient_ring_element -from sage.structure.category_object import normalize_names -from sage.structure.richcmp import richcmp_method, richcmp import sage.structure.parent_gens -from sage.misc.cachefunc import cached_method -from sage.categories.rings import Rings from sage.categories.commutative_rings import CommutativeRings - -import sage.interfaces.abc +from sage.categories.rings import Rings +from sage.misc.cachefunc import cached_method +from sage.rings import ideal, quotient_ring_element, ring +from sage.structure.category_object import normalize_names +from sage.structure.richcmp import richcmp, richcmp_method _Rings = Rings() _CommRings = CommutativeRings() @@ -302,7 +301,9 @@ def QuotientRing(R, I, names=None, **kwds): else: names = normalize_names(R.ngens(), names) if kwds.get('implementation') == 'pbori': - from sage.rings.polynomial.polynomial_ring_constructor import BooleanPolynomialRing_constructor as BooleanPolynomialRing + from sage.rings.polynomial.polynomial_ring_constructor import ( + BooleanPolynomialRing_constructor as BooleanPolynomialRing, + ) kwds.pop('implementation') return BooleanPolynomialRing(R.ngens(), names=names, **kwds) # workaround to silence warning from #34806 @@ -538,6 +539,7 @@ def construction(self): Finite Field of size 5 """ from sage.categories.pushout import QuotientFunctor + # Is there a better generic way to distinguish between things like Z/pZ as a field and Z/pZ as a ring? from sage.rings.ring import Field try: @@ -1006,7 +1008,9 @@ def ideal(self, *gens, **kwds): """ if len(gens) == 1: gens = gens[0] - from sage.rings.polynomial.multi_polynomial_ring_base import MPolynomialRing_base + from sage.rings.polynomial.multi_polynomial_ring_base import ( + MPolynomialRing_base, + ) if not (isinstance(self.__R, MPolynomialRing_base) and self.__R._has_singular): # pass through return super().ideal(gens, **kwds) @@ -1019,7 +1023,9 @@ def ideal(self, *gens, **kwds): global MPolynomialIdeal_quotient if MPolynomialIdeal_quotient is None: - from sage.rings.polynomial.multi_polynomial_ideal import MPolynomialIdeal_quotient + from sage.rings.polynomial.multi_polynomial_ideal import ( + MPolynomialIdeal_quotient, + ) return MPolynomialIdeal_quotient(self, gens, **kwds) def _element_constructor_(self, x, coerce=True): @@ -1276,7 +1282,7 @@ def _singular_(self, singular=None): try: Q = self.__singular - if not (Q.parent() is singular): + if Q.parent() is not singular: raise ValueError Q._check_valid() return Q diff --git a/src/sage/rings/rational.pyx b/src/sage/rings/rational.pyx index 0b398428006..63ad2b36bee 100644 --- a/src/sage/rings/rational.pyx +++ b/src/sage/rings/rational.pyx @@ -72,9 +72,9 @@ from sage.structure.richcmp cimport rich_to_bool_sgn import sage.rings.rational_field cimport sage.rings.integer as integer -from .integer cimport Integer +from sage.rings.integer cimport Integer -from .integer_ring import ZZ +from sage.rings.integer_ring import ZZ from sage.structure.coerce cimport is_numpy_type diff --git a/src/sage/rings/rational_field.py b/src/sage/rings/rational_field.py index 7296d227097..341c0d536d0 100644 --- a/src/sage/rings/rational_field.py +++ b/src/sage/rings/rational_field.py @@ -54,16 +54,17 @@ """ -from .rational import Rational -from .integer import Integer +from sage.rings.integer import Integer +from sage.rings.rational import Rational ZZ = None -from sage.structure.parent_gens import ParentWithGens -from sage.structure.sequence import Sequence import sage.rings.number_field.number_field_base as number_field_base from sage.misc.fast_methods import Singleton from sage.misc.superseded import deprecated_function_alias +from sage.structure.parent_gens import ParentWithGens +from sage.structure.sequence import Sequence + class RationalField(Singleton, number_field_base.NumberField): r""" @@ -317,6 +318,7 @@ def construction(self): (FractionField, Integer Ring) """ from sage.categories.pushout import FractionField + from . import integer_ring return FractionField(), integer_ring.ZZ @@ -446,8 +448,8 @@ def __truediv__(self, I): sage: QQ / ZZ # needs sage.modules Q/Z """ - from sage.rings.ideal import Ideal_generic from sage.groups.additive_abelian.qmodnz import QmodnZ + from sage.rings.ideal import Ideal_generic if I is ZZ: return QmodnZ(1) elif isinstance(I, Ideal_generic) and I.base_ring() is ZZ: @@ -834,15 +836,15 @@ def hilbert_symbol_negative_at_S(self, S, b, check=True): - Simon Brandhorst, Juanita Duque, Anna Haensch, Manami Roy, Sandi Rudzinski (10-24-2017) """ + from sage.arith.misc import hilbert_symbol, is_prime + from sage.matrix.constructor import matrix + from sage.modules.free_module import VectorSpace from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF from sage.rings.padics.factory import Qp - from sage.modules.free_module import VectorSpace - from sage.matrix.constructor import matrix from sage.sets.primes import Primes - from sage.arith.misc import hilbert_symbol, is_prime # input checks - if not type(S) is list: + if type(S) is not list: raise TypeError("first argument must be a list or integer") # -1 is used for the infinite place infty = -1 @@ -1375,8 +1377,9 @@ def selmer_group_iterator(self, S, m, proof=True): """ KSgens, ords = self.selmer_generators(S=S, m=m, proof=proof, orders=True) one = self.one() - from sage.misc.misc_c import prod from itertools import product + + from sage.misc.misc_c import prod for ev in product(*[range(o) for o in ords]): yield prod((p**e for p,e in zip(KSgens, ev)), one) @@ -1490,8 +1493,8 @@ def quadratic_defect(self, a, p, check=True): sage: QQ.quadratic_defect(5, 5) 1 """ - from sage.rings.infinity import Infinity from sage.arith.misc import legendre_symbol + from sage.rings.infinity import Infinity if a not in self: raise TypeError(str(a) + " must be an element of " + str(self)) if p.parent() == ZZ.ideal_monoid(): @@ -1596,8 +1599,8 @@ def _sympy_(self): sage: QQ._sympy_() # needs sympy Rationals """ - from sympy import Rationals from sage.interfaces.sympy import sympy_init + from sympy import Rationals sympy_init() return Rationals diff --git a/src/sage/rings/real_arb.pyx b/src/sage/rings/real_arb.pyx index 17961ac36b2..8509b19cc66 100644 --- a/src/sage/rings/real_arb.pyx +++ b/src/sage/rings/real_arb.pyx @@ -898,7 +898,7 @@ class RealBallField(UniqueRepresentation, sage.rings.abc.RealBallField): sage: RBF.gamma(5) 24.00000000000000 sage: RBF.gamma(10**20) - [+/- ...e+1956570552410610660600] + [1.932849514310098...+1956570551809674817225 +/- ...] sage: RBF.gamma(1/3) [2.678938534707747 +/- ...e-16] sage: RBF.gamma(-5) @@ -1102,7 +1102,7 @@ class RealBallField(UniqueRepresentation, sage.rings.abc.RealBallField): 15.00000000000000, 48.00000000000000] sage: RBF.double_factorial(2**20) - [1.4483729903e+2928836 +/- ...e+2928825] + [1.448372990...e+2928836 +/- ...] sage: RBF.double_factorial(2**1000) Traceback (most recent call last): ... diff --git a/src/sage/rings/real_double_element_gsl.pxd b/src/sage/rings/real_double_element_gsl.pxd index 39c36999ec4..1762c5f944b 100644 --- a/src/sage/rings/real_double_element_gsl.pxd +++ b/src/sage/rings/real_double_element_gsl.pxd @@ -1,4 +1,4 @@ -from .real_double cimport RealDoubleElement +from sage.rings.real_double cimport RealDoubleElement cdef class RealDoubleElement_gsl(RealDoubleElement): diff --git a/src/sage/rings/real_mpfi.pxd b/src/sage/rings/real_mpfi.pxd index 32332d81e3e..f9fc7a1969c 100644 --- a/src/sage/rings/real_mpfi.pxd +++ b/src/sage/rings/real_mpfi.pxd @@ -5,8 +5,8 @@ from sage.rings.ring cimport Field cimport sage.rings.abc from sage.structure.element cimport RingElement -from .rational cimport Rational -from .real_mpfr cimport RealField_class +from sage.rings.rational cimport Rational +from sage.rings.real_mpfr cimport RealField_class cdef class RealIntervalFieldElement(RingElement) # forward decl diff --git a/src/sage/rings/real_mpfi.pyx b/src/sage/rings/real_mpfi.pyx index 6e389b53ac2..58e3d8de737 100644 --- a/src/sage/rings/real_mpfi.pyx +++ b/src/sage/rings/real_mpfi.pyx @@ -269,11 +269,11 @@ from sage.structure.element cimport have_same_parent from sage.structure.parent cimport Parent from sage.structure.richcmp cimport richcmp -from .convert.mpfi cimport mpfi_set_sage -from .real_mpfr cimport RealField_class, RealNumber, RealField -from .integer cimport Integer -from .integer_ring import ZZ -from .rational_field import QQ +from sage.rings.convert.mpfi cimport mpfi_set_sage +from sage.rings.real_mpfr cimport RealField_class, RealNumber, RealField +from sage.rings.integer cimport Integer +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ cimport sage.rings.abc diff --git a/src/sage/rings/real_mpfr.pyx b/src/sage/rings/real_mpfr.pyx index 4a091fd9191..9117dfcd4ce 100644 --- a/src/sage/rings/real_mpfr.pyx +++ b/src/sage/rings/real_mpfr.pyx @@ -148,12 +148,12 @@ from cypari2.stack cimport new_gen from sage.libs.mpmath.utils cimport mpfr_to_mpfval -from .integer cimport Integer -from .rational cimport Rational +from sage.rings.integer cimport Integer +from sage.rings.rational cimport Rational from sage.categories.map cimport Map -from .real_double cimport RealDoubleElement +from sage.rings.real_double cimport RealDoubleElement import sage.rings.rational_field diff --git a/src/sage/rings/sum_of_squares.pyx b/src/sage/rings/sum_of_squares.pyx index e6ec62dc7f1..04be29e0fdc 100644 --- a/src/sage/rings/sum_of_squares.pyx +++ b/src/sage/rings/sum_of_squares.pyx @@ -22,7 +22,7 @@ from libc.math cimport sqrt from cysignals.signals cimport sig_on, sig_off cimport sage.rings.integer as integer -from . import integer +from sage.rings import integer cdef int two_squares_c(uint_fast32_t n, uint_fast32_t res[2]) noexcept: r""" diff --git a/src/sage/sat/boolean_polynomials.py b/src/sage/sat/boolean_polynomials.py index 80b1a13d89c..32753175384 100644 --- a/src/sage/sat/boolean_polynomials.py +++ b/src/sage/sat/boolean_polynomials.py @@ -1,3 +1,4 @@ +# sage.doctest: optional - pycryptosat, needs sage.modules sage.rings.polynomial.pbori """ SAT Functions for Boolean Polynomials @@ -71,7 +72,7 @@ def solve(F, converter=None, solver=None, n=1, target_variables=None, **kwds): We construct a very small-scale AES system of equations:: - sage: sr = mq.SR(1,1,1,4,gf2=True,polybori=True) + sage: sr = mq.SR(1, 1, 1, 4, gf2=True, polybori=True) sage: while True: # workaround (see :trac:`31891`) ....: try: ....: F, s = sr.polynomial_system() @@ -81,66 +82,70 @@ def solve(F, converter=None, solver=None, n=1, target_variables=None, **kwds): and pass it to a SAT solver:: - sage: from sage.sat.boolean_polynomials import solve as solve_sat # optional - pycryptosat - sage: s = solve_sat(F) # optional - pycryptosat - sage: F.subs(s[0]) # optional - pycryptosat + sage: from sage.sat.boolean_polynomials import solve as solve_sat + sage: s = solve_sat(F) + sage: F.subs(s[0]) Polynomial Sequence with 36 Polynomials in 0 Variables This time we pass a few options through to the converter and the solver:: - sage: s = solve_sat(F, c_max_vars_sparse=4, c_cutting_number=8) # optional - pycryptosat - sage: F.subs(s[0]) # optional - pycryptosat + sage: s = solve_sat(F, c_max_vars_sparse=4, c_cutting_number=8) + sage: F.subs(s[0]) Polynomial Sequence with 36 Polynomials in 0 Variables - We construct a very simple system with three solutions and ask for a specific number of solutions:: + We construct a very simple system with three solutions + and ask for a specific number of solutions:: - sage: B. = BooleanPolynomialRing() # optional - pycryptosat - sage: f = a*b # optional - pycryptosat - sage: l = solve_sat([f],n=1) # optional - pycryptosat - sage: len(l) == 1, f.subs(l[0]) # optional - pycryptosat + sage: B. = BooleanPolynomialRing() + sage: f = a*b + sage: l = solve_sat([f],n=1) + sage: len(l) == 1, f.subs(l[0]) (True, 0) - sage: l = solve_sat([a*b],n=2) # optional - pycryptosat - sage: len(l) == 2, f.subs(l[0]), f.subs(l[1]) # optional - pycryptosat + sage: l = solve_sat([a*b],n=2) + sage: len(l) == 2, f.subs(l[0]), f.subs(l[1]) (True, 0, 0) - sage: sorted((d[a], d[b]) for d in solve_sat([a*b],n=3)) # optional - pycryptosat + sage: sorted((d[a], d[b]) for d in solve_sat([a*b], n=3)) [(0, 0), (0, 1), (1, 0)] - sage: sorted((d[a], d[b]) for d in solve_sat([a*b],n=4)) # optional - pycryptosat + sage: sorted((d[a], d[b]) for d in solve_sat([a*b], n=4)) [(0, 0), (0, 1), (1, 0)] - sage: sorted((d[a], d[b]) for d in solve_sat([a*b],n=infinity)) # optional - pycryptosat + sage: sorted((d[a], d[b]) for d in solve_sat([a*b], n=infinity)) [(0, 0), (0, 1), (1, 0)] In the next example we see how the ``target_variables`` parameter works:: - sage: from sage.sat.boolean_polynomials import solve as solve_sat # optional - pycryptosat - sage: R. = BooleanPolynomialRing() # optional - pycryptosat - sage: F = [a+b,a+c+d] # optional - pycryptosat + sage: from sage.sat.boolean_polynomials import solve as solve_sat + sage: R. = BooleanPolynomialRing() + sage: F = [a + b, a + c + d] First the normal use case:: - sage: sorted((D[a], D[b], D[c], D[d]) for D in solve_sat(F,n=infinity)) # optional - pycryptosat + sage: sorted((D[a], D[b], D[c], D[d]) + ....: for D in solve_sat(F, n=infinity)) [(0, 0, 0, 0), (0, 0, 1, 1), (1, 1, 0, 1), (1, 1, 1, 0)] Now we are only interested in the solutions of the variables a and b:: - sage: solve_sat(F,n=infinity,target_variables=[a,b]) # optional - pycryptosat + sage: solve_sat(F, n=infinity, target_variables=[a,b]) [{b: 0, a: 0}, {b: 1, a: 1}] Here, we generate and solve the cubic equations of the AES SBox (see :trac:`26676`):: - sage: from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence # optional - pycryptosat, long time - sage: from sage.sat.boolean_polynomials import solve as solve_sat # optional - pycryptosat, long time - sage: sr = sage.crypto.mq.SR(1, 4, 4, 8, allow_zero_inversions = True) # optional - pycryptosat, long time - sage: sb = sr.sbox() # optional - pycryptosat, long time - sage: eqs = sb.polynomials(degree = 3) # optional - pycryptosat, long time - sage: eqs = PolynomialSequence(eqs) # optional - pycryptosat, long time - sage: variables = map(str, eqs.variables()) # optional - pycryptosat, long time - sage: variables = ",".join(variables) # optional - pycryptosat, long time - sage: R = BooleanPolynomialRing(16, variables) # optional - pycryptosat, long time - sage: eqs = [R(eq) for eq in eqs] # optional - pycryptosat, long time - sage: sls_aes = solve_sat(eqs, n = infinity) # optional - pycryptosat, long time - sage: len(sls_aes) # optional - pycryptosat, long time + sage: # long time + sage: from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence + sage: from sage.sat.boolean_polynomials import solve as solve_sat + sage: sr = sage.crypto.mq.SR(1, 4, 4, 8, + ....: allow_zero_inversions=True) + sage: sb = sr.sbox() + sage: eqs = sb.polynomials(degree=3) + sage: eqs = PolynomialSequence(eqs) + sage: variables = map(str, eqs.variables()) + sage: variables = ",".join(variables) + sage: R = BooleanPolynomialRing(16, variables) + sage: eqs = [R(eq) for eq in eqs] + sage: sls_aes = solve_sat(eqs, n=infinity) + sage: len(sls_aes) 256 TESTS: @@ -148,7 +153,7 @@ def solve(F, converter=None, solver=None, n=1, target_variables=None, **kwds): Test that :trac:`26676` is fixed:: sage: varl = ['k{0}'.format(p) for p in range(29)] - sage: B = BooleanPolynomialRing(names = varl) + sage: B = BooleanPolynomialRing(names=varl) sage: B.inject_variables(verbose=False) sage: keqs = [ ....: k0 + k6 + 1, @@ -162,7 +167,7 @@ def solve(F, converter=None, solver=None, n=1, target_variables=None, **kwds): ....: k9 + k28, ....: k11 + k20] sage: from sage.sat.boolean_polynomials import solve as solve_sat - sage: solve_sat(keqs, n=1, solver=SAT('cryptominisat')) # optional - pycryptosat + sage: solve_sat(keqs, n=1, solver=SAT('cryptominisat')) [{k28: 0, k26: 1, k24: 0, @@ -187,7 +192,7 @@ def solve(F, converter=None, solver=None, n=1, target_variables=None, **kwds): k2: 0, k1: 0, k0: 0}] - sage: solve_sat(keqs, n=1, solver=SAT('picosat')) # optional - pycosat + sage: solve_sat(keqs, n=1, solver=SAT('picosat')) # optional - pycosat [{k28: 0, k26: 1, k24: 0, @@ -336,16 +341,16 @@ def learn(F, converter=None, solver=None, max_learnt_length=3, interreduction=Fa EXAMPLES:: - sage: from sage.sat.boolean_polynomials import learn as learn_sat # optional - pycryptosat + sage: from sage.sat.boolean_polynomials import learn as learn_sat We construct a simple system and solve it:: - sage: set_random_seed(2300) # optional - pycryptosat - sage: sr = mq.SR(1,2,2,4,gf2=True,polybori=True) # optional - pycryptosat - sage: F,s = sr.polynomial_system() # optional - pycryptosat - sage: H = learn_sat(F) # optional - pycryptosat - sage: H[-1] # optional - pycryptosat - k033 + 1 + sage: set_random_seed(2300) + sage: sr = mq.SR(1, 2, 2, 4, gf2=True, polybori=True) + sage: F,s = sr.polynomial_system() + sage: H = learn_sat(F) + sage: H[-1] + k033 + 1 """ try: len(F) diff --git a/src/sage/sat/converters/__init__.py b/src/sage/sat/converters/__init__.py index 70e0cdfdfaa..bb7b60bbb9c 100644 --- a/src/sage/sat/converters/__init__.py +++ b/src/sage/sat/converters/__init__.py @@ -1,2 +1,5 @@ +from sage.misc.lazy_import import lazy_import + from .anf2cnf import ANF2CNFConverter -from sage.rings.polynomial.pbori.cnf import CNFEncoder as PolyBoRiCNFEncoder + +lazy_import('sage.rings.polynomial.pbori.cnf', 'CNFEncoder', as_='PolyBoRiCNFEncoder') diff --git a/src/sage/sat/converters/polybori.py b/src/sage/sat/converters/polybori.py index ca39def12c1..49da6f1819c 100644 --- a/src/sage/sat/converters/polybori.py +++ b/src/sage/sat/converters/polybori.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.rings.polynomial.pbori """ An ANF to CNF Converter using a Dense/Sparse Strategy diff --git a/src/sage/sat/solvers/cryptominisat.py b/src/sage/sat/solvers/cryptominisat.py index d2a8ae9e5a6..82f1ffd9086 100644 --- a/src/sage/sat/solvers/cryptominisat.py +++ b/src/sage/sat/solvers/cryptominisat.py @@ -182,12 +182,13 @@ def __call__(self, assumptions=None): EXAMPLES:: + sage: # optional - pycryptosat sage: from sage.sat.solvers.cryptominisat import CryptoMiniSat - sage: solver = CryptoMiniSat() # optional - pycryptosat - sage: solver.add_clause((1,2)) # optional - pycryptosat - sage: solver.add_clause((-1,2)) # optional - pycryptosat - sage: solver.add_clause((-1,-2)) # optional - pycryptosat - sage: solver() # optional - pycryptosat + sage: solver = CryptoMiniSat() + sage: solver.add_clause((1,2)) + sage: solver.add_clause((-1,2)) + sage: solver.add_clause((-1,-2)) + sage: solver() (None, False, True) sage: solver.add_clause((1,-2)) # optional - pycryptosat @@ -231,23 +232,25 @@ def clauses(self, filename=None): EXAMPLES:: + sage: # optional - pycryptosat sage: from sage.sat.solvers import CryptoMiniSat - sage: solver = CryptoMiniSat() # optional - pycryptosat - sage: solver.add_clause((1,2,3,4,5,6,7,8,-9)) # optional - pycryptosat - sage: solver.add_xor_clause((1,2,3,4,5,6,7,8,9), rhs=True) # optional - pycryptosat - sage: solver.clauses() # optional - pycryptosat + sage: solver = CryptoMiniSat() + sage: solver.add_clause((1,2,3,4,5,6,7,8,-9)) + sage: solver.add_xor_clause((1,2,3,4,5,6,7,8,9), rhs=True) + sage: solver.clauses() [((1, 2, 3, 4, 5, 6, 7, 8, -9), False, None), ((1, 2, 3, 4, 5, 6, 7, 8, 9), True, True)] DIMACS format output:: + sage: # optional - pycryptosat sage: from sage.sat.solvers import CryptoMiniSat - sage: solver = CryptoMiniSat() # optional - pycryptosat - sage: solver.add_clause((1, 2, 4)) # optional - pycryptosat - sage: solver.add_clause((1, 2, -4)) # optional - pycryptosat - sage: fn = tmp_filename() # optional - pycryptosat - sage: solver.clauses(fn) # optional - pycryptosat - sage: print(open(fn).read()) # optional - pycryptosat + sage: solver = CryptoMiniSat() + sage: solver.add_clause((1, 2, 4)) + sage: solver.add_clause((1, 2, -4)) + sage: fn = tmp_filename() + sage: solver.clauses(fn) + sage: print(open(fn).read()) p cnf 4 2 1 2 4 0 1 2 -4 0 diff --git a/src/sage/sat/solvers/dimacs.py b/src/sage/sat/solvers/dimacs.py index cfe3c7cd4ed..51e81a925a1 100644 --- a/src/sage/sat/solvers/dimacs.py +++ b/src/sage/sat/solvers/dimacs.py @@ -490,14 +490,14 @@ def __call__(self, assumptions=None): TESTS:: sage: from sage.sat.boolean_polynomials import solve as solve_sat - sage: sr = mq.SR(1,1,1,4,gf2=True,polybori=True) - sage: while True: # workaround (see :trac:`31891`) + sage: sr = mq.SR(1, 1, 1, 4, gf2=True, polybori=True) # needs sage.rings.finite_rings sage.rings.polynomial.pbori + sage: while True: # workaround (see :trac:`31891`) # needs sage.rings.finite_rings sage.rings.polynomial.pbori ....: try: ....: F, s = sr.polynomial_system() ....: break ....: except ZeroDivisionError: ....: pass - sage: solve_sat(F, solver=sage.sat.solvers.RSat) # optional - RSat + sage: solve_sat(F, solver=sage.sat.solvers.RSat) # optional - rsat, needs sage.rings.finite_rings sage.rings.polynomial.pbori """ if assumptions is not None: diff --git a/src/sage/sat/solvers/picosat.py b/src/sage/sat/solvers/picosat.py index a1a80e71794..a88f69da883 100644 --- a/src/sage/sat/solvers/picosat.py +++ b/src/sage/sat/solvers/picosat.py @@ -147,12 +147,13 @@ def __call__(self, assumptions=None): EXAMPLES:: + sage: # optional - pycosat sage: from sage.sat.solvers.picosat import PicoSAT - sage: solver = PicoSAT() # optional - pycosat - sage: solver.add_clause((1,2)) # optional - pycosat - sage: solver.add_clause((-1,2)) # optional - pycosat - sage: solver.add_clause((-1,-2)) # optional - pycosat - sage: solver() # optional - pycosat + sage: solver = PicoSAT() + sage: solver.add_clause((1,2)) + sage: solver.add_clause((-1,2)) + sage: solver.add_clause((-1,-2)) + sage: solver() (None, False, True) sage: solver.add_clause((1,-2)) # optional - pycosat @@ -207,13 +208,14 @@ def clauses(self, filename=None): DIMACS format output:: + sage: # optional - pycosat sage: from sage.sat.solvers.picosat import PicoSAT - sage: solver = PicoSAT() # optional - pycosat - sage: solver.add_clause((1, 2, 4)) # optional - pycosat - sage: solver.add_clause((1, 2, -4)) # optional - pycosat - sage: fn = tmp_filename() # optional - pycosat - sage: solver.clauses(fn) # optional - pycosat - sage: print(open(fn).read()) # optional - pycosat + sage: solver = PicoSAT() + sage: solver.add_clause((1, 2, 4)) + sage: solver.add_clause((1, 2, -4)) + sage: fn = tmp_filename() + sage: solver.clauses(fn) + sage: print(open(fn).read()) p cnf 4 2 1 2 4 0 1 2 -4 0 diff --git a/src/sage/sat/solvers/sat_lp.py b/src/sage/sat/solvers/sat_lp.py index d96ed62b125..9b65b1d241d 100644 --- a/src/sage/sat/solvers/sat_lp.py +++ b/src/sage/sat/solvers/sat_lp.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.numerical.mip r""" Solve SAT problems Integer Linear Programming diff --git a/src/sage/sat/solvers/satsolver.pyx b/src/sage/sat/solvers/satsolver.pyx index 1c4ac400cb6..83735c86989 100644 --- a/src/sage/sat/solvers/satsolver.pyx +++ b/src/sage/sat/solvers/satsolver.pyx @@ -139,9 +139,9 @@ cdef class SatSolver: sage: from io import StringIO sage: file_object = StringIO("c A sample .cnf file with xor clauses.\np cnf 3 3\n1 2 0\n3 0\nx1 2 3 0") - sage: from sage.sat.solvers.sat_lp import SatLP - sage: solver = SatLP() - sage: solver.read(file_object) + sage: from sage.sat.solvers.sat_lp import SatLP # needs sage.numerical.mip + sage: solver = SatLP() # needs sage.numerical.mip + sage: solver.read(file_object) # needs sage.numerical.mip Traceback (most recent call last): ... NotImplementedError: the solver "an ILP-based SAT Solver" does not support xor clauses @@ -339,7 +339,7 @@ def SAT(solver=None, *args, **kwds): EXAMPLES:: - sage: SAT(solver="LP") + sage: SAT(solver="LP") # needs sage.numerical.mip an ILP-based SAT Solver TESTS:: @@ -351,12 +351,12 @@ def SAT(solver=None, *args, **kwds): Forcing CryptoMiniSat:: - sage: SAT(solver="cryptominisat") # optional - pycryptosat + sage: SAT(solver="cryptominisat") # optional - pycryptosat CryptoMiniSat solver: 0 variables, 0 clauses. Forcing PicoSat:: - sage: SAT(solver="picosat") # optional - pycosat + sage: SAT(solver="picosat") # optional - pycosat PicoSAT solver: 0 variables, 0 clauses. Forcing Glucose:: diff --git a/src/sage/schemes/curves/affine_curve.py b/src/sage/schemes/curves/affine_curve.py index ce8c0ff0655..e1032861b2f 100644 --- a/src/sage/schemes/curves/affine_curve.py +++ b/src/sage/schemes/curves/affine_curve.py @@ -2118,8 +2118,10 @@ def function(self, f): INPUT: - - ``f`` -- an element of the coordinate ring of either the curve or its - ambient space. + - ``f`` -- an element of the fraction field of the coordinate ring of + the ambient space or the coordinate ring of the curve + + OUTPUT: An element of the function field of this curve. EXAMPLES:: @@ -2141,7 +2143,7 @@ def function(self, f): if f not in R and f.parent() is self.coordinate_ring(): f = f.lift() - phi = self._lift_to_function_field + phi = self._map_to_function_field num = R(f.numerator()) den = R(f.denominator()) return phi(num) / phi(den) @@ -2161,15 +2163,51 @@ def coordinate_functions(self): """ return self._coordinate_functions + def pull_from_function_field(self, f): + """ + Return the fraction corresponding to ``f``. + + INPUT: + + - ``f`` -- an element of the function field + + OUTPUT: + + A fraction of polynomials in the coordinate ring of the ambient space + of the curve. + + EXAMPLES:: + + sage: # needs sage.rings.finite_rings + sage: A. = AffineSpace(GF(8), 2) + sage: C = Curve(x^5 + y^5 + x*y + 1) + sage: F = C.function_field() + sage: C.pull_from_function_field(F.gen()) + y + sage: C.pull_from_function_field(F.one()) + 1 + sage: C.pull_from_function_field(F.zero()) + 0 + sage: f1 = F.gen() + sage: f2 = F.base_ring().gen() + sage: C.function(C.pull_from_function_field(f1)) == f1 + True + sage: C.function(C.pull_from_function_field(f2)) == f2 + True + """ + return self._map_from_function_field(f) + @lazy_attribute def _nonsingular_model(self): """ Return the data of a nonsingular model of the curve. - The data consists of an abstract function field `M` and a map from the - coordinate ring `R` of the ambient space of the curve into the function - field. The coordinate ring of the curve is thus the quotient of `R` by - the kernel of the map. + The data consists of an abstract function field `M`, a map from the + fraction field of the coordinate ring `R` of the ambient space of the + curve to the function field, and the inverse map. + + The coordinate ring of the curve is the quotient of `R` by the kernel + of the map restricted to `R`. TESTS:: @@ -2178,21 +2216,28 @@ def _nonsingular_model(self): sage: C._nonsingular_model (Function field in z defined by z^3 + 10*x, Ring morphism: - From: Multivariate Polynomial Ring in x, y, z + From: Fraction Field of Multivariate Polynomial Ring in x, y, z over Finite Field of size 11 To: Function field in z defined by z^3 + 10*x Defn: x |--> x y |--> z^2 - z |--> z) + z |--> z, + Ring morphism: + From: Function field in z defined by z^3 + 10*x + To: Fraction Field of Multivariate Polynomial Ring in x, y, z + over Finite Field of size 11) """ + from sage.structure.sequence import Sequence + from sage.rings.fraction_field import FractionField from sage.rings.function_field.constructor import FunctionField + from sage.rings.function_field.maps import FunctionFieldRingMorphism k = self.base_ring() - I0 = self.defining_ideal() + I = self.defining_ideal() # invlex is the lex order with x < y < z for R = k[x,y,z] for instance - R = I0.parent().ring().change_ring(order='invlex') - I0 = I0.change_ring(R) + R = I.parent().ring().change_ring(order='invlex') + I0 = I.change_ring(R) n = R.ngens() names = R.variable_names() @@ -2228,6 +2273,7 @@ def _nonsingular_model(self): # syzygy for z. Now x is the generator of a rational function field F0; # y is the generator of the extension F1 of F0 by f3; z is the # generator of the extension F2 of F1 by f2. + basis = list(gbasis) syzygy = {} for i in range(n): @@ -2241,11 +2287,11 @@ def _nonsingular_model(self): basis.append(f) break - indep = [i for i in range(n) if i not in syzygy] - if len(indep) != 1: + # sanity check + indeps = [i for i in range(n) if i not in syzygy] + if len(indeps) != 1: raise TypeError("not a curve") - else: - indep = indep[0] + indep = indeps[0] F = FunctionField(k, names[indep]) coords = {indep: F.gen()} @@ -2258,20 +2304,60 @@ def _nonsingular_model(self): F = F.extension(f, names[i]) coords[i] = F.gen() - if F.base_field() is not F: # proper extension + proper_extension = F.base_field() is not F + + if proper_extension: N, from_N, to_N = F.simple_model() M, from_M, to_M = N.separable_model() coordinate_functions = tuple([to_M(to_N(F(coords[i]))) for i in range(n)]) - else: # rational function field - M = F + else: + M = F # is rational function field coordinate_functions = tuple([coords[i] for i in range(n)]) - lift_to_function_field = hom(R, M, coordinate_functions) + # map to M + + FR = FractionField(I.ring()) + map_to_function_field = hom(FR, M, coordinate_functions) + + # map from M + + def convert(f, i): + if i == indep: + i = i - 1 + if i < 0: + return f._x # fraction representing rational function field element + fx = f._x # polynomial representing function field element + if not fx: + fxlist = [fx.base_ring().zero()] + else: + fxlist = fx.list() + coeffs = Sequence(convert(c, i - 1) for c in fxlist) + B = coeffs.universe() + S = B[names[i]] + return S(coeffs) + + z = M.gen() + + if proper_extension: + Z = FR(convert(from_N(from_M(z)), n - 1)) + + def evaluate(f): + coeffs = f._x.list() + v = 0 + while coeffs: + v = v * Z + coeffs.pop()._x + return FR(v) + else: + def evaluate(f): + return FR(f._x) + + map_from_function_field = FunctionFieldRingMorphism(Hom(M, FR), evaluate) # sanity check - assert all(lift_to_function_field(f).is_zero() for f in I0.gens()) + assert all(map_to_function_field(f).is_zero() for f in I.gens()) + assert map_to_function_field(map_from_function_field(z)) == z - return M, lift_to_function_field + return M, map_to_function_field, map_from_function_field @lazy_attribute def _function_field(self): @@ -2288,17 +2374,17 @@ def _function_field(self): return self._nonsingular_model[0] @lazy_attribute - def _lift_to_function_field(self): + def _map_to_function_field(self): """ - Return the map to function field of the curve. + Return the map to the function field of the curve. TESTS:: sage: A. = AffineSpace(GF(11), 3) sage: C = Curve([x*z - y^2, y - z^2, x - y*z], A) - sage: C._lift_to_function_field + sage: C._map_to_function_field Ring morphism: - From: Multivariate Polynomial Ring in x, y, z + From: Fraction Field of Multivariate Polynomial Ring in x, y, z over Finite Field of size 11 To: Function field in z defined by z^3 + 10*x Defn: x |--> x @@ -2321,20 +2407,39 @@ def _coordinate_functions(self): """ return self._nonsingular_model[1].im_gens() + @lazy_attribute + def _map_from_function_field(self): + """ + Return the map from the function field of the curve. + + TESTS:: + + sage: A. = AffineSpace(GF(11), 3) + sage: C = Curve([x*z - y^2, y - z^2, x - y*z], A) + sage: C._map_from_function_field + Ring morphism: + From: Function field in z defined by z^3 + 10*x + To: Fraction Field of Multivariate Polynomial Ring in x, y, z + over Finite Field of size 11 + """ + return self._nonsingular_model[2] + @lazy_attribute def _singularities(self): """ - Return a list of the pairs of singular closed points and the places above it. + Return a list of the pairs of a singular closed point and the places + above it. TESTS:: - sage: A. = AffineSpace(GF(7^2), 2) # needs sage.rings.finite_rings - sage: C = Curve(x^2 - x^4 - y^4) # needs sage.rings.finite_rings - sage: C._singularities # long time # needs sage.rings.finite_rings + sage: # needs sage.rings.finite_rings + sage: A. = AffineSpace(GF(7^2), 2) + sage: C = Curve(x^2 - x^4 - y^4) + sage: C._singularities # long time [(Point (x, y), [Place (x, 1/x*y^3 + 1/x*y^2 + 1), Place (x, 1/x*y^3 + 1/x*y^2 + 6)])] """ - to_F = self._lift_to_function_field + to_F = self._map_to_function_field sing = self.singular_subscheme() funcs = [] @@ -2370,9 +2475,10 @@ def singular_closed_points(self): EXAMPLES:: - sage: A. = AffineSpace(GF(7^2), 2) # needs sage.rings.finite_rings - sage: C = Curve(x^2 - x^4 - y^4) # needs sage.rings.finite_rings - sage: C.singular_closed_points() # needs sage.rings.finite_rings + sage: # needs sage.rings.finite_rings + sage: A. = AffineSpace(GF(7^2), 2) + sage: C = Curve(x^2 - x^4 - y^4) + sage: C.singular_closed_points() [Point (x, y)] :: @@ -2550,7 +2656,7 @@ def places_on(self, point): sage: Cp = Curve(x^3*y + y^3*z + x*z^3) sage: C = Cp.affine_patch(0) """ - phi = self._lift_to_function_field + phi = self._map_to_function_field gs = [phi(g) for g in point.prime_ideal().gens()] fs = [g for g in gs if not g.is_zero()] f = fs.pop() @@ -2726,11 +2832,12 @@ class IntegralAffinePlaneCurve_finite_field(AffinePlaneCurve_finite_field, Integ EXAMPLES:: - sage: A. = AffineSpace(GF(8), 2) # needs sage.rings.finite_rings - sage: C = Curve(x^5 + y^5 + x*y + 1); C # needs sage.rings.finite_rings + sage: # needs sage.rings.finite_rings + sage: A. = AffineSpace(GF(8), 2) + sage: C = Curve(x^5 + y^5 + x*y + 1); C Affine Plane Curve over Finite Field in z3 of size 2^3 defined by x^5 + y^5 + x*y + 1 - sage: C.function_field() # needs sage.rings.finite_rings + sage: C.function_field() Function field in y defined by y^5 + x*y + x^5 + 1 """ _point = IntegralAffinePlaneCurvePoint_finite_field diff --git a/src/sage/schemes/curves/projective_curve.py b/src/sage/schemes/curves/projective_curve.py index 5a4f9f5f4ce..7c82026b3c1 100644 --- a/src/sage/schemes/curves/projective_curve.py +++ b/src/sage/schemes/curves/projective_curve.py @@ -2325,7 +2325,14 @@ def __call__(self, *args): def function(self, f): """ - Return the function field element coerced from ``x``. + Return the function field element corresponding to ``f``. + + INPUT: + + - ``f`` -- a fraction of homogeneous polynomials of the coordinate ring + of the ambient space of the curve + + OUTPUT: An element of the function field. EXAMPLES:: @@ -2343,7 +2350,7 @@ def function(self, f): - Place (y, z + 1) """ S = self.ambient_space().coordinate_ring() - phi = self._lift_to_function_field + phi = self._map_to_function_field num = S(f.numerator()) den = S(f.denominator()) if num.degree() != den.degree(): @@ -2373,6 +2380,40 @@ def coordinate_functions(self, i=None): inv = ~coords[i] return tuple([coords[j]*inv for j in range(len(coords)) if j != i]) + def pull_from_function_field(self, f): + """ + Return the fraction corresponding to ``f``. + + INPUT: + + - ``f`` -- an element of the function field + + OUTPUT: + + A fraction of homogeneous polynomials in the coordinate ring of the + ambient space of the curve. + + EXAMPLES:: + + sage: # needs sage.rings.finite_rings + sage: P. = ProjectiveSpace(GF(4), 2) + sage: C = Curve(x^5 + y^5 + x*y*z^3 + z^5) + sage: F = C.function_field() + sage: C.pull_from_function_field(F.gen()) + z/x + sage: C.pull_from_function_field(F.one()) + 1 + sage: C.pull_from_function_field(F.zero()) + 0 + sage: f1 = F.gen() + sage: f2 = F.base_ring().gen() + sage: C.function(C.pull_from_function_field(f1)) == f1 + True + sage: C.function(C.pull_from_function_field(f2)) == f2 + True + """ + return self._map_from_function_field(f) + @lazy_attribute def _function_field(self): """ @@ -2388,15 +2429,15 @@ def _function_field(self): return self._open_affine._function_field @lazy_attribute - def _lift_to_function_field(self): + def _map_to_function_field(self): """ - Return the map to function field of the curve. + Return the map to the function field of the curve. TESTS:: sage: P. = ProjectiveSpace(GF(5), 2) sage: C = Curve(y^2*z^7 - x^9 - x*z^8) - sage: C._lift_to_function_field + sage: C._map_to_function_field Ring morphism: From: Multivariate Polynomial Ring in x, y, z over Finite Field of size 5 To: Function field in z defined by z^8 + 4*y^2*z^7 + 1 @@ -2425,6 +2466,33 @@ def _coordinate_functions(self): coords.insert(self._open_affine_index, self._function_field.one()) return tuple(coords) + @lazy_attribute + def _map_from_function_field(self): + """ + Return the map from the function field of the curve. + + TESTS:: + + sage: P. = ProjectiveSpace(GF(5), 2) + sage: C = Curve(y^2*z^7 - x^9 - x*z^8) + sage: F = C.function_field() + sage: f = F.random_element() + sage: C.function(C._map_from_function_field(f)) == f + True + """ + F = self._function_field + S = self.ambient_space().coordinate_ring() + phi = self._open_affine._nonsingular_model[2] + i = self._open_affine_index + + def m(f): + pf = phi(f) + num = S(pf.numerator()).homogenize(i) + den = S(pf.denominator()).homogenize(i) + return num / den * S.gen(i) ** (den.total_degree() - num.total_degree()) + + return m + @lazy_attribute def _singularities(self): """ @@ -2442,7 +2510,7 @@ def _singularities(self): """ S = self.ambient_space().coordinate_ring() - to_F = self._lift_to_function_field + to_F = self._map_to_function_field sing = self.singular_subscheme() # singular locus # for each affine patch, places on which the dehomogenized polynomials @@ -2628,7 +2696,7 @@ def places_on(self, point): if not S.gen(i) in prime: break - phi = self._lift_to_function_field + phi = self._map_to_function_field denom = self._coordinate_functions[i] gs = [phi(f)/denom**f.degree() for f in prime.gens()] fs = [g for g in gs if not g.is_zero()] diff --git a/src/sage/schemes/elliptic_curves/all.py b/src/sage/schemes/elliptic_curves/all.py index fd2fb992360..e339c40d843 100644 --- a/src/sage/schemes/elliptic_curves/all.py +++ b/src/sage/schemes/elliptic_curves/all.py @@ -40,4 +40,6 @@ from .ell_curve_isogeny import EllipticCurveIsogeny, isogeny_codomain_from_kernel +lazy_import('sage.schemes.elliptic_curves.mod_poly', 'classical_modular_polynomial') + from .heegner import heegner_points, heegner_point diff --git a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py index 75d10d147d6..59bf8882f1f 100644 --- a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py +++ b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py @@ -2838,11 +2838,18 @@ def scaling_factor(self): sage: phi.dual().scaling_factor() 43 + TESTS: + + Check for :issue:`36638`:: + + sage: phi.scaling_factor().parent() # needs sage.rings.finite_rings + Finite Field in z2 of size 257^2 + ALGORITHM: The "inner" isogeny is normalized by construction, so we only need to account for the scaling factors of a pre- and post-isomorphism. """ - sc = Integer(1) + sc = self.__base_field.one() if self.__pre_isomorphism is not None: sc *= self.__pre_isomorphism.scaling_factor() if self.__post_isomorphism is not None: @@ -2879,28 +2886,19 @@ def kernel_polynomial(self): self.__init_kernel_polynomial() return self.__kernel_polynomial - def is_separable(self): + def inseparable_degree(self): r""" - Determine whether or not this isogeny is separable. + Return the inseparable degree of this isogeny. - Since :class:`EllipticCurveIsogeny` only implements - separable isogenies, this method always returns ``True``. + Since this class only implements separable isogenies, + this method always returns one. - EXAMPLES:: - - sage: E = EllipticCurve(GF(17), [0,0,0,3,0]) - sage: phi = EllipticCurveIsogeny(E, E((0,0))) - sage: phi.is_separable() - True - - :: + TESTS:: - sage: E = EllipticCurve('11a1') - sage: phi = EllipticCurveIsogeny(E, E.torsion_points()) - sage: phi.is_separable() - True + sage: EllipticCurveIsogeny.inseparable_degree(None) + 1 """ - return True + return Integer(1) def _set_pre_isomorphism(self, preWI): """ diff --git a/src/sage/schemes/elliptic_curves/ell_field.py b/src/sage/schemes/elliptic_curves/ell_field.py index 7dd65c95749..78712572239 100644 --- a/src/sage/schemes/elliptic_curves/ell_field.py +++ b/src/sage/schemes/elliptic_curves/ell_field.py @@ -791,18 +791,17 @@ def descend_to(self, K, f=None): Elist = [E.minimal_model() for E in Elist] return Elist - def division_field(self, l, names='t', map=False, **kwds): + def division_field(self, n, names='t', map=False, **kwds): r""" - Given an elliptic curve over a number field or finite field `F` - and a prime number `\ell`, construct the `\ell`-division field - `F(E[\ell])`. + Given an elliptic curve over a number field or finite field `F` and + a positive integer `n`, construct the `n`-division field `F(E[n])`. - The `\ell`-division field is the smallest extension of `F` over - which all `\ell`-torsion points of `E` are defined. + The `n`-division field is the smallest extension of `F` over which + all `n`-torsion points of `E` are defined. INPUT: - - `\ell` -- a prime number (an element of `\ZZ`) + - `n` -- a positive integer - ``names`` -- (default: ``'t'``) a variable name for the division field - ``map`` -- (default: ``False``) also return an embedding of the :meth:`base_field` into the resulting field @@ -819,7 +818,7 @@ def division_field(self, l, names='t', map=False, **kwds): .. WARNING:: This can take a very long time when the degree of the division - field is large (e.g. when `\ell` is large or when the Galois + field is large (e.g. when `n` is large or when the Galois representation is surjective). The ``simplify`` flag also has a big influence on the running time over number fields: sometimes ``simplify=False`` is faster, sometimes the default @@ -845,8 +844,8 @@ def division_field(self, l, names='t', map=False, **kwds): Number Field in b with defining polynomial x^6 + 10*x^5 + 24*x^4 - 212*x^3 + 1364*x^2 + 24072*x + 104292 - For odd primes `\ell`, the division field is either the splitting - field of the `\ell`-division polynomial, or a quadratic extension + For odd primes `n`, the division field is either the splitting + field of the `n`-division polynomial, or a quadratic extension of it. :: sage: # needs sage.rings.number_field @@ -880,8 +879,7 @@ def division_field(self, l, names='t', map=False, **kwds): by y^2 = x^3 + 5*a0*x^2 + (-200*a0^2)*x + (-42000*a0^2+42000*a0+126000) over Number Field in a0 with defining polynomial x^3 - 3*x^2 + 3*x + 9 sage: K. = E.division_field(3, simplify_all=True); K - Number Field in b with defining polynomial - x^12 + 5*x^10 + 40*x^8 + 315*x^6 + 750*x^4 + 675*x^2 + 2025 + Number Field in b with defining polynomial x^12 - 25*x^10 + 130*x^8 + 645*x^6 + 1050*x^4 + 675*x^2 + 225 Some higher-degree examples:: @@ -957,9 +955,35 @@ def division_field(self, l, names='t', map=False, **kwds): sage: K. = E.division_field(7); K # needs sage.rings.finite_rings Finite Field in v of size 433^16 + It also works for composite orders:: + + sage: E = EllipticCurve(GF(11), [5,5]) + sage: E.change_ring(E.division_field(8)).abelian_group().torsion_subgroup(8).invariants() + (8, 8) + sage: E.change_ring(E.division_field(9)).abelian_group().torsion_subgroup(9).invariants() + (9, 9) + sage: E.change_ring(E.division_field(10)).abelian_group().torsion_subgroup(10).invariants() + (10, 10) + sage: E.change_ring(E.division_field(36)).abelian_group().torsion_subgroup(36).invariants() + (36, 36) + sage: E.change_ring(E.division_field(11)).abelian_group().torsion_subgroup(11).invariants() + (11,) + sage: E.change_ring(E.division_field(66)).abelian_group().torsion_subgroup(66).invariants() + (6, 66) + + ...also over number fields:: + + sage: R. = PolynomialRing(QQ) + sage: K. = NumberField(x^2 + 1) + sage: E = EllipticCurve([0,0,0,0,i]) + sage: L,emb = E.division_field(6, names='b', map=True); L + Number Field in b with defining polynomial x^24 + 12*x^23 + ... + sage: E.change_ring(emb).torsion_subgroup().invariants() + (6, 6) + .. SEEALSO:: - To compute a basis of the `\ell`-torsion once the base field + To compute a basis of the `n`-torsion once the base field has been extended, you may use :meth:`sage.schemes.elliptic_curves.ell_number_field.EllipticCurve_number_field.torsion_subgroup` or @@ -967,7 +991,7 @@ def division_field(self, l, names='t', map=False, **kwds): TESTS: - Some random testing:: + Some random for prime orders:: sage: # needs sage.rings.finite_rings sage: def check(E, l, K): @@ -1014,71 +1038,80 @@ def division_field(self, l, names='t', map=False, **kwds): ``splitting_field`` method, moved from ``gal_reps.py``, make it work over number fields. - Lorenz Panny (2022): extend to finite fields + - Lorenz Panny (2023): extend to composite `n`. """ from sage.misc.verbose import verbose - l = Integer(l) - if not l.is_prime(): - raise ValueError("l must be a prime number") - verbose("Adjoining X-coordinates of %s-torsion points" % l) + n = Integer(n) + if n <= 0: + raise ValueError("n must be a positive integer") + + verbose("Adjoining X-coordinates of %s-torsion points" % n) + F = self.base_ring() - f = self.division_polynomial(l) - if l == 2 or f.is_constant(): - # For l = 2, the division field is the splitting field of + f = self.division_polynomial(n).radical() + + if n == 2 or f.is_constant(): + # For n = 2, the division field is the splitting field of # the division polynomial. - # If f is a non-zero constant, the l-torsion is trivial: - # This means the curve must be supersingular and l == p. + # If f is a non-zero constant, the n-torsion is trivial: + # This means the curve must be supersingular and n == p. return f.splitting_field(names, map=map, **kwds) + # We divide out the part defining points of non-maximal order. + # Clearly all points of non-maximal order are multiples of points + # of maximal order, so they cannot be defined over a larger field. + if not n.is_prime(): + for d in n.prime_divisors(): + g = self.division_polynomial(n // d) + f //= f.gcd(g) + # Compute splitting field of X-coordinates. - # The Galois group of the division field is a subgroup of GL(2,l). - # The Galois group of the X-coordinates is a subgroup of GL(2,l)/{-1,+1}. - # We need the map to change the elliptic curve invariants to K. + # The Galois group of the division field is a subgroup of GL(2,n). + # The Galois group of the X-coordinates is a subgroup of GL(2,n)/{-1,+1}. if F in NumberFields(): - deg_mult = F.degree() * l * (l+1) * (l-1)**2 // 2 + from sage.misc.misc_c import prod + deg_mult = F.degree() * prod(l * (l+1) * (l-1)**2 * l**(4*(e-1)) for l,e in n.factor()) // 2 K, F_to_K = f.splitting_field(names, degree_multiple=deg_mult, map=True, **kwds) elif F in FiniteFields(): K, F_to_K = f.splitting_field('u', map=True, **kwds) else: raise NotImplementedError('only number fields and finite fields are currently supported') - verbose("Adjoining Y-coordinates of %s-torsion points" % l) + verbose("Adjoining Y-coordinates of %s-torsion points" % n) - # THEOREM (Cremona, https://github.com/sagemath/sage/issues/11905#comment:21). - # Let K be a field, E an elliptic curve over K and p an odd - # prime number. Assume that K contains all roots of the - # p-division polynomial of E. Then either K contains all - # p-torsion points on E, or it does not contain any p-torsion - # point. + # THEOREM + # (Cremona, https://github.com/sagemath/sage/issues/11905#comment:21) + # (Later generalized to composite n by Lorenz Panny) + # + # Let K be a field, E an elliptic curve over K and n a positive + # integer. Assume that K contains all roots of the n-division + # polynomial of E, and that at least one point P of full order n + # is defined over K. Then K contains all n-torsion points on E. # # PROOF. Let G be the absolute Galois group of K (every element - # in it fixes all elements of K). For any p-torsion point P + # in it fixes all elements of K). For any n-torsion point Q # over the algebraic closure and any sigma in G, we must have - # either sigma(P) = P or sigma(P) = -P (since K contains the - # X-coordinate of P). Now assume that K does not contain all - # p-torsion points. Then there exists a point P1 and a sigma in - # G such that sigma(P1) = -P1. Now take a different p-torsion - # point P2. Since sigma(P2) must be P2 or -P2 and - # sigma(P1+P2) = sigma(P1)+sigma(P2) = sigma(P1)-P2 must - # be P1+P2 or -(P1+P2), it follows that sigma(P2) = -sigma(P2). - # Therefore, K cannot contain any p-torsion point. + # either sigma(Q) = Q or sigma(Q) = -Q (since K contains the + # X-coordinate of Q). Similarly, sigma(P+Q) must equal either + # P+Q or -(P+Q). However, since sigma is a group homomorphism, + # we have sigma(P+Q) = sigma(P) + sigma(Q) = P + sigma(Q), + # so either P + sigma(Q) = P+Q, which implies sigma(Q) = Q, + # or P + sigma(Q) = -(P+Q), which implies sigma(Q) = -2P-Q. + # The latter is impossible except for the easier case n = 2. + # Hence, sigma(Q) = Q in all cases. # # This implies that it suffices to adjoin the Y-coordinate - # of just one point. + # of just one full-order point. - # First factor f over F and then compute a root X of f over K. - g = f.factor()[0][0] - X = g.map_coefficients(F_to_K).roots(multiplicities=False)[0] + x = f.change_ring(F_to_K).any_root(assume_squarefree=True) + h = self.defining_polynomial().change_ring(F_to_K)(x, polygen(K), 1) + L = h.splitting_field(names, map=map, **kwds) - # Polynomial defining the corresponding Y-coordinate - curve = self.defining_polynomial().map_coefficients(F_to_K) - ypol = curve(X, polygen(K), 1) - L = ypol.splitting_field(names, map=map, **kwds) if map: L, K_to_L = L - return L, F_to_K.post_compose(K_to_L) - else: - return L + L = L, F_to_K.post_compose(K_to_L) + return L def isogeny(self, kernel, codomain=None, degree=None, model=None, check=True, algorithm=None): r""" @@ -2049,13 +2082,13 @@ def compute_model(E, name): raise NotImplementedError(f'cannot compute {name} model') -def point_of_order(E, l): +def point_of_order(E, n): r""" Given an elliptic curve `E` over a finite field or a number field - and an integer `\ell \geq 1`, construct a point of order `\ell` on `E`, + and an integer `n \geq 1`, construct a point of order `n` on `E`, possibly defined over an extension of the base field of `E`. - Currently only prime values of `\ell` are supported. + Currently only prime powers `n` are supported. EXAMPLES:: @@ -2070,6 +2103,13 @@ def point_of_order(E, l): sage: P.curve().a_invariants() (1, 2, 3, 4, 5) + :: + + sage: Q = point_of_order(E, 8); Q + (69*x^5 + 24*x^4 + 100*x^3 + 65*x^2 + 88*x + 97 : 65*x^5 + 28*x^4 + 5*x^3 + 45*x^2 + 42*x + 18 : 1) + sage: 8*Q == 0 and 4*Q != 0 + True + :: sage: from sage.schemes.elliptic_curves.ell_field import point_of_order @@ -2078,10 +2118,23 @@ def point_of_order(E, l): (x : -Y : 1) sage: P.base_ring() Number Field in Y with defining polynomial Y^2 - x^3 - 7*x - 7 over its base field + sage: P.base_ring().base_field() + Number Field in x with defining polynomial x^4 + 14*x^2 + 28*x - 49/3 sage: P.order() 3 sage: P.curve().a_invariants() (0, 0, 0, 7, 7) + + :: + + sage: Q = point_of_order(E, 4); Q # random + (x : Y : 1) + sage: Q.base_ring() + Number Field in Y with defining polynomial Y^2 - x^3 - 7*x - 7 over its base field + sage: Q.base_ring().base_field() + Number Field in x with defining polynomial x^6 + 35*x^4 + 140*x^3 - 245*x^2 - 196*x - 735 + sage: Q.order() + 4 """ # Construct the field extension defined by the given polynomial, # in such a way that the result is recognized by Sage as a field. @@ -2094,14 +2147,16 @@ def ffext(poly): return poly.splitting_field(rng.variable_name()) return fld.extension(poly, rng.variable_name()) - l = ZZ(l) - if l == 1: + n = ZZ(n) + if n == 1: return E(0) - if not l.is_prime(): - raise NotImplementedError('composite orders are currently unsupported') + l,m = n.is_prime_power(get_data=True) + if not m: + raise NotImplementedError('only prime-power orders are currently supported') - xpoly = E.division_polynomial(l) + xpoly = E.division_polynomial(n).radical() + xpoly //= E.division_polynomial(n//l).radical() if xpoly.degree() < 1: # supersingular and l == p raise ValueError('curve does not have any points of the specified order') @@ -2116,4 +2171,6 @@ def ffext(poly): xx = FF(xx) EE = E.change_ring(FF) - return EE.lift_x(xx) + pt = EE.lift_x(xx) + pt.set_order(n, check=False) + return pt diff --git a/src/sage/schemes/elliptic_curves/ell_point.py b/src/sage/schemes/elliptic_curves/ell_point.py index 1e760dcfd6c..d35790a13f3 100644 --- a/src/sage/schemes/elliptic_curves/ell_point.py +++ b/src/sage/schemes/elliptic_curves/ell_point.py @@ -1359,9 +1359,10 @@ def set_order(self, value=None, *, multiple=None, check=True): raise ValueError('Value %s illegal for point order' % value) E = self.curve() q = E.base_ring().cardinality() - low, hi = Hasse_bounds(q) - if value > hi: - raise ValueError('Value %s illegal: outside max Hasse bound' % value) + if q < oo: + _, hi = Hasse_bounds(q) + if value > hi: + raise ValueError('Value %s illegal: outside max Hasse bound' % value) if value * self != E(0): raise ValueError('Value %s illegal: %s * %s is not the identity' % (value, value, self)) if hasattr(self, '_order') and self._order != value: # already known diff --git a/src/sage/schemes/elliptic_curves/hom.py b/src/sage/schemes/elliptic_curves/hom.py index 995420ae438..fb7855993ea 100644 --- a/src/sage/schemes/elliptic_curves/hom.py +++ b/src/sage/schemes/elliptic_curves/hom.py @@ -10,6 +10,7 @@ - :class:`~sage.schemes.elliptic_curves.ell_curve_isogeny.EllipticCurveIsogeny` - :class:`~sage.schemes.elliptic_curves.weierstrass_morphism.WeierstrassIsomorphism` - :class:`~sage.schemes.elliptic_curves.hom_composite.EllipticCurveHom_composite` +- :class:`~sage.schemes.elliptic_curves.hom_composite.EllipticCurveHom_sum` - :class:`~sage.schemes.elliptic_curves.hom_scalar.EllipticCurveHom_scalar` - :class:`~sage.schemes.elliptic_curves.hom_frobenius.EllipticCurveHom_frobenius` - :class:`~sage.schemes.elliptic_curves.hom_velusqrt.EllipticCurveHom_velusqrt` @@ -134,6 +135,51 @@ def _composition_(self, other, homset): from sage.schemes.elliptic_curves.hom_composite import EllipticCurveHom_composite return EllipticCurveHom_composite.from_factors([other, self]) + def _add_(self, other): + r""" + Add two :class:`EllipticCurveHom` objects by constructing a + formal :class:`EllipticCurveHom_sum`. + + EXAMPLES:: + + sage: E = EllipticCurve(GF(101), [5,5]) + sage: phi = E.isogenies_prime_degree(7)[0] + sage: phi + phi # indirect doctest + Sum morphism: + From: Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 + To: Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101 + Via: (Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101, Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101) + """ + from sage.schemes.elliptic_curves.hom_sum import EllipticCurveHom_sum + phis = [] + if isinstance(self, EllipticCurveHom_sum): + phis += self.summands() + else: + phis.append(self) + if isinstance(other, EllipticCurveHom_sum): + phis += other.summands() + else: + phis.append(other) + #TODO should probably try to simplify some more? + return EllipticCurveHom_sum(phis) + + def _sub_(self, other): + r""" + Subtract two :class:`EllipticCurveHom` objects by negating + and constructing a formal :class:`EllipticCurveHom_sum`. + + EXAMPLES:: + + sage: E = EllipticCurve(GF(101), [5,5]) + sage: phi = E.isogenies_prime_degree(7)[0] + sage: phi - phi # indirect doctest + Sum morphism: + From: Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 + To: Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101 + Via: (Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101, Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101) + """ + return self + (-other) + @staticmethod def _comparison_impl(left, right, op): r""" @@ -384,6 +430,7 @@ def kernel_polynomial(self): - :meth:`EllipticCurveIsogeny.kernel_polynomial` - :meth:`sage.schemes.elliptic_curves.weierstrass_morphism.WeierstrassIsomorphism.kernel_polynomial` - :meth:`sage.schemes.elliptic_curves.hom_composite.EllipticCurveHom_composite.kernel_polynomial` + - :meth:`sage.schemes.elliptic_curves.hom_sum.EllipticCurveHom_sum.kernel_polynomial` - :meth:`sage.schemes.elliptic_curves.hom_scalar.EllipticCurveHom_scalar.kernel_polynomial` - :meth:`sage.schemes.elliptic_curves.hom_frobenius.EllipticCurveHom_frobenius.kernel_polynomial` @@ -406,6 +453,7 @@ def dual(self): - :meth:`EllipticCurveIsogeny.dual` - :meth:`sage.schemes.elliptic_curves.weierstrass_morphism.WeierstrassIsomorphism.dual` - :meth:`sage.schemes.elliptic_curves.hom_composite.EllipticCurveHom_composite.dual` + - :meth:`sage.schemes.elliptic_curves.hom_sum.EllipticCurveHom_sum.dual` - :meth:`sage.schemes.elliptic_curves.hom_scalar.EllipticCurveHom_scalar.dual` - :meth:`sage.schemes.elliptic_curves.hom_frobenius.EllipticCurveHom_frobenius.dual` @@ -430,6 +478,7 @@ def rational_maps(self): - :meth:`EllipticCurveIsogeny.rational_maps` - :meth:`sage.schemes.elliptic_curves.weierstrass_morphism.WeierstrassIsomorphism.rational_maps` - :meth:`sage.schemes.elliptic_curves.hom_composite.EllipticCurveHom_composite.rational_maps` + - :meth:`sage.schemes.elliptic_curves.hom_sum.EllipticCurveHom_sum.rational_maps` - :meth:`sage.schemes.elliptic_curves.hom_scalar.EllipticCurveHom_scalar.rational_maps` - :meth:`sage.schemes.elliptic_curves.hom_frobenius.EllipticCurveHom_frobenius.rational_maps` @@ -453,6 +502,7 @@ def x_rational_map(self): - :meth:`EllipticCurveIsogeny.x_rational_map` - :meth:`sage.schemes.elliptic_curves.weierstrass_morphism.WeierstrassIsomorphism.x_rational_map` - :meth:`sage.schemes.elliptic_curves.hom_composite.EllipticCurveHom_composite.x_rational_map` + - :meth:`sage.schemes.elliptic_curves.hom_sum.EllipticCurveHom_sum.x_rational_map` - :meth:`sage.schemes.elliptic_curves.hom_scalar.EllipticCurveHom_scalar.x_rational_map` - :meth:`sage.schemes.elliptic_curves.hom_frobenius.EllipticCurveHom_frobenius.x_rational_map` @@ -484,6 +534,7 @@ def scaling_factor(self): - :meth:`EllipticCurveIsogeny.scaling_factor` - :meth:`sage.schemes.elliptic_curves.weierstrass_morphism.WeierstrassIsomorphism.scaling_factor` - :meth:`sage.schemes.elliptic_curves.hom_composite.EllipticCurveHom_composite.scaling_factor` + - :meth:`sage.schemes.elliptic_curves.hom_sum.EllipticCurveHom_sum.scaling_factor` - :meth:`sage.schemes.elliptic_curves.hom_scalar.EllipticCurveHom_scalar.scaling_factor` TESTS:: @@ -623,40 +674,137 @@ def is_normalized(self): ALGORITHM: We check if :meth:`scaling_factor` returns `1`. """ - return self.scaling_factor() == 1 + return self.scaling_factor().is_one() - def is_separable(self): + def inseparable_degree(self): r""" - Determine whether or not this morphism is separable. + Return the inseparable degree of this isogeny. Implemented by child classes. For examples, see: - - :meth:`EllipticCurveIsogeny.is_separable` - - :meth:`sage.schemes.elliptic_curves.weierstrass_morphism.WeierstrassIsomorphism.is_separable` - - :meth:`sage.schemes.elliptic_curves.hom_composite.EllipticCurveHom_composite.is_separable` - - :meth:`sage.schemes.elliptic_curves.hom_scalar.EllipticCurveHom_scalar.is_separable` - - :meth:`sage.schemes.elliptic_curves.hom_frobenius.EllipticCurveHom_frobenius.is_separable` + - :meth:`EllipticCurveIsogeny.inseparable_degree` + - :meth:`sage.schemes.elliptic_curves.weierstrass_morphism.WeierstrassIsomorphism.inseparable_degree` + - :meth:`sage.schemes.elliptic_curves.hom_composite.EllipticCurveHom_composite.inseparable_degree` + - :meth:`sage.schemes.elliptic_curves.hom_sum.EllipticCurveHom_sum.inseparable_degree` + - :meth:`sage.schemes.elliptic_curves.hom_scalar.EllipticCurveHom_scalar.inseparable_degree` + - :meth:`sage.schemes.elliptic_curves.hom_frobenius.EllipticCurveHom_frobenius.inseparable_degree` TESTS:: sage: from sage.schemes.elliptic_curves.hom import EllipticCurveHom - sage: EllipticCurveHom.is_separable(None) + sage: EllipticCurveHom.inseparable_degree(None) Traceback (most recent call last): ... NotImplementedError: ... """ raise NotImplementedError('children must implement') - def is_surjective(self): + def separable_degree(self): r""" - Determine whether or not this morphism is surjective. + Return the separable degree of this isogeny. - .. NOTE:: + The separable degree is the result of dividing the :meth:`degree` + by the :meth:`inseparable_degree`. + + EXAMPLES:: + + sage: E = EllipticCurve(GF(11), [5,5]) + sage: E.is_supersingular() + False + sage: E.scalar_multiplication(-77).separable_degree() + 539 + sage: E = EllipticCurve(GF(11), [5,0]) + sage: E.is_supersingular() + True + sage: E.scalar_multiplication(-77).separable_degree() + 49 + """ + return self.degree() // self.inseparable_degree() + + def is_separable(self): + r""" + Determine whether or not this morphism is a separable isogeny. + + EXAMPLES:: + + sage: E = EllipticCurve(GF(17), [0,0,0,3,0]) + sage: phi = EllipticCurveIsogeny(E, E((0,0))) + sage: phi.is_separable() + True + + :: + + sage: E = EllipticCurve('11a1') + sage: phi = EllipticCurveIsogeny(E, E.torsion_points()) + sage: phi.is_separable() + True + + :: + + sage: E = EllipticCurve(GF(31337), [0,1]) # needs sage.rings.finite_rings + sage: {f.is_separable() for f in E.automorphisms()} # needs sage.rings.finite_rings + {True} + + :: + + sage: # needs sage.rings.finite_rings + sage: from sage.schemes.elliptic_curves.hom_composite import EllipticCurveHom_composite + sage: E = EllipticCurve(GF(7^2), [3,2]) + sage: P = E.lift_x(1) + sage: phi = EllipticCurveHom_composite(E, P); phi + Composite morphism of degree 7 = 7: + From: Elliptic Curve defined by y^2 = x^3 + 3*x + 2 + over Finite Field in z2 of size 7^2 + To: Elliptic Curve defined by y^2 = x^3 + 3*x + 2 + over Finite Field in z2 of size 7^2 + sage: phi.is_separable() + True + + :: + + sage: E = EllipticCurve(GF(11), [4,4]) + sage: E.scalar_multiplication(11).is_separable() + False + sage: E.scalar_multiplication(-11).is_separable() + False + sage: E.scalar_multiplication(777).is_separable() + True + sage: E.scalar_multiplication(-1).is_separable() + True + sage: E.scalar_multiplication(77).is_separable() + False + sage: E.scalar_multiplication(121).is_separable() + False + + :: + + sage: from sage.schemes.elliptic_curves.hom_frobenius import EllipticCurveHom_frobenius + sage: E = EllipticCurve(GF(11), [1,1]) + sage: pi = EllipticCurveHom_frobenius(E) + sage: pi.degree() + 11 + sage: pi.is_separable() + False + sage: pi = EllipticCurveHom_frobenius(E, 0) + sage: pi.degree() + 1 + sage: pi.is_separable() + True + + :: + + sage: E = EllipticCurve(GF(17), [0,0,0,3,0]) + sage: phi = E.isogeny(E((1,2)), algorithm='velusqrt') + sage: phi.is_separable() + True + """ + if self.is_zero(): + raise ValueError('constant zero map is not an isogeny') + return self.inseparable_degree().is_one() - This method currently always returns ``True``, since a - non-constant map of algebraic curves must be surjective, - and Sage does not yet implement the constant zero map. - This will probably change in the future. + def is_surjective(self): + r""" + Determine whether or not this morphism is surjective. EXAMPLES:: @@ -689,6 +837,9 @@ def is_injective(self): r""" Determine whether or not this morphism has trivial kernel. + The kernel is trivial if and only if this morphism is a + purely inseparable isogeny. + EXAMPLES:: sage: E = EllipticCurve('11a1') @@ -711,22 +862,59 @@ def is_injective(self): sage: phi = EllipticCurveIsogeny(E, E(0)) sage: phi.is_injective() True + + :: + + sage: from sage.schemes.elliptic_curves.hom_composite import EllipticCurveHom_composite + sage: E = EllipticCurve([1,0]) + sage: phi = EllipticCurveHom_composite(E, E(0,0)) + sage: phi.is_injective() + False + sage: E = EllipticCurve_from_j(GF(3).algebraic_closure()(0)) + sage: nu = EllipticCurveHom_composite.from_factors(E.automorphisms()) + sage: nu + Composite morphism of degree 1 = 1^12: + From: Elliptic Curve defined by y^2 = x^3 + x + over Algebraic closure of Finite Field of size 3 + To: Elliptic Curve defined by y^2 = x^3 + x + over Algebraic closure of Finite Field of size 3 + sage: nu.is_injective() + True + + :: + + sage: E = EllipticCurve(GF(23), [1,0]) + sage: E.scalar_multiplication(4).is_injective() + False + sage: E.scalar_multiplication(5).is_injective() + False + sage: E.scalar_multiplication(1).is_injective() + True + sage: E.scalar_multiplication(-1).is_injective() + True + sage: E.scalar_multiplication(23).is_injective() + True + sage: E.scalar_multiplication(-23).is_injective() + True + sage: E.scalar_multiplication(0).is_injective() + False + + :: + + sage: from sage.schemes.elliptic_curves.hom_frobenius import EllipticCurveHom_frobenius + sage: E = EllipticCurve(GF(11), [1,1]) + sage: pi = EllipticCurveHom_frobenius(E, 5) + sage: pi.is_injective() + True """ - if not self.is_separable(): - # TODO: should implement .separable_degree() or similar - raise NotImplementedError - return self.degree() == 1 + if self.is_zero(): + return False + return self.separable_degree().is_one() def is_zero(self): r""" Check whether this elliptic-curve morphism is the zero map. - .. NOTE:: - - This function currently always returns ``True`` as Sage - does not yet implement the constant zero morphism. This - will probably change in the future. - EXAMPLES:: sage: E = EllipticCurve(j=GF(7)(0)) @@ -926,11 +1114,11 @@ def matrix_on_subgroup(self, domain_gens, codomain_gens=None): if R.weil_pairing(S, n).multiplicative_order() != n: raise ValueError('generator points on codomain are not independent') - imP = self(P) - imQ = self(Q) + imP = self._eval(P) + imQ = self._eval(Q) from sage.groups.additive_abelian.additive_abelian_wrapper import AdditiveAbelianGroupWrapper - H = AdditiveAbelianGroupWrapper(self.codomain().point_homset(), [R,S], [n,n]) + H = AdditiveAbelianGroupWrapper(R.parent(), [R,S], [n,n]) vecP = H.discrete_log(imP) vecQ = H.discrete_log(imQ) diff --git a/src/sage/schemes/elliptic_curves/hom_composite.py b/src/sage/schemes/elliptic_curves/hom_composite.py index e457c9854ee..ed87349bdcd 100644 --- a/src/sage/schemes/elliptic_curves/hom_composite.py +++ b/src/sage/schemes/elliptic_curves/hom_composite.py @@ -814,30 +814,6 @@ def dual(self): phis = (phi.dual() for phi in self._phis[::-1]) return EllipticCurveHom_composite.from_factors(phis) - def is_separable(self): - """ - Determine whether this composite isogeny is separable. - - A composition of isogenies is separable if and only if - all factors are. - - EXAMPLES:: - - sage: # needs sage.rings.finite_rings - sage: from sage.schemes.elliptic_curves.hom_composite import EllipticCurveHom_composite - sage: E = EllipticCurve(GF(7^2), [3,2]) - sage: P = E.lift_x(1) - sage: phi = EllipticCurveHom_composite(E, P); phi - Composite morphism of degree 7 = 7: - From: Elliptic Curve defined by y^2 = x^3 + 3*x + 2 - over Finite Field in z2 of size 7^2 - To: Elliptic Curve defined by y^2 = x^3 + 3*x + 2 - over Finite Field in z2 of size 7^2 - sage: phi.is_separable() - True - """ - return all(phi.is_separable() for phi in self._phis) - def formal(self, prec=20): """ Return the formal isogeny corresponding to this composite @@ -899,29 +875,21 @@ def scaling_factor(self): """ return prod(phi.scaling_factor() for phi in self._phis) - def is_injective(self): - """ - Determine whether this composite morphism has trivial kernel. + def inseparable_degree(self): + r""" + Return the inseparable degree of this morphism. - In other words, return ``True`` if and only if ``self`` is a - purely inseparable isogeny. + Like the degree, the inseparable degree is multiplicative + under composition, so this method returns the product of + the inseparable degrees of the factors. EXAMPLES:: - sage: from sage.schemes.elliptic_curves.hom_composite import EllipticCurveHom_composite - sage: E = EllipticCurve([1,0]) - sage: phi = EllipticCurveHom_composite(E, E(0,0)) - sage: phi.is_injective() - False - sage: E = EllipticCurve_from_j(GF(3).algebraic_closure()(0)) - sage: nu = EllipticCurveHom_composite.from_factors(E.automorphisms()) - sage: nu - Composite morphism of degree 1 = 1^12: - From: Elliptic Curve defined by y^2 = x^3 + x - over Algebraic closure of Finite Field of size 3 - To: Elliptic Curve defined by y^2 = x^3 + x - over Algebraic closure of Finite Field of size 3 - sage: nu.is_injective() - True + sage: E = EllipticCurve(j=GF(11^5).random_element()) + sage: phi = E.frobenius_isogeny(2) * E.scalar_multiplication(77) + sage: type(phi) + + sage: phi.inseparable_degree() + 1331 """ - return all(phi.is_injective() for phi in self._phis) + return prod(phi.inseparable_degree() for phi in self._phis) diff --git a/src/sage/schemes/elliptic_curves/hom_frobenius.py b/src/sage/schemes/elliptic_curves/hom_frobenius.py index fb4496aedbb..0c1254e15b0 100644 --- a/src/sage/schemes/elliptic_curves/hom_frobenius.py +++ b/src/sage/schemes/elliptic_curves/hom_frobenius.py @@ -309,20 +309,6 @@ def _repr_(self): # EllipticCurveHom methods - def degree(self): - """ - Return the degree of this Frobenius isogeny. - - EXAMPLES:: - - sage: from sage.schemes.elliptic_curves.hom_frobenius import EllipticCurveHom_frobenius - sage: E = EllipticCurve(GF(11), [1,1]) - sage: pi = EllipticCurveHom_frobenius(E, 4) - sage: pi.degree() - 14641 - """ - return self._degree - def rational_maps(self): """ Return the explicit rational maps defining this Frobenius @@ -515,44 +501,21 @@ def dual(self): iso = find_post_isomorphism(Phi * self, scalar_mul) return iso * Phi - def is_separable(self): - """ - Determine whether or not this Frobenius isogeny is separable. - - Since Frobenius isogenies are purely inseparable, this method - returns ``True`` if and only if the degree is `1`. - - EXAMPLES:: - - sage: from sage.schemes.elliptic_curves.hom_frobenius import EllipticCurveHom_frobenius - sage: E = EllipticCurve(GF(11), [1,1]) - sage: pi = EllipticCurveHom_frobenius(E) - sage: pi.degree() - 11 - sage: pi.is_separable() - False - sage: pi = EllipticCurveHom_frobenius(E, 0) - sage: pi.degree() - 1 - sage: pi.is_separable() - True - """ - return self._degree == 1 - - def is_injective(self): + def inseparable_degree(self): """ - Determine whether or not this Frobenius isogeny has trivial - kernel. + Return the inseparable degree of this Frobenius isogeny. - Since Frobenius isogenies are purely inseparable, this method - always returns ``True``. + Since this class implements only purely inseparable isogenies, + the inseparable degree equals the degree. EXAMPLES:: sage: from sage.schemes.elliptic_curves.hom_frobenius import EllipticCurveHom_frobenius sage: E = EllipticCurve(GF(11), [1,1]) - sage: pi = EllipticCurveHom_frobenius(E, 5) - sage: pi.is_injective() + sage: pi = EllipticCurveHom_frobenius(E, 4) + sage: pi.inseparable_degree() + 14641 + sage: pi.inseparable_degree() == pi.degree() True """ - return True + return self._degree diff --git a/src/sage/schemes/elliptic_curves/hom_scalar.py b/src/sage/schemes/elliptic_curves/hom_scalar.py index 66e675250f9..03f042fd830 100644 --- a/src/sage/schemes/elliptic_curves/hom_scalar.py +++ b/src/sage/schemes/elliptic_curves/hom_scalar.py @@ -452,69 +452,38 @@ def dual(self): """ return self - def is_separable(self): - """ - Determine whether this scalar-multiplication map is a - separable isogeny. (This is the case if and only if the - scalar `m` is coprime to the characteristic.) + def inseparable_degree(self): + r""" + Return the inseparable degree of this scalar-multiplication map. EXAMPLES:: - sage: E = EllipticCurve(GF(11), [4,4]) - sage: E.scalar_multiplication(11).is_separable() - False - sage: E.scalar_multiplication(-11).is_separable() - False - sage: E.scalar_multiplication(777).is_separable() - True - sage: E.scalar_multiplication(-1).is_separable() - True - sage: E.scalar_multiplication(77).is_separable() + sage: E = EllipticCurve(GF(7), [0,1]) + sage: E.is_supersingular() False - sage: E.scalar_multiplication(121).is_separable() - False - - TESTS:: - - sage: E.scalar_multiplication(0).is_separable() - Traceback (most recent call last): - ... - ValueError: [0] is not an isogeny - """ - if self._m.is_zero(): - raise ValueError('[0] is not an isogeny') - return bool(self.scaling_factor()) + sage: E.scalar_multiplication(4).inseparable_degree() + 1 + sage: E.scalar_multiplication(-7).inseparable_degree() + 7 - def is_injective(self): - """ - Determine whether this scalar multiplication defines an - injective map (over the algebraic closure). - - Equivalently, return ``True`` if and only if this scalar - multiplication is a purely inseparable isogeny. - - EXAMPLES:: + :: - sage: E = EllipticCurve(GF(23), [1,0]) - sage: E.scalar_multiplication(4).is_injective() - False - sage: E.scalar_multiplication(5).is_injective() - False - sage: E.scalar_multiplication(1).is_injective() - True - sage: E.scalar_multiplication(-1).is_injective() - True - sage: E.scalar_multiplication(23).is_injective() + sage: E = EllipticCurve(GF(7), [1,0]) + sage: E.is_supersingular() True - sage: E.scalar_multiplication(-23).is_injective() - True - sage: E.scalar_multiplication(0).is_injective() - False + sage: E.scalar_multiplication(4).inseparable_degree() + 1 + sage: E.scalar_multiplication(-7).inseparable_degree() + 49 """ - if self._m.is_zero(): - return False - p = self._domain.base_ring().characteristic() - return self._m.abs().is_power_of(p) and self._domain.is_supersingular() + p = self.base_ring().characteristic() + if not p: + return ZZ.one() + v = self._m.valuation(p) + if not v: + return ZZ.one() + rk = 1 + self._domain.is_supersingular() + return p**(rk*v) def __neg__(self): """ diff --git a/src/sage/schemes/elliptic_curves/hom_sum.py b/src/sage/schemes/elliptic_curves/hom_sum.py new file mode 100644 index 00000000000..6660035634d --- /dev/null +++ b/src/sage/schemes/elliptic_curves/hom_sum.py @@ -0,0 +1,676 @@ +r""" +Sums of morphisms of elliptic curves + +The set `\mathrm{Hom}(E,E')` of morphisms between two elliptic curves +forms an abelian group under pointwise addition. An important special +case is the endomorphism ring `\mathrm{End}(E) = \mathrm{Hom}(E,E)`. +However, it is not immediately obvious how to compute some properties +of the sum `\varphi+\psi` of two isogenies, even when both are given +explicitly. This class provides functionality for representing sums of +elliptic-curve morphisms (in particular, isogenies and endomorphisms) +formally, and explicitly computing important properties (such as the +degree or the kernel polynomial) from the formal representation. + +EXAMPLES:: + + sage: E = EllipticCurve(GF(101), [5,5]) + sage: phi = E.isogenies_prime_degree(7)[0] + sage: phi + phi + Sum morphism: + From: Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 + To: Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101 + Via: (Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101, Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101) + sage: phi + phi == phi * E.scalar_multiplication(2) + True + sage: phi + phi + phi == phi * E.scalar_multiplication(3) + True + +An example of computing with a supersingular endomorphism ring:: + + sage: E = EllipticCurve(GF(419^2), [1,0]) + sage: i = E.automorphisms()[-1] + sage: j = E.frobenius_isogeny() + sage: i * j == - j * i # i,j anticommute + True + sage: (i + j) * i == i^2 - i*j # distributive law + True + sage: (j - E.scalar_multiplication(1)).degree() # point counting! + 420 + +AUTHORS: + +- Lorenz Panny (2023) +""" + +from sage.misc.cachefunc import cached_method +from sage.structure.sequence import Sequence + +from sage.arith.misc import gcd + +from sage.rings.integer_ring import ZZ +from sage.rings.polynomial.polynomial_ring import polygen + +from sage.sets.primes import Primes + +from sage.schemes.elliptic_curves.ell_field import point_of_order +from sage.groups.generic import discrete_log, order_from_multiple + +from sage.schemes.elliptic_curves.hom import EllipticCurveHom, compare_via_evaluation + + +class EllipticCurveHom_sum(EllipticCurveHom): + + _degree = None + _phis = None + + def __init__(self, phis, domain=None, codomain=None): + r""" + Construct a sum morphism of elliptic curves from its summands. + (For empty sums, the domain and codomain curves must be given.) + + EXAMPLES:: + + sage: from sage.schemes.elliptic_curves.hom_sum import EllipticCurveHom_sum + sage: E = EllipticCurve(GF(101), [5,5]) + sage: phi = E.isogenies_prime_degree(7)[0] + sage: EllipticCurveHom_sum([phi, phi]) + Sum morphism: + From: Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 + To: Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101 + Via: (Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101, Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101) + + The zero morphism can be constructed even between non-isogenous curves:: + + sage: E1 = EllipticCurve(GF(101), [5,5]) + sage: E2 = EllipticCurve(GF(101), [7,7]) + sage: E1.is_isogenous(E2) + False + sage: EllipticCurveHom_sum([], E1, E2) + Sum morphism: + From: Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 + To: Elliptic Curve defined by y^2 = x^3 + 7*x + 7 over Finite Field of size 101 + Via: () + """ + phis = tuple(phis) + + if not phis and (domain is None or codomain is None): + raise ValueError('need either phis or both domain and codomain') + + for phi in phis: + if not isinstance(phi, EllipticCurveHom): + raise ValueError(f'not an elliptic-curve morphism: {phi}') + + if domain is None: + domain = phis[0].domain() + if codomain is None: + codomain = phis[0].codomain() + for phi in phis: + if phi.domain() != domain: + raise ValueError(f'summand {phi} has incorrect domain (need {domain})') + if phi.codomain() != codomain: + raise ValueError(f'summand {phi} has incorrect codomain (need {codomain})') + + self._phis = phis + self._domain = domain + self._codomain = codomain + + # We temporarily overwrite the _degree attribute here to prevent the + # EllipticCurveHom constructor from attempting to compute the degree. + self._degree = 0 + EllipticCurveHom.__init__(self, self._domain, self._codomain) + self._degree = None + + def _call_(self, P): + r""" + Evaluate this sum morphism at a point. + + EXAMPLES:: + + sage: E = EllipticCurve(GF(101), [5,5]) + sage: phi = E.isogenies_prime_degree(7)[0] + sage: P = E.lift_x(0) + sage: (phi + phi)(P) + (72 : 56 : 1) + sage: (phi - phi)(P) + (0 : 1 : 0) + """ + return sum((phi(P) for phi in self._phis), self._codomain(0)) + + def _eval(self, P): + r""" + Less strict evaluation method for internal use. + + In particular, this can be used to evaluate ``self`` at a + point defined over an extension field. + + INPUT: a sequence of 3 coordinates defining a point on ``self`` + + OUTPUT: the result of evaluating ``self`` at the given point + + EXAMPLES:: + + sage: E = EllipticCurve(GF(101), [5,5]) + sage: phi = E.isogenies_prime_degree(7)[0] + sage: P = E.change_ring(GF(101^2)).lift_x(1) + sage: (phi + phi)._eval(P) + (11 : 15*z2 + 71 : 1) + sage: (phi - phi)._eval(P) + (0 : 1 : 0) + """ + if self._domain.defining_polynomial()(*P): + raise ValueError(f'{P} not on {self._domain}') + k = Sequence(P).universe() + return sum((phi._eval(P) for phi in self._phis), self._codomain.base_extend(k)(0)) + + def _repr_(self): + r""" + Return basic facts about this sum morphism as a string. + + EXAMPLES:: + + sage: E = EllipticCurve(GF(101), [5,5]) + sage: phi = E.isogenies_prime_degree(7)[0] + sage: phi + phi # indirect doctest + Sum morphism: + From: Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 + To: Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101 + Via: (Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101, Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101) + """ + return f'Sum morphism:' \ + f'\n From: {self._domain}' \ + f'\n To: {self._codomain}' \ + f'\n Via: {self._phis}' + + def summands(self): + r""" + Return the individual summands making up this sum morphism. + + EXAMPLES:: + + sage: E = EllipticCurve(j=5) + sage: m2 = E.scalar_multiplication(2) + sage: m3 = E.scalar_multiplication(3) + sage: m2 + m3 + Sum morphism: + From: Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 180*x + 17255 over Rational Field + To: Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 180*x + 17255 over Rational Field + Via: (Scalar-multiplication endomorphism [2] of Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 180*x + 17255 over Rational Field, Scalar-multiplication endomorphism [3] of Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 180*x + 17255 over Rational Field) + """ + return self._phis + + @cached_method + def to_isogeny_chain(self): + r""" + Convert this formal sum of elliptic-curve morphisms into a + :class:`~sage.schemes.elliptic_curves.hom_composite.EllipticCurveHom_composite` + object representing the same morphism. + + EXAMPLES:: + + sage: E = EllipticCurve(GF(101), [5,5]) + sage: phi = E.isogenies_prime_degree(7)[0] + sage: (phi + phi).to_isogeny_chain() + Composite morphism of degree 28 = 4*1*7: + From: Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 + To: Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101 + + :: + + sage: p = 419 + sage: E = EllipticCurve(GF(p^2), [1,0]) + sage: iota = E.automorphisms()[2] # sqrt(-1) + sage: pi = E.frobenius_isogeny() # sqrt(-p) + sage: endo = iota + pi + sage: endo.degree() + 420 + sage: endo.to_isogeny_chain() + Composite morphism of degree 420 = 4*1*3*5*7: + From: Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 419^2 + To: Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 419^2 + + The decomposition is impossible for the constant zero map:: + + sage: endo = iota*pi + pi*iota + sage: endo.degree() + 0 + sage: endo.to_isogeny_chain() + Traceback (most recent call last): + ... + ValueError: zero morphism cannot be written as a composition of isogenies + + Isomorphisms are supported as well:: + + sage: E = EllipticCurve(j=5); E + Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 180*x + 17255 over Rational Field + sage: m2 = E.scalar_multiplication(2) + sage: m3 = E.scalar_multiplication(3) + sage: (m2 - m3).to_isogeny_chain() + Composite morphism of degree 1 = 1^2: + From: Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 180*x + 17255 over Rational Field + To: Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 180*x + 17255 over Rational Field + sage: (m2 - m3).rational_maps() + (x, -x - y) + """ + deg = self.degree() + if deg.is_zero(): + raise ValueError('zero morphism cannot be written as a composition of isogenies') + + p = self.base_ring().characteristic() + insep = self.inseparable_degree().valuation(p) if p else 0 + + scalar = 1 #TODO Can we detect scalar factors earlier to save some extensions below? + + ker = [] + for l,m in deg.factor(): + if l == p: # possibly inseparable + if insep < m: + # kernel of the separable p-power part is unique + P = point_of_order(self.domain(), p**(m-insep)) + ker.append(P) + continue + +# F = self.domain().division_field(l**m) #FIXME this can be used once #35936 is done; workaround below + F = self.domain().division_polynomial(l**m).splitting_field('X').extension(2,'Y') + + P,Q = self.domain().change_ring(F).torsion_basis(l**m) + if self.is_endomorphism(): + R,S = P,Q + else: + R,S = self.codomain().change_ring(F).torsion_basis(l**m) + M = self.matrix_on_subgroup((P,Q), (R,S)) + g = ZZ(gcd(M.list())).p_primary_part(l) + if g > 1: + scalar *= g + M = (M.change_ring(ZZ) / g).change_ring(M.base_ring()) + K = M.left_kernel_matrix() + for row in K: + u,v = map(ZZ, row) + pt = u*P + v*Q + pt.set_order(row.additive_order()) + ker.append(pt) + + from sage.schemes.elliptic_curves.hom_composite import EllipticCurveHom_composite + phi = EllipticCurveHom_composite(self.domain(), []) + + if scalar != 1: + phi *= phi.codomain().scalar_multiplication(scalar) + + while ker: + K = ker.pop(0) + + (l,e), = K.order().factor() + for i in reversed(range(e)): + Kl = l**i * K + Kl.set_order(l) + + from sage.groups.generic import multiples + from sage.misc.misc_c import prod + x = polygen(Kl.base_ring()) + poly = prod(x - T.xy()[0] for T in multiples(Kl, l//2, Kl)) + poly = poly.change_ring(self.base_ring()) + + psi = phi.codomain().isogeny(poly) + phi = psi * phi + K = psi._eval(K) + ker = [psi._eval(P) for P in ker] + + if insep: + frob = phi.codomain().frobenius_isogeny(insep) + phi = frob * phi + + from sage.schemes.elliptic_curves.hom import find_post_isomorphism + iso = find_post_isomorphism(phi, self) + return iso * phi + + # EllipticCurveHom methods + + def _degree_bounds(self): + r""" + Return a lower and upper bound on the degree of this sum morphism. + + EXAMPLES:: + + sage: E = EllipticCurve(GF(307), [5,5]) + sage: phi = E.isogenies_prime_degree(3)[0]; phi + Isogeny of degree 3 from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 307 to Elliptic Curve defined by y^2 = x^3 + 227*x + 163 over Finite Field of size 307 + sage: psi = next(iso*psi for psi in E.isogenies_prime_degree(43) + ....: for iso in psi.codomain().isomorphisms(phi.codomain())); psi + Isogeny of degree 43 from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 307 to Elliptic Curve defined by y^2 = x^3 + 227*x + 163 over Finite Field of size 307 + sage: (phi + psi)._degree_bounds() + (24, 68) + sage: (phi + psi).degree() + 61 + sage: (phi - phi)._degree_bounds() + (0, 12) + sage: (phi - phi).degree() + 0 + + :: + + sage: E = EllipticCurve(GF(443), [1,1]) + sage: pi = E.frobenius_endomorphism() + sage: m1 = E.scalar_multiplication(1) + sage: (pi - m1)._degree_bounds() + (402, 486) + sage: (pi - m1)._degree_bounds() == Hasse_bounds(443) + True + sage: (pi - m1).degree() + 433 + + ALGORITHM: Repeated application of the Cauchy-Schwarz inequality, + here in the form + `|\deg(f+g) - \deg(f) - \deg(g)| \leq 2\sqrt{\deg(f)\cdot\deg(g)}`. + See for instance Lemma V.1.2 of [Sil2009]_. + """ + lo, hi = ZZ.zero(), ZZ.zero() + for phi in self._phis: + m = (hi * phi.degree()).isqrt() + hi += phi.degree() + 2*m + lo += phi.degree() - 2*m + lo = max(lo, 0) + return lo, hi + + def _compute_degree(self): + r""" + Internal method to compute and cache the degree of this sum morphism + (and its dual). + + ALGORITHM: Evaluate the composition with the dual on points of small + order and solve logarithms to eventually recover the degree using CRT. + (This is essentially Schoof's algorithm, applied to a scalar.) + + EXAMPLES:: + + sage: E = EllipticCurve(GF(101), [5,5]) + sage: phi = E.isogenies_prime_degree(7)[0] + sage: isog = phi + phi + sage: print(isog._degree) + None + sage: isog._compute_degree() + sage: isog._degree + 28 + + :: + + sage: E = EllipticCurve(GF(443), [1,1]) + sage: pi = E.frobenius_endomorphism() + sage: m1 = E.scalar_multiplication(1) + sage: endo = pi - m1 + sage: print(endo._degree) + None + sage: endo._compute_degree() + sage: endo._degree + 433 + sage: endo.dual()._degree + 433 + """ + if self._degree is not None: + return + if len(self._phis) == 0: + self._degree = 0 + elif len(self._phis) == 1: + self._degree = self._phis[0].degree() + else: + #TODO In some cases it would probably be faster to simply + # compute the kernel polynomial using the addition formulas? + from sage.rings.finite_rings.integer_mod import Mod + + lo, hi = self._degree_bounds() + M = hi - lo + 1 + rem = Mod(0,1) + for l in Primes(): + if rem.modulus() >= M: + break + try: + P = point_of_order(self._domain, l) + except ValueError: + continue # supersingular and l == p + + Q = self.dual()._eval(self._eval(P)) + d = discrete_log(Q, P, ord=l, operation='+') + rem = rem.crt(Mod(d-lo, l)) + + self._degree = lo + rem.lift() + self.dual()._degree = self._degree + + @staticmethod + def _comparison_impl(left, right, op): + r""" + Compare a sum morphism to another elliptic-curve morphism. + + Called by :meth:`EllipticCurveHom._richcmp_`. + + If possible, we use + :func:`~sage.schemes.elliptic_curves.hom.compare_via_evaluation`. + The complexity in that case is polynomial in the logarithm of + the degree. + + TESTS:: + + sage: from sage.schemes.elliptic_curves.hom_sum import EllipticCurveHom_sum + sage: E = EllipticCurve(GF(419^2), [1,0]) + sage: i = E.automorphisms()[-1] + sage: j = E.frobenius_isogeny() + sage: i + j == j + i + True + """ + from sage.structure.richcmp import op_EQ + if op != op_EQ: + return NotImplemented + try: + return compare_via_evaluation(left, right) + except NotImplementedError: + return NotImplemented + + def degree(self): + r""" + Return the degree of this sum morphism. + + EXAMPLES:: + + sage: E = EllipticCurve(GF(101), [5,5]) + sage: phi = E.isogenies_prime_degree(7)[0] + sage: (phi + phi).degree() + 28 + + This method yields a simple toy point-counting algorithm:: + + sage: E = EllipticCurve(GF(101), [5,5]) + sage: m1 = E.scalar_multiplication(1) + sage: pi = E.frobenius_endomorphism() + sage: (pi - m1).degree() + 119 + sage: E.count_points() + 119 + + ALGORITHM: Essentially Schoof's algorithm; see :meth:`_compute_degree`. + """ + if self._degree is None: + self._compute_degree() + return self._degree + + def rational_maps(self): + r""" + Return the rational maps of this sum morphism. + + EXAMPLES:: + + sage: E = EllipticCurve(GF(101), [5,5]) + sage: phi = E.isogenies_prime_degree(7)[0] + sage: (phi + phi).rational_maps() + ((5*x^28 + 43*x^27 + 26*x^26 - ... + 7*x^2 - 23*x + 38)/(23*x^27 + 16*x^26 + 9*x^25 + ... - 43*x^2 - 22*x + 37), + (42*x^42*y - 44*x^41*y - 22*x^40*y + ... - 26*x^2*y - 50*x*y - 18*y)/(-24*x^42 - 47*x^41 - 12*x^40 + ... + 18*x^2 - 48*x + 18)) + + ALGORITHM: :meth:`to_isogeny_chain`. + """ + #TODO In some cases it would probably be faster to compute this + # directly using the addition formulas? + return self.to_isogeny_chain().rational_maps() + + def x_rational_map(self): + r""" + Return the `x`-coordinate rational map of this sum morphism. + + EXAMPLES:: + + sage: E = EllipticCurve(GF(101), [5,5]) + sage: phi = E.isogenies_prime_degree(7)[0] + sage: (phi + phi).x_rational_map() + (9*x^28 + 37*x^27 + 67*x^26 + ... + 53*x^2 + 100*x + 28)/(x^27 + 49*x^26 + 97*x^25 + ... + 64*x^2 + 21*x + 6) + + ALGORITHM: :meth:`to_isogeny_chain`. + """ + #TODO In some cases it would probably be faster to compute this + # directly using the addition formulas? + return self.to_isogeny_chain().x_rational_map() + + def kernel_polynomial(self): + r""" + Return the kernel polynomial of this sum morphism. + + EXAMPLES:: + + sage: E = EllipticCurve(GF(101), [5,5]) + sage: phi = E.isogenies_prime_degree(7)[0] + sage: (phi + phi).kernel_polynomial() + x^15 + 75*x^14 + 16*x^13 + 59*x^12 + 28*x^11 + 60*x^10 + 69*x^9 + 79*x^8 + 79*x^7 + 52*x^6 + 35*x^5 + 11*x^4 + 37*x^3 + 69*x^2 + 66*x + 63 + + :: + + sage: E = EllipticCurve(GF(11), [5,5]) + sage: pi = E.frobenius_endomorphism() + sage: m1 = E.scalar_multiplication(1) + sage: (pi - m1).kernel_polynomial() + x^9 + 7*x^8 + 2*x^7 + 4*x^6 + 10*x^4 + 4*x^3 + 9*x^2 + 7*x + + ALGORITHM: :meth:`to_isogeny_chain`. + """ + #TODO In some cases it would probably be faster to compute this + # directly using the addition formulas? + return self.to_isogeny_chain().kernel_polynomial() + + def scaling_factor(self): + r""" + Return the Weierstrass scaling factor associated to this + sum morphism. + + The scaling factor is the constant `u` (in the base field) + such that `\varphi^* \omega_2 = u \omega_1`, where + `\varphi: E_1\to E_2` is this morphism and `\omega_i` are + the standard Weierstrass differentials on `E_i` defined by + `\mathrm dx/(2y+a_1x+a_3)`. + + + EXAMPLES:: + + sage: E = EllipticCurve(GF(101), [5,5]) + sage: phi = E.isogenies_prime_degree(7)[0] + sage: phi.scaling_factor() + 84 + sage: (phi + phi).scaling_factor() + 67 + + ALGORITHM: The scaling factor is additive under addition + of elliptic-curve morphisms, so we simply add together the + scaling factors of the :meth:`summands`. + """ + return sum(phi.scaling_factor() for phi in self._phis) + + @cached_method + def dual(self): + r""" + Return the dual of this sum morphism. + + EXAMPLES:: + + sage: E = EllipticCurve(GF(101), [5,5]) + sage: phi = E.isogenies_prime_degree(7)[0] + sage: (phi + phi).dual() + Sum morphism: + From: Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101 + To: Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 + Via: (Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101, Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101) + sage: (phi + phi).dual() == phi.dual() + phi.dual() + True + + :: + + sage: E = EllipticCurve(GF(431^2), [1,0]) + sage: iota = E.automorphisms()[2] + sage: m2 = E.scalar_multiplication(2) + sage: endo = m2 + iota + sage: endo.dual() + Sum morphism: + From: Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 431^2 + To: Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 431^2 + Via: (Scalar-multiplication endomorphism [2] of Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 431^2, Elliptic-curve endomorphism of Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 431^2 + Via: (u,r,s,t) = (8*z2 + 427, 0, 0, 0)) + sage: endo.dual() == (m2 - iota) + True + + ALGORITHM: Taking the dual distributes over addition. + """ + psi = EllipticCurveHom_sum((phi.dual() for phi in self._phis), + domain=self._codomain, codomain=self._domain) + psi._degree = self._degree + if self.trace.is_in_cache(): + psi.trace.set_cache(-self.trace.cache) + psi.dual.set_cache(self) + return psi + + @cached_method + def inseparable_degree(self): + r""" + Compute the inseparable degree of this sum morphism. + + EXAMPLES:: + + sage: E = EllipticCurve(GF(7), [0,1]) + sage: m3 = E.scalar_multiplication(3) + sage: m3.inseparable_degree() + 1 + sage: m4 = E.scalar_multiplication(4) + sage: m7 = m3 + m4; m7 + Sum morphism: + From: Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7 + To: Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7 + Via: (Scalar-multiplication endomorphism [3] of Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7, Scalar-multiplication endomorphism [4] of Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7) + sage: m7.degree() + 49 + sage: m7.inseparable_degree() + 7 + + A supersingular example:: + + sage: E = EllipticCurve(GF(7), [1,0]) + sage: m3 = E.scalar_multiplication(3) + sage: m3.inseparable_degree() + 1 + sage: m4 = E.scalar_multiplication(4) + sage: m7 = m3 + m4; m7 + Sum morphism: + From: Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 7 + To: Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 7 + Via: (Scalar-multiplication endomorphism [3] of Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 7, Scalar-multiplication endomorphism [4] of Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 7) + sage: m7.inseparable_degree() + 49 + """ + if self.is_zero(): + raise ValueError('zero morphism is not an isogeny') + + p = self.base_ring().characteristic() + if not p: + return ZZ.one() + + m = self.degree().valuation(p) + if not m: + return ZZ.one() + + try: + P = point_of_order(self.domain(), p**m) + except ValueError: + # supersingular; every p-isogeny is purely inseparable + return p**m + + Q = self._eval(P) + return order_from_multiple(Q, p**m) diff --git a/src/sage/schemes/elliptic_curves/hom_velusqrt.py b/src/sage/schemes/elliptic_curves/hom_velusqrt.py index 4bc84d944f8..fbe4887dbae 100644 --- a/src/sage/schemes/elliptic_curves/hom_velusqrt.py +++ b/src/sage/schemes/elliptic_curves/hom_velusqrt.py @@ -1173,21 +1173,21 @@ def scaling_factor(self): """ return self._pre_iso.scaling_factor() * self._post_iso.scaling_factor() - def is_separable(self): + def inseparable_degree(self): r""" - Determine whether or not this isogeny is separable. + Return the inseparable degree of this square-root Vélu + isogeny. Since :class:`EllipticCurveHom_velusqrt` only implements - separable isogenies, this method always returns ``True``. + separable isogenies, this method always returns one. - EXAMPLES:: + TESTS:: - sage: E = EllipticCurve(GF(17), [0,0,0,3,0]) - sage: phi = E.isogeny(E((1,2)), algorithm='velusqrt') - sage: phi.is_separable() - True + sage: from sage.schemes.elliptic_curves.hom_velusqrt import EllipticCurveHom_velusqrt + sage: EllipticCurveHom_velusqrt.inseparable_degree(None) + 1 """ - return True + return Integer(1) def _random_example_for_testing(): diff --git a/src/sage/schemes/elliptic_curves/mod_poly.py b/src/sage/schemes/elliptic_curves/mod_poly.py new file mode 100644 index 00000000000..cb8cd703f69 --- /dev/null +++ b/src/sage/schemes/elliptic_curves/mod_poly.py @@ -0,0 +1,167 @@ +r""" +Modular polynomials for elliptic curves + +For a positive integer `\ell`, the classical modular polynomial +`\Phi_\ell \in \ZZ[X,Y]` is characterized by the property that its +zero set is exactly the set of pairs of `j`-invariants connected +by a cyclic `\ell`-isogeny. + +AUTHORS: + +- Lorenz Panny (2023) +""" + +from sage.structure.element import parent + +from sage.rings.integer_ring import ZZ + +from sage.libs.pari import pari +from cypari2.handle_error import PariError + +from sage.databases.db_modular_polynomials import ClassicalModularPolynomialDatabase +_db = ClassicalModularPolynomialDatabase() + +_cache_bound = 100 +_cache = dict() + +def classical_modular_polynomial(l, j=None): + r""" + Return the classical modular polynomial `\Phi_\ell`, either as a + "generic" bivariate polynomial over `\ZZ`, or as an "instantiated" + modular polynomial where one variable has been replaced by the + given `j`-invariant. + + Generic polynomials are cached up to a certain size of `\ell`, + which significantly accelerates subsequent invocations with the + same `\ell`. The default bound is `\ell \leq 100`, which can be + adjusted using ``classical_modular_polynomial.set_cache_bound()`` + with a different value. Beware that modular polynomials are very + big objects and the amount of memory consumed by the cache will + grow rapidly when the bound is set to a large value. + + INPUT: + + - ``l`` -- positive integer. + - ``j`` -- either ``None`` or a ring element: + + * if ``None`` is given, the original modular polynomial + is returned as an element of `\ZZ[X,Y]` + * if a ring element `j \in R` is given, the evaluation + `\Phi_\ell(j,Y)` is returned as an element of the + univariate polynomial ring `R[Y]` + + ALGORITHMS: + + - The Kohel database + :class:`~sage.databases.db_modular_polynomials.ClassicalModularPolynomialDatabase` + - :pari:`polmodular` + + EXAMPLES:: + + sage: classical_modular_polynomial(2) + -X^2*Y^2 + X^3 + 1488*X^2*Y + 1488*X*Y^2 + Y^3 - 162000*X^2 + 40773375*X*Y - 162000*Y^2 + 8748000000*X + 8748000000*Y - 157464000000000 + sage: j = Mod(1728, 419) + sage: classical_modular_polynomial(3, j) + Y^4 + 230*Y^3 + 84*Y^2 + 118*Y + 329 + + Increasing the cache size can be useful for repeated invocations:: + + sage: %timeit classical_modular_polynomial(101) # not tested + 6.11 s ± 1.21 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) + sage: %timeit classical_modular_polynomial(101, GF(65537).random_element()) # not tested + 5.43 s ± 2.71 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) + + sage: classical_modular_polynomial.set_cache_bound(150) # not tested + sage: %timeit classical_modular_polynomial(101) # not tested + The slowest run took 10.35 times longer than the fastest. This could mean that an intermediate result is being cached. + 1.84 µs ± 1.84 µs per loop (mean ± std. dev. of 7 runs, 1 loop each) + sage: %timeit classical_modular_polynomial(101, GF(65537).random_element()) # not tested + 59.8 ms ± 29.4 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) + + TESTS:: + + sage: q = random_prime(50)^randrange(1,4) + sage: j = GF(q).random_element() + sage: l = random_prime(50) + sage: Y = polygen(parent(j), 'Y') + sage: classical_modular_polynomial(l,j) == classical_modular_polynomial(l)(j,Y) + True + """ + l = ZZ(l) + + if j is None: + # We are supposed to return the generic modular polynomial. First + # check if it is already in the cache, then check the database, + # finally compute it using PARI. + try: + return _cache[l] + except KeyError: + pass + + try: + Phi = ZZ['X,Y'](_db[l]) + except ValueError: + try: + pari_Phi = pari.polmodular(l) + except PariError: + raise NotImplementedError('modular polynomial is not in database and computing it on the fly is not yet implemented') + d = {(i, j): c for i,f in enumerate(pari_Phi) for j, c in enumerate(f)} + Phi = ZZ['X,Y'](d) + + if l <= _cache_bound: + _cache[l] = Phi + + return Phi + + R = parent(j)['Y'] + Y = R.gen() + + # If the generic polynomial is in the cache or the database, evaluating + # it directly should always be faster than recomputing it from scratch. + if l in _cache: + return _cache[l](j, Y) + try: + Phi = _db[l] + except ValueError: + pass + else: + if l <= _cache_bound: + _cache[l] = ZZ['X,Y'](Phi) + return Phi(j, Y) + + # Now try to get the instantiated modular polynomial directly from PARI. + # This should be slightly more efficient (in particular regarding memory + # usage) than computing and evaluating the generic modular polynomial. + try: + pari_Phi = pari.polmodular(l, 0, j) + except PariError: + pass + else: + return R(pari_Phi) + + # Nothing worked. Fall back to computing the generic modular polynomial + # and simply evaluating it. + return classical_modular_polynomial(l)(j, Y) + +def _set_cache_bound(bnd): + r""" + Internal helper function to allow setting the caching cutoff for + :func:`classical_modular_polynomial`. + + Exposed as ``classical_modular_polynomial.set_cache_bound()``. + + EXAMPLES:: + + sage: import sage.schemes.elliptic_curves.mod_poly as m + sage: m._cache_bound + 100 + sage: m._set_cache_bound(123) + sage: m._cache_bound + 123 + sage: classical_modular_polynomial.set_cache_bound is m._set_cache_bound + True + """ + global _cache_bound + _cache_bound = bnd + +classical_modular_polynomial.set_cache_bound = _set_cache_bound diff --git a/src/sage/schemes/elliptic_curves/weierstrass_morphism.py b/src/sage/schemes/elliptic_curves/weierstrass_morphism.py index 57ff015a2b2..952d19ad0a6 100644 --- a/src/sage/schemes/elliptic_curves/weierstrass_morphism.py +++ b/src/sage/schemes/elliptic_curves/weierstrass_morphism.py @@ -611,7 +611,7 @@ def _eval(self, P): Q = baseWI.__call__(self, P) return self._codomain.base_extend(k).point(Q) - def __call__(self, P): + def _call_(self, P): r""" Call function for WeierstrassIsomorphism class. @@ -648,6 +648,24 @@ def __call__(self, P): 432 sage: E(i(P))._order 432 + + Check that the isomorphism cannot be evaluated on points outside + its domain (see :issue:`35799`):: + + sage: # needs sage.rings.finite_rings + sage: E = EllipticCurve(GF(101), [1,1]) + sage: f = E.automorphisms()[0] + sage: EE = EllipticCurve(GF(101), [5,5]) + sage: P = EE.lift_x(2) + sage: P in f.domain() + False + sage: f(P) + Traceback (most recent call last): + ... + TypeError: (2 : 15 : 1) fails to convert into the map's + domain Elliptic Curve defined by y^2 = x^3 + x + 1 over + Finite Field of size 101, but a `pushforward` method is + not properly implemented """ if P[2] == 0: return self._codomain(0) @@ -849,21 +867,6 @@ def kernel_polynomial(self): """ return self._poly_ring(1) - def is_separable(self): - r""" - Determine whether or not this isogeny is separable. - - Since :class:`WeierstrassIsomorphism` only implements - isomorphisms, this method always returns ``True``. - - EXAMPLES:: - - sage: E = EllipticCurve(GF(31337), [0,1]) # needs sage.rings.finite_rings - sage: {f.is_separable() for f in E.automorphisms()} # needs sage.rings.finite_rings - {True} - """ - return True - def dual(self): """ Return the dual isogeny of this isomorphism. @@ -956,6 +959,20 @@ def scaling_factor(self): """ return self.u + def inseparable_degree(self): + r""" + Return the inseparable degree of this Weierstrass isomorphism. + + For isomorphisms, this method always returns one. + + TESTS:: + + sage: from sage.schemes.elliptic_curves.weierstrass_morphism import WeierstrassIsomorphism + sage: WeierstrassIsomorphism.inseparable_degree(None) + 1 + """ + return Integer(1) + def identity_morphism(E): r""" 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 05d24e78a85..581102b5c5b 100644 --- a/src/sage/schemes/plane_conics/con_rational_function_field.py +++ b/src/sage/schemes/plane_conics/con_rational_function_field.py @@ -198,38 +198,6 @@ def has_rational_point(self, point=False, algorithm='default', Fraction Field of Univariate Polynomial Ring in u over Rational Field with modulus v^2 - u^3 - 1 - ``has_rational_point`` fails for some conics over function fields - over finite fields, due to :trac:`20003`:: - - sage: K. = PolynomialRing(GF(7)) - sage: C = Conic([5*t^2 + 4, t^2 + 3*t + 3, 6*t^2 + 3*t + 2, - ....: 5*t^2 + 5, 4*t + 3, 4*t^2 + t + 5]) - sage: C.has_rational_point() # needs sage.libs.singular - Traceback (most recent call last): - ... - TypeError: self (=Scheme morphism: - From: Projective Conic Curve over Fraction Field of Univariate - Polynomial Ring in t over Finite Field of size 7 defined by - (-2*t^2 - 3)*x^2 + (-t^3 + 3*t^2 - 2*t - 2)/(t + 3)*y^2 + (-t^6 + 3*t^5 + t^3 - t^2 - t + 2)/(t^4 + t^3 - 3*t^2 + 3*t + 1)*z^2 - To: Projective Conic Curve over Fraction Field of Univariate - Polynomial Ring in t over Finite Field of size 7 defined by - (-2*t^2 - 3)*x^2 + (t^2 + 3*t + 3)*x*y + (-2*t^2 - 2)*y^2 + (-t^2 + 3*t + 2)*x*z + (-3*t + 3)*y*z + (-3*t^2 + t - 2)*z^2 - Defn: Defined on coordinates by sending (x : y : z) to - (x + (2*t - 2)/(t + 3)*y + (3*t^4 + 2*t^3 - 2*t^2 - 2*t + 3)/(t^4 + t^3 - 3*t^2 + 3*t + 1)*z - : y + (-t^3 - t^2 + 3*t - 1)/(t^3 - 3*t^2 + 2*t + 2)*z : z)) - domain must equal right (=Scheme morphism: - From: Projective Conic Curve over Fraction Field of Univariate - Polynomial Ring in t over Finite Field of size 7 defined by - (-2*t^3 - t^2 + 3*t + 3)*x^2 + (t - 3)*y^2 + (-t^7 + 2*t^5 + t^4 + 2*t^3 + 3*t^2 - t - 1)*z^2 - To: Projective Conic Curve over Fraction Field of Univariate - Polynomial Ring in t over Finite Field of size 7 defined by - -2/(t^3 - 3*t^2 + 2*t + 2)*x^2 + 1/(t^3 + 3*t^2 - 2*t + 1)*y^2 + (-t^6 + 3*t^5 + t^3 - t^2 - t + 2)/(t^9 - 2*t^8 + t^7 - t^6 + 3*t^5 - 3*t^3 + t^2 - 2*t + 3)*z^2 - Defn: Defined on coordinates by sending (x : y : z) to - ((t^3 - 3*t^2 + 2*t + 2)*x : (t^2 - 2)*y : (t^5 - 3*t^4 + t^2 + 3*t + 3)*z)) - codomain - - - TESTS:: sage: K. = FractionField(PolynomialRing(QQ, 't')) @@ -250,6 +218,16 @@ def has_rational_point(self, point=False, algorithm='default', sage: C.has_rational_point(point=True) # long time (4 seconds) # needs sage.libs.singular (True, ((-2/117*t^8 + 304/1053*t^7 + 40/117*t^6 - 1/27*t^5 - 110/351*t^4 - 2/195*t^3 + 11/351*t^2 + 1/117)/(t^4 + 2/39*t^3 + 4/117*t^2 + 2/39*t + 14/39) : -5/3*t^4 + 19*t^3 : 1)) + + ``has_rational_point`` used to fail for some conics over function fields + over finite fields, due to :trac:`20003`:: + + sage: K. = PolynomialRing(GF(7)) + sage: C = Conic([5*t^2 + 4, t^2 + 3*t + 3, 6*t^2 + 3*t + 2, + ....: 5*t^2 + 5, 4*t + 3, 4*t^2 + t + 5]) + sage: C.has_rational_point() + True + """ from .constructor import Conic diff --git a/src/sage/structure/coerce.pyx b/src/sage/structure/coerce.pyx index 8eed934aea3..1e7c4dd1a49 100644 --- a/src/sage/structure/coerce.pyx +++ b/src/sage/structure/coerce.pyx @@ -517,6 +517,8 @@ cdef class CoercionModel: Check that :trac:`8426` is fixed (see also :trac:`18076`):: sage: import numpy # needs numpy + + sage: # needs sage.rings.real_mpfr sage: x = polygen(RR) sage: numpy.float32('1.5') * x # needs numpy 1.50000000000000*x diff --git a/src/sage/structure/factorization.py b/src/sage/structure/factorization.py index 00571876e39..00ad9658e59 100644 --- a/src/sage/structure/factorization.py +++ b/src/sage/structure/factorization.py @@ -1232,9 +1232,10 @@ def __call__(self, *args, **kwds): sage: F(t=0) 0 - sage: R. = LaurentPolynomialRing(QQ, 1) # needs sage.modules - sage: F = ((x+2)/x**3).factor() # needs sage.modules - sage: F(x=4) # needs sage.modules + sage: # needs sage.libs.pari sage.modules + sage: R. = LaurentPolynomialRing(QQ, 1) + sage: F = ((x+2)/x**3).factor() + sage: F(x=4) 1/64 * 6 """ unit = self.__unit.subs(*args, **kwds) diff --git a/src/sage/structure/parent_old.pyx b/src/sage/structure/parent_old.pyx index c093febf375..c2afaa89000 100644 --- a/src/sage/structure/parent_old.pyx +++ b/src/sage/structure/parent_old.pyx @@ -52,7 +52,7 @@ cdef class Parent(parent.Parent): [(0, 0), (1, 0), (0, 1), (1, 1)] sage: MatrixSpace(GF(3), 1, 1).list() [[0], [1], [2]] - sage: DirichletGroup(3).list() # needs sage.modular + sage: DirichletGroup(3).list() # needs sage.libs.pari sage.modular [Dirichlet character modulo 3 of conductor 1 mapping 2 |--> 1, Dirichlet character modulo 3 of conductor 3 mapping 2 |--> -1] diff --git a/src/sage/symbolic/function.pyx b/src/sage/symbolic/function.pyx index 589c500d00d..792d81ebcc9 100644 --- a/src/sage/symbolic/function.pyx +++ b/src/sage/symbolic/function.pyx @@ -642,10 +642,11 @@ cdef class Function(SageObject): sage: hurwitz_zeta(1/2, b) hurwitz_zeta(1/2, [1.500000000 +/- 1.01e-10]) - sage: iv = RIF(1, 1.0001) - sage: airy_ai(iv) + sage: iv = RIF(1, 1.0001) # needs sage.rings.real_interval_field + + sage: airy_ai(iv) # needs sage.rings.real_interval_field airy_ai(1.0001?) - sage: airy_ai(CIF(iv)) + sage: airy_ai(CIF(iv)) # needs sage.rings.complex_interval_field airy_ai(1.0001?) """ if isinstance(x, (float, complex)): diff --git a/src/sage/symbolic/ginac/inifcns_orthopoly.cpp b/src/sage/symbolic/ginac/inifcns_orthopoly.cpp index a591cb4cd7c..a90f2050c59 100644 --- a/src/sage/symbolic/ginac/inifcns_orthopoly.cpp +++ b/src/sage/symbolic/ginac/inifcns_orthopoly.cpp @@ -20,6 +20,7 @@ #include "utils.h" #include "gmp.h" +#include "flint/fmpz_poly.h" #include "flint/fmpq_poly.h" #include "flint/fmpq.h" @@ -63,7 +64,7 @@ static ex chebyt_eval(const ex& n_, const ex& x) for (int i = 0; i= 0 # long time + sage: out.find(version()) >= 0 True - sage: err # long time + sage: err '' - sage: ret # long time + sage: ret 0 - sage: (out, err, ret) = test_executable([ # long time + sage: # long time + sage: (out, err, ret) = test_executable([ ....: "sage"], "3^33\n", pydebug_ignore_warnings=True) - sage: out.find(version()) >= 0 # long time + sage: out.find(version()) >= 0 True - sage: out.find("5559060566555523") >= 0 # long time + sage: out.find("5559060566555523") >= 0 True - sage: err # long time + sage: err '' - sage: ret # long time + sage: ret 0 - sage: (out, err, ret) = test_executable([ # long time + sage: # long time + sage: (out, err, ret) = test_executable([ ....: "sage", "-q"], "3^33\n", pydebug_ignore_warnings=True) - sage: out.find(version()) >= 0 # long time + sage: out.find(version()) >= 0 False - sage: out.find("5559060566555523") >= 0 # long time + sage: out.find("5559060566555523") >= 0 True - sage: err # long time + sage: err '' - sage: ret # long time + sage: ret 0 - sage: (out, err, ret) = test_executable([ # long time + sage: # long time + sage: (out, err, ret) = test_executable([ ....: "sage", "-c", "print(3^33)"]) - sage: print(out) # long time + sage: print(out) 5559060566555523 - sage: err # long time + sage: err '' - sage: ret # long time + sage: ret 0 - sage: (out, err, ret) = test_executable([ # long time + sage: # long time + sage: (out, err, ret) = test_executable([ ....: "sage", "--min", "-c", "print(3^33)"]) - sage: print(out) # long time + sage: print(out) 5559060566555523 - sage: err # long time + sage: err '' - sage: ret # long time + sage: ret 0 - sage: (out, err, ret) = test_executable([ # long time + sage: # long time + sage: (out, err, ret) = test_executable([ ....: "sage", "--startuptime"]) - sage: out.find("Slowest module import") >= 0 # long time + sage: out.find("Slowest module import") >= 0 True - sage: err # long time + sage: err '' - sage: ret # long time + sage: ret 0 Test help:: @@ -208,25 +214,27 @@ def test_executable(args, input="", timeout=100.0, pydebug_ignore_warnings=False sage: ret 0 - sage: (out, err, ret) = test_executable(["sage", "--root"]) # optional - sage_spkg - sage: len(out) >= 2 # at least one character + newline; optional - sage_spkg + sage: # optional - sage_spkg + sage: (out, err, ret) = test_executable(["sage", "--root"]) + sage: len(out) >= 2 True - sage: err # optional - sage_spkg + sage: err '' - sage: ret # optional - sage_spkg + sage: ret 0 Test ``sage --info [packages]``:: - sage: out, err, ret = test_executable(["sage", "--info", "sqlite"]) # optional - sage_spkg - sage: print(out) # optional - sage_spkg + sage: # optional - sage_spkg + sage: out, err, ret = test_executable(["sage", "--info", "sqlite"]) + sage: print(out) sqlite... SQLite is a software library that implements a self-contained, serverless, zero-configuration, transactional SQL database engine. ... - sage: err # optional - sage_spkg + sage: err '' - sage: ret # optional - sage_spkg + sage: ret 0 Test ``sage-run`` on a Python file, both with an absolute and with a relative path:: @@ -292,17 +300,18 @@ def test_executable(args, input="", timeout=100.0, pydebug_ignore_warnings=False Now test my_script.sage and the preparsed version my_script.sage.py:: - sage: (out, err, ret) = test_executable([ # long time + sage: # long time + sage: (out, err, ret) = test_executable([ ....: "sage", "-t", "--optional=sage", script]) - sage: ret # long time + sage: ret 0 - sage: out.find("All tests passed!") >= 0 # long time + sage: out.find("All tests passed!") >= 0 True - sage: (out, err, ret) = test_executable([ # long time + sage: (out, err, ret) = test_executable([ ....: "sage", "-t", "--optional=sage", script_py]) - sage: ret # long time + sage: ret 0 - sage: out.find("All tests passed!") >= 0 # long time + sage: out.find("All tests passed!") >= 0 True Test that the coding line and doctest are preserved:: @@ -438,13 +447,14 @@ def test_executable(args, input="", timeout=100.0, pydebug_ignore_warnings=False sage: ret 42 - sage: (out, err, ret) = test_executable([ # long time + sage: # long time + sage: (out, err, ret) = test_executable([ ....: "sage", "--ipython"], "\n3**33\n", pydebug_ignore_warnings=True) - sage: out.find("5559060566555523") >= 0 # long time + sage: out.find("5559060566555523") >= 0 True - sage: err # long time + sage: err '' - sage: ret # long time + sage: ret 0 sage: (out, err, ret) = test_executable(["sage", "--python"], "print(3^33)\n") @@ -494,13 +504,14 @@ def test_executable(args, input="", timeout=100.0, pydebug_ignore_warnings=False sage: ret 0 - sage: (out, err, ret) = test_executable([ # long time + sage: # long time + sage: (out, err, ret) = test_executable([ ....: "sage", "--gap", "-q"], "Size(SymmetricGroup(5));\n") - sage: out # long time + sage: out '120\n' - sage: err.replace('gap: halving pool size.', '').strip() # long time + sage: err.replace('gap: halving pool size.', '').strip() '' - sage: ret # long time + sage: ret 0 sage: (out, err, ret) = test_executable([ # long time # optional - gdb @@ -551,12 +562,13 @@ def test_executable(args, input="", timeout=100.0, pydebug_ignore_warnings=False sage: ret 0 - sage: (out, err, ret) = test_executable(["sage", "--R", "--version"]) # optional - r - sage: out.find("R version ") >= 0 # optional - r + sage: # optional - r + sage: (out, err, ret) = test_executable(["sage", "--R", "--version"]) + sage: out.find("R version ") >= 0 True - sage: err # optional - r + sage: err '' - sage: ret # optional - r + sage: ret 0 sage: (out, err, ret) = test_executable(["sage", "--sqlite3", "--version"]) @@ -569,28 +581,31 @@ def test_executable(args, input="", timeout=100.0, pydebug_ignore_warnings=False Check some things requiring an internet connection:: - sage: (out, err, ret) = test_executable(["sage", "--standard"]) # optional - internet - sage: out.find("cython") >= 0 # optional - internet + sage: # optional - internet + sage: (out, err, ret) = test_executable(["sage", "--standard"]) + sage: out.find("cython") >= 0 True - sage: err # optional - internet + sage: err '' - sage: ret # optional - internet + sage: ret 0 - sage: (out, err, ret) = test_executable(["sage", "--optional"]) # optional - internet - sage: out.find("database_cremona_ellcurve") >= 0 # optional - internet + sage: # optional - internet + sage: (out, err, ret) = test_executable(["sage", "--optional"]) + sage: out.find("database_cremona_ellcurve") >= 0 True - sage: err # optional - internet + sage: err '' - sage: ret # optional - internet + sage: ret 0 - sage: (out, err, ret) = test_executable(["sage", "--experimental"]) # optional - internet - sage: out.find("valgrind") >= 0 # optional - internet + sage: # optional - internet + sage: (out, err, ret) = test_executable(["sage", "--experimental"]) + sage: out.find("valgrind") >= 0 True - sage: err # optional - internet + sage: err '' - sage: ret # optional - internet + sage: ret 0 Check an illegal command line option. This outputs an error to stdout, diff --git a/src/sage/tests/combinatorial_hopf_algebras.py b/src/sage/tests/combinatorial_hopf_algebras.py index 6ac40f7aad5..33c0472f404 100644 --- a/src/sage/tests/combinatorial_hopf_algebras.py +++ b/src/sage/tests/combinatorial_hopf_algebras.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.combinat sage.modules r""" Tests For Combinatorial Hopf Algebras diff --git a/src/sage/tests/finite_poset.py b/src/sage/tests/finite_poset.py index 11092c3d966..d04221dcc13 100644 --- a/src/sage/tests/finite_poset.py +++ b/src/sage/tests/finite_poset.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.graphs sage.modules """ This file contains test functions that can be used to search bugs by testing random finite posets and lattices. @@ -104,7 +105,7 @@ def test_attrcall(name, L): sage: N5 = posets.PentagonPoset() sage: N5.is_modular() == test_attrcall('is_modular', N5) True - sage: N5.is_constructible_by_doublings('convex') == test_attrcall('is_doubling_convex', N5) + sage: N5.is_constructible_by_doublings('convex') == test_attrcall('is_doubling_convex', N5) # needs sage.combinat True """ if name == 'is_doubling_any': diff --git a/src/sage/tests/gap_packages.py b/src/sage/tests/gap_packages.py index c302b169b8a..b13bba24a83 100644 --- a/src/sage/tests/gap_packages.py +++ b/src/sage/tests/gap_packages.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.libs.gap """ Test the optional GAP packages diff --git a/src/sage/tests/gosper-sum.py b/src/sage/tests/gosper-sum.py index 76c2438d1c9..84679ac0ff3 100644 --- a/src/sage/tests/gosper-sum.py +++ b/src/sage/tests/gosper-sum.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.symbolic """ Some tests about Gosper sums. diff --git a/src/sage/tests/lazy_imports.py b/src/sage/tests/lazy_imports.py index e9bd2aea2c0..8ea93a15ab5 100644 --- a/src/sage/tests/lazy_imports.py +++ b/src/sage/tests/lazy_imports.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.all r""" TESTS: diff --git a/src/sage/tests/modular_group_cohomology.py b/src/sage/tests/modular_group_cohomology.py index be00146dc6f..35bc8b5387f 100644 --- a/src/sage/tests/modular_group_cohomology.py +++ b/src/sage/tests/modular_group_cohomology.py @@ -1,3 +1,4 @@ +# sage.doctest: optional - p_group_cohomology r""" Tests for the optional ``p_group_cohomology`` package. @@ -7,26 +8,26 @@ TESTS:: - sage: from pGroupCohomology import CohomologyRing # optional - p_group_cohomology + sage: from pGroupCohomology import CohomologyRing Computation of a modular cohomology ring of a prime power group in characteristic 2, and comparison with stored result in a database:: - sage: CohomologyRing.set_workspace(tmp_dir()) # optional - p_group_cohomology - sage: H = CohomologyRing(64,14,from_scratch=True) # optional - p_group_cohomology - sage: H.make() # optional - p_group_cohomology - sage: CohomologyRing.set_workspace(tmp_dir()) # optional - p_group_cohomology - sage: H0 = CohomologyRing(64,14) # optional - p_group_cohomology - sage: H.is_isomorphic(H0) # optional - p_group_cohomology + sage: CohomologyRing.set_workspace(tmp_dir()) + sage: H = CohomologyRing(64,14,from_scratch=True) + sage: H.make() + sage: CohomologyRing.set_workspace(tmp_dir()) + sage: H0 = CohomologyRing(64,14) + sage: H.is_isomorphic(H0) ('1*a_2_1', '1*c_2_2', '1*c_4_4', '1*a_1_0', '1*a_1_1', '1*a_3_3') Computation of a modular cohomology ring of a prime power group in odd characteristic, and some algebraic constructions in the cohomology ring:: - sage: H = CohomologyRing(27,4) # optional - p_group_cohomology - sage: H.make() # optional - p_group_cohomology - sage: print(H) # optional - p_group_cohomology + sage: H = CohomologyRing(27,4) + sage: H.make() + sage: print(H) Cohomology ring of Extraspecial 3-group of order 27 and exponent 9 with coefficients in GF(3) @@ -45,14 +46,14 @@ b_2_1*a_3_1, a_1_0*a_5_1, a_3_1*a_5_1] - sage: H.5.massey_power() # optional - p_group_cohomology + sage: H.5.massey_power() : 8-Cocycle in H^*(M27; GF(3)) - sage: H.5.massey_power().as_polynomial() # optional - p_group_cohomology + sage: H.5.massey_power().as_polynomial() '-c_6_2*a_1_0*a_1_1' - sage: H.essential_ideal() # optional - p_group_cohomology + sage: H.essential_ideal() a_1_0*a_1_1, a_1_1*a_3_1 - sage: ascii_art(H.bar_code('LowerCentralSeries')[2]) # known bug (possibly, the output might be correct) # optional - p_group_cohomology + sage: ascii_art(H.bar_code('LowerCentralSeries')[2]) # known bug * *-* *-* @@ -61,11 +62,11 @@ Computation of a modular cohomology ring of a non prime power group in characteristic 2:: - sage: H = CohomologyRing(libgap.AlternatingGroup(6), # optional - p_group_cohomology + sage: H = CohomologyRing(libgap.AlternatingGroup(6), ....: GroupName="A(6)", prime=2, ....: from_scratch=True) - sage: H.make() # optional - p_group_cohomology - sage: print(H) # optional - p_group_cohomology + sage: H.make() + sage: print(H) Cohomology ring of A(6) with coefficients in GF(2) Computation complete diff --git a/src/sage/tests/numpy.py b/src/sage/tests/numpy.py index 8c1c42f385c..5cd78b148d2 100644 --- a/src/sage/tests/numpy.py +++ b/src/sage/tests/numpy.py @@ -1,3 +1,4 @@ +# sage.doctest: needs numpy r""" TESTS: diff --git a/src/sage/tests/parigp.py b/src/sage/tests/parigp.py index 4692b613de4..1049149a147 100644 --- a/src/sage/tests/parigp.py +++ b/src/sage/tests/parigp.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.libs.pari sage.modules r""" This file is meant to catch errors in the PARI/GP package which are not caught by any other tests. @@ -39,32 +40,35 @@ Check that the optional PARI databases work:: - sage: gp.ellinit('"299998a1"') # optional -- pari_elldata + sage: # optional - pari_elldata + sage: gp.ellinit('"299998a1"') [1, 0, 1, 110, -3660, ...] - sage: E = EllipticCurve("1728ba1") - sage: gp(E).ellidentify() # optional -- pari_elldata + sage: E = EllipticCurve("1728ba1") # needs sage.schemes + sage: gp(E).ellidentify() # needs sage.schemes [["1728ba1", [0, 0, 0, -6, 6], [[1, 1]]], [1, 0, 0, 0]] - sage: pari("ellmodulareqn(211)") # optional -- pari_seadata - [x^212 + (-y^7 + 5207*y^6 - 10241606*y^5 + 9430560101*y^4 - 4074860204015*y^3 + 718868274900397*y^2 - 34897101275826114*y + 104096378056356968)*x^211... + sage: pari("ellmodulareqn(211)") # optional - pari_seadata + [x^212 + (-y^7 + 5207*y^6 - 10241606*y^5 + 9430560101*y^4 - 4074860204015*y^3 + + 718868274900397*y^2 - 34897101275826114*y + 104096378056356968)*x^211... The following requires the modular polynomials up to degree 223, while only those up to degree 199 come standard in Sage:: sage: p = next_prime(2^328) - sage: E = EllipticCurve(GF(p), [6,1]) - sage: E.cardinality() # long time (108s on sage.math, 2013), optional -- pari_seadata + sage: E = EllipticCurve(GF(p), [6,1]) # needs sage.schemes + sage: E.cardinality() # long time (108s on sage.math, 2013), optional - pari_seadata, needs sage.schemes 546812681195752981093125556779405341338292357723293496548601032930284335897180749997402596957976244 Create a number field with Galois group `A4`. Group `A4` corresponds to transitive group `(12,3)` in GAP:: + sage: # optional - pari_galpol sage: R. = PolynomialRing(ZZ) - sage: pol = pari("galoisgetpol(12,3)[1]") # optional -- pari_galpol - sage: K. = NumberField(R(pol)) # optional -- pari_galpol - sage: factor(K.discriminant()) # optional -- pari_galpol + sage: pol = pari("galoisgetpol(12,3)[1]") + sage: K. = NumberField(R(pol)) + sage: factor(K.discriminant()) 163^8 - sage: [F.degree() for F,a,b in K.subfields()] # optional -- pari_galpol + sage: [F.degree() for F,a,b in K.subfields()] [1, 3, 4, 4, 4, 4, 6, 6, 6, 12] sage: sorted([12/H.cardinality() for H in AlternatingGroup(4).subgroups()]) [1, 3, 4, 4, 4, 4, 6, 6, 6, 12] diff --git a/src/sage/tests/symbolic-series.py b/src/sage/tests/symbolic-series.py index fb42289074d..5e53d1e07af 100644 --- a/src/sage/tests/symbolic-series.py +++ b/src/sage/tests/symbolic-series.py @@ -1,3 +1,4 @@ +# sage.doctest: needs sage.symbolic """ Tests for the fast univariate series expansion in Pynac ------------------------------------------------------- diff --git a/src/sage/tests/sympy.py b/src/sage/tests/sympy.py index a42dcab7b2a..2f98f95e00c 100644 --- a/src/sage/tests/sympy.py +++ b/src/sage/tests/sympy.py @@ -1,3 +1,4 @@ +# sage.doctest: optional - sympy r""" TESTS: diff --git a/src/sage/version.py b/src/sage/version.py index bdb6c002ac5..f7c0467ee4e 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.2.rc5' -date = '2023-11-30' -banner = 'SageMath version 10.2.rc5, Release Date: 2023-11-30' +version = '10.3.beta0' +date = '2023-12-05' +banner = 'SageMath version 10.3.beta0, Release Date: 2023-12-05' diff --git a/src/sage_setup/autogen/__init__.py b/src/sage_setup/autogen/__init__.py index 6a0a6fdc5da..380983c06c7 100644 --- a/src/sage_setup/autogen/__init__.py +++ b/src/sage_setup/autogen/__init__.py @@ -1,6 +1,7 @@ import os + from . import interpreters -from sage.env import SAGE_SRC + def autogen_all(): """ @@ -9,6 +10,7 @@ def autogen_all(): Return a list of sub-packages that should be appended to the list of packages built/installed by setup.py. """ + from sage.env import SAGE_SRC interpreters.rebuild(os.path.join(SAGE_SRC, "sage", "ext", "interpreters")) return ['sage.ext.interpreters'] diff --git a/src/sage_setup/autogen/interpreters/__main__.py b/src/sage_setup/autogen/interpreters/__main__.py index fa78a6ab9b8..398a7b30039 100644 --- a/src/sage_setup/autogen/interpreters/__main__.py +++ b/src/sage_setup/autogen/interpreters/__main__.py @@ -1,9 +1,11 @@ -from __future__ import print_function, absolute_import +# Usage: python -m sage_setup.autogen.interpreters -import os -from sage.env import SAGE_SRC +import argparse from . import rebuild +parser = argparse.ArgumentParser() +parser.add_argument("output_dir", help="Output directory") +args = parser.parse_args() -rebuild(os.path.join(SAGE_SRC, "sage", "ext", "interpreters")) +rebuild(args.output_dir) diff --git a/src/sage_setup/library_order.py b/src/sage_setup/library_order.py index f40690f8d22..9ae0d2579a7 100644 --- a/src/sage_setup/library_order.py +++ b/src/sage_setup/library_order.py @@ -16,17 +16,12 @@ aliases = cython_aliases(required_modules=(), optional_modules=modules) -if "ARB_LIBRARY" in aliases: - arb_dylib_names = [aliases["ARB_LIBRARY"]] -else: - arb_dylib_names = [] - library_order_list = aliases.get("SINGULAR_LIBRARIES", []) + [ "giac", "intl", "curl", "ec", "ecm" ] + aliases.get("LINBOX_LIBRARIES", []) + aliases.get("FFLASFFPACK_LIBRARIES", []) + aliases.get("GSL_LIBRARIES", []) + [ "pari", "flint", "ecl", "glpk", "ppl", -] + arb_dylib_names + [ +] + [ "mpfi", "mpfr", "mpc", "ntl", "gmp", "gmpxx", "brial", "brial_groebner", diff --git a/src/tox.ini b/src/tox.ini index fea30bea362..00f7a153f35 100644 --- a/src/tox.ini +++ b/src/tox.ini @@ -51,6 +51,41 @@ allowlist_externals = {[sagedirect]allowlist_externals} commands = {env:SAGE} -t -p 0 {posargs:--all} +[testenv:coverage.py] +# https://coverage.readthedocs.io/en/latest/index.html +description = + run the Sage doctester with Coverage.py +## This toxenv bypasses the virtual environment set up by tox. +passenv = {[sagedirect]passenv} +setenv = {[sagedirect]setenv} +envdir = {[sagedirect]envdir} +allowlist_externals = {[sagedirect]allowlist_externals} +commands_pre = + {env:SAGE} -pip install -U coverage +commands = + {env:SAGE} --python -m coverage run "{toxinidir}/../venv/bin/sage-runtests" -p 0 {posargs:--all} +commands_post = + {env:SAGE} --python -m coverage combine + {env:SAGE} --python -m coverage report + +[testenv:coverage.py-html] +# https://coverage.readthedocs.io/en/latest/index.html +description = + run the Sage doctester with Coverage.py, generate HTML report +## This toxenv bypasses the virtual environment set up by tox. +passenv = {[sagedirect]passenv} +setenv = {[sagedirect]setenv} +envdir = {[sagedirect]envdir} +allowlist_externals = {[sagedirect]allowlist_externals} +commands_pre = + {env:SAGE} -pip install -U coverage +commands = + {env:SAGE} --python -m coverage run "{toxinidir}/../venv/bin/sage-runtests" -p 0 {posargs:--all} +commands_post = + {env:SAGE} --python -m coverage combine + {env:SAGE} --python -m coverage report + {env:SAGE} --python -m coverage html -d "{envdir}" + [testenv:coverage] description = give information about doctest coverage of files @@ -201,7 +236,7 @@ commands = flake8 --select=RST {posargs:{toxinidir}/sage/} [testenv:cython-lint] description = - Check Cython files for code style + check Cython files for code style deps = cython-lint commands = cython-lint --no-pycodestyle {posargs:{toxinidir}/sage/} diff --git a/tox.ini b/tox.ini index 438c1ca8763..e068204f603 100644 --- a/tox.ini +++ b/tox.ini @@ -793,6 +793,15 @@ envdir = {[sage_src]envdir} commands = {[sage_src]commands} allowlist_externals = {[sage_src]allowlist_externals} +[testenv:coverage.py] +description = + run the Sage doctester with Coverage.py + (https://coverage.readthedocs.io/en/latest/index.html) +passenv = {[sage_src]passenv} +envdir = {[sage_src]envdir} +commands = {[sage_src]commands} +allowlist_externals = {[sage_src]allowlist_externals} + [testenv:coverage] description = give information about doctest coverage of files (same as "sage --coverage[all]") @@ -860,7 +869,7 @@ allowlist_externals = {[sage_src]allowlist_externals} [testenv:cython-lint] description = - Check Cython files for code style + check Cython files for code style passenv = {[sage_src]passenv} envdir = {[sage_src]envdir} commands = {[sage_src]commands}