diff --git a/.github/workflows/tox-experimental.yml b/.github/workflows/tox-experimental.yml index 554a058cdb9..54c8373a362 100644 --- a/.github/workflows/tox-experimental.yml +++ b/.github/workflows/tox-experimental.yml @@ -41,7 +41,7 @@ jobs: # This list is different from the one in tox.yml: # Trac #31526 switches gcc 4.x-based distributions to using the gcc_spkg configuration factor # Trac #32281 removes gcc 4.x-based distributions whose binutils are unusable - tox_system_factor: [ubuntu-xenial, ubuntu-bionic, ubuntu-focal, ubuntu-groovy, ubuntu-hirsute, debian-jessie-gcc_spkg, debian-stretch, debian-buster, debian-bullseye, debian-sid, linuxmint-18, linuxmint-19, linuxmint-19.3, linuxmint-20.1, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, centos-7-gcc_spkg, centos-8, gentoo, archlinux-latest, opensuse-15, opensuse-15.3, opensuse-tumbleweed, slackware-14.2, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386-gcc_spkg] + tox_system_factor: [ubuntu-xenial, ubuntu-bionic, ubuntu-focal, ubuntu-groovy, ubuntu-hirsute, debian-jessie-gcc_spkg, debian-stretch, debian-buster, debian-bullseye, debian-sid, linuxmint-18, linuxmint-19, linuxmint-19.3, linuxmint-20.1, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, centos-7-gcc_spkg, centos-8, gentoo-python3.9, gentoo-python3.10, archlinux-latest, opensuse-15, opensuse-15.3, opensuse-tumbleweed, slackware-14.2, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386-gcc_spkg] tox_packages_factor: [maximal] targets_pattern: [0-g, h-o, p, q-z] env: diff --git a/.github/workflows/tox-optional.yml b/.github/workflows/tox-optional.yml index be97ecd37a8..bcdf349bee7 100644 --- a/.github/workflows/tox-optional.yml +++ b/.github/workflows/tox-optional.yml @@ -41,7 +41,7 @@ jobs: # This list is different from the one in tox.yml: # Trac #31526 switches gcc 4.x-based distributions to using the gcc_spkg configuration factor # Trac #32281 removes gcc 4.x-based distributions whose binutils are unusable - tox_system_factor: [ubuntu-xenial, ubuntu-bionic, ubuntu-focal, ubuntu-groovy, ubuntu-hirsute, debian-jessie-gcc_spkg, debian-stretch, debian-buster, debian-bullseye, debian-sid, linuxmint-18, linuxmint-19, linuxmint-19.3, linuxmint-20.1, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, centos-7-gcc_spkg, centos-8, gentoo, archlinux-latest, opensuse-15, opensuse-15.3, opensuse-tumbleweed, slackware-14.2, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386-gcc_spkg] + tox_system_factor: [ubuntu-xenial, ubuntu-bionic, ubuntu-focal, ubuntu-groovy, ubuntu-hirsute, debian-jessie-gcc_spkg, debian-stretch, debian-buster, debian-bullseye, debian-sid, linuxmint-18, linuxmint-19, linuxmint-19.3, linuxmint-20.1, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, centos-7-gcc_spkg, centos-8, gentoo-python3.9, gentoo-python3.10, archlinux-latest, opensuse-15, opensuse-15.3, opensuse-tumbleweed, slackware-14.2, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386-gcc_spkg] tox_packages_factor: [maximal] targets_pattern: [0-g, h-o, p, q-z] env: diff --git a/.github/workflows/tox.yml b/.github/workflows/tox.yml index 68d5661c5bb..493e8342920 100644 --- a/.github/workflows/tox.yml +++ b/.github/workflows/tox.yml @@ -38,7 +38,7 @@ jobs: fail-fast: false max-parallel: 20 matrix: - tox_system_factor: [ubuntu-trusty, ubuntu-xenial, ubuntu-bionic, ubuntu-focal, ubuntu-groovy, ubuntu-hirsute, ubuntu-impish, debian-jessie, debian-stretch, debian-buster, debian-bullseye, debian-sid, linuxmint-17, linuxmint-18, linuxmint-19, linuxmint-19.3, linuxmint-20.1, linuxmint-20.2, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, fedora-35, centos-7, centos-8, gentoo, gentoo-python3.7, archlinux-latest, opensuse-15, opensuse-15.3, opensuse-tumbleweed, slackware-14.2, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386] + tox_system_factor: [ubuntu-trusty, ubuntu-xenial, ubuntu-bionic, ubuntu-focal, ubuntu-groovy, ubuntu-hirsute, ubuntu-impish, debian-jessie, debian-stretch, debian-buster, debian-bullseye, debian-sid, linuxmint-17, linuxmint-18, linuxmint-19, linuxmint-19.3, linuxmint-20.1, linuxmint-20.2, fedora-26, fedora-27, fedora-28, fedora-29, fedora-30, fedora-31, fedora-32, fedora-33, fedora-34, fedora-35, centos-7, centos-8, gentoo-python3.9, gentoo-python3.10, archlinux-latest, opensuse-15, opensuse-15.3, opensuse-tumbleweed, slackware-14.2, conda-forge, ubuntu-bionic-i386, manylinux-2_24-i686, debian-buster-i386, centos-7-i386] tox_packages_factor: [minimal, standard] env: TOX_ENV: docker-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} diff --git a/.zenodo.json b/.zenodo.json index 489c739efdd..fd96736f3c1 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -1,10 +1,10 @@ { "description": "Mirror of the Sage https://sagemath.org/ source tree", "license": "other-open", - "title": "sagemath/sage: 9.5.beta6", - "version": "9.5.beta6", + "title": "sagemath/sage: 9.5.beta7", + "version": "9.5.beta7", "upload_type": "software", - "publication_date": "2021-11-12", + "publication_date": "2021-11-18", "creators": [ { "affiliation": "SageMath.org", @@ -15,7 +15,7 @@ "related_identifiers": [ { "scheme": "url", - "identifier": "https://github.com/sagemath/sage/tree/9.5.beta6", + "identifier": "https://github.com/sagemath/sage/tree/9.5.beta7", "relation": "isSupplementTo" }, { diff --git a/README.md b/README.md index f4d21b555c1..cf1c448835c 100644 --- a/README.md +++ b/README.md @@ -349,9 +349,9 @@ Simplified directory layout (only essential files/directories): SAGE_ROOT Root directory (sage-x.y.z in Sage tarball) ├── build │ └── pkgs Every package is a subdirectory here -│ ├── 4ti2 +│ ├── 4ti2/ │ … -│ └── zn_poly +│ └── zn_poly/ ├── configure Top-level configure script ├── COPYING.txt Copyright information ├── pkgs Source trees of Python distribution packages @@ -359,24 +359,40 @@ SAGE_ROOT Root directory (sage-x.y.z in Sage tarball) │ │ ├── sage_conf.py │ │ └── setup.py │ ├── sage-docbuild -│ │ ├── sage_docbuild +│ │ ├── sage_docbuild/ +│ │ └── setup.py +│ ├── sage-setup +│ │ ├── sage_setup/ │ │ └── setup.py │ ├── sage-sws2rst -│ │ ├── sage_sws2rst +│ │ ├── sage_sws2rst/ │ │ └── setup.py │ └── sagemath-standard -│ ├── bin -│ ├── sage +│ ├── bin/ +│ ├── sage -> ../../src/sage │ └── setup.py -├── local (SAGE_LOCAL) Compiled packages are installed here +├── local (SAGE_LOCAL) Installation hierarchy for non-Python packages │ ├── bin Executables │ ├── include C/C++ headers -│ ├── lib Shared libraries +│ ├── lib Shared libraries, architecture-dependent data │ ├── share Databases, architecture-independent data, docs │ │ └── doc Viewable docs of Sage and of some components │ └── var -│ ├── lib/sage List of installed packages -│ └── tmp/sage Temporary files when building Sage +│ ├── lib/sage +│ │ ├── installed/ +│ │ │ Records of installed non-Python packages +│ │ ├── scripts/ Scripts for uninstalling installed packages +│ │ └── venv-python3.9 (SAGE_VENV) +│ │ │ Installation hierarchy (virtual environment) +│ │ │ for Python packages +│ │ ├── bin/ Executables and installed scripts +│ │ ├── lib/python3.9/site-packages/ +│ │ │ Python modules/packages are installed here +│ │ └── var/lib/sage/ +│ │ └── wheels/ +│ │ Python wheels for all installed Python packages +│ │ +│ └── tmp/sage/ Temporary files when building Sage ├── logs │ ├── dochtml.log Log of the documentation build │ ├── install.log Full install log @@ -384,19 +400,21 @@ SAGE_ROOT Root directory (sage-x.y.z in Sage tarball) │ ├── alabaster-0.7.12.log │ … │ └── zn_poly-0.9.2.log -├── m4 M4 macros for configure +├── m4 M4 macros for generating the configure script │ └── *.m4 ├── Makefile Running "make" uses this file +├── prefix -> SAGE_LOCAL Convenience symlink to the installation tree ├── README.md This file ├── sage Script to start Sage ├── src Monolithic Sage library source tree -│ ├── bin Scripts that Sage uses internally -│ ├── doc Sage documentation sources -│ └── sage The Sage library source code +│ ├── bin/ Scripts that Sage uses internally +│ ├── doc/ Sage documentation sources +│ └── sage/ The Sage library source code ├── upstream Source tarballs of packages │ ├── Babel-2.9.1.tar.gz │ … │ └── zn_poly-0.9.2.tar.gz +├── venv -> SAGE_VENV Convenience symlink to the virtual environment └── VERSION.txt ``` For more details see [our Developer's Guide](https://doc.sagemath.org/html/en/developer/coding_basics.html#files-and-directory-structure). diff --git a/VERSION.txt b/VERSION.txt index b437f328147..be62107d97e 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -SageMath version 9.5.beta6, Release Date: 2021-11-12 +SageMath version 9.5.beta7, Release Date: 2021-11-18 diff --git a/build/bin/sage-bootstrap-python b/build/bin/sage-bootstrap-python index faee444e8dc..5c5cd1cc097 100755 --- a/build/bin/sage-bootstrap-python +++ b/build/bin/sage-bootstrap-python @@ -40,7 +40,19 @@ if [ "$LC_ALL" = "C" -o "$LANG" = "C" -o "$LC_CTYPE" = "C" ]; then export LANG fi -PYTHONS="python python3 python3.8 python3.7 python2.7 python3.6 python2" +PYTHONS="python python3 python3.10 python3.9 python3.8 python3.7 python2.7 python3.6 python2" +# Trac #32405: Prefer a Python that provides ssl with SNI, which allows developers +# to download from upstream URLs (configure --enable-download-from-upstream-url), +# in particular from PyPI, which requires SNI. +for PY in $PYTHONS; do + PYTHON="$(PATH="$SAGE_ORIG_PATH" command -v $PY)" + if [ -n "$PYTHON" ]; then + if "$PYTHON" -c "import argparse; import urllib; from hashlib import sha1; from ssl import HAS_SNI; assert HAS_SNI; from os import listdir; listdir(\"$(pwd)\");" 2>/dev/null; then + exec "$PYTHON" "$@" + fi + fi +done +# Second round, no ssl/SNI test. for PY in $PYTHONS; do PYTHON="$(PATH="$SAGE_ORIG_PATH" command -v $PY)" if [ -n "$PYTHON" ]; then diff --git a/build/bin/sage-dist-helpers b/build/bin/sage-dist-helpers index 704985a5e37..c573dee0360 100644 --- a/build/bin/sage-dist-helpers +++ b/build/bin/sage-dist-helpers @@ -268,6 +268,12 @@ sdh_pip_install() { sdh_store_and_pip_install_wheel $install_options . } +sdh_pip_editable_install() { + echo "Installing $PKG_NAME (editable mode)" + python3 -m pip install --verbose --no-deps --no-index --no-build-isolation --isolated --editable "$@" || \ + sdh_die "Error installing $PKG_NAME" +} + sdh_store_wheel() { if [ -n "$SAGE_DESTDIR" ]; then local sudo="" diff --git a/build/make/Makefile.in b/build/make/Makefile.in index 1972e1a14ce..4673be50224 100644 --- a/build/make/Makefile.in +++ b/build/make/Makefile.in @@ -52,6 +52,10 @@ SAGE_SPKG = sage-spkg # These are added to SAGE_SPKG in the call SAGE_SPKG_OPTIONS = @SAGE_SPKG_OPTIONS@ +# Where the Sage distribution installs documentation. +# set to empty if --disable-doc is used +SAGE_DOCS = $(SAGE_LOCAL) + # Where the Sage distribution installs Python packages. # This can be overridden by 'make SAGE_VENV=/some/venv'. SAGE_VENV = @SAGE_VENV@ @@ -142,7 +146,7 @@ SCRIPT_PACKAGES = @SAGE_SCRIPT_PACKAGES@ # inst_git = $(INST)/.dummy $(foreach pkgname,$(BUILT_PACKAGES),\ - $(eval inst_$(pkgname) = $(foreach tree, $(trees_$(pkgname)), $($(tree))/$(SPKG_INST_RELDIR)/$(pkgname)-$(vers_$(pkgname))))) + $(eval inst_$(pkgname) = $(foreach tree, $(trees_$(pkgname)), $(and $($(tree)), $($(tree))/$(SPKG_INST_RELDIR)/$(pkgname)-$(vers_$(pkgname)))))) $(foreach pkgname,$(DUMMY_PACKAGES),\ $(eval inst_$(pkgname) = $(SAGE_LOCAL)/$(SPKG_INST_RELDIR)/.dummy)) @@ -157,7 +161,7 @@ $(SAGE_LOCAL)/$(SPKG_INST_RELDIR)/.dummy: # Filtered by installation tree -$(foreach tree,SAGE_LOCAL SAGE_VENV, \ +$(foreach tree,SAGE_LOCAL SAGE_VENV SAGE_DOCS, \ $(eval $(tree)_INSTALLED_PACKAGE_INSTS = \ $(foreach pkgname,$(INSTALLED_PACKAGES), \ $(if $(findstring $(tree),$(trees_$(pkgname))), \ @@ -228,11 +232,11 @@ build-start: all-build base-toolchain: _clean-broken-gcc base +$(MAKE_REC) toolchain -# All targets except for the base packages +# All targets except for the base packages and except the documentation all-sage: \ sagelib \ - $(INSTALLED_PACKAGE_INSTS) \ - $(UNINSTALLED_PACKAGES_CLEANS) + $(SAGE_LOCAL_INSTALLED_PACKAGE_INSTS) $(SAGE_LOCAL_UNINSTALLED_PACKAGES_CLEANS) \ + $(SAGE_VENV_INSTALLED_PACKAGE_INSTS) $(SAGE_VENV_UNINSTALLED_PACKAGES_CLEANS) # Same but filtered by installation trees: all-build-local: toolchain-deps @@ -245,6 +249,11 @@ all-build-venv: toolchain-deps all-sage-venv: $(SAGE_VENV_INSTALLED_PACKAGE_INSTS) $(SAGE_VENV_UNINSTALLED_PACKAGES_CLEANS) +all-build-docs: toolchain-deps + +$(MAKE_REC) all-sage-docs + +all-sage-docs: $(SAGE_DOCS_INSTALLED_PACKAGE_INSTS) $(SAGE_DOCS_UNINSTALLED_PACKAGES_CLEANS) + # Download all packages which should be inside an sdist tarball (the -B # option to make forces all targets to be built unconditionally) download-for-sdist: @@ -316,35 +325,28 @@ base: $(inst_patch) $(inst_pkgconf) # # $ ./sage --docbuild -H -# Building the documentation has many dependencies, because all -# documented modules are imported and because we use matplotlib to -# produce plots. -DOC_DEPENDENCIES = sagelib sage_docbuild $(inst_sphinx) \ - | $(SAGERUNTIME) $(inst_maxima) $(inst_networkx) $(inst_scipy) $(inst_sympy) \ - $(inst_matplotlib) $(inst_pillow) $(inst_mathjax) $(inst_mpmath) \ - $(inst_ipykernel) $(inst_jupyter_client) $(inst_conway_polynomials) \ - $(inst_tachyon) $(inst_jmol) $(inst_thebe) $(inst_ipywidgets) - -doc: doc-html +doc: $(SAGE_DOCS_INSTALLED_PACKAGE_INSTS) $(SAGE_DOCS_UNINSTALLED_PACKAGES_CLEANS) -doc-html: $(DOC_DEPENDENCIES) - $(AM_V_at)cd "$(SAGE_SRC)/doc" && sage-logger -p "$(MAKE) doc-html" $(SAGE_ROOT)/logs/dochtml.log +# All doc-building is delegated to the script packages +# sagemath_doc_html, sagemath_doc_pdf +doc-html: sagemath_doc_html # 'doc-html-no-plot': build docs without building the graphics coming # from the '.. plot' directive, in case you want to save a few # megabytes of disk space. 'doc-clean' is a prerequisite because the # presence of graphics is cached in src/doc/output. doc-html-no-plot: doc-clean - $(AM_V_at)sage-logger -p "$(MAKE) SAGE_DOCBUILD_OPTS=\"$(SAGE_DOCBUILD_OPTS) --no-plot\" doc-html" $(SAGE_ROOT)/logs/dochtml.log + +$(MAKE_REC) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) --no-plot" doc-html +# Using mathjax is actually the default, but this target can be used +# to override an environment setting of SAGE_DOC_MATHJAX=no doc-html-mathjax: - $(AM_V_at)sage-logger -p "$(MAKE) SAGE_DOCBUILD_OPTS=\"$(SAGE_DOCBUILD_OPTS) -j\" doc-html" $(SAGE_ROOT)/logs/dochtml.log + +$(MAKE_REC) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) -j" doc-html # Keep target 'doc-html-jsmath' for backwards compatibility. doc-html-jsmath: doc-html-mathjax -doc-pdf: $(DOC_DEPENDENCIES) - $(AM_V_at)cd "$(SAGE_SRC)/doc" && sage-logger -p "$(MAKE) doc-pdf" $(SAGE_ROOT)/logs/docpdf.log +doc-pdf: sagemath_doc_pdf doc-clean: doc-src-clean doc-output-clean diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index b05711699f4..f97cfada907 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,4 +1,4 @@ tarball=configure-VERSION.tar.gz -sha1=bdfd5753a2548365230216455d9a543fe238f092 -md5=49ffa01e32a876dd4feea975d822351e -cksum=3517586928 +sha1=d9fff88398cb15f16c7dcb3b6180163bb206a699 +md5=585dece094717b58049a2bfaf9811162 +cksum=3669459096 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index d6c01edf77e..0cae6c531de 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -fda367752b5e7afa3ec0fda483b162645192e008 +cdb3614b34926cee3c4cc918313678d3deea4e8d diff --git a/build/pkgs/flit_core/spkg-install.in b/build/pkgs/flit_core/spkg-install.in index 37ac1a53437..8d6f80f4cc7 100644 --- a/build/pkgs/flit_core/spkg-install.in +++ b/build/pkgs/flit_core/spkg-install.in @@ -1,2 +1,3 @@ cd src -sdh_pip_install . +# We use --no-deps to suppress a warning regarding tomli. +sdh_pip_install --no-deps . diff --git a/build/pkgs/gmp/checksums.ini b/build/pkgs/gmp/checksums.ini index d2cf090de11..11a552f2352 100644 --- a/build/pkgs/gmp/checksums.ini +++ b/build/pkgs/gmp/checksums.ini @@ -1,5 +1,5 @@ tarball=gmp-VERSION.tar.xz -sha1=052a5411dc74054240eec58132d2cf41211d0ff6 -md5=a325e3f09e6d91e62101e59f9bda3ec1 -cksum=942462047 +sha1=0578d48607ec0e272177d175fd1807c30b00fdf2 +md5=0b82665c4a92fd2ade7440c13fcaa42b +cksum=1546558141 upstream_url=https://gmplib.org/download/gmp/gmp-VERSION.tar.xz diff --git a/build/pkgs/gmp/package-version.txt b/build/pkgs/gmp/package-version.txt index 6abaeb2f907..024b066c0bb 100644 --- a/build/pkgs/gmp/package-version.txt +++ b/build/pkgs/gmp/package-version.txt @@ -1 +1 @@ -6.2.0 +6.2.1 diff --git a/build/pkgs/memory_allocator/distros/conda.txt b/build/pkgs/memory_allocator/distros/conda.txt new file mode 100644 index 00000000000..8dda733d5a5 --- /dev/null +++ b/build/pkgs/memory_allocator/distros/conda.txt @@ -0,0 +1 @@ +memory-allocator diff --git a/build/pkgs/networkx/checksums.ini b/build/pkgs/networkx/checksums.ini index b71ff5f1866..075e0c74047 100644 --- a/build/pkgs/networkx/checksums.ini +++ b/build/pkgs/networkx/checksums.ini @@ -1,5 +1,5 @@ tarball=networkx-VERSION.tar.gz -sha1=5a39af7b0b6a6180b733c280b0ee70b9868a8566 -md5=ac9cf192fc525bb877a042a684091d72 -cksum=1918700937 +sha1=659f640c03fe52c98fa7a1d03fe3a6f6bbce2015 +md5=407eb28c54e08725559754ca7ab185e0 +cksum=3378468789 upstream_url=https://pypi.io/packages/source/n/networkx/networkx-VERSION.tar.gz diff --git a/build/pkgs/networkx/package-version.txt b/build/pkgs/networkx/package-version.txt index 097a15a2af3..ec1cf33c3f6 100644 --- a/build/pkgs/networkx/package-version.txt +++ b/build/pkgs/networkx/package-version.txt @@ -1 +1 @@ -2.6.2 +2.6.3 diff --git a/build/pkgs/numpy/checksums.ini b/build/pkgs/numpy/checksums.ini index b306701d888..f4013779be9 100644 --- a/build/pkgs/numpy/checksums.ini +++ b/build/pkgs/numpy/checksums.ini @@ -1,5 +1,5 @@ tarball=numpy-VERSION.zip -sha1=c7eb91a2232f7843301c355795860baaa0280909 -md5=5638d5dae3ca387be562912312db842e -cksum=2204147896 +sha1=91a1faeb617601453ebf6e2855e5ce6bf94d3588 +md5=b3c4477a027d5b6fba5e1065064fd076 +cksum=1917168823 upstream_url=https://pypi.io/packages/source/n/numpy/numpy-VERSION.zip diff --git a/build/pkgs/numpy/package-version.txt b/build/pkgs/numpy/package-version.txt index 0369d0b1e93..20a1265cf39 100644 --- a/build/pkgs/numpy/package-version.txt +++ b/build/pkgs/numpy/package-version.txt @@ -1 +1 @@ -1.21.2 +1.21.4 diff --git a/build/pkgs/python3/trees.txt b/build/pkgs/python3/trees.txt new file mode 100644 index 00000000000..f01330b2fe5 --- /dev/null +++ b/build/pkgs/python3/trees.txt @@ -0,0 +1 @@ +SAGE_VENV diff --git a/build/pkgs/sage_conf/spkg-install b/build/pkgs/sage_conf/spkg-install index 468970ba085..e572d89f80d 100755 --- a/build/pkgs/sage_conf/spkg-install +++ b/build/pkgs/sage_conf/spkg-install @@ -9,4 +9,9 @@ if [ $? -ne 0 ]; then echo >&2 "Is $SAGE_ROOT the correct SAGE_ROOT?" exit 1 fi -cd src && sdh_pip_install . +cd src +if [ "$SAGE_EDITABLE" = yes ]; then + sdh_pip_editable_install . +else + sdh_pip_install . +fi diff --git a/build/pkgs/sage_docbuild/spkg-install b/build/pkgs/sage_docbuild/spkg-install index ea7a36674d7..1bb66bc4a07 100755 --- a/build/pkgs/sage_docbuild/spkg-install +++ b/build/pkgs/sage_docbuild/spkg-install @@ -9,4 +9,9 @@ if [ $? -ne 0 ]; then echo >&2 "Is $SAGE_ROOT the correct SAGE_ROOT?" exit 1 fi -cd src && sdh_pip_install . +cd src +if [ "$SAGE_EDITABLE" = yes ]; then + sdh_pip_editable_install . +else + sdh_pip_install . +fi diff --git a/build/pkgs/sage_setup/spkg-install b/build/pkgs/sage_setup/spkg-install index ea7a36674d7..1bb66bc4a07 100755 --- a/build/pkgs/sage_setup/spkg-install +++ b/build/pkgs/sage_setup/spkg-install @@ -9,4 +9,9 @@ if [ $? -ne 0 ]; then echo >&2 "Is $SAGE_ROOT the correct SAGE_ROOT?" exit 1 fi -cd src && sdh_pip_install . +cd src +if [ "$SAGE_EDITABLE" = yes ]; then + sdh_pip_editable_install . +else + sdh_pip_install . +fi diff --git a/build/pkgs/sagelib/package-version.txt b/build/pkgs/sagelib/package-version.txt index a72129631b5..8f24c817c21 100644 --- a/build/pkgs/sagelib/package-version.txt +++ b/build/pkgs/sagelib/package-version.txt @@ -1 +1 @@ -9.5.beta6 +9.5.beta7 diff --git a/build/pkgs/sagemath_doc_html/SPKG.rst b/build/pkgs/sagemath_doc_html/SPKG.rst new file mode 100644 index 00000000000..2ece53ab56e --- /dev/null +++ b/build/pkgs/sagemath_doc_html/SPKG.rst @@ -0,0 +1,10 @@ +sagemath_doc_html: SageMath documentation in HTML format +======================================================== + +Upon installation, this package builds the SageMath documentation +in HTML format. + +It is a standard package. It is built on every invocation +of ``make`` or ``make all``, but not on ``make build``. +The documentation build can also be run separately using +``make doc-html``. diff --git a/build/pkgs/sagemath_doc_html/dependencies b/build/pkgs/sagemath_doc_html/dependencies new file mode 100644 index 00000000000..fc793f07bae --- /dev/null +++ b/build/pkgs/sagemath_doc_html/dependencies @@ -0,0 +1,5 @@ +sagelib sphinx | $(SAGERUNTIME) maxima networkx scipy sympy matplotlib pillow mathjax mpmath ipykernel jupyter_client conway_polynomials tachyon jmol thebe ipywidgets sage_docbuild + +# Building the documentation has many dependencies, because all +# documented modules are imported and because we use matplotlib to +# produce plots. diff --git a/build/pkgs/sagemath_doc_html/spkg-install b/build/pkgs/sagemath_doc_html/spkg-install new file mode 100755 index 00000000000..71e805869c0 --- /dev/null +++ b/build/pkgs/sagemath_doc_html/spkg-install @@ -0,0 +1,17 @@ +#! /usr/bin/env bash + +# When building documentation, use MathJax by default. To turn it off, +# set SAGE_DOC_MATHJAX to be "no" or "False". +if [ -z "$SAGE_DOC_MATHJAX" ]; then + # For backwards compatibility, we use the value of SAGE_DOC_JSMATH + # if it is set. + if [ -n "$SAGE_DOC_JSMATH" ]; then + SAGE_DOC_MATHJAX="$SAGE_DOC_JSMATH" + else + SAGE_DOC_MATHJAX="True" + fi + export SAGE_DOC_MATHJAX +fi + +cd $SAGE_ROOT/src/doc +$MAKE doc-html diff --git a/build/pkgs/sagemath_doc_html/trees.txt b/build/pkgs/sagemath_doc_html/trees.txt new file mode 100644 index 00000000000..77be9495f24 --- /dev/null +++ b/build/pkgs/sagemath_doc_html/trees.txt @@ -0,0 +1 @@ +SAGE_DOCS diff --git a/build/pkgs/sagemath_doc_html/type b/build/pkgs/sagemath_doc_html/type new file mode 100644 index 00000000000..a6a7b9cd726 --- /dev/null +++ b/build/pkgs/sagemath_doc_html/type @@ -0,0 +1 @@ +standard diff --git a/build/pkgs/sagemath_doc_pdf/SPKG.rst b/build/pkgs/sagemath_doc_pdf/SPKG.rst new file mode 100644 index 00000000000..25c77ff12ea --- /dev/null +++ b/build/pkgs/sagemath_doc_pdf/SPKG.rst @@ -0,0 +1,9 @@ +sagemath_doc_pdf: SageMath documentation in PDF format +====================================================== + +Upon installation, this package builds the SageMath documentation +in PDF format. + +It is an optional package. It can be enabled at configuration time +using ``./configure --enable-sagemath_doc_pdf``. Alternatively, +it can be installed by using ``make doc-pdf``. diff --git a/build/pkgs/sagemath_doc_pdf/dependencies b/build/pkgs/sagemath_doc_pdf/dependencies new file mode 100644 index 00000000000..4bdc1055372 --- /dev/null +++ b/build/pkgs/sagemath_doc_pdf/dependencies @@ -0,0 +1 @@ +sagemath_doc_html diff --git a/build/pkgs/sagemath_doc_pdf/spkg-install b/build/pkgs/sagemath_doc_pdf/spkg-install new file mode 100755 index 00000000000..947fc17511f --- /dev/null +++ b/build/pkgs/sagemath_doc_pdf/spkg-install @@ -0,0 +1,7 @@ +#! /usr/bin/env bash +# This must be set; otherwise, sage.docs.conf uses sphinx.ext.imgmath, +# which leads to errors. +export SAGE_DOC_MATHJAX=yes + +cd $SAGE_ROOT/src/doc +$MAKE doc-pdf diff --git a/build/pkgs/sagemath_doc_pdf/trees.txt b/build/pkgs/sagemath_doc_pdf/trees.txt new file mode 100644 index 00000000000..77be9495f24 --- /dev/null +++ b/build/pkgs/sagemath_doc_pdf/trees.txt @@ -0,0 +1 @@ +SAGE_DOCS diff --git a/build/pkgs/sagemath_doc_pdf/type b/build/pkgs/sagemath_doc_pdf/type new file mode 100644 index 00000000000..134d9bc32d5 --- /dev/null +++ b/build/pkgs/sagemath_doc_pdf/type @@ -0,0 +1 @@ +optional diff --git a/build/pkgs/traitlets/checksums.ini b/build/pkgs/traitlets/checksums.ini index 415ba07704b..dd2af5d21ac 100644 --- a/build/pkgs/traitlets/checksums.ini +++ b/build/pkgs/traitlets/checksums.ini @@ -1,5 +1,5 @@ tarball=traitlets-VERSION.tar.gz -sha1=08d9b2db5b0cf7794e9c4ca76f7981cccc3233b6 -md5=19483ec0685e837912cff128209aa845 -cksum=3463913536 +sha1=86d03557843700d6dd0657371d15f0520c2f392f +md5=31f7fd84518fe08cb40ab18f6dde0d54 +cksum=1147319509 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 831446cbd27..ac14c3dfaa8 100644 --- a/build/pkgs/traitlets/package-version.txt +++ b/build/pkgs/traitlets/package-version.txt @@ -1 +1 @@ -5.1.0 +5.1.1 diff --git a/m4/sage_spkg_collect.m4 b/m4/sage_spkg_collect.m4 index e6dcecdd24c..90f10986f78 100644 --- a/m4/sage_spkg_collect.m4 +++ b/m4/sage_spkg_collect.m4 @@ -181,10 +181,14 @@ for DIR in $SAGE_ROOT/build/pkgs/*; do dnl trees. For example, if we decide to create a separate tree for a venv with the dnl Jupyter notebook, then packages such as jupyter_core would have to be installed into dnl two trees. - SPKG_TREE_VAR=SAGE_LOCAL - if test -f "$DIR/requirements.txt" -o -f "$DIR/install-requires.txt" -o "$SPKG_NAME" = python3; then - dnl A Python package or spkg installation of python3 itself - SPKG_TREE_VAR=SAGE_VENV + if test -f "$DIR/trees.txt"; then + SPKG_TREE_VAR="$(sed "s/#.*//;" "$DIR/trees.txt")" + else + SPKG_TREE_VAR=SAGE_LOCAL + if test -f "$DIR/requirements.txt" -o -f "$DIR/install-requires.txt"; then + dnl A Python package + SPKG_TREE_VAR=SAGE_VENV + fi fi SAGE_PACKAGE_TREES="${SAGE_PACKAGE_TREES}$(printf '\ntrees_')${SPKG_NAME} = ${SPKG_TREE_VAR}" diff --git a/pkgs/sagemath-standard/setup.py b/pkgs/sagemath-standard/setup.py index 369c0b70f99..09f2063352b 100755 --- a/pkgs/sagemath-standard/setup.py +++ b/pkgs/sagemath-standard/setup.py @@ -26,21 +26,34 @@ sage.env.SAGE_SRC = os.getcwd() from sage.env import * -from sage_setup.excepthook import excepthook -sys.excepthook = excepthook - -from sage_setup.setenv import setenv -setenv() - ######################################################### ### Configuration ######################################################### -if len(sys.argv) > 1 and sys.argv[1] == "sdist": +if len(sys.argv) > 1 and (sys.argv[1] == "sdist" or sys.argv[1] == "egg_info"): sdist = True else: sdist = False +if sdist: + cmdclass = {} +else: + from sage_setup.excepthook import excepthook + sys.excepthook = excepthook + + from sage_setup.setenv import setenv + setenv() + + from sage_setup.command.sage_build import sage_build + from sage_setup.command.sage_build_cython import sage_build_cython + from sage_setup.command.sage_build_ext import sage_build_ext + from sage_setup.command.sage_install import sage_install_and_clean + + cmdclass = dict(build=sage_build, + build_cython=sage_build_cython, + build_ext=sage_build_ext, + install=sage_install_and_clean) + ######################################################### ### Testing related stuff ######################################################### @@ -50,27 +63,22 @@ if os.path.exists(sage.misc.lazy_import_cache.get_cache_file()): os.unlink(sage.misc.lazy_import_cache.get_cache_file()) - -from sage_setup.command.sage_build import sage_build -from sage_setup.command.sage_build_cython import sage_build_cython -from sage_setup.command.sage_build_ext import sage_build_ext - - ######################################################### ### Discovering Sources ######################################################### -# TODO: This should be quiet by default -print("Discovering Python/Cython source code....") -t = time.time() - -from sage_setup.optional_extension import is_package_installed_and_updated - if sdist: # No need to compute distributions. This avoids a dependency on Cython # just to make an sdist. distributions = None + python_packages = [] + python_modules = [] + cython_modules = [] else: + # TODO: This should be quiet by default + print("Discovering Python/Cython source code....") + t = time.time() + from sage_setup.optional_extension import is_package_installed_and_updated distributions = [''] optional_packages_with_extensions = ['mcqd', 'bliss', 'tdlib', 'primecount', 'coxeter3', 'fes', 'sirocco', 'meataxe'] @@ -78,17 +86,13 @@ for pkg in optional_packages_with_extensions if is_package_installed_and_updated(pkg)] log.warn('distributions = {0}'.format(distributions)) + from sage_setup.find import find_python_sources + python_packages, python_modules, cython_modules = find_python_sources( + SAGE_SRC, ['sage'], distributions=distributions) -from sage_setup.find import find_python_sources -python_packages, python_modules, cython_modules = find_python_sources( - SAGE_SRC, ['sage'], distributions=distributions) - -log.debug('python_packages = {0}'.format(python_packages)) - -print("Discovered Python/Cython sources, time: %.2f seconds." % (time.time() - t)) - + log.debug('python_packages = {0}'.format(python_packages)) + print("Discovered Python/Cython sources, time: %.2f seconds." % (time.time() - t)) -from sage_setup.command.sage_install import sage_install_and_clean ######################################################### ### Distutils @@ -96,8 +100,5 @@ code = setup( packages = python_packages, - cmdclass = dict(build=sage_build, - build_cython=sage_build_cython, - build_ext=sage_build_ext, - install=sage_install_and_clean), + cmdclass = cmdclass, ext_modules = cython_modules) diff --git a/pkgs/sagemath-standard/tox.ini b/pkgs/sagemath-standard/tox.ini index f9ac7336547..5fa331ae3c8 100644 --- a/pkgs/sagemath-standard/tox.ini +++ b/pkgs/sagemath-standard/tox.ini @@ -25,7 +25,7 @@ envlist = # Build dependencies according to requirements.txt (all versions fixed). # Use ONLY the wheels built and stored by the Sage distribution (no PyPI): # - # ./sage -sh -c '(cd pkgs/sagelib && tox -v -v -v -e python-sagewheels-nopypi)' + # ./sage -sh -c '(cd pkgs/sagemath-standard && tox -v -v -v -e python-sagewheels-nopypi)' # python-sagewheels-nopypi, # @@ -33,7 +33,7 @@ envlist = # using the dependencies declared in pyproject.toml and setup.cfg (install-requires) only: # Still use ONLY the wheels built and stored by the Sage distribution (no PyPI). # - # ./sage -sh -c '(cd pkgs/sagelib && tox -v -v -v -e python-sagewheels-nopypi-norequirements)' + # ./sage -sh -c '(cd pkgs/sagemath-standard && tox -v -v -v -e python-sagewheels-nopypi-norequirements)' # python-sagewheels-nopypi-norequirements, # @@ -44,7 +44,7 @@ envlist = # and additionally allow packages from PyPI. # Because all versions are fixed, we "should" end up using the prebuilt wheels. # - # ./sage -sh -c '(cd pkgs/sagelib && tox -v -v -v -e python-sagewheels)' + # ./sage -sh -c '(cd pkgs/sagemath-standard && tox -v -v -v -e python-sagewheels)' # python-sagewheels, # @@ -81,8 +81,8 @@ passenv = PKG_CONFIG_PATH # Parallel build SAGE_NUM_THREADS - # SAGE_LOCAL only for finding the wheels - sagewheels: SAGE_LOCAL + # SAGE_VENV only for finding the wheels + sagewheels: SAGE_VENV # Location of the wheels (needs to include a PEP 503 compliant # Simple Repository index, i.e., a subdirectory "simple") sagewheels: SAGE_SPKG_WHEELS @@ -92,7 +92,7 @@ setenv = HOME={envdir} # We supply pip options by environment variables so that they # apply both to the installation of the dependencies and of the package - sagewheels: PIP_FIND_LINKS=file://{env:SAGE_SPKG_WHEELS:{env:SAGE_LOCAL:{toxinidir}/../../../../local}/var/lib/sage/wheels} + sagewheels: PIP_FIND_LINKS=file://{env:SAGE_SPKG_WHEELS:{env:SAGE_VENV:{toxinidir}/../../../../venv}/var/lib/sage/wheels} nopypi: PIP_NO_INDEX=true # No build isolation for PEP 517 packages - use what is already in the environment # Note that this pip env "NO" variable uses inverted logic: diff --git a/src/VERSION.txt b/src/VERSION.txt index a72129631b5..8f24c817c21 100644 --- a/src/VERSION.txt +++ b/src/VERSION.txt @@ -1 +1 @@ -9.5.beta6 +9.5.beta7 diff --git a/src/bin/sage-env b/src/bin/sage-env index a0426df5233..6ec3ba4b6ce 100644 --- a/src/bin/sage-env +++ b/src/bin/sage-env @@ -636,19 +636,6 @@ export MAKE export PIP_FORMAT="columns" -# When building documentation, use MathJax by default. To turn it off, -# set SAGE_DOC_MATHJAX to be "no" or "False". -if [ -z "$SAGE_DOC_MATHJAX" ]; then - # For backwards compatibility, we use the value of SAGE_DOC_JSMATH - # if it is set. - if [ -n "$SAGE_DOC_JSMATH" ]; then - SAGE_DOC_MATHJAX="$SAGE_DOC_JSMATH" - else - SAGE_DOC_MATHJAX="True" - fi - export SAGE_DOC_MATHJAX -fi - # Set the cysignals crash logs directory if [ -z "$CYSIGNALS_CRASH_LOGS" ]; then export CYSIGNALS_CRASH_LOGS="$DOT_SAGE/crash_logs" diff --git a/src/bin/sage-runtests b/src/bin/sage-runtests index 882456dd15d..288c889bd12 100755 --- a/src/bin/sage-runtests +++ b/src/bin/sage-runtests @@ -28,7 +28,10 @@ def _get_optional_defaults(): if __name__ == "__main__": - parser = argparse.ArgumentParser(usage="sage -t [options] filenames") + parser = argparse.ArgumentParser(usage="sage -t [options] filenames", + description="Run all tests in a file or a list of files whose extensions " + "are one of the following: " + ".py, .pyx, .pxd, .pxi, .sage, .spyx, .tex, .rst.") parser.add_argument("-p", "--nthreads", dest="nthreads", type=int, nargs='?', const=0, default=1, metavar="N", help="tests in parallel using N threads with 0 interpreted as max(2, min(8, cpu_count()))") @@ -56,7 +59,8 @@ if __name__ == "__main__": 'if "build" is listed, will also run tests specific to Sage\'s build/packaging system; ' 'if set to "all", then all tests will be run') parser.add_argument("--randorder", type=int, metavar="SEED", help="randomize order of tests") - parser.add_argument("--random-seed", dest="random_seed", type=int, metavar="SEED", help="random seed (integer) for fuzzing doctests") + parser.add_argument("--random-seed", dest="random_seed", type=int, metavar="SEED", help="random seed (integer) for fuzzing doctests", + default=os.environ.get("SAGE_DOCTEST_RANDOM_SEED")) parser.add_argument("--global-iterations", "--global_iterations", type=int, default=0, help="repeat the whole testing process this many times") parser.add_argument("--file-iterations", "--file_iterations", type=int, default=0, help="repeat each file this many times, stopping on the first failure") parser.add_argument("--environment", type=str, default="sage.repl.ipython_kernel.all_jupyter", help="name of a module that provides the global environment for tests") diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index 547dbe14054..5d9a4f586f3 100644 --- a/src/bin/sage-version.sh +++ b/src/bin/sage-version.sh @@ -1,5 +1,5 @@ # Sage version information for shell scripts # This file is auto-generated by the sage-update-version script, do not edit! -SAGE_VERSION='9.5.beta6' -SAGE_RELEASE_DATE='2021-11-12' -SAGE_VERSION_BANNER='SageMath version 9.5.beta6, Release Date: 2021-11-12' +SAGE_VERSION='9.5.beta7' +SAGE_RELEASE_DATE='2021-11-18' +SAGE_VERSION_BANNER='SageMath version 9.5.beta7, Release Date: 2021-11-18' diff --git a/src/doc/Makefile b/src/doc/Makefile index 304d5aca147..5d2031bd964 100644 --- a/src/doc/Makefile +++ b/src/doc/Makefile @@ -30,6 +30,7 @@ doc-inventory-reference: else doc-inventory-reference: $(eval DOCS = $(shell cd $(SAGE_ROOT) && ./sage --docbuild --all-documents reference)) + @if [ -z "$(DOCS)" ]; then echo "Error: './sage --docbuild --all-documents' failed"; exit 1; fi $(eval BIBLIO = $(firstword $(DOCS))) $(eval OTHER_DOCS = $(wordlist 2, 100, $(DOCS))) $(MAKE) doc-inventory--$(subst /,-,$(BIBLIO)) @@ -40,6 +41,7 @@ endif # reference manual, html doc-html-reference: doc-inventory-reference $(eval DOCS = $(shell cd $(SAGE_ROOT) && ./sage --docbuild --all-documents reference)) + @if [ -z "$(DOCS)" ]; then echo "Error: './sage --docbuild --all-documents' failed"; exit 1; fi $(eval BIBLIO = $(firstword $(DOCS))) $(eval OTHER_DOCS = $(wordlist 2, 100, $(DOCS))) $(MAKE) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) --no-prune-empty-dirs" doc-html--$(subst /,-,$(BIBLIO)) @@ -48,7 +50,9 @@ doc-html-reference: doc-inventory-reference # other documentation, html doc-html-other: doc-html-reference - $(MAKE) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) --no-prune-empty-dirs" $(foreach doc, $(wordlist 2, 100, $(shell cd $(SAGE_ROOT) && ./sage --docbuild --all-documents all)), doc-html--$(subst /,-,$(doc))) + $(eval DOCS = $(shell cd $(SAGE_ROOT) && ./sage --docbuild --all-documents all)) + @if [ -z "$(DOCS)" ]; then echo "Error: './sage --docbuild --all-documents' failed"; exit 1; fi + $(MAKE) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) --no-prune-empty-dirs" $(foreach doc, $(wordlist 2, 100, $(DOCS)), doc-html--$(subst /,-,$(doc))) doc-html: doc-html-reference doc-html-other @@ -59,6 +63,7 @@ doc-pdf--%: # reference manual, pdf doc-pdf-reference: doc-inventory-reference $(eval DOCS = $(shell cd $(SAGE_ROOT) && ./sage --docbuild --all-documents reference)) + @if [ -z "$(DOCS)" ]; then echo "Error: './sage --docbuild --all-documents' failed"; exit 1; fi $(eval BIBLIO = $(firstword $(DOCS))) $(eval OTHER_DOCS = $(wordlist 2, 100, $(DOCS))) $(MAKE) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) --no-prune-empty-dirs" doc-pdf--$(subst /,-,$(BIBLIO)) @@ -67,7 +72,9 @@ doc-pdf-reference: doc-inventory-reference # other documentation, pdf doc-pdf-other: doc-html-reference - $(MAKE) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) --no-prune-empty-dirs" $(foreach doc, $(wordlist 2, 100, $(shell cd $(SAGE_ROOT) && ./sage --docbuild --all-documents all)), doc-pdf--$(subst /,-,$(doc))) + $(eval DOCS = $(shell cd $(SAGE_ROOT) && ./sage --docbuild --all-documents all)) + @if [ -z "$(DOCS)" ]; then echo "Error: './sage --docbuild --all-documents' failed"; exit 1; fi + $(MAKE) SAGE_DOCBUILD_OPTS="$(SAGE_DOCBUILD_OPTS) --no-prune-empty-dirs" $(foreach doc, $(wordlist 2, 100, $(DOCS)), doc-pdf--$(subst /,-,$(doc))) doc-pdf: doc-pdf-reference doc-pdf-other diff --git a/src/doc/en/developer/doctesting.rst b/src/doc/en/developer/doctesting.rst index e26d7329095..7b8aa79554a 100644 --- a/src/doc/en/developer/doctesting.rst +++ b/src/doc/en/developer/doctesting.rst @@ -855,6 +855,9 @@ This seed can be set explicitly to reproduce possible failures:: cpu time: 0.0 seconds cumulative wall time: 0.0 seconds +It can also be set explicitly using the environment variable +``SAGE_DOCTEST_RANDOM_SEED``. + .. _section-optional-doctest-flag: Run Optional Doctests diff --git a/src/doc/en/developer/index.rst b/src/doc/en/developer/index.rst index 899ebe45a88..38074743daa 100644 --- a/src/doc/en/developer/index.rst +++ b/src/doc/en/developer/index.rst @@ -160,6 +160,14 @@ Sage Coding Details coding_in_cython coding_in_other +Packaging the Sage Library +-------------------------- + +.. toctree:: + :maxdepth: 3 + + packaging_sage_library + Packaging Third-Party Code -------------------------- diff --git a/src/doc/en/developer/packaging.rst b/src/doc/en/developer/packaging.rst index 498825377c5..aaa294986d1 100644 --- a/src/doc/en/developer/packaging.rst +++ b/src/doc/en/developer/packaging.rst @@ -171,7 +171,8 @@ The following are some additional files which can be added: | `-- baz.patch |-- spkg-check.in |-- spkg-configure.m4 - `-- spkg-src + |-- spkg-src + `-- trees.txt We discuss the individual files in the following sections. @@ -411,6 +412,13 @@ begin with ``sdh_``, which stands for "Sage-distribution helper". creating a wheel file in ``dist/``, followed by ``sdh_store_and_pip_install_wheel`` (see below). +- ``sdh_pip_editable_install [...]``: The equivalent of running ``pip install -e`` + with the given arguments, as well as additional default arguments used for + installing packages into Sage with pip. The last argument must be + ``.`` to indicate installation from the current directory. + See `pip documentation `_ + for more details concerning editable installs. + - ``sdh_pip_uninstall [...]``: Runs ``pip uninstall`` with the given arguments. If unsuccessful, it displays a warning. @@ -537,7 +545,12 @@ would simply contain: Python-based packages --------------------- -The best way to install a Python-based package is to use pip, in which +Python-based packages should declare ``$(PYTHON)`` as a dependency, +and most Python-based packages will also have ``$(PYTHON_TOOLCHAIN)`` as +an order-only dependency, which will ensure that fundamental packages such +as ``pip`` and ``setuptools`` are available at the time of building the package. + +The best way to install a Python-based package is to use ``pip``, in which case the ``spkg-install.in`` script template might just consist of .. CODE-BLOCK:: bash @@ -548,19 +561,18 @@ Where ``sdh_pip_install`` is a function provided by ``sage-dist-helpers`` that points to the correct ``pip`` for the Python used by Sage, and includes some default flags needed for correct installation into Sage. -If pip will not work but a command like ``python3 setup.py install`` +If ``pip`` will not work for a package but a command like ``python3 setup.py install`` will, you may use ``sdh_setup_bdist_wheel``, followed by ``sdh_store_and_pip_install_wheel .``. -For ``spkg-check.in`` script templates, make sure to call -``sage-python23`` rather than ``python``. This will ensure that the -correct version of Python is used to check the package. -The same holds for ; for example, the ``scipy`` ``spkg-check.in`` -file contains the line +For ``spkg-check.in`` script templates, use ``python3`` rather +than just ``python``. The paths are set by the Sage build system +so that this runs the correct version of Python. +For example, the ``scipy`` ``spkg-check.in`` file contains the line .. CODE-BLOCK:: bash - exec sage-python23 spkg-check.py + exec python3 spkg-check.py All normal Python packages must have a file ``install-requires.txt``. If a Python package is available on PyPI, this file must contain the @@ -717,6 +729,28 @@ packages and optional packages should only depend on standard or optional packages. +.. _section-trees: + +Where packages are installed +---------------------------- + +The Sage distribution has the notion of several installation trees. + +- ``$SAGE_VENV`` is the default installation tree for all Python packages, i.e., + normal packages with an ``install-requires.txt`` and pip packages + with a ``requirements.txt``. + +- ``$SAGE_LOCAL`` is the default installation tree for all non-Python packages. + +- ``$SAGE_DOCS`` (only set at build time) is an installation tree for the + HTML and PDF documentation. + +By placing a file ``trees.txt`` in the package directory, the installation tree +can be overridden. For example, ``build/pkgs/python3/trees.txt`` contains the +word ``SAGE_VENV``, and ``build/pkgs/sagemath_doc_html/trees.txt`` contains the +word ``SAGE_DOCS``. + + .. _section-spkg-patching: Patching Sources diff --git a/src/doc/en/developer/packaging_sage_library.rst b/src/doc/en/developer/packaging_sage_library.rst new file mode 100644 index 00000000000..172e7a9db01 --- /dev/null +++ b/src/doc/en/developer/packaging_sage_library.rst @@ -0,0 +1,523 @@ + +.. _chapter-modularization: + +============================ + Packaging the Sage Library +============================ + + +Modules, packages, distribution packages +======================================== + +The Sage library consists of a large number of Python modules, +organized into a hierarchical set of packages that fill the namespace +:mod:`sage`. All source files are located in a subdirectory of the +directory ``SAGE_ROOT/src/sage/``. + +For example, + +- the file ``SAGE_ROOT/src/sage/coding/code_bounds.py`` provides the + module :mod:`sage.coding.code_bounds`; + +- the directory containing this file, ``SAGE_ROOT/src/sage/coding/``, + thus provides the package :mod:`sage.coding`. + +There is another notion of "package" in Python, the **distribution +package** (also known as a "distribution" or a "pip-installable +package"). Currently, the entire Sage library is provided by a +single distribution, +`sagemath-standard `_, +which is generated from the directory +``SAGE_ROOT/pkgs/sagemath-standard``. + +Note that the distribution name is not required to be a Python +identifier. In fact, using dashes (``-``) is preferred to underscores in +distribution names; **setuptools** and other parts of Python's packaging +infrastructure normalize underscores to dashes. (Using dots in +distribution names, to indicate ownership by organizations, still +mentioned in `PEP 423 `_, appears to +have largely fallen out of favor, and we will not use it in the SageMath +project.) + +A distribution that provides Python modules in the :mod:`sage.*` namespace, say +mainly from :mod:`sage.PAC.KAGE`, should be named **sagemath-DISTRI-BUTION**. +Example: + +- The distribution + `sagemath-categories `_ + provides a small subset of the modules of the Sage library, mostly + from the packages :mod:`sage.structure`, :mod:`sage.categories`, and + :mod:`sage.misc`. + +Other distributions should not use the prefix **sagemath-** in the +distribution name. Example: + +- The distribution `sage-sws2rst `_ + provides the Python package :mod:`sage_sws2rst`, so it does not fill + the :mod:`sage.*` namespace and therefore does not use the prefix + **sagemath-**. + +A distribution that provides functionality that does not need to +import anything from the :mod:`sage` namespace should not use the +:mod:`sage` namespace for its own packages/modules. It should be +positioned as part of the general Python ecosystem instead of as a +Sage-specific distribution. Examples: + +- The distribution `pplpy `_ provides the Python + package :mod:`ppl` and is a much extended version of what used to be + :mod:`sage.libs.ppl`, a part of the Sage library. The package :mod:`sage.libs.ppl` had + dependencies on :mod:`sage.rings` to convert to/from Sage number + types. **pplpy** has no such dependencies and is therefore usable in a + wider range of Python projects. + +- The distribution `memory-allocator `_ + provides the Python package :mod:`memory_allocator`. This used to be + :mod:`sage.ext.memory_allocator`, a part of the Sage library. + + +Ordinary packages vs. implicit namespace packages +------------------------------------------------- + +Each module of the Sage library must be packaged in exactly one distribution +package. However, modules in a package may be included in different +distribution packages. In this regard, there is an important constraint that an +ordinary package (directory with ``__init__.py`` file) cannot be split into +more than one distribution package. + +By removing the ``__init__.py`` file, however, we can make the package an +"implicit" (or "native") "namespace" package, following +`PEP 420 `_. Implicit namespace packages can be +included in more than one distribution package. Hence whenever there are two +distribution packages that provide modules with a common prefix of Python +packages, that prefix needs to be a implicit namespace package, i.e., there +cannot be an ``__init__.py`` file. + +For example, + +- **sagemath-tdlib** will provide :mod:`sage.graphs.graph_decompositions.tdlib`, + +- **sagemath-rw** will provide :mod:`sage.graphs.graph_decompositions.rankwidth`, + +- **sagemath-graphs** will provide all of the rest of + :mod:`sage.graphs.graph_decompositions` (and most of :mod:`sage.graphs`). + +Then, none of + +- :mod:`sage`, + +- :mod:`sage.graphs`, + +- :mod:`sage.graphs.graph_decomposition` + +can be an ordinary package (with an ``__init__.py`` file), but rather +each of them has to be an implicit namespace package (no +``__init__.py`` file). + +For an implicit namespace package, ``__init__.py`` cannot be used any more for +initializing the package. + +In the Sage 9.6 development cycle, we still use ordinary packages by +default, but several packages are converted to implicit namespace +packages to support modularization. + + +Source directories of distribution packages +=========================================== + +The development of the Sage library uses a monorepo strategy for +all distribution packages that fill the :mod:`sage.*` namespace. This +means that the source trees of these distributions are included in a +single ``git`` repository, in a subdirectory of ``SAGE_ROOT/pkgs``. + +All these distribution packages have matching version numbers. From +the viewpoint of a single distribution, this means that sometimes +there will be a new release of some distribution where the only thing +changing is the version number. + +The source directory of a distribution package, such as +``SAGE_ROOT/pkgs/sagemath-standard``, contains the following files: + +- ``sage`` -- a relative symbolic link to the monolithic Sage library + source tree ``SAGE_ROOT/src/sage/`` + +- `MANIFEST.in `_ -- + controls which files and directories of the + monolithic Sage library source tree are included in the distribution + +- `pyproject.toml `_, + `setup.cfg `_, + and `requirements.txt `_ -- + standard Python packaging metadata, declaring the distribution name, dependencies, + etc. + +- ``README.rst`` -- a description of the distribution + +- ``VERSION.txt``, ``LICENSE.txt`` -- relative symbolic links to the same files + in ``SAGE_ROOT/src`` + +- ``setup.py`` -- a `setuptools `_-based + installation script + +- ``tox.ini`` -- configuration for testing with `tox `_ + +The technique of using symbolic links pointing into ``SAGE_ROOT/src`` +has allowed the modularization effort to keep the ``SAGE_ROOT/src`` +tree monolithic: Modularization has been happening behind the scenes +and will not change where Sage developers find the source files. + +Some of these files may actually be generated from source files with suffix ``.m4`` by the +``SAGE_ROOT/bootstrap`` script via the ``m4`` macro processor. + + + + +Dependencies and distribution packages +====================================== + +When preparing a portion of the Sage library as a distribution +package, dependencies matter. + + +Build-time dependencies +----------------------- + +If the portion of the library contains any Cython modules, these +modules are compiled during the wheel-building phase of the +distribution package. If the Cython module uses ``cimport`` to pull in +anything from ``.pxd`` files, these files must be either part of the +portion shipped as the distribution being built, or the distribution +that provides these files must be installed in the build +environment. Also, any C/C++ libraries that the Cython module uses +must be accessible from the build environment. + +*Declaring build-time dependencies:* Modern Python packaging provides a +mechanism to declare build-time dependencies on other distribution +packages via the file `pyproject.toml `_ +(``[build-system] requires``); this +has superseded the older ``setup_requires`` declaration. (There is no +mechanism to declare anything regarding the C/C++ libraries.) + +While the namespace :mod:`sage.*` is organized roughly according to +mathematical fields or categories, how we partition the implementation +modules into distribution packages has to respect the hard constraints +that are imposed by the build-time dependencies. + +We can define some meaningful small distributions that just consist of +a single or a few Cython modules. For example, **sagemath-tdlib** +(https://trac.sagemath.org/ticket/29864) would just package the single +Cython module that must be linked with ``tdlib``, +:mod:`sage.graphs.graph_decompositions.tdlib`. Starting with the Sage +9.6 development cycle, as soon as namespace packages are activated, we +can start to create these distributions. This is quite a mechanical +task. + +*Reducing build-time dependencies:* Sometimes it is possible to +replace build-time dependencies of a Cython module on a library by a +runtime dependency. In other cases, it may be possible to split a +module that simultaneously depends on several libraries into smaller +modules, each of which has narrower dependencies. + + +Module-level runtime dependencies +--------------------------------- + +Any ``import`` statements at the top level of a Python or Cython +module are executed when the module is imported. Hence, the imported +modules must be part of the distribution, or provided by another +distribution -- which then must be declared as a run-time dependency. + +*Declaring run-time dependencies:* These dependencies are declared in +``setup.cfg`` (generated from ``setup.cfg.m4``) as +`install_requires `_. + +*Reducing module-level run-time dependencies:* + +- Avoid importing from :mod:`sage.PAC.KAGE.all` modules when :mod:`sage.PAC.KAGE` is + a namespace package. The main purpose of the :mod:`*.all` modules is for + populating the global interactive environment that is available to users at + the ``sage:`` prompt. In particular, no Sage library code should import from + :mod:`sage.rings.all`. + +- Replace module-level imports by method-level imports. Note that + this comes with a small runtime overhead, which can become + noticeable if the method is called in tight inner loops. + +- Sage provides the :func:`~sage.misc.lazy_import.lazy_import` + mechanism. Lazy imports can be + declared at the module level, but the actual importing is only done + on demand. It is a runtime error at that time if the imported module + is not present. This can be convenient compared to local imports in + methods when the same imports are needed in several methods. + +- Avoid the "modularization anti-pattern" of importing a class from + another module just to run an ``isinstance(object, Class)`` test, in + particular when the module implementing ``Class`` has heavy + dependencies. For example, importing the class + :class:`~sage.rings.padics.generic_nodes.pAdicField` (or the + function :class:`~sage.rings.padics.generic_nodes.is_pAdicField`) + requires the libraries NTL and PARI. + + Instead, provide an abstract base class (ABC) in a module that only + has light dependencies, make ``Class`` a subclass of ``ABC``, and + use ``isinstance(object, ABC)``. For example, :mod:`sage.rings.abc` + provides abstract base classes for many ring (parent) classes, + including :class:`sage.rings.abc.pAdicField`. So we can replace:: + + from sage.rings.padics.generic_nodes import pAdicField # heavy dependencies + isinstance(object, pAdicField) + + and:: + + from sage.rings.padics.generic_nodes import pAdicField # heavy dependencies + is_pAdicField(object) # deprecated + + by:: + + import sage.rings.abc # no dependencies + isinstance(object, sage.rings.abc.pAdicField) + + +Other runtime dependencies +-------------------------- + +If ``import`` statements are used within a method, the imported module +is loaded the first time that the method is called. Hence the module +defining the method can still be imported even if the module needed by +the method is not present. + +It is then a question whether a run-time dependency should be +declared. If the method needing that import provides core +functionality, then probably yes. But if it only provides what can be +considered "optional functionality", then probably not, and in this +case it will be up to the user to install the distribution enabling +this optional functionality. + +As an example, let us consider designing a distribution that centers +around the package :mod:`sage.coding`. First, let's see if it uses symbolics:: + + (9.5.beta6) $ git grep -E 'sage[.](symbolic|functions|calculus)' src/sage/coding + src/sage/coding/code_bounds.py: from sage.functions.other import ceil + ... + src/sage/coding/grs_code.py:from sage.symbolic.ring import SR + ... + src/sage/coding/guruswami_sudan/utils.py:from sage.functions.other import floor + +Apparently it does not in a very substantial way: + +- The imports of the symbolic functions :func:`~sage.functions.other.ceil` + and :func:`~sage.functions.other.floor` can + likely be replaced by the artithmetic functions + :func:`~sage.arith.misc.integer_floor` and + :func:`~sage.arith.misc.integer_ceil`. + +- Looking at the import of ``SR`` by :mod:`sage.coding.grs_code`, it + seems that ``SR`` is used for running some symbolic sum, but the + doctests do not show symbolic results, so it is likely that this can + be replaced. + +- Note though that the above textual search for the module names is + merely a heuristic. Looking at the source of "entropy", through + ``log`` from :mod:`sage.misc.functional`, a runtime dependency on + symbolics comes in. In fact, for this reason, two doctests there are + already marked as ``# optional - sage.symbolic``. + +So if packaged as **sagemath-coding**, now a domain expert would have +to decide whether these dependencies on symbolics are strong enough to +declare a runtime dependency (``install_requires``) on +**sagemath-symbolics**. This declaration would mean that any user who +installs **sagemath-coding** (``pip install sagemath-coding``) would +pull in **sagemath-symbolics**, which has heavy compile-time +dependencies (ECL/Maxima/FLINT/Singular/...). + +The alternative is to consider the use of symbolics by +**sagemath-coding** merely as something that provides some extra +features, which will only be working if the user also has installed +**sagemath-symbolics**. + +*Declaring optional run-time dependencies:* It is possible to declare +such optional dependencies as `extras_require `_ in ``setup.cfg`` +(generated from ``setup.cfg.m4``). This is a very limited mechanism +-- in particular it does not affect the build phase of the +distribution in any way. It basically only provides a way to give a +nickname to a distribution that can be installed as an add-on. + +In our example, we could declare an ``extras_require`` so that users +could use ``pip install sagemath-coding[symbolics]``. + + +Doctest-only dependencies +------------------------- + +Doctests often use examples constructed using functionality provided +by other portions of the Sage library. This kind of integration +testing is one of the strengths of Sage; but it also creates extra +dependencies. + +Fortunately, these dependencies are very mild, and we can deal with +them using the same mechanism that we use for making doctests +conditional on the presence of optional libraries: using ``# optional - +FEATURE`` directives in the doctests. Adding these directives will +allow developers to test the distribution separately, without +requiring all of Sage to be present. + +*Declaring doctest-only dependencies:* The +`extras_require `_ +mechanism mentioned above can also be used for this. + + +Version constraints of dependencies +----------------------------------- + +The version information for dependencies comes from the files +``build/pkgs/*/install-requires.txt`` and +``build/pkgs/*/package-version.txt``. We use the +`m4 `_ +macro processor to insert the version information in the generated files +``pyproject.toml``, ``setup.cfg``, ``requirements.txt``. + + +Hierarchy of distribution packages +================================== + +.. PLOT:: + + def node(label, pos): + return text(label, (3*pos[0],2*pos[1]), background_color='pink', color='black') + def edge(start, end): + return arrow((3*start[0],2*start[1]+.5),(3*end[0],2*end[1]-.5), arrowsize=2) + g = Graphics() + g += (node("sagemath-objects", (1,0)) + edge((1,0),(1,1))) + g += (node("sagemath-categories", (1,1)) + edge((1,1),(0,2)) + + edge((1,1),(1,2)) + edge((1,1),(2,2))) + g += (node("sagemath-graphs", (0,2)) + node("sagemath-polyhedra", (1,2)) + node("sagemath-singular", (2,2)) + + edge((0,2),(0,3)) + edge((0,2),(1,3)) + edge((1,2),(1,3)) + edge((2,2),(2,3))) + g += (node("sagemath-tdlib", (0,3)) + node("sagemath-standard-no-symbolics", (1,3)) + node("sagemath-symbolics", (2,3)) + + edge((1,3),(1,4)) + edge((2,3),(1,4))) + g += node("sagemath-standard", (1,4)) + sphinx_plot(g, figsize=(8, 4), axes=False) + + +Testing distribution packages +============================= + +Of course, we need tools for testing modularized distributions of +portions of the Sage library. + +- Modularized distributions must be testable separately! + +- But we want to keep integration testing with other portions of Sage too! + +Preparing doctests +------------------ + +Whenever an optional package is needed for a particular test, we use the +doctest annotation ``# optional``. This mechanism can also be used for making a +doctest conditional on the presence of a portion of the Sage library. + +The available tags take the form of package or module names such as +:mod:`sage.combinat`, :mod:`sage.graphs`, :mod:`sage.plot`, :mod:`sage.rings.number_field`, +:mod:`sage.rings.real_double`, and :mod:`sage.symbolic`. They are defined via +:class:`~sage.features.Feature` subclasses in the module :mod:`sage.features.sagemath`, which +also provides the mapping from features to the distributions providing them +(actually, to SPKG names). Using this mapping, Sage can issue installation +hints to the user. + +For example, the package :mod:`sage.tensor` is purely algebraic and has +no dependency on symbolics. However, there are a small number of +doctests that depend on :class:`sage.symbolic.ring.SymbolicRing` for integration +testing. Hence, these doctests are marked ``# optional - +sage.symbolic``. + +Testing the distribution in virtual environments with tox +--------------------------------------------------------- + +So how to test that this works? + +Sure, we could go into the installation directory +``SAGE_VENV/lib/python3.9/site-packages/`` and do ``rm -rf +sage/symbolic`` and test that things still work. But that's not a good +way of testing. + +Instead, we use a virtual environment in which we only install the +distribution to be tested (and its Python dependencies). + +Let's try it out first with the entire Sage library, represented by +the distribution **sagemath-standard**. Note that after Sage has been +built normally, a set of wheels for all installed Python packages is +available in ``SAGE_VENV/var/lib/sage/wheels/``:: + + $ ls venv/var/lib/sage/wheels + Babel-2.9.1-py2.py3-none-any.whl + Cython-0.29.24-cp39-cp39-macosx_11_0_x86_64.whl + Jinja2-2.11.2-py2.py3-none-any.whl + ... + sage_conf-9.5b6-py3-none-any.whl + ... + scipy-1.7.2-cp39-cp39-macosx_11_0_x86_64.whl + setuptools-58.2.0-py3-none-any.whl + ... + wheel-0.37.0-py2.py3-none-any.whl + widgetsnbextension-3.5.1-py2.py3-none-any.whl + zipp-3.5.0-py3-none-any.whl + +Note in particular the wheel for **sage-conf**, which provides +configuration variable settings and the connection to the non-Python +packages installed in ``SAGE_LOCAL``. + +We can now set up a separate virtual environment, in which we install +these wheels and our distribution to be tested. This is where +`tox `_ +comes into play: It is the standard Python tool for creating +disposable virtual environments for testing. Every distribution in +``SAGE_ROOT/pkgs/`` provides a configuration file ``tox.ini``. + +Following the comments in the file +``SAGE_ROOT/pkgs/sagemath-standard/tox.ini``, we can try the following +command:: + + $ ./bootstrap && ./sage -sh -c '(cd pkgs/sagemath-standard && SAGE_NUM_THREADS=16 tox -v -v -v -e py39-sagewheels-nopypi)' + +This command does not make any changes to the normal installation of +Sage. The virtual environment is created in a subdirectory of +``SAGE_ROOT/pkgs/sagemath-standard-no-symbolics/.tox/``. After the command +finishes, we can start the separate installation of the Sage library +in its virtual environment:: + + $ pkgs/sagemath-standard/.tox/py39-sagewheels-nopypi/bin/sage + +We can also run parts of the testsuite:: + + $ pkgs/sagemath-standard/.tox/py39-sagewheels-nopypi/bin/sage -tp 4 src/sage/graphs/ + +The whole ``.tox`` directory can be safely deleted at any time. + +We can do the same with other distributions, for example the large +distribution **sagemath-standard-no-symbolics** +(from :trac:`32601`), which is intended to provide +everything that is currently in the standard Sage library, i.e., +without depending on optional packages, but without the packages +:mod:`sage.symbolic`, :mod:`sage.functions`, :mod:`sage.calculus`, etc. + +Again we can run the test with ``tox`` in a separate virtual environment:: + + $ ./bootstrap && ./sage -sh -c '(cd pkgs/sagemath-standard-no-symbolics && SAGE_NUM_THREADS=16 tox -v -v -v -e py39-sagewheels-nopypi)' + +Some small distributions, for example the ones providing the two +lowest levels, `sagemath-objects `_ +and `sagemath-categories `_ +(from :trac:`29865`), can be installed and tested +without relying on the wheels from the Sage build:: + + $ ./bootstrap && ./sage -sh -c '(cd pkgs/sagemath-objects && SAGE_NUM_THREADS=16 tox -v -v -v -e py39)' + +This command finds the declared build-time and run-time dependencies +on PyPI, either as source tarballs or as prebuilt wheels, and builds +and installs the distribution +`sagemath-objects `_ in a virtual +environment in a subdirectory of ``pkgs/sagemath-objects/.tox``. + +Building these small distributions serves as a valuable regression +testsuite. However, a current issue with both of these distributions +is that they are not separately testable: The doctests for these +modules depend on a lot of other functionality from higher-level parts +of the Sage library. diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 8a7e133e0ae..981d1454c9f 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -1716,6 +1716,9 @@ REFERENCES: C. R. Acad. Sci. Paris Sér. I Math. 296 (1983) 14 781--784. +.. [Cro2004] Peter R. Cromwell, *Knots and links*, Cambridge University Press (2004). + :doi:`10.1017/CBO9780511809767` + .. [CRS2016] Dean Crnković, Sanja Rukavina, and Andrea Švob. *Strongly regular graphs from orthogonal groups* `O^+(6,2)` *and* `O^-(6,2)`. :arxiv:`1609.07133` diff --git a/src/doc/en/thematic_tutorials/coercion_and_categories.rst b/src/doc/en/thematic_tutorials/coercion_and_categories.rst index 4a8d86c0ae9..846b68f5210 100644 --- a/src/doc/en/thematic_tutorials/coercion_and_categories.rst +++ b/src/doc/en/thematic_tutorials/coercion_and_categories.rst @@ -1742,7 +1742,7 @@ The new test is inherited from the category. Since ``an_element()`` is returning complicated element, ``_test_factorisation`` is a serious test:: sage: P.an_element()._test_factorisation - + .. end of output diff --git a/src/requirements.txt.m4 b/src/requirements.txt.m4 index 57dca4227a6..9a2e448c603 100644 --- a/src/requirements.txt.m4 +++ b/src/requirements.txt.m4 @@ -23,6 +23,7 @@ gmpy2==esyscmd(`printf $(sed "s/[.]p.*//;" ../gmpy2/package-version.txt)') jinja2==esyscmd(`printf $(sed "s/[.]p.*//;" ../jinja2/package-version.txt)') dnl ... for sage_setup.autogen.interpreters jupyter_core==esyscmd(`printf $(sed "s/[.]p.*//;" ../jupyter_core/package-version.txt)') +memory_allocator==esyscmd(`printf $(sed "s/[.]p.*//;" ../memory_allocator/package-version.txt)') numpy==esyscmd(`printf $(sed "s/[.]p.*//;" ../numpy/package-version.txt)') dnl ... already needed by sage.env pkgconfig==esyscmd(`printf $(sed "s/[.]p.*//;" ../pkgconfig/package-version.txt)') diff --git a/src/sage/algebras/free_algebra.py b/src/sage/algebras/free_algebra.py index 1165d82c02c..ea885e6f4d7 100644 --- a/src/sage/algebras/free_algebra.py +++ b/src/sage/algebras/free_algebra.py @@ -294,7 +294,7 @@ def create_key(self, base_ring, arg1=None, arg2=None, sparse=sparse, order=T) return tuple(degrees), R # normalise the generator names - from sage.all import Integer + from sage.rings.integer import Integer if isinstance(arg1, (Integer, int)): arg1, arg2 = arg2, arg1 if names is not None: diff --git a/src/sage/algebras/steenrod/steenrod_algebra.py b/src/sage/algebras/steenrod/steenrod_algebra.py index 3eb15efd811..6d4c7363a02 100644 --- a/src/sage/algebras/steenrod/steenrod_algebra.py +++ b/src/sage/algebras/steenrod/steenrod_algebra.py @@ -591,7 +591,7 @@ def __init__(self, p=2, basis='milnor', **kwds): from sage.sets.set_from_iterator import EnumeratedSetFromIterator from functools import partial from .steenrod_algebra_bases import steenrod_algebra_basis - from sage.rings.all import GF + from sage.rings.finite_rings.finite_field_constructor import GF profile = kwds.get('profile', None) truncation_type = kwds.get('truncation_type', 'auto') self._generic = kwds.get('generic') @@ -1088,7 +1088,7 @@ def homogeneous_component(self, n): sage: max([H[n].dimension() - G[n].dimension() for n in range(100)]) 0 """ - from sage.rings.all import GF + from sage.rings.finite_rings.finite_field_constructor import GF basis = self._basis_fcn(n) M = CombinatorialFreeModule(GF(self.prime()), basis, element_class=self.Element, @@ -1780,7 +1780,7 @@ def _change_basis_on_basis(self, t, basis='milnor'): P^4 P^2 + P^5 P^1 + P^6 """ from sage.matrix.constructor import matrix - from sage.rings.all import GF + from sage.rings.finite_rings.finite_field_constructor import GF from .steenrod_algebra_bases import steenrod_algebra_basis,\ convert_from_milnor_matrix from .steenrod_algebra_misc import get_basis_name @@ -2153,7 +2153,7 @@ def __contains__(self, x): sage: A_3.P(1) * A_3.Q(2) in B_3 False """ - from sage.rings.all import GF + from sage.rings.finite_rings.finite_field_constructor import GF p = self.prime() if x in GF(p): return True @@ -2321,7 +2321,7 @@ def P(self, *nums): sage: SteenrodAlgebra(generic=True).P(2,0,1) P(2,0,1) """ - from sage.rings.all import Integer + from sage.rings.integer import Integer if self.basis_name() != 'milnor': return self(SteenrodAlgebra(p=self.prime(),generic=self._generic).P(*nums)) while nums and nums[-1] == 0: @@ -2478,7 +2478,7 @@ def an_element(self): sage: SteenrodAlgebra(basis='pst', profile=[3,2,1]).an_element() P^0_1 """ - from sage.rings.all import GF + from sage.rings.finite_rings.finite_field_constructor import GF basis = self.basis_name() p = self.prime() @@ -2542,7 +2542,7 @@ def pst(self,s,t): sage: SteenrodAlgebra(5).pst(3,5) P(0,0,0,0,125) """ - from sage.rings.all import Integer + from sage.rings.integer import Integer if self.basis_name() != 'milnor': return self(SteenrodAlgebra(p=self.prime(),generic=self._generic).pst(s,t)) if not isinstance(s, (Integer, int)) and s >= 0: @@ -2628,7 +2628,7 @@ 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] @@ -2647,7 +2647,7 @@ 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``:: @@ -2731,7 +2731,7 @@ def gen(self, i=0): P^1_1 """ from sage.rings.infinity import Infinity - from sage.rings.all import Integer + from sage.rings.integer import Integer p = self.prime() if not isinstance(i, (Integer, int)) and i >= 0: raise ValueError("%s is not a non-negative integer" % i) @@ -3586,7 +3586,7 @@ def may_weight(self): 3 """ from sage.rings.infinity import Infinity - from sage.rings.all import Integer + from sage.rings.integer import Integer p = self.prime() generic = self.parent()._generic if self == 0: @@ -3694,7 +3694,7 @@ def wall_height(self): sage: Sq(0,0,3).wall_height() [1, 2, 2, 1] """ - from sage.rings.all import Integer + from sage.rings.integer import Integer if self.parent()._generic: raise NotImplementedError("Wall height is not defined at odd primes.") if self == 0 or self == 1: diff --git a/src/sage/algebras/steenrod/steenrod_algebra_bases.py b/src/sage/algebras/steenrod/steenrod_algebra_bases.py index c759b8955cf..65b5fc89f6a 100644 --- a/src/sage/algebras/steenrod/steenrod_algebra_bases.py +++ b/src/sage/algebras/steenrod/steenrod_algebra_bases.py @@ -163,7 +163,7 @@ def convert_to_milnor_matrix(n, basis, p=2, generic='auto'): [1 2 0] """ from sage.matrix.constructor import matrix - from sage.rings.all import GF + from sage.rings.finite_rings.finite_field_constructor import GF from .steenrod_algebra import SteenrodAlgebra if generic == 'auto': generic = False if p==2 else True @@ -479,7 +479,7 @@ def xi_degrees(n,p=2, reverse=True): sage: sage.algebras.steenrod.steenrod_algebra_bases.xi_degrees(400,p=17) [307, 18, 1] """ - from sage.rings.all import Integer + from sage.rings.integer import Integer if n <= 0: return [] N = Integer(n*(p-1) + 1) @@ -1029,7 +1029,7 @@ def sorting_pair(s,t,basis): # pair used for sorting the basis else: return (((), ()),) - from sage.rings.all import Integer + from sage.rings.integer import Integer from sage.rings.infinity import Infinity from sage.combinat.integer_vector_weighted import WeightedIntegerVectors profile = kwds.get("profile", None) diff --git a/src/sage/algebras/steenrod/steenrod_algebra_mult.py b/src/sage/algebras/steenrod/steenrod_algebra_mult.py index 3de17e9c138..2a359410217 100644 --- a/src/sage/algebras/steenrod/steenrod_algebra_mult.py +++ b/src/sage/algebras/steenrod/steenrod_algebra_mult.py @@ -437,7 +437,7 @@ def milnor_multiplication_odd(m1,m2,p): iterate through the possible matrices: see http://mathweb.scranton.edu/monks/software/Steenrod/steen.html. """ - from sage.rings.all import GF + from sage.rings.finite_rings.finite_field_constructor import GF F = GF(p) (f,s) = m2 # First compute Q_e0 Q_e1 ... P(r1, r2, ...) Q_f0 Q_f1 ... @@ -890,7 +890,7 @@ def make_mono_admissible(mono, p=2, generic=None): sage: SteenrodAlgebra(p=2, basis='adem').Q(2) * (Sq(6) * Sq(2)) # indirect doctest Sq^10 Sq^4 Sq^1 + Sq^10 Sq^5 + Sq^12 Sq^3 + Sq^13 Sq^2 """ - from sage.rings.all import GF + from sage.rings.finite_rings.finite_field_constructor import GF if generic is None: generic = False if p==2 else True F = GF(p) diff --git a/src/sage/arith/misc.py b/src/sage/arith/misc.py index 2c6d4b85c85..b8113b7f5f9 100644 --- a/src/sage/arith/misc.py +++ b/src/sage/arith/misc.py @@ -1932,7 +1932,7 @@ def xgcd(a, b): sage: xgcd(y^2, a*y+b) (1, a^2/b^2, ((-a)/b^2)*y + 1/b) sage: xgcd((b+g)*y^2, (a+g)*y+b) - (1, (a^2 + (2*g)*a + 3)/(b^3 + (g)*b^2), ((-a + (-g))/b^2)*y + 1/b) + (1, (a^2 + (2*g)*a + 3)/(b^3 + g*b^2), ((-a + (-g))/b^2)*y + 1/b) Here is an example of a xgcd for two polynomials over the integers, where the linear combination is not the gcd but the gcd multiplied by the resultant:: diff --git a/src/sage/categories/algebras_with_basis.py b/src/sage/categories/algebras_with_basis.py index 701b428a836..972c9a94b76 100644 --- a/src/sage/categories/algebras_with_basis.py +++ b/src/sage/categories/algebras_with_basis.py @@ -56,7 +56,7 @@ class AlgebrasWithBasis(CategoryWithAxiom_over_base_ring): B[word: acb] sage: A.product - sage: A.product(a*b,b) B[word: abb] diff --git a/src/sage/categories/category_with_axiom.py b/src/sage/categories/category_with_axiom.py index 075e1542a7b..cbd3823ab5e 100644 --- a/src/sage/categories/category_with_axiom.py +++ b/src/sage/categories/category_with_axiom.py @@ -358,7 +358,7 @@ class from the base category class:: nested class ``Ds.Green`` or not (an implementation detail):: sage: Cs().Green - + Thanks to this feature (implemented in :meth:`CategoryWithAxiom.__classget__`), the user is systematically referred to the documentation of this diff --git a/src/sage/categories/examples/semigroups_cython.pyx b/src/sage/categories/examples/semigroups_cython.pyx index 6b6e179bc3a..c05ab880fb6 100644 --- a/src/sage/categories/examples/semigroups_cython.pyx +++ b/src/sage/categories/examples/semigroups_cython.pyx @@ -189,17 +189,17 @@ class LeftZeroSemigroup(LeftZeroSemigroupPython): That's really the only method which is obtained from the category ... :: sage: S(42).is_idempotent - + sage: S(42).is_idempotent() True sage: S(42)._pow_int - + sage: S(42)^10 42 sage: S(42).is_idempotent - + sage: S(42).is_idempotent() True """ diff --git a/src/sage/categories/finite_enumerated_sets.py b/src/sage/categories/finite_enumerated_sets.py index 0f423dbb5de..b4f98de21f2 100644 --- a/src/sage/categories/finite_enumerated_sets.py +++ b/src/sage/categories/finite_enumerated_sets.py @@ -117,7 +117,7 @@ def _cardinality_from_iterator(self, *ignored_args, **ignored_kwds): sage: class FreshExample(Example): pass sage: C = FreshExample(); C.rename("FreshExample") sage: C.cardinality - + This method shall return an ``Integer``; we test this here, because :meth:`_test_enumerated_set_iter_cardinality` @@ -323,21 +323,21 @@ def _list_from_iterator(self): sage: class FreshExample(Example): pass sage: C = FreshExample(); C.rename("FreshExample") sage: C.list - + sage: C.unrank - + sage: C.cardinality - + sage: l1 = C.list(); l1 [1, 2, 3] sage: C.list - + sage: C.unrank - + sage: C.cardinality - + sage: C.__iter__ - + We finally check that nothing breaks before and after calling explicitly the method ``.list()``:: diff --git a/src/sage/categories/hopf_algebras_with_basis.py b/src/sage/categories/hopf_algebras_with_basis.py index e5e0e05fe57..f74ff60b7dd 100644 --- a/src/sage/categories/hopf_algebras_with_basis.py +++ b/src/sage/categories/hopf_algebras_with_basis.py @@ -58,7 +58,7 @@ class HopfAlgebrasWithBasis(CategoryWithAxiom_over_base_ring): B[(1,2)] sage: A.product # todo: not quite ... - + sage: A.product(b,b) B[()] diff --git a/src/sage/categories/magmas.py b/src/sage/categories/magmas.py index 5aa2b09e0c4..a2707f5f3dd 100644 --- a/src/sage/categories/magmas.py +++ b/src/sage/categories/magmas.py @@ -1185,7 +1185,7 @@ def product_by_coercion(self, left, right): sage: Out = Sets().WithRealizations().example().Out(); Out The subset algebra of {1, 2, 3} over Rational Field in the Out basis sage: Out.product - + sage: Out.product.__module__ 'sage.categories.magmas' sage: x = Out.an_element() diff --git a/src/sage/categories/realizations.py b/src/sage/categories/realizations.py index 757b2f3aba3..1d64bca5f03 100644 --- a/src/sage/categories/realizations.py +++ b/src/sage/categories/realizations.py @@ -36,7 +36,7 @@ class RealizationsCategory(RegressiveCovariantConstructionCategory): TESTS:: sage: Sets().Realizations - + sage: Sets().Realizations() Category of realizations of sets sage: Sets().Realizations().super_categories() diff --git a/src/sage/categories/sets_cat.py b/src/sage/categories/sets_cat.py index fdebfd93799..f86d8e961ea 100644 --- a/src/sage/categories/sets_cat.py +++ b/src/sage/categories/sets_cat.py @@ -956,14 +956,13 @@ def _element_constructor_(self): sage: A.element_class sage: A._element_constructor_ - + sage: B = SymmetricGroup(3).algebra(ZZ) sage: B.element_class <...SymmetricGroupAlgebra_n_with_category.element_class'> sage: B._element_constructor_ - + """ if hasattr(self, "element_class"): return self._element_constructor_from_element_class diff --git a/src/sage/coding/ag_code.py b/src/sage/coding/ag_code.py index 9b12c412f18..72bf5c37d5f 100644 --- a/src/sage/coding/ag_code.py +++ b/src/sage/coding/ag_code.py @@ -8,8 +8,8 @@ EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -72,6 +72,7 @@ from sage.modules.free_module_element import vector from sage.matrix.constructor import matrix from sage.matrix.matrix_space import MatrixSpace +from sage.rings.function_field.place import FunctionFieldPlace from .linear_code import (AbstractLinearCode, LinearCodeGeneratorMatrixEncoder, @@ -97,8 +98,8 @@ def base_function_field(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -123,10 +124,12 @@ class EvaluationAGCode(AGCode): - ``G`` -- a divisor whose support is disjoint from ``pls`` + If ``G`` is a place, then it is regarded as a prime divisor. + EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -135,6 +138,10 @@ class EvaluationAGCode(AGCode): sage: G = 5*Q sage: codes.EvaluationAGCode(pls, G) [8, 5] evaluation AG code over GF(4) + + sage: G = F.get_place(5) + sage: codes.EvaluationAGCode(pls, G) + [8, 5] evaluation AG code over GF(4) """ _registered_encoders = {} _registered_decoders = {} @@ -145,8 +152,8 @@ def __init__(self, pls, G): TESTS:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -156,6 +163,9 @@ def __init__(self, pls, G): sage: code = codes.EvaluationAGCode(pls, G) sage: TestSuite(code).run() """ + if issubclass(type(G), FunctionFieldPlace): + G = G.divisor() # place is converted to a prime divisor + F = G.parent().function_field() K = F.constant_base_field() n = len(pls) @@ -197,8 +207,8 @@ def __eq__(self, other): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -221,8 +231,8 @@ def __hash__(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -240,8 +250,8 @@ def _repr_(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -259,8 +269,8 @@ def _latex_(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -279,8 +289,8 @@ def basis_functions(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -302,8 +312,8 @@ def generator_matrix(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -325,8 +335,8 @@ def designed_distance(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -353,17 +363,24 @@ class DifferentialAGCode(AGCode): - ``G`` -- a divisor whose support is disjoint from ``pls`` + If ``G`` is a place, then it is regarded as a prime divisor. + EXAMPLES:: - sage: F. = GF(4) - sage: A2. = AffineSpace(F, 2) - sage: C = A2.curve(y^3 + y - x^4) + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) + sage: C = A.curve(y^3 + y - x^4) sage: Q = C.places_at_infinity()[0] sage: O = C([0,0]).place() sage: pls = [p for p in C.places() if p not in [O, Q]] sage: G = -O + 3*Q sage: codes.DifferentialAGCode(pls, -O + Q) [3, 2] differential AG code over GF(4) + + sage: F = C.function_field() + sage: G = F.get_place(1) + sage: codes.DifferentialAGCode(pls, G) + [3, 1] differential AG code over GF(4) """ _registered_encoders = {} _registered_decoders = {} @@ -374,8 +391,8 @@ def __init__(self, pls, G): TESTS:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -384,6 +401,9 @@ def __init__(self, pls, G): sage: code = codes.DifferentialAGCode(pls, 3*Q) sage: TestSuite(code).run() """ + if issubclass(type(G), FunctionFieldPlace): + G = G.divisor() # place is converted to a prime divisor + F = G.parent().function_field() K = F.constant_base_field() n = len(pls) @@ -424,8 +444,8 @@ def __eq__(self, other): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -452,8 +472,8 @@ def __hash__(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -471,8 +491,8 @@ def _repr_(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -490,8 +510,8 @@ def _latex_(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -510,8 +530,8 @@ def basis_differentials(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -533,8 +553,8 @@ def generator_matrix(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() @@ -558,8 +578,8 @@ def designed_distance(self): EXAMPLES:: - sage: F. = GF(4) - sage: P. = AffineSpace(F, 2); + sage: k. = GF(4) + sage: A. = AffineSpace(k, 2) sage: C = Curve(y^2 + y - x^3) sage: F = C.function_field() sage: pls = F.places() diff --git a/src/sage/coding/ag_code_decoders.pyx b/src/sage/coding/ag_code_decoders.pyx index 4a9771f221b..8d28e242030 100644 --- a/src/sage/coding/ag_code_decoders.pyx +++ b/src/sage/coding/ag_code_decoders.pyx @@ -19,27 +19,27 @@ EXAMPLES:: sage: pls.remove(O) sage: G = -O + 18*Q sage: code = codes.EvaluationAGCode(pls, G) # long time - sage: code # long time + sage: code # long time [26, 15] evaluation AG code over GF(9) - sage: decoder = code.decoder('K') # long time - sage: tau = decoder.decoding_radius() # long time - sage: tau # long time + sage: decoder = code.decoder('K') # long time + sage: tau = decoder.decoding_radius() # long time + sage: tau # long time 4 The ``decoder`` is now ready for correcting vectors received from a noisy channel:: sage: channel = channels.StaticErrorRateChannel(code.ambient_space(), tau) # long time - sage: message_space = decoder.message_space() # long time - sage: message = message_space.random_element() # long time - sage: encoder = decoder.connected_encoder() # long time - sage: sent_codeword = encoder.encode(message) # long time - sage: received_vector = channel(sent_codeword) # long time - sage: (received_vector - sent_codeword).hamming_weight() # long time + sage: message_space = decoder.message_space() # long time + sage: message = message_space.random_element() # long time + sage: encoder = decoder.connected_encoder() # long time + sage: sent_codeword = encoder.encode(message) # long time + sage: received_vector = channel(sent_codeword) # long time + sage: (received_vector - sent_codeword).hamming_weight() # long time 4 sage: decoder.decode_to_code(received_vector) == sent_codeword # long time True - sage: decoder.decode_to_message(received_vector) == message # long time + sage: decoder.decode_to_message(received_vector) == message # long time True AUTHORS: diff --git a/src/sage/coding/databases.py b/src/sage/coding/databases.py index c2b1a2a9e23..2fe3a632e2d 100644 --- a/src/sage/coding/databases.py +++ b/src/sage/coding/databases.py @@ -2,19 +2,19 @@ r""" Access functions to online databases for coding theory """ - -from sage.interfaces.all import gap +from sage.libs.gap.libgap import libgap from sage.features.gap import GapPackage -# Don't put any global imports here since this module is accessible as +# Do not put any global imports here since this module is accessible as # sage.codes.databases. + def best_linear_code_in_guava(n, k, F): r""" - Returns the linear code of length ``n``, dimension ``k`` over field ``F`` + Return the linear code of length ``n``, dimension ``k`` over field ``F`` with the maximal minimum distance which is known to the GAP package GUAVA. - The function uses the tables described in ``bounds_on_minimum_distance_in_guava`` to + The function uses the tables described in :func:`bounds_on_minimum_distance_in_guava` to construct this code. This requires the optional GAP package GUAVA. INPUT: @@ -27,7 +27,7 @@ def best_linear_code_in_guava(n, k, F): OUTPUT: - - A :class:`LinearCode` which is a best linear code of the given parameters known to GUAVA. + A :class:`LinearCode` which is a best linear code of the given parameters known to GUAVA. EXAMPLES:: @@ -41,22 +41,22 @@ def best_linear_code_in_guava(n, k, F): between 2 and 4. Use ``bounds_on_minimum_distance_in_guava(10,5,GF(2))`` for further details. """ - GapPackage("guava", spkg="gap_packages").require() - gap.load_package("guava") - q = F.order() - C = gap("BestKnownLinearCode(%s,%s,GF(%s))"%(n,k,q)) from .linear_code import LinearCode + GapPackage("guava", spkg="gap_packages").require() + libgap.load_package("guava") + C = libgap.BestKnownLinearCode(n, k, F) return LinearCode(C.GeneratorMat()._matrix_(F)) + def bounds_on_minimum_distance_in_guava(n, k, F): r""" - Computes a lower and upper bound on the greatest minimum distance of a + Compute a lower and upper bound on the greatest minimum distance of a `[n,k]` linear code over the field ``F``. This function requires the optional GAP package GUAVA. The function returns a GAP record with the two bounds and an explanation for - each bound. The function Display can be used to show the explanations. + each bound. The method ``Display`` can be used to show the explanations. The values for the lower and upper bound are obtained from a table constructed by Cen Tjhai for GUAVA, derived from the table of @@ -81,21 +81,16 @@ def bounds_on_minimum_distance_in_guava(n, k, F): EXAMPLES:: sage: gap_rec = codes.databases.bounds_on_minimum_distance_in_guava(10,5,GF(2)) # optional - gap_packages (Guava package) - sage: print(gap_rec) # optional - gap_packages (Guava package) + sage: gap_rec.Display() # optional - gap_packages (Guava package) rec( - construction := - [ , - [ - [ , - [ - [ , - [ [ , [ 8, 2 ] ] ] ], - [ , - [ - [ , - [ [ , [ 4, 2 ] ] ] ] - , [ , [ 4, 2 ] ] ] ] - ] ], [ 1, 2, 3, 4, 5, 6 ] ] ], + construction := [ , + [ [ , + [ [ , + [ [ , [ 8, 2 ] ] ] ], + [ , [ [ , + [ [ , [ 4, 2 ] ] ] ], + [ , [ 4, 2 ] ] ] ] ] ], + [ 1, 2, 3, 4, 5, 6 ] ] ], k := 5, lowerBound := 4, lowerBoundExplanation := ... @@ -107,11 +102,9 @@ def bounds_on_minimum_distance_in_guava(n, k, F): upperBoundExplanation := ... ) """ GapPackage("guava", spkg="gap_packages").require() - gap.load_package("guava") - q = F.order() - gap.eval("data := BoundsMinimumDistance(%s,%s,GF(%s))"%(n,k,q)) - Ldata = gap.eval("Display(data)") - return Ldata + libgap.load_package("guava") + return libgap.BoundsMinimumDistance(n, k, F) + def best_linear_code_in_codetables_dot_de(n, k, F, verbose=False): r""" @@ -275,8 +268,6 @@ def self_orthogonal_binary_codes(n, k, b=2, parent=None, BC=None, equal=False, from sage.rings.finite_rings.finite_field_constructor import FiniteField from sage.matrix.constructor import Matrix - - d=int(b) if d!=b or d%2==1 or d <= 0: raise ValueError("b (%s) must be a positive even integer."%b) @@ -285,11 +276,11 @@ def self_orthogonal_binary_codes(n, k, b=2, parent=None, BC=None, equal=False, if k < 1 or n < 2: return if equal: - in_test = lambda M : (M.ncols() - M.nrows()) <= (n-k) - out_test = lambda C : (C.dimension() == k) and (C.length() == n) + in_test = lambda M: (M.ncols() - M.nrows()) <= (n-k) + out_test = lambda C: (C.dimension() == k) and (C.length() == n) else: - in_test = lambda M : True - out_test = lambda C : True + in_test = lambda M: True + out_test = lambda C: True if BC is None: BC = BinaryCodeClassifier() if parent is None: diff --git a/src/sage/coding/grs_code.py b/src/sage/coding/grs_code.py index 74c59ffec89..1bdbc70727f 100644 --- a/src/sage/coding/grs_code.py +++ b/src/sage/coding/grs_code.py @@ -1965,13 +1965,14 @@ def decode_to_message(self, word_and_erasure_vector): n, k = C.length(), C.dimension() if word not in C.ambient_space(): raise ValueError("The word to decode has to be in the ambient space of the code") - if not erasure_vector in VectorSpace(GF(2), n): + if erasure_vector not in VectorSpace(GF(2), n): raise ValueError("The erasure vector has to be a vector over GF(2) of the same length as the code") if erasure_vector.hamming_weight() >= self.code().minimum_distance(): raise DecodingError("Too many erasures in the received word") - punctured_word = vector(self.code().base_ring(), [word[i] for i in - range(len(word)) if erasure_vector[i]!=1]) + punctured_word = vector(self.code().base_ring(), + [word[i] for i in range(len(word)) + if not erasure_vector[i]]) C1_length = len(punctured_word) if C1_length == k: return self.connected_encoder().unencode_nocheck(word) diff --git a/src/sage/coding/linear_code.py b/src/sage/coding/linear_code.py index 643e7239460..c335f04e1a9 100644 --- a/src/sage/coding/linear_code.py +++ b/src/sage/coding/linear_code.py @@ -2309,12 +2309,12 @@ def __init__(self, generator, d=None): try: basis = None - if hasattr(generator,"nrows"): # generator matrix case + if hasattr(generator, "nrows"): # generator matrix case if generator.rank() < generator.nrows(): basis = generator.row_space().basis() else: - basis = generator.basis() # vector space etc. case - if not basis is None: + basis = generator.basis() # vector space etc. case + if basis is not None: from sage.matrix.constructor import matrix generator = matrix(base_ring, basis) if generator.nrows() == 0: diff --git a/src/sage/coding/linear_code_no_metric.py b/src/sage/coding/linear_code_no_metric.py index 85fd48f3226..9e4b6115ad3 100644 --- a/src/sage/coding/linear_code_no_metric.py +++ b/src/sage/coding/linear_code_no_metric.py @@ -179,9 +179,9 @@ def __init__(self, base_field, length, default_encoder_name, default_decoder_nam if not base_field.is_field(): raise ValueError("'base_field' must be a field (and {} is not one)".format(base_field)) - if not default_encoder_name in self._registered_encoders: + if default_encoder_name not in self._registered_encoders: raise ValueError("You must set a valid encoder as default encoder for this code, by filling in the dictionary of registered encoders") - if not default_decoder_name in self._registered_decoders: + if default_decoder_name not in self._registered_decoders: raise ValueError("You must set a valid decoder as default decoder for this code, by filling in the dictionary of registered decoders") #if not self.dimension() <= length: @@ -509,7 +509,7 @@ def __contains__(self, v): sage: vector((1, 0, 0, 0, 0, 1/2, 1)) in C # indirect doctest False """ - if not v in self.ambient_space() or len(v) != self.length(): + if v not in self.ambient_space() or len(v) != self.length(): return False return self.syndrome(v) == 0 @@ -1296,13 +1296,13 @@ def systematic_permutation(self): n = self.code().length() systematic_positions = self.systematic_positions() k = len(systematic_positions) - lp = [ None ]*n - for (i,j) in zip(range(k), systematic_positions): + lp = [None] * n + for (i, j) in zip(range(k), systematic_positions): lp[i] = j j = k set_sys_pos = set(systematic_positions) for i in range(n): - if not i in set_sys_pos: + if i not in set_sys_pos: lp[j] = i j += 1 from sage.combinat.permutation import Permutation diff --git a/src/sage/coding/linear_rank_metric.py b/src/sage/coding/linear_rank_metric.py index f746acf3c91..c06b16aa05b 100644 --- a/src/sage/coding/linear_rank_metric.py +++ b/src/sage/coding/linear_rank_metric.py @@ -694,12 +694,12 @@ def __init__(self, generator, sub_field=None, basis=None): try: gen_basis = None - if hasattr(generator,"nrows"): # generator matrix case + if hasattr(generator, "nrows"): # generator matrix case if generator.rank() < generator.nrows(): gen_basis = generator.row_space().basis() else: - gen_basis = generator.basis() # vector space etc. case - if not gen_basis is None: + gen_basis = generator.basis() # vector space etc. case + if gen_basis is not None: from sage.matrix.constructor import matrix generator = matrix(base_field, gen_basis) if generator.nrows() == 0: diff --git a/src/sage/coding/relative_finite_field_extension.py b/src/sage/coding/relative_finite_field_extension.py index 2319d708f85..1a329624cce 100644 --- a/src/sage/coding/relative_finite_field_extension.py +++ b/src/sage/coding/relative_finite_field_extension.py @@ -120,7 +120,7 @@ def __init__(self, absolute_field, relative_field, embedding=None): if not s.divides(sm): raise ValueError("relative_field has to be a subfield of absolute_field") H = Hom(relative_field, absolute_field) - if embedding is not None and not embedding in H: + if embedding is not None and embedding not in H: raise ValueError("embedding has to be an embedding from relative_field to absolute_field") elif embedding is not None: self._phi = embedding @@ -231,7 +231,7 @@ def _flattened_relative_field_representation(self, b): sage: FE._flattened_relative_field_representation(b) (1, 0, 1, 1) """ - if not b in self.absolute_field(): + if b not in self.absolute_field(): raise ValueError("The input has to be an element of the absolute field") return self._representation_matrix() * vector(b) @@ -254,19 +254,18 @@ def relative_field_representation(self, b): sage: FE.relative_field_representation(b) (1, a + 1) """ - if not b in self.absolute_field(): + if b not in self.absolute_field(): raise ValueError("The input has to be an element of the absolute field") s = self.relative_field_degree() if s == 1: return vector(b) - else: - Fq = self.relative_field() - vect = self._flattened_relative_field_representation(b) - sm = self.absolute_field_degree() - list_elts = [] - for i in range(0, sm, s): - list_elts.append(Fq(vect[i:i+s])) - return vector(Fq, list_elts) + Fq = self.relative_field() + vect = self._flattened_relative_field_representation(b) + sm = self.absolute_field_degree() + list_elts = [] + for i in range(0, sm, s): + list_elts.append(Fq(vect[i:i + s])) + return vector(Fq, list_elts) def absolute_field_representation(self, a): r""" diff --git a/src/sage/coding/subfield_subcode.py b/src/sage/coding/subfield_subcode.py index c08d27a4cb3..ed7b18d7a90 100644 --- a/src/sage/coding/subfield_subcode.py +++ b/src/sage/coding/subfield_subcode.py @@ -86,7 +86,7 @@ def __init__(self, original_code, subfield, embedding=None): raise ValueError("subfield has to be a subfield of the base field of the original code") self._original_code = original_code H = Hom(subfield, F) - if embedding is not None and not embedding in H: + if embedding is not None and embedding not in H: raise ValueError("embedding has to be an embedding from subfield to original_code's base field") elif embedding is not None: self._embedding = RelativeFiniteFieldExtension(F, subfield, embedding) diff --git a/src/sage/combinat/alternating_sign_matrix.py b/src/sage/combinat/alternating_sign_matrix.py index 057dbfe6e06..acc735174d8 100644 --- a/src/sage/combinat/alternating_sign_matrix.py +++ b/src/sage/combinat/alternating_sign_matrix.py @@ -44,7 +44,7 @@ from sage.matrix.matrix_space import MatrixSpace from sage.matrix.constructor import matrix from sage.modules.free_module_element import zero_vector -from sage.misc.all import cached_method +from sage.misc.cachefunc import cached_method from sage.rings.integer_ring import ZZ from sage.arith.all import factorial from sage.rings.integer import Integer diff --git a/src/sage/combinat/baxter_permutations.py b/src/sage/combinat/baxter_permutations.py index 59d9a0256fb..0e3c722f480 100644 --- a/src/sage/combinat/baxter_permutations.py +++ b/src/sage/combinat/baxter_permutations.py @@ -81,7 +81,7 @@ def __init__(self, n): self.element_class = Permutations(n).element_class self._n = ZZ(n) from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets - super(BaxterPermutations, self).__init__(category=FiniteEnumeratedSets()) + super(BaxterPermutations_size, self).__init__(category=FiniteEnumeratedSets()) def _repr_(self): """ @@ -128,7 +128,7 @@ def __contains__(self, x): if x_j > a and x_j < b and x_j > max_l: max_l = x_j min_r = len(x) + 1 - for x_j in x[i+2:]: + for x_j in x[i + 2:]: if x_j > a and x_j < b and x_j < min_r: min_r = x_j if max_l > min_r: @@ -139,7 +139,7 @@ def __contains__(self, x): if x_j < a and x_j > b and x_j < min_l: min_l = x_j max_r = 0 - for x_j in x[i+2:]: + for x_j in x[i + 2:]: if x_j < a and x_j > b and x_j > max_r: max_r = x_j if min_l < max_r: @@ -186,7 +186,8 @@ def __iter__(self): else: for b in BaxterPermutations(self._n - 1): # Left to right maxima. - for i in [self._n - 2 - i for i in b.reverse().saliances()]: + for j in b.reverse().saliances(): + i = self._n - 2 - j yield Permutations(self._n)(b[:i] + [self._n] + b[i:]) # Right to left maxima. for i in b.saliances(): diff --git a/src/sage/combinat/cartesian_product.py b/src/sage/combinat/cartesian_product.py index e2069f38e53..7b9cf8e62e6 100644 --- a/src/sage/combinat/cartesian_product.py +++ b/src/sage/combinat/cartesian_product.py @@ -57,7 +57,7 @@ class for ``cartesian_product``; sage: c = cartesian_product([F1, F2, F3]) sage: type(C.an_element()) - <... 'list'> + sage: type(c.an_element()) diff --git a/src/sage/combinat/cluster_algebra_quiver/mutation_type.py b/src/sage/combinat/cluster_algebra_quiver/mutation_type.py index 7a728780003..181e911c43d 100644 --- a/src/sage/combinat/cluster_algebra_quiver/mutation_type.py +++ b/src/sage/combinat/cluster_algebra_quiver/mutation_type.py @@ -25,7 +25,7 @@ from copy import copy -from sage.misc.all import cached_function +from sage.misc.cachefunc import cached_function from sage.misc.flatten import flatten from sage.graphs.all import DiGraph from sage.combinat.all import Combinations diff --git a/src/sage/combinat/composition.py b/src/sage/combinat/composition.py index 5f899c71106..46a6be10fad 100644 --- a/src/sage/combinat/composition.py +++ b/src/sage/combinat/composition.py @@ -2017,7 +2017,7 @@ def composition_iterator_fast(n): sage: L = list(composition_iterator_fast(4)); L [[1, 1, 1, 1], [1, 1, 2], [1, 2, 1], [1, 3], [2, 1, 1], [2, 2], [3, 1], [4]] sage: type(L[0]) - <... 'list'> + """ # Special cases if n < 0: diff --git a/src/sage/combinat/composition_signed.py b/src/sage/combinat/composition_signed.py index ae2b3b648bc..8d8b78bcd59 100644 --- a/src/sage/combinat/composition_signed.py +++ b/src/sage/combinat/composition_signed.py @@ -19,7 +19,7 @@ from sage.rings.integer_ring import ZZ from .composition import Compositions_n, Composition -from sage.rings.all import Integer +from sage.rings.integer import Integer from sage.arith.all import binomial diff --git a/src/sage/combinat/crystals/induced_structure.py b/src/sage/combinat/crystals/induced_structure.py index ec01e07b651..0cf36648bba 100644 --- a/src/sage/combinat/crystals/induced_structure.py +++ b/src/sage/combinat/crystals/induced_structure.py @@ -89,7 +89,7 @@ class InducedCrystal(UniqueRepresentation, Parent): True sage: I = crystals.Induced(P, phi, phi_inv) sage: I.digraph() - Multi-digraph on 24 vertices + Digraph on 24 vertices We construct an example without a specified inverse map:: diff --git a/src/sage/combinat/designs/database.py b/src/sage/combinat/designs/database.py index af61d7e3ace..02023998fc1 100644 --- a/src/sage/combinat/designs/database.py +++ b/src/sage/combinat/designs/database.py @@ -4206,7 +4206,7 @@ def BIBD_45_9_8(from_code=False): '7up5z9m9u', '7w7esu6fm', '7zmqtlrpd', '81tsbnzsw', '8kofgi1he', '8mhi35nc1', '9cv1pjiaw', '9d6ef1dah', '9dftsor9c', '9du8c1vcw', '9jr5vsnj4', 'a8b405mps', 'ajqhmxkj4', 'ax2xsvfic'] B = [Integer(x, base=36) for x in B] - return [[i for i in range(45) if x&(1< + sage: type(I.blocks()[0][0]) - <... 'sage.rings.finite_rings.integer_mod.IntegerMod_int'> + TESTS:: @@ -1290,7 +1290,7 @@ def complement(self,uniform=False): if k is False: raise ValueError("The incidence structure is not uniform.") - blocks = [] + blocks = [] num_blocks = self.num_blocks() i = 0 from itertools import combinations @@ -1388,9 +1388,9 @@ def relabel(self, perm=None, inplace=True): self._points = [perm[x] for x in self._points] if self._points == list(range(self.num_points())): - self._point_to_index = None + self._point_to_index = None else: - self._point_to_index = {v:i for i,v in enumerate(self._points)} + self._point_to_index = {v: i for i, v in enumerate(self._points)} __hash__ = None # This object is mutable because of .relabel() @@ -2128,7 +2128,7 @@ def edge_coloring(self): blocks = self.blocks() blocks_sets = [frozenset(b) for b in blocks] g = Graph([list(range(self.num_blocks())), - lambda x, y: len(blocks_sets[x]&blocks_sets[y])], + lambda x, y: len(blocks_sets[x] & blocks_sets[y])], loops=False) return [[blocks[i] for i in C] for C in g.coloring(algorithm="MILP")] diff --git a/src/sage/combinat/e_one_star.py b/src/sage/combinat/e_one_star.py index 2cca168d20f..924ee53e754 100644 --- a/src/sage/combinat/e_one_star.py +++ b/src/sage/combinat/e_one_star.py @@ -1066,7 +1066,7 @@ def repaint(self, cmap='Set1') -> None: global cm if cm is None: from matplotlib import cm - + assert cm is not None if cmap not in cm.datad: raise RuntimeError("Color map %s not known (type sorted(colors) for valid names)" % cmap) cmap = cm.__dict__[cmap] diff --git a/src/sage/combinat/finite_state_machine.py b/src/sage/combinat/finite_state_machine.py index bf3ddb74d45..2aa6cee9f37 100644 --- a/src/sage/combinat/finite_state_machine.py +++ b/src/sage/combinat/finite_state_machine.py @@ -3886,10 +3886,10 @@ def __call__(self, *args, **kwargs): (1, 0, 1, 1, 0, 1, 0, 1, 1, 0) sage: type(inverter((1, 0, 1, 1, 0, 1, 0, 1, 1, 0), ....: automatic_output_type=False)) - <... 'list'> + sage: type(inverter((1, 0, 1, 1, 0, 1, 0, 1, 1, 0), ....: automatic_output_type=True)) - <... 'tuple'> + """ if not args: raise TypeError("Called with too few arguments.") diff --git a/src/sage/combinat/free_module.py b/src/sage/combinat/free_module.py index d9f5d7c8144..9f3e07bf013 100644 --- a/src/sage/combinat/free_module.py +++ b/src/sage/combinat/free_module.py @@ -15,7 +15,7 @@ from sage.structure.parent import Parent from sage.structure.indexed_generators import IndexedGenerators, parse_indices_names from sage.modules.module import Module -from sage.rings.all import Integer +from sage.rings.integer import Integer from sage.structure.element import parent from sage.modules.with_basis.indexed_element import IndexedFreeModuleElement from sage.sets.finite_enumerated_set import FiniteEnumeratedSet @@ -338,7 +338,7 @@ def element_class(self): sage: A.element_class.mro() [, - <... 'sage.modules.with_basis.indexed_element.IndexedFreeModuleElement'>, + , ...] sage: a,b,c = A.algebra_generators() sage: a * b @@ -1152,7 +1152,7 @@ class CombinatorialFreeModule_Tensor(CombinatorialFreeModule): The basis of T is indexed by tuples of basis indices of F and G:: sage: T.basis().keys() - Image of Cartesian product of {1, 2}, {3, 4} by <... 'tuple'> + Image of Cartesian product of {1, 2}, {3, 4} by sage: T.basis().keys().list() [(1, 3), (1, 4), (2, 3), (2, 4)] diff --git a/src/sage/combinat/gelfand_tsetlin_patterns.py b/src/sage/combinat/gelfand_tsetlin_patterns.py index ff5a145cd92..08615c0eae7 100644 --- a/src/sage/combinat/gelfand_tsetlin_patterns.py +++ b/src/sage/combinat/gelfand_tsetlin_patterns.py @@ -920,11 +920,11 @@ def _list_iter(self, n): sage: len(L) == G.cardinality() True sage: type(L[0]) - <... 'list'> + """ # Setup the first row - iters = [None]*n - ret = [None]*n + iters = [None] * n + ret = [None] * n iters[0] = self._top_row_iter(n) ret[0] = next(iters[0]) min_pos = 0 @@ -959,7 +959,7 @@ def _top_row_iter(self, n): sage: for x in G._top_row_iter(3): x [2, 1, 0] """ - row = [-1]*n + row = [-1] * n pos = 0 while pos >= 0: if pos == n: @@ -967,7 +967,7 @@ def _top_row_iter(self, n): pos -= 1 continue # If it would create an invalid entry, backstep - if ( pos > 0 and (row[pos] >= row[pos-1] \ + if (pos > 0 and (row[pos] >= row[pos-1] or (self._strict and row[pos] == row[pos-1]-1)) ) \ or (self._k is not None and row[pos] >= self._k): row[pos] = -1 diff --git a/src/sage/combinat/integer_lists/lists.py b/src/sage/combinat/integer_lists/lists.py index 8795add6e56..5143e5cb5e8 100644 --- a/src/sage/combinat/integer_lists/lists.py +++ b/src/sage/combinat/integer_lists/lists.py @@ -299,7 +299,7 @@ def _element_constructor_default(self, l): ....: Element = MyElt sage: L = MyIntegersLists(5) sage: L._element_constructor_ - + """ return self.element_class(self, l) @@ -320,7 +320,7 @@ def _element_constructor_nocheck(self, l): iterator:: sage: L._element_constructor_ - + sage: L._element_constructor_([1,2,3]) [1, 2, 3] """ diff --git a/src/sage/combinat/integer_vector_weighted.py b/src/sage/combinat/integer_vector_weighted.py index 8f1b68ffe85..1c2c109217c 100644 --- a/src/sage/combinat/integer_vector_weighted.py +++ b/src/sage/combinat/integer_vector_weighted.py @@ -237,12 +237,12 @@ def __iter__(self): return perm = Word(self._weights).standard_permutation() - perm = [len(self._weights)-i for i in perm] + perm = [len(self._weights) - i for i in perm] l = [x for x in sorted(self._weights, reverse=True)] for x in iterator_fast(self._n, l): yield self.element_class(self, [x[i] for i in perm]) - #.action(x) - #_left_to_right_multiply_on_right(Permutation(x)) + # .action(x) + # _left_to_right_multiply_on_right(Permutation(x)) class WeightedIntegerVectors_all(DisjointUnionEnumeratedSets): @@ -360,7 +360,7 @@ def iterator_fast(n, l): Test that :trac:`20491` is fixed:: sage: type(list(iterator_fast(2, [2]))[0][0]) - <... 'sage.rings.integer.Integer'> + """ if n < 0: return diff --git a/src/sage/combinat/integer_vectors_mod_permgroup.py b/src/sage/combinat/integer_vectors_mod_permgroup.py index 911558b4921..ef7f278e98a 100644 --- a/src/sage/combinat/integer_vectors_mod_permgroup.py +++ b/src/sage/combinat/integer_vectors_mod_permgroup.py @@ -293,7 +293,7 @@ def _repr_(self): sage: IntegerVectorsModPermutationGroup(PermutationGroup([[(1,2,3)]])) Integer vectors of length 3 enumerated up to the action of Permutation Group with generators [(1,2,3)] """ - return "Integer vectors of length %s enumerated up to the action of %r"%(self.n, self._permgroup) + return "Integer vectors of length %s enumerated up to the action of %r" % (self.n, self._permgroup) def ambient(self): r""" @@ -317,7 +317,7 @@ def lift(self, elt): sage: v = S.lift(S([4,3,0,1])); v [4, 3, 0, 1] sage: type(v) - <... 'list'> + """ # TODO: For now, Sage integer vectors are just python list. # Once Integer vectors will have an element class, update this @@ -360,7 +360,7 @@ def retract(self, elt): """ # TODO: Once Sage integer vector will have a data structure # based on ClonableIntArray, remove the conversion intarray - assert len(elt) == self.n, "%s is a quotient set of %s"%(self, self.ambient()) + assert len(elt) == self.n, "%s is a quotient set of %s" % (self, self.ambient()) intarray = self.element_class(self, elt, check=False) return self.element_class(self, canonical_representative_of_orbit_of(self._sgs, intarray), check=False) @@ -628,11 +628,11 @@ def _repr_(self): """ if self._sum is not None: if self._max_part >= 0: - return "Vectors of length %s and of sum %s whose entries is in {0, ..., %s} enumerated up to the action of %s"%(self.n, self._sum, self._max_part, self.permutation_group()) + return "Vectors of length %s and of sum %s whose entries is in {0, ..., %s} enumerated up to the action of %s" % (self.n, self._sum, self._max_part, self.permutation_group()) else: - return "Integer vectors of length %s and of sum %s enumerated up to the action of %s"%(self.n, self._sum, self.permutation_group()) + return "Integer vectors of length %s and of sum %s enumerated up to the action of %s" % (self.n, self._sum, self.permutation_group()) else: - return "Integer vectors of length %s whose entries is in {0, ..., %s} enumerated up to the action of %s"%(self.n, self._max_part, self.permutation_group()) + return "Integer vectors of length %s whose entries is in {0, ..., %s} enumerated up to the action of %s" % (self.n, self._max_part, self.permutation_group()) def roots(self): r""" @@ -858,11 +858,11 @@ def retract(self, elt): """ # TODO: Once Sage integer vector will have a data structure # based on ClonableIntArray, remove the conversion intarray - assert len(elt) == self.n, "%s is a quotient set of %s"%(self, self.ambient()) + assert len(elt) == self.n, "%s is a quotient set of %s" % (self, self.ambient()) if self._sum is not None: - assert sum(elt) == self._sum, "%s is a quotient set of %s"%(self, self.ambient()) + assert sum(elt) == self._sum, "%s is a quotient set of %s" % (self, self.ambient()) if self._max_part >= 0: - assert max(elt) <= self._max_part, "%s is a quotient set of %s"%(self, self.ambient()) + assert max(elt) <= self._max_part, "%s is a quotient set of %s" % (self, self.ambient()) intarray = self.element_class(self, elt, check=False) return self.element_class(self, canonical_representative_of_orbit_of(self._sgs, intarray), check=False) diff --git a/src/sage/combinat/k_tableau.py b/src/sage/combinat/k_tableau.py index 17fccecd104..9d5a40e532d 100644 --- a/src/sage/combinat/k_tableau.py +++ b/src/sage/combinat/k_tableau.py @@ -2369,14 +2369,15 @@ def __classcall_private__(cls, T, k, weight=None): """ if isinstance(T, cls): return T - outer_shape = Core([len(t) for t in T], k+1) - inner_shape = Core([x for x in [row.count(None) for row in T] if x], k+1) - Te = [v for row in T for v in row if v is not None]+[0] + outer_shape = Core([len(t) for t in T], k + 1) + loop = (row.count(None) for row in T) + inner_shape = Core([x for x in loop if x], k + 1) + Te = [v for row in T for v in row if v is not None] + [0] count_marks = tuple(Te.count(-(i+1)) for i in range(-min(Te))) - if not all( v==1 for v in count_marks ): + if not all(v == 1 for v in count_marks): # if T is not standard -> turn into standard - if weight is not None and tuple(weight)!=count_marks: - raise ValueError("Weight = %s and tableau = %s do not agree"%(weight, T)) + if weight is not None and tuple(weight) != count_marks: + raise ValueError("Weight = %s and tableau = %s do not agree" % (weight, T)) tijseq = StrongTableaux.marked_CST_to_transposition_sequence(T, k) if tijseq is None or len(tijseq) + TESTS: @@ -1064,17 +1064,17 @@ cdef class dancing_linksWrapper: # Construction of the columns (transpose of the rows) columns = [[] for _ in range(self.ncols())] - for i,row in enumerate(self.rows()): + for i, row in enumerate(self.rows()): for a in row: columns[a].append(i) # Constraints: exactly one 1 in each column - for j,column in enumerate(columns): + for j, column in enumerate(columns): S = p.sum(x[a] for a in column) name = "one 1 in {}-th column".format(j) - p.add_constraint(S==1, name=name) + p.add_constraint(S == 1, name=name) - return p,x + return p, x def one_solution_using_milp_solver(self, solver=None, integrality_tolerance=1e-3): r""" diff --git a/src/sage/combinat/matrices/latin.py b/src/sage/combinat/matrices/latin.py index 367facaa301..3274ed077e2 100644 --- a/src/sage/combinat/matrices/latin.py +++ b/src/sage/combinat/matrices/latin.py @@ -131,7 +131,7 @@ from sage.matrix.constructor import matrix from sage.rings.integer_ring import ZZ -from sage.rings.all import Integer +from sage.rings.integer import Integer from sage.matrix.matrix_integer_dense import Matrix_integer_dense from sage.groups.perm_gps.permgroup_element import PermutationGroupElement from sage.groups.perm_gps.constructor import PermutationGroupElement as PermutationConstructor diff --git a/src/sage/combinat/multiset_partition_into_sets_ordered.py b/src/sage/combinat/multiset_partition_into_sets_ordered.py index 61bb667e2ba..1789a6d551a 100755 --- a/src/sage/combinat/multiset_partition_into_sets_ordered.py +++ b/src/sage/combinat/multiset_partition_into_sets_ordered.py @@ -2623,6 +2623,7 @@ def _has_nonempty_sets(x): and block and len(set(block)) == len(block)) for block in x) + def _union_of_sets(list_of_sets): """ Return the union of a list of iterables as a frozenset. @@ -2634,7 +2635,9 @@ def _union_of_sets(list_of_sets): sage: _union_of_sets(L) frozenset({1, 2, 3, 5, 6, 7}) """ - return reduce(lambda a,b: frozenset(a)|frozenset(b), list_of_sets, frozenset()) + return reduce(lambda a, b: frozenset(a) | frozenset(b), + list_of_sets, frozenset()) + def _concatenate(list_of_iters): """ diff --git a/src/sage/combinat/partitions.pyx b/src/sage/combinat/partitions.pyx index 12dc88c17b5..c528131892a 100644 --- a/src/sage/combinat/partitions.pyx +++ b/src/sage/combinat/partitions.pyx @@ -42,7 +42,7 @@ def ZS1_iterator(int n): sage: next(it) [4] sage: type(_) - <... 'list'> + """ # Easy cases. if n < 0: @@ -102,7 +102,7 @@ def ZS1_iterator_nk(int n, int k): sage: next(it) [4] sage: type(_) - <... 'list'> + """ # Easy cases. if n <= 0: @@ -137,7 +137,7 @@ def ZS1_iterator_nk(int n, int k): h -= 1 yield x[:m+1] else: - t = m - h + 1 # 1 + "the number of 1s to the right of x[h] that belong to the partition" + t = m - h + 1 # 1 + "the number of 1s to the right of x[h] that belong to the partition" r = x[h] - 1 # This loop finds the largest h such that x[:h] can be completed diff --git a/src/sage/combinat/permutation.py b/src/sage/combinat/permutation.py index 4b39eda2e2f..cf053311550 100644 --- a/src/sage/combinat/permutation.py +++ b/src/sage/combinat/permutation.py @@ -2780,11 +2780,7 @@ def reduced_word(self): [] """ code = self.to_lehmer_code() - reduced_word = [] - for piece in [ [ i + code[i] - j for j in range(code[i])] for i in range(len(code)) ]: - reduced_word += piece - - return reduced_word + return [i + ci - j for i, ci in enumerate(code) for j in range(ci)] def reduced_words_iterator(self): r""" diff --git a/src/sage/combinat/posets/poset_examples.py b/src/sage/combinat/posets/poset_examples.py index c94a00a29db..f47310ccb35 100644 --- a/src/sage/combinat/posets/poset_examples.py +++ b/src/sage/combinat/posets/poset_examples.py @@ -213,7 +213,7 @@ def BooleanLattice(n, facade=None, use_subsets=False): if use_subsets: from sage.sets.set import Set - cur_level = [frozenset(range(1, n+1))] + cur_level = [frozenset(range(1, n + 1))] D = DiGraph() D.add_vertex(Set(cur_level[0])) while cur_level: @@ -227,7 +227,8 @@ def BooleanLattice(n, facade=None, use_subsets=False): return FiniteLatticePoset(D, category=FiniteLatticePosets(), facade=facade) - D = DiGraph({v: [Integer(v|(1< + sage: r {'a': 0, 'b': 1, 'c': 2} @@ -157,7 +157,7 @@ def count(): i = 0 while True: yield i - i+=1 + i += 1 counter = count() diff --git a/src/sage/combinat/root_system/__init__.py b/src/sage/combinat/root_system/__init__.py index bc24bff5c96..e69de29bb2d 100644 --- a/src/sage/combinat/root_system/__init__.py +++ b/src/sage/combinat/root_system/__init__.py @@ -1,9 +0,0 @@ -# currently needed to activate the backward compatibility -# register_unpickle_override -from . import type_A -from . import type_B -from . import type_C -from . import type_D -from . import type_E -from . import type_F -from . import type_G diff --git a/src/sage/combinat/root_system/integrable_representations.py b/src/sage/combinat/root_system/integrable_representations.py index de677e03deb..2f39e19b8b2 100644 --- a/src/sage/combinat/root_system/integrable_representations.py +++ b/src/sage/combinat/root_system/integrable_representations.py @@ -15,7 +15,7 @@ from sage.structure.category_object import CategoryObject from sage.categories.modules import Modules from sage.rings.integer_ring import ZZ -from sage.misc.all import cached_method +from sage.misc.cachefunc import cached_method from sage.matrix.constructor import Matrix from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet from sage.combinat.root_system.weyl_characters import WeylCharacterRing diff --git a/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py b/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py index f1dc9f608b4..482f7bb9215 100644 --- a/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py +++ b/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py @@ -91,11 +91,11 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: E = NonSymmetricMacdonaldPolynomials(["A",2,1], q=q, q1=t, q2=-1) sage: vars = K['x0,x1,x2'].gens() sage: E[L0([2,0,1])].expand(vars) - ((-t + 1)/(-q*t + 1))*x0^2*x1 + x0^2*x2 + ((-q*t + q)/(-q*t + 1))*x0*x1*x2 + (t - 1)/(q*t - 1)*x0^2*x1 + x0^2*x2 + (q*t - q)/(q*t - 1)*x0*x1*x2 sage: from sage.combinat.sf.ns_macdonald import E sage: E([2,0,1]) - ((-t + 1)/(-q*t + 1))*x0^2*x1 + x0^2*x2 + ((-q*t + q)/(-q*t + 1))*x0*x1*x2 + (t - 1)/(q*t - 1)*x0^2*x1 + x0^2*x2 + (q*t - q)/(q*t - 1)*x0*x1*x2 Here is a type `G_2^{(1)}` nonsymmetric Macdonald polynomial:: @@ -431,14 +431,14 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: NS.E([1,0]) x0 sage: EE([0,1]) - ((-t + 1)/(-q*t + 1))*x0 + x1 + (t - 1)/(q*t - 1)*x0 + x1 sage: NS.E([0,1]) - ((-t + 1)/(-q*t + 1))*x0 + x1 + (t - 1)/(q*t - 1)*x0 + x1 sage: NS.E([2,0]) - x0^2 + ((-q*t + q)/(-q*t + 1))*x0*x1 + x0^2 + (q*t - q)/(q*t - 1)*x0*x1 sage: EE([2,0]) - x0^2 + ((-q*t + q)/(-q*t + 1))*x0*x1 + x0^2 + (q*t - q)/(q*t - 1)*x0*x1 The same, directly in the ambient lattice with several shifts:: @@ -940,28 +940,28 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: E = NonSymmetricMacdonaldPolynomials(KL,q, t, -1) sage: L0 = E.keys() sage: omega = L0.fundamental_weights() - sage: P = K['x1,x2,x3'] + sage: P = K['x0,x1,x2'] sage: def EE(weight): return E[L0(weight)].expand(P.gens()) sage: EE([0,0,0]) 1 sage: EE([1,0,0]) - x1 + x0 sage: EE([0,1,0]) - ((-t + 1)/(-q*t^2 + 1))*x1 + x2 + (t - 1)/(q*t^2 - 1)*x0 + x1 sage: EE([0,0,1]) - ((-t + 1)/(-q*t + 1))*x1 + ((-t + 1)/(-q*t + 1))*x2 + x3 + (t - 1)/(q*t - 1)*x0 + (t - 1)/(q*t - 1)*x1 + x2 sage: EE([1,1,0]) - x1*x2 + x0*x1 sage: EE([1,0,1]) - ((-t + 1)/(-q*t^2 + 1))*x1*x2 + x1*x3 + (t - 1)/(q*t^2 - 1)*x0*x1 + x0*x2 sage: EE([0,1,1]) - ((-t + 1)/(-q*t + 1))*x1*x2 + ((-t + 1)/(-q*t + 1))*x1*x3 + x2*x3 + (t - 1)/(q*t - 1)*x0*x1 + (t - 1)/(q*t - 1)*x0*x2 + x1*x2 sage: EE([2,0,0]) - x1^2 + ((-q*t + q)/(-q*t + 1))*x1*x2 + ((-q*t + q)/(-q*t + 1))*x1*x3 + x0^2 + (q*t - q)/(q*t - 1)*x0*x1 + (q*t - q)/(q*t - 1)*x0*x2 sage: EE([0,2,0]) - ((-t + 1)/(-q^2*t^2 + 1))*x1^2 + ((-q^2*t^3 + q^2*t^2 - q*t^2 + 2*q*t - q + t - 1)/(-q^3*t^3 + q^2*t^2 + q*t - 1))*x1*x2 + x2^2 + ((q*t^2 - 2*q*t + q)/(q^3*t^3 - q^2*t^2 - q*t + 1))*x1*x3 + ((-q*t + q)/(-q*t + 1))*x2*x3 + (t - 1)/(q^2*t^2 - 1)*x0^2 + (q^2*t^3 - q^2*t^2 + q*t^2 - 2*q*t + q - t + 1)/(q^3*t^3 - q^2*t^2 - q*t + 1)*x0*x1 + x1^2 + (q*t^2 - 2*q*t + q)/(q^3*t^3 - q^2*t^2 - q*t + 1)*x0*x2 + (q*t - q)/(q*t - 1)*x1*x2 Systematic checks with Sage's implementation of [HHL06]_:: @@ -1781,9 +1781,9 @@ def symmetric_macdonald_polynomial(self, mu): sage: P = SymmetricFunctions(K).macdonald().P() sage: g = P[2,1].expand(3); g - x0^2*x1 + x0*x1^2 + x0^2*x2 + ((-2*q*t^2 + q*t - t^2 + q - t + 2)/(-q*t^2 + 1))*x0*x1*x2 + x1^2*x2 + x0*x2^2 + x1*x2^2 + x0^2*x1 + x0*x1^2 + x0^2*x2 + (2*q*t^2 - q*t - q + t^2 + t - 2)/(q*t^2 - 1)*x0*x1*x2 + x1^2*x2 + x0*x2^2 + x1*x2^2 sage: fe = f.expand(g.parent().gens()); fe - x0^2*x1 + x0*x1^2 + x0^2*x2 + ((2*q*v^4 + v^4 - q*v^2 + v^2 - q - 2)/(q*v^4 - 1))*x0*x1*x2 + x1^2*x2 + x0*x2^2 + x1*x2^2 + x0^2*x1 + x0*x1^2 + x0^2*x2 + (2*q*v^4 - q*v^2 - q + v^4 + v^2 - 2)/(q*v^4 - 1)*x0*x1*x2 + x1^2*x2 + x0*x2^2 + x1*x2^2 sage: g.map_coefficients(lambda x: x.subs(t=v*v)) == fe True diff --git a/src/sage/combinat/root_system/plot.py b/src/sage/combinat/root_system/plot.py index 41371737f7a..706cc57fc18 100644 --- a/src/sage/combinat/root_system/plot.py +++ b/src/sage/combinat/root_system/plot.py @@ -846,7 +846,7 @@ def __init__(self, space, 2 sage: options._projections [Weight space over the Rational Field of the Root system of type ['B', 2], - ] + ] sage: L = RootSystem(['B',2,1]).ambient_space() sage: options = L.plot_parse_options() @@ -854,24 +854,24 @@ def __init__(self, space, 2 sage: options._projections [Ambient space of the Root system of type ['B', 2], - ] + ] sage: options = L.plot_parse_options(affine=True) sage: options.dimension 2 sage: options._projections [Ambient space of the Root system of type ['B', 2], - ] + ] sage: options = L.plot_parse_options(affine=False) sage: options._projections - [] + [] sage: options.dimension 3 sage: options = L.plot_parse_options(affine=False, projection='barycentric') sage: options._projections - [] + [] sage: options.dimension 3 """ diff --git a/src/sage/combinat/root_system/root_lattice_realization_algebras.py b/src/sage/combinat/root_system/root_lattice_realization_algebras.py index ca2dba85e12..86b1e561f87 100644 --- a/src/sage/combinat/root_system/root_lattice_realization_algebras.py +++ b/src/sage/combinat/root_system/root_lattice_realization_algebras.py @@ -42,7 +42,7 @@ def _repr_(self): sage: RootSystem(["A",2,1]).ambient_space().algebra(QQ) # indirect doctest Algebra of the Ambient space of the Root system of type ['A', 2, 1] over Rational Field """ - return "Algebra of the %s over %s"%(self.basis().keys(),self.base_ring()) + return "Algebra of the %s over %s" % (self.basis().keys(), self.base_ring()) def some_elements(self): r""" @@ -1168,13 +1168,15 @@ def expand(self, alphabet): TESTS:: sage: type(p.expand(F.gens())) - <... 'sage.rings.polynomial.laurent_polynomial.LaurentPolynomial_mpair'> + sage: p = KL.zero() sage: p.expand(F.gens()) 0 sage: type(p.expand(F.gens())) - <... 'sage.rings.polynomial.laurent_polynomial.LaurentPolynomial_mpair'> + """ codomain = alphabet[0].parent() - return codomain.sum( c * prod(X**int(n) for X,n in zip(alphabet,vector(m))) for m,c in self) + return codomain.sum(c * prod(X**int(n) + for X, n in zip(alphabet, vector(m))) + for m, c in self) diff --git a/src/sage/combinat/root_system/root_system.py b/src/sage/combinat/root_system/root_system.py index a10c57e5cf6..3957ee889a3 100644 --- a/src/sage/combinat/root_system/root_system.py +++ b/src/sage/combinat/root_system/root_system.py @@ -20,7 +20,7 @@ from .cartan_type import CartanType from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ -from sage.misc.all import cached_method +from sage.misc.cachefunc import cached_method from .root_space import RootSpace from .weight_space import WeightSpace diff --git a/src/sage/combinat/root_system/type_reducible.py b/src/sage/combinat/root_system/type_reducible.py index 3943f5573fd..2a503a7ff58 100644 --- a/src/sage/combinat/root_system/type_reducible.py +++ b/src/sage/combinat/root_system/type_reducible.py @@ -56,7 +56,7 @@ class CartanType(SageObject, CartanType_abstract): super classes (see :meth:`~sage.combinat.root_system.cartan_type.CartanType_abstract._add_abstract_superclass`):: sage: t.__class__.mro() - [, , <... 'sage.structure.sage_object.SageObject'>, , , , <... 'object'>] + [, , , , , , ] The index set of the reducible Cartan type is obtained by relabelling successively the nodes of the Dynkin diagrams of @@ -134,7 +134,7 @@ def __init__(self, types): if all(isinstance(t, cls) for t in types) ) self._add_abstract_superclass(super_classes) - def _repr_(self, compact = True): # We should make a consistent choice here + def _repr_(self, compact=True): # We should make a consistent choice here """ EXAMPLES:: @@ -144,7 +144,7 @@ def _repr_(self, compact = True): # We should make a consistent choice here sage: CartanType("A2",CartanType("F4~").dual()) A2xF4~* """ - return "x".join(t._repr_(compact = True) for t in self._types) + return "x".join(t._repr_(compact=True) for t in self._types) def _latex_(self): r""" diff --git a/src/sage/combinat/root_system/weight_lattice_realizations.py b/src/sage/combinat/root_system/weight_lattice_realizations.py index bc9baf632b4..946d116fbde 100644 --- a/src/sage/combinat/root_system/weight_lattice_realizations.py +++ b/src/sage/combinat/root_system/weight_lattice_realizations.py @@ -248,8 +248,8 @@ def _test_weight_lattice_realization(self, **options): sage: RootSystem(['A',3]).weight_lattice()._test_weight_lattice_realization() """ from sage.rings.integer_ring import ZZ - tester = self._tester(**options) - Lambda = self.fundamental_weights() + tester = self._tester(**options) + Lambda = self.fundamental_weights() alphacheck = self.simple_coroots() tester.assertEqual(tuple(Lambda.keys()), self.index_set()) @@ -868,7 +868,7 @@ def weyl_dimension(self, highest_weight): 16 sage: type(RootSystem(['A',3]).ambient_lattice().weyl_dimension([2,1,0,0])) - <... 'sage.rings.integer.Integer'> + """ highest_weight = self(highest_weight) if not highest_weight.is_dominant(): diff --git a/src/sage/combinat/sf/ns_macdonald.py b/src/sage/combinat/sf/ns_macdonald.py index d2a0928b2a6..a6d9420a5da 100644 --- a/src/sage/combinat/sf/ns_macdonald.py +++ b/src/sage/combinat/sf/ns_macdonald.py @@ -863,19 +863,19 @@ def E(mu, q=None, t=None, pi=None): sage: E([1,0,0]) x0 sage: E([0,1,0]) - ((-t + 1)/(-q*t^2 + 1))*x0 + x1 + (t - 1)/(q*t^2 - 1)*x0 + x1 sage: E([0,0,1]) - ((-t + 1)/(-q*t + 1))*x0 + ((-t + 1)/(-q*t + 1))*x1 + x2 + (t - 1)/(q*t - 1)*x0 + (t - 1)/(q*t - 1)*x1 + x2 sage: E([1,1,0]) x0*x1 sage: E([1,0,1]) - ((-t + 1)/(-q*t^2 + 1))*x0*x1 + x0*x2 + (t - 1)/(q*t^2 - 1)*x0*x1 + x0*x2 sage: E([0,1,1]) - ((-t + 1)/(-q*t + 1))*x0*x1 + ((-t + 1)/(-q*t + 1))*x0*x2 + x1*x2 + (t - 1)/(q*t - 1)*x0*x1 + (t - 1)/(q*t - 1)*x0*x2 + x1*x2 sage: E([2,0,0]) - x0^2 + ((-q*t + q)/(-q*t + 1))*x0*x1 + ((-q*t + q)/(-q*t + 1))*x0*x2 + x0^2 + (q*t - q)/(q*t - 1)*x0*x1 + (q*t - q)/(q*t - 1)*x0*x2 sage: E([0,2,0]) - ((-t + 1)/(-q^2*t^2 + 1))*x0^2 + ((-q^2*t^3 + q^2*t^2 - q*t^2 + 2*q*t - q + t - 1)/(-q^3*t^3 + q^2*t^2 + q*t - 1))*x0*x1 + x1^2 + ((q*t^2 - 2*q*t + q)/(q^3*t^3 - q^2*t^2 - q*t + 1))*x0*x2 + ((-q*t + q)/(-q*t + 1))*x1*x2 + (t - 1)/(q^2*t^2 - 1)*x0^2 + (q^2*t^3 - q^2*t^2 + q*t^2 - 2*q*t + q - t + 1)/(q^3*t^3 - q^2*t^2 - q*t + 1)*x0*x1 + x1^2 + (q*t^2 - 2*q*t + q)/(q^3*t^3 - q^2*t^2 - q*t + 1)*x0*x2 + (q*t - q)/(q*t - 1)*x1*x2 """ P, q, t, n, R, x = _check_muqt(mu, q, t, pi) res = 0 diff --git a/src/sage/combinat/shifted_primed_tableau.py b/src/sage/combinat/shifted_primed_tableau.py index 3b05c7f9a85..5fed1789092 100644 --- a/src/sage/combinat/shifted_primed_tableau.py +++ b/src/sage/combinat/shifted_primed_tableau.py @@ -686,8 +686,8 @@ def restrict(self, n): """ t = self[:] n = PrimedEntry(n) - return ShiftedPrimedTableau([z for z in [[y for y in x if y is not None and y <= n] - for x in t] if z], skew=self._skew) + loop = ([y for y in x if y is not None and y <= n] for x in t) + return ShiftedPrimedTableau([z for z in loop if z], skew=self._skew) def restriction_outer_shape(self, n): """ diff --git a/src/sage/combinat/sidon_sets.py b/src/sage/combinat/sidon_sets.py index e9924762024..3f5cfcb3173 100644 --- a/src/sage/combinat/sidon_sets.py +++ b/src/sage/combinat/sidon_sets.py @@ -12,8 +12,8 @@ # https://www.gnu.org/licenses/ # **************************************************************************** from sage.sets.set import Set -from sage.misc.all import cached_function -from sage.rings.all import Integer +from sage.misc.cachefunc import cached_function +from sage.rings.integer import Integer def sidon_sets(N, g = 1): diff --git a/src/sage/combinat/skew_partition.py b/src/sage/combinat/skew_partition.py index 585e1802c74..ab84c33b0af 100644 --- a/src/sage/combinat/skew_partition.py +++ b/src/sage/combinat/skew_partition.py @@ -1005,7 +1005,7 @@ def to_list(self): sage: s.to_list() [[4, 3, 1], [2]] sage: type(s.to_list()) - <... 'list'> + """ return [list(_) for _ in list(self)] @@ -1504,9 +1504,9 @@ def from_row_and_column_length(self, rowL, colL): if not all(i>0 for i in rowL) or not all(i>0 for i in colL): raise ValueError("row and column length must be positive") if rowL == []: - return self.element_class(self, [[],[]]) + return self.element_class(self, [[], []]) colL_new = colL[:] - resIn = [] + resIn = [] resOut = [] inPOld = len(colL) for row in rowL: @@ -1714,13 +1714,10 @@ def _count_slide(self, co, overlap=0): sage: [ sp for sp in s if sp.row_lengths() == [2,1] ] [[2, 1] / []] """ - nn = len(co) result = 1 - for i in range(nn-1): - comb = min(co[i], co[i+1]) - comb += 1 - overlap - result *= comb - + shift = 1 - overlap + for i in range(len(co) - 1): + result *= min(co[i], co[i + 1]) + shift return result def cardinality(self): diff --git a/src/sage/combinat/sloane_functions.py b/src/sage/combinat/sloane_functions.py index 4307051be34..93349075c17 100644 --- a/src/sage/combinat/sloane_functions.py +++ b/src/sage/combinat/sloane_functions.py @@ -125,11 +125,18 @@ # just used for handy .load, .save, etc. import sys import inspect + from sage.structure.sage_object import SageObject from sage.arith.srange import srange from sage.rings.integer_ring import ZZ from sage.functions.all import prime_pi from sage.rings.integer import Integer as Integer_class +# You may have to import more here when defining new sequences +import sage.arith.all as arith +from sage.matrix.matrix_space import MatrixSpace +from sage.rings.rational_field import QQ +from sage.combinat import combinat +from sage.misc.misc_c import prod class SloaneSequence(SageObject): @@ -307,22 +314,16 @@ def __getitem__(self, n): return self(n) LENGTH = 100000 - (start, stop, step) = n.indices(2*LENGTH) + (start, stop, step) = n.indices(2 * LENGTH) if abs(stop - start) > LENGTH: - raise IndexError("slice (=%s) too long"%n) + raise IndexError("slice (=%s) too long" % n) return [self(i) for i in range(start, stop, step) if i >= self.offset] + ######################################################################## # II. Actual implementations of Sloane sequences. ######################################################################## -# You may have to import more here when defining new sequences -import sage.arith.all as arith -from sage.matrix.matrix_space import MatrixSpace -from sage.rings.rational_field import QQ -from sage.combinat import combinat -from sage.misc.misc_c import prod - # This one should be here! class A000001(SloaneSequence): @@ -638,7 +639,7 @@ def __init__(self): - Jaap Spies (2007-01-30) """ SloaneSequence.__init__(self, offset=0) - self._b=[] + self._b = [] self._precompute(2) def _repr_(self): @@ -770,7 +771,7 @@ def pi(self): d, d1 = a//b, a1//b1 while d == d1: yield d - a, a1 = 10*(a%b), 10*(a1%b1) + a, a1 = 10*(a % b), 10*(a1 % b1) d, d1 = a//b, a1//b1 @@ -867,7 +868,7 @@ def _eval(self, n): sage: [sloane.A003418._eval(n) for n in range(1,11)] [1, 2, 6, 12, 60, 60, 420, 840, 2520, 2520] """ - return arith.lcm([i for i in range(1,n+1)]) + return arith.lcm([i for i in range(1, n+1)]) class A007318(SloaneSequence): @@ -929,7 +930,7 @@ def _eval(self, n): m += 1 m -= 1 k = n - m*(m+1)//2 - return arith.binomial(m,k) + return arith.binomial(m, k) class A008275(SloaneSequence): @@ -998,7 +999,7 @@ def s(self, n, k): sage: sloane.A008275.s(5,3) 35 """ - return (-1)**(n-k) * combinat.stirling_number1(n,k) + return (-1)**(n-k) * combinat.stirling_number1(n, k) def _eval(self, n): """ @@ -1076,7 +1077,7 @@ def s2(self, n, k): sage: sloane.A008277.s2(4,2) 7 """ - return combinat.stirling_number2(n,k) + return combinat.stirling_number2(n, k) def _eval(self, n): """ @@ -1155,10 +1156,10 @@ def _eval(self, n): m += 1 m -= 1 k = n - m*(m+1)//2 - if (m+k)%2: + if (m+k) % 2: return ZZ(0) sign = (-1)**((m+k)//2 + k) - return sign * arith.binomial((m+k)//2,k) + return sign * arith.binomial((m+k)//2, k) class A000010(SloaneSequence): @@ -1977,7 +1978,7 @@ def _repr_(self): """ return "1's-counting sequence: number of 1's in binary expansion of n." - def f(self,n): + def f(self, n): """ EXAMPLES:: @@ -2383,7 +2384,8 @@ def _eval(self, n): """ if n == 0: return ZZ.one() - return ZZ(sum( (i%2) * arith.euler_phi(i) * 2**(n//i) / (2*n) for i in arith.divisors(n) )) + return ZZ(sum((i % 2) * arith.euler_phi(i) * 2**(n//i) / (2*n) + for i in arith.divisors(n))) class A000032(SloaneSequence): @@ -2562,12 +2564,12 @@ def _precompute(self, how_many=150): """ try: self._b - n = self._n + self._n except AttributeError: self._b = [] - n = self.offset - self._n = n - self._b += [i for i in range(self._n, self._n+how_many) if sloane.A004086(i) == i] + self._n = self.offset + self._b += [i for i in range(self._n, self._n + how_many) + if sloane.A004086(i) == i] self._n += how_many def _eval(self, n): @@ -2861,8 +2863,8 @@ def _eval(self, n): [1, 4, 6, 8, 9, 10, 12, 14, 15, 16] """ if n == 1: - return ZZ.one() - return sloane.A002808(n-1) + return ZZ.one() + return sloane.A002808(n - 1) class A000043(SloaneSequence): @@ -3291,7 +3293,7 @@ def _eval(self, n): sage: [sloane.A002110._eval(n) for n in range(10)] [1, 2, 6, 30, 210, 2310, 30030, 510510, 9699690, 223092870] """ - return prod([sloane.A000040(i) for i in range(1,n+1)]) #n-th prime = A000040(n) + return prod([sloane.A000040(i) for i in range(1, n + 1)]) # n-th prime = A000040(n) class A000720(SloaneSequence): @@ -3404,7 +3406,7 @@ def _eval(self, n): sage: [sloane.A064553._eval(n) for n in range(1,11)] [1, 2, 3, 4, 4, 6, 5, 8, 9, 8] """ - return prod([(prime_pi(p)+1)**e for p,e in arith.factor(n)]) + return prod([(prime_pi(p)+1)**e for p, e in arith.factor(n)]) class A001055(SloaneSequence): @@ -3469,15 +3471,15 @@ def nwf(self, n, m): return ZZ.one() if arith.is_prime(n): if m < n: - return ZZ(0) + return ZZ.zero() else: return ZZ.one() s = ZZ(0) for d in arith.divisors(n): if d > 1 and d <= m and d < n: - s += self.nwf(n//d, d) + s += self.nwf(n // d, d) if n <= m: - s += 1 + s += 1 return s def _eval(self, n): @@ -3692,7 +3694,8 @@ def _precompute(self, how_many=150): sage: len(sloane.A005117._b) - initial > 0 True """ - self._b += [i for i in range(self._n, self._n+how_many) if max(e for _,e in arith.factor(i)) <= 1] + self._b += [i for i in range(self._n, self._n+how_many) + if max(e for _, e in arith.factor(i)) <= 1] self._n += how_many def _eval(self, n): @@ -4580,7 +4583,8 @@ def _eval(self, n): # a(n) = Sum from k=1 to n of k! StirlingS2(n, k) if n == 0: return ZZ.one() - return sum(arith.factorial(k) * combinat.stirling_number2(n,k) for k in range(1, n+1)) + return sum(arith.factorial(k) * combinat.stirling_number2(n, k) + for k in range(1, n+1)) class A006318(SloaneSequence): @@ -4745,6 +4749,7 @@ def _eval(self, n): """ return arith.factorial(2*n) / (arith.factorial(n)*2**n) + class A006882(SloaneSequence): def __init__(self): r""" @@ -4897,7 +4902,7 @@ def _eval(self, n): sage: [sloane.A000984._eval(n) for n in range(10)] [1, 2, 6, 20, 70, 252, 924, 3432, 12870, 48620] """ - return arith.binomial(2*n,n) + return arith.binomial(2 * n, n) class A001405(SloaneSequence): @@ -5060,8 +5065,6 @@ def _eval(self, n): return ZZ(n * (n+1) * (2*n+1) // 6) - - # Theme: maximal permanent of an m x n (0,1)- matrix: # Seok-Zun Song et al. Extremes of permanents of (0,1)-matrices, p. 201-202. @@ -5083,7 +5086,7 @@ def _precompute(self, how_many=20): f = self._f self._b += [next(f) for i in range(how_many)] - def gen(self,a0,a1,d): + def gen(self, a0, a1, d): """ EXAMPLES:: @@ -5120,7 +5123,7 @@ def list(self, n): """ self._eval(n) # force computation return self._b[:n] - _k = 1 + _k = 1 class A000153(ExtremesOfPermanentsSequence): @@ -5163,7 +5166,7 @@ def __init__(self): """ SloaneSequence.__init__(self, offset=0) self._b = [] - self._a0a1d = (0,1,2) + self._a0a1d = (0, 1, 2) self._precompute(2) # force precomputation, e.g. a(0) will fail when asked first def _repr_(self): @@ -5218,7 +5221,7 @@ def __init__(self): """ SloaneSequence.__init__(self, offset=0) self._b = [] - self._a0a1d = (1,1,1) + self._a0a1d = (1, 1, 1) self._precompute(2) # force precomputation, e.g. a(0) will fail when asked first def _repr_(self): @@ -5277,7 +5280,7 @@ def __init__(self): - Jaap Spies (2007-01-23) """ SloaneSequence.__init__(self, offset=1) - self._a0a1d = (0,1,3) + self._a0a1d = (0, 1, 3) self._b = [] self._k = self.offset + 1 @@ -5337,7 +5340,7 @@ def __init__(self): - Jaap Spies (2007-01-13) """ SloaneSequence.__init__(self, offset=2) - self._a0a1d = (0,1,4) + self._a0a1d = (0, 1, 4) self._b = [] self._k = self.offset + 1 @@ -5397,7 +5400,7 @@ def __init__(self): - Jaap Spies (2007-01-13) """ SloaneSequence.__init__(self, offset=3) - self._a0a1d = (0,1,5) + self._a0a1d = (0, 1, 5) self._b = [] self._k = self.offset + 1 @@ -5410,8 +5413,9 @@ def _repr_(self): """ return "a(n) = n*a(n-1) + (n-5)*a(n-2), a(3) = 0, a(4) = 1." + class ExtremesOfPermanentsSequence2(ExtremesOfPermanentsSequence): - def gen(self,a0,a1,d): + def gen(self, a0, a1, d): """ EXAMPLES:: @@ -5483,7 +5487,7 @@ def __init__(self): - Jaap Spies (2007-01-23) """ SloaneSequence.__init__(self, offset=1) - self._a0a1d = (6,43,6) + self._a0a1d = (6, 43, 6) self._k = self.offset + 1 self._b = [] @@ -5545,7 +5549,7 @@ def __init__(self): - Jaap Spies (2007-01-23) """ SloaneSequence.__init__(self, offset=0) - self._a0a1d = (0,2,1) + self._a0a1d = (0, 2, 1) self._b = [] self._precompute(2) self._k1 = 2 @@ -6054,7 +6058,7 @@ def _eval(self, n): sage: [sloane.A000203._eval(n) for n in range(1,11)] [1, 3, 4, 7, 6, 12, 8, 15, 13, 18] """ - return sum(arith.divisors(n)) #alternative: return arith.sigma(n) + return sum(arith.divisors(n)) # alternative: return arith.sigma(n) class A001157(SloaneSequence): @@ -6110,7 +6114,7 @@ def _eval(self, n): sage: [sloane.A001157._eval(n) for n in range(1,11)] [1, 5, 10, 21, 26, 50, 50, 85, 91, 130] """ - return arith.sigma(n,2) + return arith.sigma(n, 2) class A008683(SloaneSequence): @@ -6395,11 +6399,8 @@ def _eval(self, n): return ZZ(10**n-1)//9 - - - # inhomogeneous second order recurrences -def recur_gen2b(a0,a1,a2,a3,b): +def recur_gen2b(a0, a1, a2, a3, b): r""" Inhomogeneous second-order linear recurrence generator with fixed coefficients and `b = f(n)` @@ -6422,6 +6423,7 @@ def recur_gen2b(a0,a1,a2,a3,b): x, y = y, a3*x+a2*y + b(n) yield x + class RecurrenceSequence(SloaneSequence): def _precompute(self, how_many=20): """ @@ -6495,7 +6497,7 @@ def __init__(self): - Jaap Spies (2007-01-19) """ SloaneSequence.__init__(self, offset=0) - self._params = (0,1,34,-1,self.g) + self._params = (0, 1, 34, -1, self.g) self._b = [] self._precompute() @@ -6510,7 +6512,7 @@ def _repr_(self): """ return "Numbers that are both triangular and square: a(n) = 34a(n-1) - a(n-2) + 2." - def g(self,k): + def g(self, k): """ EXAMPLES:: @@ -6645,7 +6647,7 @@ def _eval(self, n): sage: [sloane.A001221._eval(n) for n in range(1,10)] [0, 1, 1, 1, 1, 2, 1, 1, 1] """ - return len(arith.prime_divisors(n)) # there is a PARI function omega + return len(arith.prime_divisors(n)) # there is a PARI function omega class A001222(SloaneSequence): @@ -6891,12 +6893,12 @@ def _precompute(self, how_many=150): """ try: self._b - n = self._n + self._n except AttributeError: self._b = [] - n = 1 - self._n = n - self._b += [i for i in range(self._n, self._n+how_many) if sum(e for _,e in arith.factor(i)) == 2] + self._n = 1 + self._b += [i for i in range(self._n, self._n + how_many) + if sum(e for _, e in arith.factor(i)) == 2] self._n += how_many def _eval(self, n): @@ -6995,12 +6997,11 @@ def _precompute(self, how_many=10000): """ try: self._b - n = self._n + self._n except AttributeError: self._b = [1] - n = 1 - self._n = n - self._b += self._powerful_numbers_in_range(self._n, self._n+how_many) + self._n = 1 + self._b += self._powerful_numbers_in_range(self._n, self._n + how_many) self._n += how_many def _powerful_numbers_in_range(self, n, m): @@ -7017,7 +7018,7 @@ def _powerful_numbers_in_range(self, n, m): n = 4 # Use PARI directly -- much faster. from sage.libs.pari.all import pari - L = pari('v=listcreate(); for(i=%s,%s,if(vecmin(factor(i)[,2])>1,listput(v,i))); v'%(n,m)) + L = pari('v=listcreate(); for(i=%s,%s,if(vecmin(factor(i)[,2])>1,listput(v,i))); v' % (n, m)) return [ZZ(x) for x in L] # not very many, so not much overhead def _eval(self, n): @@ -7159,12 +7160,12 @@ def _precompute(self, how_many=150): """ try: self._b - n = self._n + self._n except AttributeError: self._b = [] - n = self.offset - self._n = n - self._b += [i for i in range(self._n, self._n+how_many) if arith.euler_phi(2*i-1) < arith.euler_phi(2*i)] + self._n = self.offset + self._b += [i for i in range(self._n, self._n + how_many) + if arith.euler_phi(2 * i - 1) < arith.euler_phi(2 * i)] self._n += how_many def _eval(self, n): @@ -7199,10 +7200,8 @@ def list(self, n): return self.list(n) - - # a group of sequences uses this function: -def recur_gen2(a0,a1,a2,a3): +def recur_gen2(a0, a1, a2, a3): r""" homogeneous general second-order linear recurrence generator with fixed coefficients @@ -7768,9 +7767,6 @@ def _repr_(self): return "Linear 2nd order recurrence, a(n) = 6 a(n-1) + 5 a(n-2)." - - - # todo jsp # # @@ -8134,7 +8130,7 @@ def _eval(self, n): # a group of sequences uses this function: -def recur_gen3(a0,a1,a2,a3,a4,a5): +def recur_gen3(a0, a1, a2, a3, a4, a5): r""" homogeneous general third-order linear recurrence generator with fixed coefficients @@ -8149,7 +8145,7 @@ def recur_gen3(a0,a1,a2,a3,a4,a5): sage: [next(it) for i in range(10)] [1, 1, 1, 3, 5, 9, 17, 31, 57, 105] """ - x, y ,z = ZZ(a0), ZZ(a1), ZZ(a2) + x, y, z = ZZ(a0), ZZ(a1), ZZ(a2) yield x while True: x, y, z = y, z, a5*x+a4*y+a3*z @@ -8583,8 +8579,11 @@ def _eval(self, n): if n == 1: return ZZ.one() m = 0 - for d in [i for i in arith.divisors(n) if i%2]: # d is odd divisor - k = min(d, 2*n/d) + for d in arith.divisors(n): + if not d % 2: + continue + # d is odd divisor + k = min(d, 2 * n // d) if k > m: m = k return ZZ(m) @@ -8660,12 +8659,12 @@ def _precompute(self, how_many=150): """ try: self._b - n = self._n + self._n except AttributeError: self._b = [] - n = 1 - self._n = n - self._b += [i for i in range(self._n, self._n+how_many) if self.is_number_of_the_third_kind(i)] + self._n = 1 + self._b += [i for i in range(self._n, self._n + how_many) + if self.is_number_of_the_third_kind(i)] self._n += how_many def _eval(self, n): @@ -8822,8 +8821,8 @@ def _eval(self, n): """ if n == 1 or n == 0: return ZZ.zero() - k = sum(i%2 for i in arith.divisors(n)) # A001227, the number of odd divisors - if n % 2 ==0: + k = sum(i % 2 for i in arith.divisors(n)) # A001227, the number of odd divisors + if n % 2 == 0: return k - 1 else: return k - 2 @@ -8902,7 +8901,7 @@ def _eval(self, n): if arith.is_prime(n) or arith.is_power_of_two(n): return ZZ.zero() - for d in srange(3,n,2): + for d in srange(3, n, 2): if n % d == 0: return min(d, 2*n//d) @@ -8942,8 +8941,8 @@ def _eval(self, n): if n < self.__n: return self.__data[n] from sage.combinat.expnums import expnums - self.__data = expnums(n+1, self.a) - self.__n = n+1 + self.__data = expnums(n + 1, self.a) + self.__n = n + 1 return self.__data[n] @@ -9111,9 +9110,8 @@ def _eval(self, n): """ if n <= 2: return ZZ.zero() - else: - return sum(sloane.A000045(i+1) * sloane.A000073(n-i-1) for i in range(n-2)) - + return sum(sloane.A000045(i + 1) * sloane.A000073(n - i - 1) + for i in range(n - 2)) ############################################################# @@ -9170,7 +9168,7 @@ def trait_names(self): EXAMPLES:: sage: type(sloane.trait_names()) - <... 'list'> + """ try: return self.__trait_names @@ -9214,5 +9212,5 @@ def __getattribute__(self, name): except (AttributeError, TypeError): raise AttributeError(name) -sloane = Sloane() +sloane = Sloane() diff --git a/src/sage/combinat/species/product_species.py b/src/sage/combinat/species/product_species.py index 77894d6f572..051bf43e096 100644 --- a/src/sage/combinat/species/product_species.py +++ b/src/sage/combinat/species/product_species.py @@ -409,7 +409,7 @@ def _equation(self, var_mapping): sage: X = species.SingletonSpecies() sage: S = X * X sage: S.algebraic_equation_system() - [node0 - z^2] + [node0 + (-z^2)] """ from sage.misc.misc_c import prod return prod(var_mapping[operand] for operand in self._state_info) diff --git a/src/sage/combinat/species/recursive_species.py b/src/sage/combinat/species/recursive_species.py index 04121797d6e..d6023264808 100644 --- a/src/sage/combinat/species/recursive_species.py +++ b/src/sage/combinat/species/recursive_species.py @@ -467,7 +467,7 @@ def _equation(self, var_mapping): sage: B = species.BinaryTreeSpecies() sage: B.algebraic_equation_system() - [-node3^2 + node1, -node1 + node3 - z] + [-node3^2 + node1, -node1 + node3 + (-z)] """ try: return var_mapping[self._reference] diff --git a/src/sage/combinat/species/series.py b/src/sage/combinat/species/series.py index b312148a2f3..64862dd9d74 100644 --- a/src/sage/combinat/species/series.py +++ b/src/sage/combinat/species/series.py @@ -33,7 +33,7 @@ from .stream import Stream, Stream_class from .series_order import bounded_decrement, increment, inf, unk -from sage.rings.all import Integer +from sage.rings.integer import Integer from sage.misc.misc_c import prod from functools import partial from sage.misc.misc import is_iterator diff --git a/src/sage/combinat/species/series_order.py b/src/sage/combinat/species/series_order.py index 17fa96201c4..f4c42d032bd 100644 --- a/src/sage/combinat/species/series_order.py +++ b/src/sage/combinat/species/series_order.py @@ -11,7 +11,7 @@ In particular, the relevant section for this file can be found at http://www.risc.uni-linz.ac.at/people/hemmecke/AldorCombinat/combinatsu30.html. """ -from sage.rings.all import Integer +from sage.rings.integer import Integer class SeriesOrderElement: pass diff --git a/src/sage/combinat/species/species.py b/src/sage/combinat/species/species.py index 26a0c2e58ec..da40645fa16 100644 --- a/src/sage/combinat/species/species.py +++ b/src/sage/combinat/species/species.py @@ -458,7 +458,7 @@ def __pow__(self, n): ... ValueError: only positive exponents are currently supported """ - from sage.rings.all import Integer + from sage.rings.integer import Integer import operator n = Integer(n) if n <= 0: @@ -769,7 +769,7 @@ def algebraic_equation_system(self): sage: B = species.BinaryTreeSpecies() sage: B.algebraic_equation_system() - [-node3^2 + node1, -node1 + node3 - z] + [-node3^2 + node1, -node1 + node3 + (-z)] :: diff --git a/src/sage/combinat/species/sum_species.py b/src/sage/combinat/species/sum_species.py index a7f0a616fdc..9168ffa76bc 100644 --- a/src/sage/combinat/species/sum_species.py +++ b/src/sage/combinat/species/sum_species.py @@ -84,7 +84,7 @@ def right_summand(self): sage: F = P + P*P sage: F.right_summand() Product of (Permutation species) and (Permutation species) - """ + """ return self._G def _name(self): @@ -214,7 +214,7 @@ def _equation(self, var_mapping): sage: X = species.SingletonSpecies() sage: S = X + X sage: S.algebraic_equation_system() - [node1 - 2*z] + [node1 + (-2*z)] """ return sum(var_mapping[operand] for operand in self._state_info) diff --git a/src/sage/combinat/tableau.py b/src/sage/combinat/tableau.py index 6301ffd4a35..0976069a23d 100644 --- a/src/sage/combinat/tableau.py +++ b/src/sage/combinat/tableau.py @@ -2628,7 +2628,7 @@ def promotion_inverse(self, n): sage: T = Tableau([[1]]) sage: type(T.promotion_inverse(2)[0][0]) - <... 'sage.rings.integer.Integer'> + """ if self.is_rectangular(): n = Integer(n) diff --git a/src/sage/combinat/tiling.py b/src/sage/combinat/tiling.py index b34dad8f9ad..a3a5774a00d 100644 --- a/src/sage/combinat/tiling.py +++ b/src/sage/combinat/tiling.py @@ -426,15 +426,14 @@ def ncube_isometry_group_cosets(n, orientation_preserving=True): sage: [len(c) for c in cosets] [8, 8, 8, 8, 8, 8] sage: type(cosets[0][0]) - <... 'sage.matrix.matrix_rational_dense.Matrix_rational_dense'> - + """ from sage.misc.misc_c import prod from sage.matrix.constructor import diagonal_matrix G = ncube_isometry_group(n, orientation_preserving) # Construct the subgroup H of G of diagonal matrices - it = itertools.product((1,-1), repeat=n) + it = itertools.product((1, -1), repeat=n) if orientation_preserving: H = [diagonal_matrix(L) for L in it if prod(L) == 1] else: @@ -1490,7 +1489,7 @@ def self_surrounding(self, radius, remove_incomplete_copies=True, # Add one row to force the placement of the central tile coord_to_int = T.coord_to_int_dict() new_row = [coord_to_int[coord] for coord in self] - new_row.append(len(coord_to_int)) # to force this row in the solution + new_row.append(len(coord_to_int)) # to force this row in the solution forced_row_number = len(rows) rows.append(new_row) diff --git a/src/sage/combinat/words/finite_word.py b/src/sage/combinat/words/finite_word.py index 18c02267c49..7cdc289a290 100644 --- a/src/sage/combinat/words/finite_word.py +++ b/src/sage/combinat/words/finite_word.py @@ -1321,7 +1321,7 @@ def factor_iterator(self, n=None): TESTS:: sage: type( Word('cacao').factor_iterator() ) - <... 'generator'> + """ return self.suffix_tree().factor_iterator(n) @@ -5288,15 +5288,15 @@ def _s(self, i): sage: w._s(1).parent() Finite words over {1, 2, 3} """ - unpaired_i = [] # positions of unpaired is - unpaired_ip = [] # positions of unpaired i+1s - for p,x in enumerate(self): + unpaired_i = [] # positions of unpaired is + unpaired_ip = [] # positions of unpaired i+1s + for p, x in enumerate(self): if x == i: if unpaired_ip: unpaired_ip.pop() else: unpaired_i.append(p) - elif x == i+1: + elif x == i + 1: unpaired_ip.append(p) unpaired = unpaired_i + unpaired_ip diff --git a/src/sage/combinat/words/lyndon_word.py b/src/sage/combinat/words/lyndon_word.py index 16115350bc8..076124ad798 100644 --- a/src/sage/combinat/words/lyndon_word.py +++ b/src/sage/combinat/words/lyndon_word.py @@ -16,7 +16,7 @@ from sage.structure.parent import Parent from sage.combinat.composition import Composition, Compositions -from sage.rings.all import Integer +from sage.rings.integer import Integer from sage.arith.all import divisors, gcd, moebius, multinomial from sage.combinat.necklace import _sfc diff --git a/src/sage/combinat/words/words.py b/src/sage/combinat/words/words.py index 852fca48876..5a75921c47f 100644 --- a/src/sage/combinat/words/words.py +++ b/src/sage/combinat/words/words.py @@ -135,9 +135,9 @@ def __init__(self, alphabet=None, category=None): True sage: Words('abc').sortkey_letters - + sage: Words('bac').sortkey_letters - + """ if isinstance(alphabet, (int, Integer)): from sage.sets.integer_range import IntegerRange @@ -408,7 +408,7 @@ def _element_classes(self): sage: d = FiniteWords()._element_classes sage: type(d) - <... 'dict'> + sage: len(d) 7 sage: e = FiniteWords('abcdefg')._element_classes @@ -1347,7 +1347,7 @@ def _element_classes(self): sage: d = InfiniteWords()._element_classes sage: type(d) - <... 'dict'> + sage: len(d) 4 sage: e = InfiniteWords('abcdefg')._element_classes diff --git a/src/sage/crypto/mq/rijndael_gf.py b/src/sage/crypto/mq/rijndael_gf.py index eb6119bafe0..619026bfe96 100644 --- a/src/sage/crypto/mq/rijndael_gf.py +++ b/src/sage/crypto/mq/rijndael_gf.py @@ -119,7 +119,7 @@ sage: mc_pc = rgf.mix_columns_poly_constr() sage: mc_pc(1, 2) - a02 + (x)*a12 + (x + 1)*a22 + a32 + a02 + x*a12 + (x + 1)*a22 + a32 sage: mc_pc(2, 3, algorithm='decrypt') (x^3 + x^2 + 1)*a03 + (x^3 + 1)*a13 + (x^3 + x^2 + x)*a23 + (x^3 + x + 1)*a33 @@ -274,7 +274,7 @@ sage: rcpc A polynomial constructor of a round component of Rijndael-GF block cipher with block length 4, key length 6, and 12 rounds. sage: rcpc(2, 1) - a01 + a12 + (x)*a23 + (x + 1)*a30 + a01 + a12 + x*a23 + (x + 1)*a30 sage: state = rgf._hex_to_GF('afb73eeb1cd1b85162280f27fb20d585') sage: result = rgf.apply_poly(state, rcpc) @@ -303,7 +303,7 @@ sage: poly = rgf.mix_columns_poly_constr()(0, 3) sage: poly - (x)*a03 + (x + 1)*a13 + a23 + a33 + x*a03 + (x + 1)*a13 + a23 + a33 sage: rgf.compose(rgf.sub_bytes_poly_constr(), poly) (x^3 + x)*a03^254 + (x^3 + x^2 + x + 1)*a13^254 + @@ -325,7 +325,7 @@ (x^2 + x + 1)*a13^239 + (x^7 + x^6 + x^5 + x^4 + x^2)*a23^239 + (x^7 + x^6 + x^5 + x^4 + x^2)*a33^239 + - (x)*a03^223 + + x*a03^223 + (x + 1)*a13^223 + a23^223 + a33^223 + @@ -462,7 +462,7 @@ def __init__(self, Nb, Nk, state_chr='a', key_chr='k'): sage: rgf = RijndaelGF(4, 6, state_chr='myChr') sage: rgf.mix_columns_poly_constr()(3, 2) - (x + 1)*myChr02 + myChr12 + myChr22 + (x)*myChr32 + (x + 1)*myChr02 + myChr12 + myChr22 + x*myChr32 We can also alter the name of variables in polynomials representing elements from round keys by changing ``key_chr``. :: @@ -1483,10 +1483,10 @@ def compose(self, f, g, algorithm='encrypt', f_attr=None, g_attr=None): sage: from sage.crypto.mq.rijndael_gf import RijndaelGF sage: rgf = RijndaelGF(4, 4) sage: mcp = rgf.mix_columns_poly_constr()(1, 3); mcp - a03 + (x)*a13 + (x + 1)*a23 + a33 + a03 + x*a13 + (x + 1)*a23 + a33 sage: result = rgf.compose(rgf.shift_rows_poly_constr(), mcp) sage: result - a03 + (x)*a10 + (x + 1)*a21 + a32 + a03 + x*a10 + (x + 1)*a21 + a32 We can test the correctness of this:: @@ -1503,7 +1503,7 @@ def compose(self, f, g, algorithm='encrypt', f_attr=None, g_attr=None): sage: fn = rgf.compose(rgf.shift_rows_poly_constr(), ....: rgf.mix_columns_poly_constr()) sage: fn(1, 3) - a03 + (x)*a10 + (x + 1)*a21 + a32 + a03 + x*a10 + (x + 1)*a21 + a32 If we use ``compose`` to make a new ``Round_Component_Poly_Constr`` object, we can use that object as input to ``apply_poly`` and @@ -1958,7 +1958,7 @@ def mix_columns_poly_constr(self): sage: mc_pc A polynomial constructor for the function 'Mix Columns' of Rijndael-GF block cipher with block length 4, key length 4, and 10 rounds. sage: mc_pc(1, 2) - a02 + (x)*a12 + (x + 1)*a22 + a32 + a02 + x*a12 + (x + 1)*a22 + a32 sage: mc_pc(1, 0, algorithm='decrypt') (x^3 + 1)*a00 + (x^3 + x^2 + x)*a10 + (x^3 + x + 1)*a20 + (x^3 + x^2 + 1)*a30 @@ -1994,7 +1994,7 @@ def _mix_columns_pc(self, row, col, algorithm='encrypt'): sage: from sage.crypto.mq.rijndael_gf import RijndaelGF sage: rgf = RijndaelGF(4, 4) sage: rgf._mix_columns_pc(3, 1) - (x + 1)*a01 + a11 + a21 + (x)*a31 + (x + 1)*a01 + a11 + a21 + x*a31 We can use this to calculate individual entries of a state matrix after the decryption version of MixColumns has been applied to it as such:: @@ -2197,7 +2197,7 @@ def __init__(self, polynomial_constr, rgf, round_component_name=None): sage: rcpc = RijndaelGF.Round_Component_Poly_Constr( ....: rgf._mix_columns_pc, rgf, "Mix Columns") sage: poly = rcpc(1, 2); poly - a02 + (x)*a12 + (x + 1)*a22 + a32 + a02 + x*a12 + (x + 1)*a22 + a32 sage: state = rgf._hex_to_GF('d1876c0f79c4300ab45594add66ff41f') sage: result = rgf.mix_columns(state) sage: result[1,2] == poly(state.list()) diff --git a/src/sage/doctest/forker.py b/src/sage/doctest/forker.py index 3307d50939e..6690c627e75 100644 --- a/src/sage/doctest/forker.py +++ b/src/sage/doctest/forker.py @@ -1475,7 +1475,7 @@ def report_unexpected_exception(self, out, test, example, exc_info): sage: old_prompt = sage0._prompt sage: sage0._prompt = r"\(Pdb\) " sage: sage0.eval("DTR.run(DT, clear_globs=False)") # indirect doctest - '... ArithmeticError("invariants " + str(ainvs) + " define a singular curve")' + '... ArithmeticError(self._equation_string() + " defines a singular curve")' sage: sage0.eval("l") '...if self.discriminant() == 0:...raise ArithmeticError...' sage: sage0.eval("u") diff --git a/src/sage/doctest/parsing.py b/src/sage/doctest/parsing.py index 3346ca14a24..4378c45c713 100644 --- a/src/sage/doctest/parsing.py +++ b/src/sage/doctest/parsing.py @@ -173,59 +173,6 @@ def normalize_long_repr(s): return _long_repr_re.sub(lambda m: m.group(1), s) -_normalize_bound_method_re = re.compile( - r'[^. ]+)\sof\s(?P.+)>', re.M | re.S) - -def normalize_bound_method_repr(s): - """ - Normalize differences between Python 2 and 3 in how bound methods are - represented. - - On Python 2 bound methods are represented using the class name of the - object the method was bound to, whereas on Python 3 they are represented - with the fully-qualified name of the function that implements the method. - - In the context of a doctest it's almost impossible to convert accurately - from the latter to the former or vice-versa, so we simplify the reprs of - bound methods to just the bare method name. - - This is slightly regressive since it means one can't use the repr of a - bound method to test whether some element is getting a method from the - correct class (important sometimes in the cases of dynamic classes). - However, such tests could be written could be written more explicitly to - emphasize that they are testing such behavior. - - EXAMPLES: - - :: - - sage: from sage.doctest.parsing import normalize_bound_method_repr - sage: el = Semigroups().example().an_element() - sage: el - 42 - sage: el.is_idempotent - - sage: normalize_bound_method_repr(repr(el.is_idempotent)) - '' - - An example where the object ``repr`` contains whitespace:: - - sage: U = DisjointUnionEnumeratedSets( - ....: Family([1, 2, 3], Partitions), facade=False) - sage: U._element_constructor_ - - sage: normalize_bound_method_repr(repr(U._element_constructor_)) - '' - """ - - def subst(m): - return ''.format(**m.groupdict()) - - return _normalize_bound_method_re.sub(subst, s) - - # Collection of fixups applied in the SageOutputChecker. Each element in this # this list a pair of functions applied to the actual test output ('g' for # "got") and the expected test output ('w' for "wanted"). The first function @@ -240,10 +187,7 @@ def subst(m): (lambda g, w: 'u"' in w or "u'" in w, lambda g, w: (g, remove_unicode_u(w))), (lambda g, w: 'L' in w or 'l' in w, - lambda g, w: (g, normalize_long_repr(w))), - (lambda g, w: ' 1: - if not err is None: + if err is not None: err = err / 2 N = ceil((R(Res).log().log() - R(d-1).log() - R(err).log())/(R(d).log())) if N < 1: @@ -2053,7 +2053,7 @@ def canonical_height(self, P, **kwds): emb = K.places(prec=prec) num_places = len(emb) + len(bad_primes) - if not error_bound is None: + if error_bound is not None: error_bound /= num_places R = RealField(prec) h = R.zero() @@ -2136,7 +2136,7 @@ def height_difference_bound(self, prec=None): 3.43967790223022 """ FF = FractionField(self.domain().base_ring()) #lift will only work over fields, so coercing into FF - if not FF in NumberFields(): + if FF not in NumberFields(): if FF == QQbar: #since this is absolute height, we can choose any number field over which the #function is defined. @@ -3948,7 +3948,7 @@ def critical_height(self, **kwds): crit_points = F.critical_points() n = len(crit_points) err_bound = kwds.get("error_bound", None) - if not err_bound is None: + if err_bound is not None: kwds["error_bound"] = err_bound / n ch = 0 for P in crit_points: @@ -5179,7 +5179,7 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', """ n = ZZ(n) - if not embedding is None: + if embedding is not None: raise ValueError('do not specify an embedding') if n < 1: raise ValueError("period must be a positive integer") @@ -5188,7 +5188,7 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point', raise NotImplementedError("not implemented for subschemes") if self.degree() <= 1: raise TypeError("must have degree at least 2") - if not type in ['point', 'cycle']: + if type not in ['point', 'cycle']: raise ValueError("type must be either point or cycle") if dom.dimension_relative() > 1 or return_polynomial: if type == 'cycle': @@ -5587,7 +5587,7 @@ def reduced_form(self, **kwds): ( Dynamical System of Projective Space of dimension 1 over Number Field in w with defining polynomial x^2 - 2 with w = 1.414213562373095? Defn: Defined on coordinates by sending (x : y) to - (x^3 : (w)*y^3) , + (x^3 : w*y^3) , [ 1 -12] [ 0 1] @@ -6280,10 +6280,10 @@ def all_periodic_points(self, **kwds): ValueError: algorithm must be 'dynatomic' or 'lifting' """ ring = kwds.pop("R", None) - if not ring is None: - #changes to the new ring + if ring is not None: + # changes to the new ring DS = self.change_ring(ring) - #ensures that the correct method is run, in case user switches to a finite field + # ensures that the correct method is run, in case user switches to a finite field return DS.all_periodic_points(**kwds) else: DS = self @@ -6326,8 +6326,8 @@ def all_periodic_points(self, **kwds): pt = [sum([P[i]*w**i for i in range(d)])] pt.insert(k,1) Q = PS(pt) - #for each periodic point get the entire cycle - if not Q in periodic_points: + # for each periodic point get the entire cycle + if Q not in periodic_points: #check periodic not preperiodic and add all points in cycle orb = set([Q]) Q2 = DS(Q) @@ -6345,7 +6345,7 @@ def all_periodic_points(self, **kwds): periods = kwds.pop("periods", None) badprimes = kwds.pop("bad_primes", None) num_cpus = kwds.pop("ncpus", ncpus()) - if not alg is None and alg not in ['dynatomic','lifting']: + if alg is not None and alg not in ['dynatomic', 'lifting']: raise ValueError("algorithm must be 'dynatomic' or 'lifting'") if not isinstance(primebound, (list, tuple)): @@ -6583,7 +6583,7 @@ def all_preperiodic_points(self, **kwds): (1/12*w + 1 : 1)] """ ring = kwds.pop("R",None) - if not ring is None: + if ring is not None: DS = self.change_ring(ring) else: DS = self @@ -6625,8 +6625,8 @@ def all_preperiodic_points(self, **kwds): pt = [sum([P[i]*w**i for i in range(d)])] pt.insert(k,1) Q = PS(pt) - #for each preperiodic point get the entire connected component - if not Q in preper: + # for each preperiodic point get the entire connected component + if Q not in preper: for t in DS.connected_rational_component(Q): preper.add(t) preper = list(preper) @@ -7349,7 +7349,7 @@ def is_polynomial(self): if self.codomain().dimension_relative() != 1: raise NotImplementedError("space must have dimension equal to 1") K = self.base_ring() - if not K in FiniteFields() and (not K in NumberFields() or not K.is_absolute()): + if K not in FiniteFields() and (K not in NumberFields() or not K.is_absolute()): raise NotImplementedError("must be over an absolute number field or finite field") if K in FiniteFields(): q = K.characteristic() @@ -7488,7 +7488,7 @@ def normal_form(self, return_conjugation=False): if self.codomain().dimension_relative() != 1: raise NotImplementedError("space must have dimension equal to 1") K = self.base_ring() - if not K in FiniteFields() and (not K in NumberFields() or not K.is_absolute()): + if K not in FiniteFields() and (K not in NumberFields() or not K.is_absolute()): raise NotImplementedError("must be over an absolute number field or finite field") if K in FiniteFields(): q = K.characteristic() @@ -8077,7 +8077,7 @@ def orbit_structure(self, P): Q.normalize_coordinates() F = copy(self) F.normalize_coordinates() - while not Q in orbit: + while Q not in orbit: orbit.append(Q) Q = F(Q) Q.normalize_coordinates() diff --git a/src/sage/dynamics/arithmetic_dynamics/wehlerK3.py b/src/sage/dynamics/arithmetic_dynamics/wehlerK3.py index c8ad02059fe..7e4ae461348 100644 --- a/src/sage/dynamics/arithmetic_dynamics/wehlerK3.py +++ b/src/sage/dynamics/arithmetic_dynamics/wehlerK3.py @@ -17,14 +17,13 @@ REFERENCES: [FH2015]_, [CS1996]_, [Weh1998]_, [Hutz2007] """ - -#***************************************************************************** +# **************************************************************************** # 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.calculus.functions import jacobian from sage.categories.fields import Fields @@ -83,7 +82,8 @@ def WehlerK3Surface(polys): elif isinstance(R, CommutativeRing): return WehlerK3Surface_ring(polys) else: - raise TypeError("R (= %s) must be a commutative ring"%R) + raise TypeError("R (= %s) must be a commutative ring" % R) + def random_WehlerK3Surface(PP): r""" @@ -267,10 +267,10 @@ def _Lcoeff(self, component, i): sage: X._Lcoeff(1, 0) x0 """ - #Error Checks for Passed in Values - if not component in [0,1]: + # Error Checks for Passed in Values + if component not in [0, 1]: raise ValueError("component can only be 1 or 0") - if not i in [0,1,2]: + if i not in [0, 1, 2]: raise ValueError("index must be 0, 1, or 2") R = self.ambient_space().coordinate_ring() return self.L.coefficient(R.gen(component*3 + i)) @@ -317,11 +317,11 @@ def _Qcoeff(self, component, i, j): sage: X._Qcoeff(1, 1, 0) x0^2 """ - #Check Errors in Passed in Values - if not component in [0,1]: + # Check Errors in Passed in Values + if component not in [0, 1]: raise ValueError("component can only be 1 or 0") - if not (i in [0,1,2]) and not (j in [0,1,2]): + if i not in [0, 1, 2] or j not in [0, 1, 2]: raise ValueError("the two indexes must be either 0, 1, or 2") R = self.ambient_space().coordinate_ring() @@ -355,11 +355,11 @@ def Gpoly(self, component, k): sage: X.Gpoly(1, 0) x0^2*x1^2 + x1^4 - x0*x1^2*x2 + x1^3*x2 + x1^2*x2^2 + x2^4 """ - #Check Errors in passed in values - if not component in [0, 1]: + # Check Errors in passed in values + if component not in [0, 1]: raise ValueError("component can only be 1 or 0") - if not k in [0,1,2]: + if k not in [0, 1, 2]: raise ValueError("index must be either 0, 1, or 2") Indices = [0, 1, 2] @@ -447,7 +447,7 @@ def Lxa(self, a): sage: X.Lxa(T[0]) y0 + y1 """ - if not a in self.ambient_space()[0]: + if a not in self.ambient_space()[0]: raise TypeError("point must be in projective space of dimension 2") AS = self.ambient_space() ASC = AS.coordinate_ring() @@ -484,7 +484,7 @@ def Qxa(self, a): sage: X.Qxa(T[0]) 5*y0^2 + 7*y0*y1 + y1^2 + 11*y1*y2 + y2^2 """ - if not a in self.ambient_space()[0]: + if a not in self.ambient_space()[0]: raise TypeError("point must be in Projective Space of dimension 2") AS = self.ambient_space() ASC = AS.coordinate_ring() @@ -525,7 +525,7 @@ def Sxa(self, a): y0 + y1, 5*y0^2 + 7*y0*y1 + y1^2 + 11*y1*y2 + y2^2 """ - if not a in self.ambient_space()[0]: + if a not in self.ambient_space()[0]: raise TypeError("point must be in projective space of dimension 2") PSY = self.ambient_space()[1] return PSY.subscheme([self.Lxa(a),self.Qxa(a)]) @@ -559,7 +559,7 @@ def Lyb(self, b): sage: X.Lyb(T[1]) x0 """ - if not b in self.ambient_space()[1]: + if b not in self.ambient_space()[1]: raise TypeError("point must be in projective space of dimension 2") AS = self.ambient_space() ASC = AS.coordinate_ring() @@ -596,7 +596,7 @@ def Qyb(self, b): sage: X.Qyb(T[1]) x0^2 + 3*x0*x1 + x1^2 """ - if not b in self.ambient_space()[1]: + if b not in self.ambient_space()[1]: raise TypeError("point must be in projective space of dimension 2") AS = self.ambient_space() ASC = AS.coordinate_ring() @@ -635,7 +635,7 @@ def Syb(self, b): x0^2 + 3*x0*x1 + x1^2 """ - if not b in self.ambient_space()[1]: + if b not in self.ambient_space()[1]: raise TypeError("point must be in projective space of dimension 2") AS = self.ambient_space() PSY = AS[0] @@ -2130,7 +2130,7 @@ def fiber(self, p, component): for x in Points: if (self.L(x) == 0) and (self.Q(x) == 0): Y = self.point(x, False) - if not Y in fiber: + if Y not in fiber: fiber.append(Y) return fiber diff --git a/src/sage/features/normaliz.py b/src/sage/features/normaliz.py new file mode 100644 index 00000000000..ceb67875b01 --- /dev/null +++ b/src/sage/features/normaliz.py @@ -0,0 +1,28 @@ +r""" +Check for pynormaliz +""" +from . import PythonModule +from .join_feature import JoinFeature + + +class PyNormaliz(JoinFeature): + r""" + A :class:`sage.features.Feature` describing the presence of the + Python package ``PyNormaliz``. + + EXAMPLES:: + + sage: from sage.features.normaliz import PyNormaliz + sage: PyNormaliz().is_present() # optional - pynormaliz + FeatureTestResult('pynormaliz', True) + """ + def __init__(self): + r""" + TESTS:: + + sage: from sage.features.normaliz import PyNormaliz + sage: isinstance(PyNormaliz(), PyNormaliz) + True + """ + JoinFeature.__init__(self, 'pynormaliz', + [PythonModule('PyNormaliz', spkg="pynormaliz")]) diff --git a/src/sage/finance/stock.py b/src/sage/finance/stock.py index ed8cb8ed90b..aa1dbb7dc99 100644 --- a/src/sage/finance/stock.py +++ b/src/sage/finance/stock.py @@ -551,9 +551,7 @@ def load_from_file(self, file): sage: with open(filename, 'w') as fobj: ....: _ = fobj.write("Date,Open,High,Low,Close,Volume\n1212405780,187.80,187.80,187.80,187.80,100\n1212407640,187.75,188.00,187.75,188.00,2000\n1212407700,188.00,188.00,188.00,188.00,1000\n1212408000,188.00,188.11,188.00,188.00,2877\n1212408060,188.00,188.00,188.00,188.00,687") sage: finance.Stock('aapl').load_from_file(filename)[:5] - doctest:warning... - DeprecationWarning: Importing finance from here is deprecated... - [ + ... 1212408060 188.00 188.00 188.00 188.00 687, 1212408000 188.00 188.11 188.00 188.00 2877, 1212407700 188.00 188.00 188.00 188.00 1000, diff --git a/src/sage/functions/gamma.py b/src/sage/functions/gamma.py index 3e58cbe5a22..3a4deef625d 100644 --- a/src/sage/functions/gamma.py +++ b/src/sage/functions/gamma.py @@ -1045,4 +1045,13 @@ def __init__(self): fricas='Beta', giac='Beta')) + def _method_arguments(self, x, y): + r""" + TESTS:: + + sage: RBF(beta(sin(3),sqrt(RBF(2).add_error(1e-8)/3))) + [7.407662 +/- 6.17e-7] + """ + return [x, y] + beta = Function_beta() diff --git a/src/sage/geometry/cone.py b/src/sage/geometry/cone.py index 4a1b567a6b0..e9cfc737b4a 100644 --- a/src/sage/geometry/cone.py +++ b/src/sage/geometry/cone.py @@ -1520,7 +1520,7 @@ def __init__(self, rays=None, lattice=None, self._ambient_ray_indices = tuple(ambient_ray_indices) superinit(ambient.rays(self._ambient_ray_indices), ambient.lattice()) - if not PPL is None: + if PPL is not None: self._PPL_C_Polyhedron = PPL def _sage_input_(self, sib, coerced): @@ -5466,7 +5466,7 @@ def random_element(self, ring=ZZ): sage: sum(K.random_element() for i in range(10)) in K.lattice() True """ - if not ring in [ZZ, QQ]: + if ring not in [ZZ, QQ]: # This cone theoretically lives in a real vector space, # but in Sage, we work over the rationals to avoid # numerical issues. Thus ``ring`` must consist of diff --git a/src/sage/geometry/cone_catalog.py b/src/sage/geometry/cone_catalog.py index 005f341e353..980d2e55c38 100644 --- a/src/sage/geometry/cone_catalog.py +++ b/src/sage/geometry/cone_catalog.py @@ -470,12 +470,12 @@ def rearrangement(p, ambient_dim=None, lattice=None): (ambient_dim, lattice) = _preprocess_args(ambient_dim, lattice) - if p < 1 or p > ambient_dim or not p in ZZ: + if p < 1 or p > ambient_dim or p not in ZZ: raise ValueError("order p=%s should be an integer between 1 " "and ambient_dim=%d, inclusive" % (p, ambient_dim)) I = matrix.identity(ZZ, ambient_dim) - M = matrix.ones(ZZ, ambient_dim) - p*I + M = matrix.ones(ZZ, ambient_dim) - p * I G = matrix.identity(ZZ, ambient_dim).rows() + M.rows() return Cone(G, lattice=lattice) diff --git a/src/sage/geometry/hasse_diagram.py b/src/sage/geometry/hasse_diagram.py index 29c46604e56..eeed5f560d9 100644 --- a/src/sage/geometry/hasse_diagram.py +++ b/src/sage/geometry/hasse_diagram.py @@ -157,7 +157,7 @@ def default_face_constructor(atoms, coatoms, **kwds): # Now G == {H[atom] : atom in minimals} for atom in minimals: # 9: for g in G: g_atoms, g_coatoms = H[atom] - if not required_atoms is None: + if required_atoms is not None: if g_atoms.isdisjoint(required_atoms): continue if (g_atoms, g_coatoms) in faces: diff --git a/src/sage/geometry/lattice_polytope.py b/src/sage/geometry/lattice_polytope.py index a02d9ed9d5a..9e663d40ea0 100644 --- a/src/sage/geometry/lattice_polytope.py +++ b/src/sage/geometry/lattice_polytope.py @@ -5520,10 +5520,10 @@ def convex_hull(points): vpoints = [] for p in points: v = vector(ZZ, p) - if not v in vpoints: + if v not in vpoints: vpoints.append(v) p0 = vpoints[0] - vpoints = [p-p0 for p in vpoints] + vpoints = [p - p0 for p in vpoints] N = ZZ**p0.degree() H = N.submodule(vpoints) if H.rank() == 0: @@ -5534,7 +5534,7 @@ def convex_hull(points): H_points = [H.coordinates(p) for p in vpoints] H_polytope = LatticePolytope(H_points) vpoints = (H_polytope.vertices() * H.basis_matrix()).rows(copy=False) - vpoints = [p+p0 for p in vpoints] + vpoints = [p + p0 for p in vpoints] return vpoints diff --git a/src/sage/geometry/newton_polygon.py b/src/sage/geometry/newton_polygon.py index 6c12c0a01d3..dd3d58f58b5 100644 --- a/src/sage/geometry/newton_polygon.py +++ b/src/sage/geometry/newton_polygon.py @@ -723,7 +723,7 @@ def _element_constructor_(self, arg, sort_slopes=True, last_slope=Infinity): return self.element_class(polyhedron, parent=self) if arg == 1: polyhedron = Polyhedron(base_ring=self.base_ring(), - vertices=[(0,0)], rays=[(0,1)]) + vertices=[(0, 0)], rays=[(0, 1)]) return self.element_class(polyhedron, parent=self) if not isinstance(arg, list): try: @@ -736,7 +736,7 @@ def _element_constructor_(self, arg, sort_slopes=True, last_slope=Infinity): x = y = 0 vertices = [(x, y)] for slope in arg: - if not slope in self.base_ring(): + if slope not in self.base_ring(): raise TypeError("argument must be a list of coordinates or a list of (rational) slopes") x += 1 y += slope diff --git a/src/sage/geometry/polyhedron/backend_cdd.py b/src/sage/geometry/polyhedron/backend_cdd.py index 3a24dca5cb2..9f1f4d86ec5 100644 --- a/src/sage/geometry/polyhedron/backend_cdd.py +++ b/src/sage/geometry/polyhedron/backend_cdd.py @@ -292,7 +292,7 @@ def parse_H_representation(intro, data): from itertools import chain # We add equations to the end of the Hrepresentation. for i in chain( - (j for j in range(len(data)) if not j in equations), + (j for j in range(len(data)) if j not in equations), equations): line = data[i] coefficients = [R(x) for x in line] diff --git a/src/sage/geometry/polyhedron/backend_normaliz.py b/src/sage/geometry/polyhedron/backend_normaliz.py index 145feafcc7e..e4c249d48a9 100644 --- a/src/sage/geometry/polyhedron/backend_normaliz.py +++ b/src/sage/geometry/polyhedron/backend_normaliz.py @@ -26,10 +26,10 @@ from sage.structure.element import Element from sage.misc.cachefunc import cached_method from sage.misc.misc_c import prod -from sage.features import PythonModule from sage.misc.lazy_import import lazy_import +import sage.features.normaliz lazy_import('PyNormaliz', ['NmzResult', 'NmzCompute', 'NmzCone', 'NmzConeCopy'], - feature=PythonModule("PyNormaliz", spkg="pynormaliz")) + feature=sage.features.normaliz.PyNormaliz()) from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index 23e68890871..c1d27faebdb 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -7225,7 +7225,7 @@ def volume(self, measure='ambient', engine='auto', **kwds): sage: Q.volume.is_in_cache() True """ - from sage.features import FeatureNotPresentError, PythonModule + from sage.features import FeatureNotPresentError if measure == 'induced_rational' and engine not in ['auto', 'latte', 'normaliz']: raise RuntimeError("the induced rational measure can only be computed with the engine set to `auto`, `latte`, or `normaliz`") if measure == 'induced_lattice' and engine not in ['auto', 'latte', 'normaliz']: @@ -7237,16 +7237,18 @@ def volume(self, measure='ambient', engine='auto', **kwds): Latte().require() engine = 'latte' except FeatureNotPresentError: + from sage.features.normaliz import PyNormaliz try: - PythonModule("PyNormaliz", spkg="pynormaliz").require() + PyNormaliz().require() engine = 'normaliz' except FeatureNotPresentError: raise RuntimeError("the induced rational measure can only be computed with the optional packages `latte_int`, or `pynormaliz`") if engine == 'auto' and measure == 'induced_lattice': # Enforce a default choice, change if a better engine is found. + from sage.features.normaliz import PyNormaliz try: - PythonModule("PyNormaliz", spkg="pynormaliz").require() + PyNormaliz().require() engine = 'normaliz' except FeatureNotPresentError: try: diff --git a/src/sage/geometry/polyhedron/base_mutable.py b/src/sage/geometry/polyhedron/base_mutable.py index d982135f1f5..6cf6a911eda 100644 --- a/src/sage/geometry/polyhedron/base_mutable.py +++ b/src/sage/geometry/polyhedron/base_mutable.py @@ -128,7 +128,7 @@ def _add_dependent_object(self, ob): sage: r Relative interior of None """ - if not ob._polyhedron is self: + if ob._polyhedron is not self: raise ValueError self._dependent_objects.append(ob) diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx index 83246cc29e5..ff697423d46 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx @@ -392,7 +392,7 @@ cdef class CombinatorialPolyhedron(SageObject): far_face = tuple(i for i in range(len(Vrep) - 1)) self._dimension = data.dim() from sage.matrix.constructor import matrix - from sage.rings.all import ZZ + from sage.rings.integer_ring import ZZ data = matrix(ZZ, data.incidence_matrix().rows() + [[ZZ.one() for _ in range(len(facets))]]) else: @@ -441,7 +441,7 @@ cdef class CombinatorialPolyhedron(SageObject): self._n_Vrepresentation = data.nrows() if not isinstance(data, Matrix_integer_dense): - from sage.rings.all import ZZ + from sage.rings.integer_ring import ZZ from sage.matrix.constructor import matrix data = matrix(ZZ, data, sparse=False) assert isinstance(data, Matrix_integer_dense), "conversion to ``Matrix_integer_dense`` didn't work" @@ -1675,7 +1675,7 @@ cdef class CombinatorialPolyhedron(SageObject): if not self._f_vector: raise ValueError("could not determine f_vector") from sage.modules.free_module_element import vector - from sage.rings.all import ZZ + from sage.rings.integer_ring import ZZ f_vector = vector(ZZ, self._f_vector) f_vector.set_immutable() return f_vector diff --git a/src/sage/geometry/polyhedron/library.py b/src/sage/geometry/polyhedron/library.py index d1f6e7333b0..c626d8f9e95 100644 --- a/src/sage/geometry/polyhedron/library.py +++ b/src/sage/geometry/polyhedron/library.py @@ -82,19 +82,17 @@ import itertools from sage.rings.integer_ring import ZZ -from sage.rings.qqbar import AA, QQbar +from sage.misc.lazy_import import lazy_import from sage.rings.rational_field import QQ -from sage.rings.real_double import RDF -from sage.rings.real_mpfr import RR -from sage.combinat.permutation import Permutations -from sage.groups.perm_gps.permgroup_named import AlternatingGroup +lazy_import('sage.combinat.permutation', 'Permutations') +lazy_import('sage.groups.perm_gps.permgroup_named', 'AlternatingGroup') from .constructor import Polyhedron from .parent import Polyhedra -from sage.graphs.digraph import DiGraph -from sage.graphs.graph import Graph -from sage.combinat.root_system.associahedron import Associahedron +lazy_import('sage.graphs.digraph', 'DiGraph') +lazy_import('sage.graphs.graph', 'Graph') +lazy_import('sage.combinat.root_system.associahedron', 'Associahedron') -def zero_sum_projection(d, base_ring=RDF): +def zero_sum_projection(d, base_ring=None): r""" Return a matrix corresponding to the projection on the orthogonal of `(1,1,\ldots,1)` in dimension `d`. @@ -126,6 +124,8 @@ def zero_sum_projection(d, base_ring=RDF): """ from sage.matrix.constructor import matrix from sage.modules.free_module_element import vector + if base_ring is None: + from sage.rings.real_double import RDF as base_ring basis = [vector(base_ring, [1]*i + [-i] + [0]*(d-i-1)) for i in range(1, d)] return matrix(base_ring, [v / v.norm() for v in basis]) @@ -190,7 +190,7 @@ def project_points(*points, **kwds): return [] base_ring = kwds.pop('base_ring', None) if base_ring is None: - base_ring = RDF + from sage.rings.real_double import RDF as base_ring from sage.modules.free_module_element import vector vecs = [vector(base_ring, p) for p in points] m = zero_sum_projection(len(vecs[0]), base_ring=base_ring) @@ -563,14 +563,15 @@ def regular_polygon(self, n, exact=True, base_ring=None, backend=None): if base_ring is None: if exact: - base_ring = AA + from sage.rings.qqbar import AA as base_ring else: - base_ring = RDF + from sage.rings.real_double import RDF as base_ring try: omega = 2*base_ring.pi() / n verts = [((i*omega).sin(), (i*omega).cos()) for i in range(n)] except AttributeError: + from sage.rings.qqbar import QQbar z = QQbar.zeta(n) verts = [(base_ring((z**k).imag()), base_ring((z**k).real())) for k in range(n)] @@ -775,7 +776,7 @@ def icosahedron(self, exact=True, base_ring=None, backend=None): base_ring = K else: if base_ring is None: - base_ring = RDF + from sage.rings.real_double import RDF as base_ring g = (1 + base_ring(5).sqrt()) / 2 r12 = base_ring.one() / 2 @@ -894,7 +895,7 @@ def small_rhombicuboctahedron(self, exact=True, base_ring=None, backend=None): base_ring = K else: if base_ring is None: - base_ring = RDF + from sage.rings.real_double import RDF as base_ring sqrt2 = base_ring(2).sqrt() one = base_ring.one() @@ -952,7 +953,7 @@ def great_rhombicuboctahedron(self, exact=True, base_ring=None, backend=None): sqrt2 = base_ring.gen() else: if base_ring is None: - base_ring = RDF + from sage.rings.real_double import RDF as base_ring sqrt2 = base_ring(2).sqrt() one = base_ring.one() @@ -1113,7 +1114,7 @@ def truncated_cube(self, exact=True, base_ring=None, backend=None): base_ring = K else: if base_ring is None: - base_ring = RDF + from sage.rings.real_double import RDF as base_ring g = base_ring(2).sqrt() - 1 v = [[a * g, b, c] for a in [-1, 1] for b in [-1, 1] for c in [-1, 1]] @@ -1373,6 +1374,7 @@ def construct_z(field): if exact and base_ring is None: # construct the exact number field + from sage.rings.qqbar import AA from sage.rings.number_field.number_field import NumberField R = QQ['x'] f = R([-1, 1, 1, 1]) @@ -1381,7 +1383,7 @@ def construct_z(field): z = base_ring.gen() else: if base_ring is None: - base_ring = RDF + from sage.rings.real_double import RDF as base_ring z = construct_z(base_ring) verts = [] @@ -1512,6 +1514,7 @@ def icosidodecahedron(self, exact=True, backend=None): if exact: return Polyhedron(vertices=verts, base_ring=K, backend=backend) else: + from sage.rings.real_mpfr import RR verts = [(RR(x), RR(y), RR(z)) for x, y, z in verts] return Polyhedron(vertices=verts, backend=backend) @@ -1575,7 +1578,7 @@ def icosidodecahedron_V2(self, exact=True, base_ring=None, backend=None): base_ring = K else: if base_ring is None: - base_ring = RDF + from sage.rings.real_double import RDF as base_ring g = (1 + base_ring(5).sqrt()) / 2 pts = [[g, 0, 0], [-g, 0, 0]] @@ -1656,7 +1659,7 @@ def truncated_dodecahedron(self, exact=True, base_ring=None, backend=None): base_ring = K else: if base_ring is None: - base_ring = RDF + from sage.rings.real_double import RDF as base_ring g = (1 + base_ring(5).sqrt()) / 2 z = base_ring.zero() @@ -1816,7 +1819,7 @@ def rhombicosidodecahedron(self, exact=True, base_ring=None, backend=None): base_ring = K else: if base_ring is None: - base_ring = RDF + from sage.rings.real_double import RDF as base_ring g = (1 + base_ring(5).sqrt()) / 2 pts = [[s1 * base_ring.one(), s2 * base_ring.one(), s3 * (g**3)] @@ -1893,7 +1896,7 @@ def truncated_icosidodecahedron(self, exact=True, base_ring=None, backend=None): base_ring = K else: if base_ring is None: - base_ring = RDF + from sage.rings.real_double import RDF as base_ring g = (1 + base_ring(5).sqrt()) / 2 pts = [[s1 * 1 / g, s2 * 1 / g, s3 * (3 + g)] @@ -1958,7 +1961,7 @@ def snub_dodecahedron(self, base_ring=None, backend=None, verbose=False): """ if base_ring is None: - base_ring = RDF + from sage.rings.real_double import RDF as base_ring phi = (1 + base_ring(5).sqrt()) / 2 xi = ((phi/2 + (phi - ZZ(5)/27).sqrt()/2)**(~ZZ(3)) + (phi/2 - (phi - ZZ(5)/27).sqrt()/2)**(~ZZ(3))) @@ -2259,8 +2262,8 @@ def six_hundred_cell(self, exact=False, backend=None): g = (1 + sqrt5) / 2 base_ring = K else: - g = (1 + RDF(5).sqrt()) / 2 - base_ring = RDF + from sage.rings.real_double import RDF as base_ring + g = (1 + base_ring(5).sqrt()) / 2 q12 = base_ring(1) / base_ring(2) z = base_ring.zero() @@ -2330,8 +2333,8 @@ def grand_antiprism(self, exact=True, backend=None, verbose=False): g = (1 + sqrt5) / 2 base_ring = K else: - g = (1 + RDF(5).sqrt()) / 2 - base_ring = RDF + from sage.rings.real_double import RDF as base_ring + g = (1 + base_ring(5).sqrt()) / 2 q12 = base_ring(1) / base_ring(2) z = base_ring.zero() @@ -2742,6 +2745,7 @@ def generalized_permutahedron(self, coxeter_type, point=None, exact=True, regula new_point.set_immutable() vertices.add(new_point) if regular: + from sage.rings.qqbar import AA from sage.matrix.constructor import matrix from sage.modules.free_module_element import vector # This transformation fixes the first root and adjust the other @@ -2766,6 +2770,7 @@ def generalized_permutahedron(self, coxeter_type, point=None, exact=True, regula vertices = [transf * v.change_ring(AA) for v in vertices] br = AA if not exact: + from sage.rings.real_double import RDF vertices = [v.change_ring(RDF) for v in vertices] br = RDF return Polyhedron(vertices=vertices, backend=backend, base_ring=br) @@ -3416,9 +3421,12 @@ def parallelotope(self, generators, backend=None): # -------------------------------------------------------- associahedron = staticmethod(Associahedron) - flow_polytope = staticmethod(DiGraph.flow_polytope) - edge_polytope = staticmethod(Graph.edge_polytope) - symmetric_edge_polytope = staticmethod(Graph.symmetric_edge_polytope) + try: + flow_polytope = staticmethod(DiGraph.flow_polytope) + edge_polytope = staticmethod(Graph.edge_polytope) + symmetric_edge_polytope = staticmethod(Graph.symmetric_edge_polytope) + except ImportError: + pass polytopes = Polytopes() diff --git a/src/sage/geometry/toric_lattice.py b/src/sage/geometry/toric_lattice.py index 87b32ec2fca..3584f53f96e 100644 --- a/src/sage/geometry/toric_lattice.py +++ b/src/sage/geometry/toric_lattice.py @@ -1170,7 +1170,7 @@ def dual(self): 2-d lattice, quotient of 3-d lattice M by Sublattice """ if "_dual" not in self.__dict__: - if not self is self.saturation(): + if self is not self.saturation(): raise ValueError("only dual lattices of saturated sublattices " "can be constructed! Got %s." % self) self._dual = (self.ambient_module().dual() / diff --git a/src/sage/geometry/triangulation/element.py b/src/sage/geometry/triangulation/element.py index c9a43dca642..1bd10eede31 100644 --- a/src/sage/geometry/triangulation/element.py +++ b/src/sage/geometry/triangulation/element.py @@ -92,7 +92,7 @@ def triangulation_render_2d(triangulation, **kwds): all_lines.append(l) else: interior_lines.append(l) - exterior_lines = [ l for l in all_lines if not l in interior_lines ] + exterior_lines = [l for l in all_lines if l not in interior_lines] plot_interior_lines = sum([ line2d([ coord[l[0]], coord[l[1]] ], zorder=1, rgbcolor=(0,1,0), **kwds) @@ -160,7 +160,7 @@ def triangulation_render_3d(triangulation, **kwds): all_lines.append(l) else: interior_lines.append(l) - exterior_lines = [ l for l in all_lines if not l in interior_lines ] + exterior_lines = [l for l in all_lines if l not in interior_lines] from sage.plot.plot3d.texture import Texture line_int = Texture(color='darkblue', ambient=1, diffuse=0) @@ -190,7 +190,7 @@ def triangulation_render_3d(triangulation, **kwds): all_triangs.append(l) else: interior_triangs.append(l) - exterior_triangs = [ l for l in all_triangs if not l in interior_triangs ] + exterior_triangs = [l for l in all_triangs if l not in interior_triangs] plot_interior_triangs = \ sum([ polygon3d([coord[t[0]], coord[t[1]], coord[t[2]]], diff --git a/src/sage/geometry/triangulation/point_configuration.py b/src/sage/geometry/triangulation/point_configuration.py index 3d900609d4a..b062c309a6d 100644 --- a/src/sage/geometry/triangulation/point_configuration.py +++ b/src/sage/geometry/triangulation/point_configuration.py @@ -1273,8 +1273,8 @@ def exclude_points(self, point_idx_list): sage: p.exclude_points( p.face_interior(codim=1) ).points() (P(-1, 0), P(0, 0), P(1, -1), P(1, 1)) """ - points = [ self.point(i) for i in range(self.n_points()) - if not i in point_idx_list ] + points = [self.point(i) for i in range(self.n_points()) + if i not in point_idx_list] return PointConfiguration(points, projective=False, connected=self._connected, @@ -1282,7 +1282,6 @@ def exclude_points(self, point_idx_list): regular=self._regular, star=self._star) - def volume(self, simplex=None): """ Find n! times the n-volume of a simplex of dimension n. diff --git a/src/sage/graphs/base/c_graph.pyx b/src/sage/graphs/base/c_graph.pyx index 515ca3076ff..8901ddbc536 100644 --- a/src/sage/graphs/base/c_graph.pyx +++ b/src/sage/graphs/base/c_graph.pyx @@ -1597,7 +1597,7 @@ cdef class CGraphBackend(GenericGraphBackend): The bug in :trac:`14967` and :trac:`14853` is fixed:: sage: DiGraph({0: {}, 1/2: {}}) - Multi-digraph on 2 vertices + Digraph on 2 vertices sage: A = Set([RDF.random_element(min=0, max=10) for k in range(10)]) sage: G = Graph() sage: G.add_vertices(A) diff --git a/src/sage/graphs/bipartite_graph.py b/src/sage/graphs/bipartite_graph.py index e95565a9e1b..b782aa989ed 100644 --- a/src/sage/graphs/bipartite_graph.py +++ b/src/sage/graphs/bipartite_graph.py @@ -1757,7 +1757,7 @@ def vertex_cover(self, algorithm="Konig", value_only=False, Y = set() for u in X: for v in self.neighbors(u): - if not v in Z and not M.has_edge(u, v): + if v not in Z and not M.has_edge(u, v): Y.add(v) Z.update(Y) @@ -1765,7 +1765,7 @@ def vertex_cover(self, algorithm="Konig", value_only=False, X = set() for u in Y: for v in M.neighbor_iterator(u): - if not v in Z: + if v not in Z: X.add(v) Z.update(X) diff --git a/src/sage/graphs/digraph_generators.py b/src/sage/graphs/digraph_generators.py index 921aa754bb5..45bf0bb7f5b 100644 --- a/src/sage/graphs/digraph_generators.py +++ b/src/sage/graphs/digraph_generators.py @@ -763,7 +763,7 @@ def Circulant(self, n, integers): # Bad input and loops loops = False for i in integers: - if not i in ZZ: + if i not in ZZ: raise ValueError("the list must contain only integers") if not i % n: loops = True @@ -1456,7 +1456,7 @@ def RandomDirectedGNM(self, n, m, loops=False): u = int(rand.random() * n) v = int(rand.random() * n) - if (u != v or loops) and (not v in adj[u]): + if (u != v or loops) and (v not in adj[u]): adj[u][v] = 1 m -= 1 if not is_dense: diff --git a/src/sage/graphs/generators/chessboard.py b/src/sage/graphs/generators/chessboard.py index 9a10f7e8ada..50f82d47dd1 100644 --- a/src/sage/graphs/generators/chessboard.py +++ b/src/sage/graphs/generators/chessboard.py @@ -154,14 +154,14 @@ def ChessboardGraphGenerator(dim_list, rook=True, rook_radius=None, if rook: if rook_radius is None: rook_radius = max(dim) - elif not rook_radius in ZZ or rook_radius < 1: + elif rook_radius not in ZZ or rook_radius < 1: raise ValueError('the rook_radius must be either None or have an integer value >= 1') if bishop: if bishop_radius is None: bishop_radius = max(dim) - elif not bishop_radius in ZZ or bishop_radius < 1: + elif bishop_radius not in ZZ or bishop_radius < 1: raise ValueError('the bishop_radius must be either None or have an integer value >= 1') - if knight and ( not knight_x in ZZ or not knight_y in ZZ or knight_x < 1 or knight_y < 1 ): + if knight and (knight_x not in ZZ or knight_y not in ZZ or knight_x < 1 or knight_y < 1): raise ValueError('the knight_x and knight_y values must be integers of value >= 1') # We build the set of vertices of the d-dimensional chessboard diff --git a/src/sage/graphs/generators/families.py b/src/sage/graphs/generators/families.py index 12975b1d9f0..9bf3508481d 100644 --- a/src/sage/graphs/generators/families.py +++ b/src/sage/graphs/generators/families.py @@ -2821,7 +2821,7 @@ def HanoiTowerGraph(pegs, disks, labels=True, positions=True): """ # sanitize input - from sage.rings.all import Integer + from sage.rings.integer import Integer pegs = Integer(pegs) if pegs < 2: raise ValueError("Pegs for Tower of Hanoi graph should be two or greater (not %d)" % pegs) diff --git a/src/sage/graphs/generators/smallgraphs.py b/src/sage/graphs/generators/smallgraphs.py index 072812c75c4..5a87ae14cf5 100644 --- a/src/sage/graphs/generators/smallgraphs.py +++ b/src/sage/graphs/generators/smallgraphs.py @@ -3571,7 +3571,7 @@ def McLaughlinGraph(): g = Graph() for b in B: for x in range(1, 23): - if not x in b: + if x not in b: g.add_edge(b, x) for b in C: diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 0df574c5721..93264c6a4fd 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -1777,13 +1777,13 @@ def to_dictionary(self, edge_labels=False, multiple_edges=False): if self.is_directed(): for u, v, l in self.edge_iterator(): - if not v in d[u]: + if v not in d[u]: d[u][v] = [] d[u][v].append(l) else: for u, v, l in self.edge_iterator(): - if not v in d[u]: + if v not in d[u]: d[u][v] = [] d[v][u] = [] @@ -3105,7 +3105,7 @@ def allow_multiple_edges(self, new, check=True, keep_label='any'): sage: D.edges() [(0, 1, None)] """ - if not keep_label in ['any', 'min', 'max']: + if keep_label not in ['any', 'min', 'max']: raise ValueError("variable keep_label must be 'any', 'min', or 'max'") # TODO: this should be much faster for c_graphs, but for now we just do this @@ -4686,7 +4686,7 @@ def cycle_basis(self, output='vertex'): [(4, 3, 'e'), (3, 2, 'b'), (2, 1, 'a'), (1, 4, 'f')]] """ - if not output in ['vertex', 'edge']: + if output not in ['vertex', 'edge']: raise ValueError('output must be either vertex or edge') if self.is_directed(): @@ -7673,7 +7673,7 @@ def hamiltonian_path(self, s=None, t=None, use_edge_labels=False, if use_edge_labels or algorithm is None: # We force the algorithm to 'MILP' algorithm = 'MILP' - elif not algorithm in ['MILP', 'backtrack']: + elif algorithm not in ['MILP', 'backtrack']: raise ValueError("algorithm must be either 'backtrack' or 'MILP'") if self.order() < 2: @@ -7704,7 +7704,7 @@ def hamiltonian_path(self, s=None, t=None, use_edge_labels=False, elif len(zeros) == 1: if new_s is None: new_s = zeros.pop() - elif not new_s in zeros: + elif new_s not in zeros: return (0, None) if use_edge_labels else None zeros = [u for u in g if not g.out_degree(u)] @@ -7713,7 +7713,7 @@ def hamiltonian_path(self, s=None, t=None, use_edge_labels=False, elif len(zeros) == 1: if new_t is None: new_t = zeros.pop() - elif not new_t in zeros: + elif new_t not in zeros: return (0, None) if use_edge_labels else None else: @@ -7725,28 +7725,27 @@ def hamiltonian_path(self, s=None, t=None, use_edge_labels=False, return (0, None) if use_edge_labels else None elif len(ones) == 2: - if not new_s is None and not new_s in ones: + if new_s is not None and new_s not in ones: return (0, None) if use_edge_labels else None - if not new_t is None and not new_t in ones: + if new_t is not None and new_t not in ones: return (0, None) if use_edge_labels else None # Set new_s and new_t if possible if new_s is None and new_t is None: new_s,new_t = ones - elif not new_s is None and new_t is None: + elif new_s is not None and new_t is None: new_t = ones[1] if new_s == ones[0] else ones[0] - elif new_s is None and not new_t is None: + elif new_s is None and new_t is not None: new_s = ones[1] if new_t == ones[0] else ones[0] elif len(ones) == 1: - if not new_s is None and not new_t is None and not (new_s in ones or new_t in ones): + if new_s is not None and new_t is not None and not (new_s in ones or new_t in ones): return (0, None) if use_edge_labels else None - elif new_s is None and (new_t is None or (not new_t is None and not new_t in ones)): + elif new_s is None and (new_t is None or (new_t is not None and new_t not in ones)): new_s = ones.pop() - elif new_t is None and not new_s is None and not new_s in ones: + elif new_t is None and new_s is not None and new_s not in ones: new_t = ones.pop() - if not use_edge_labels and algorithm == "backtrack": path = g.longest_path(s=new_s, t=new_t, algorithm="backtrack") return path if path.order() == g.order() else None @@ -10918,7 +10917,8 @@ def merge_vertices(self, vertices): if self.is_directed(): out_edges = self.edge_boundary(vertices) - in_edges = self.edge_boundary([v for v in self if not v in vertices]) + in_edges = self.edge_boundary([v for v in self + if v not in vertices]) self.delete_vertices(vertices[1:]) self.add_edges((u, v0, l) for (u0, v0, l) in out_edges if u0 != u) self.add_edges((v0, u, l) for (v0, u0, l) in in_edges if u0 != u) @@ -13619,7 +13619,7 @@ def is_chordal(self, certificate=False, algorithm="B"): nb1 = [u for u in g.neighbor_iterator(v) if pos_in_peo[u] > pos_in_peo[v]] for xi in nb1: for yi in nb1: - if not yi in neighbors_subsets[xi]: + if yi not in neighbors_subsets[xi]: new_tup = (pos_in_peo[xi], pos_in_peo[yi]) if max_tup < new_tup: max_tup = new_tup @@ -13645,7 +13645,7 @@ def is_chordal(self, certificate=False, algorithm="B"): # ---------------- # 1- The graph is not chordal - if not hole is None: + if hole is not None: # There was a bug there once, so it's better to check the # answer is valid, especially when it is so cheap ;-) @@ -14478,7 +14478,7 @@ def clustering_average(self, implementation=None): else: implementation = 'sparse_copy' - if not implementation in ['networkx', 'boost', 'dense_copy', 'sparse_copy']: + if implementation not in ['networkx', 'boost', 'dense_copy', 'sparse_copy']: raise ValueError("the implementation can only be 'networkx', " "'boost', 'sparse_copy', 'dense_copy' or None") @@ -14602,7 +14602,7 @@ def clustering_coeff(self, else: implementation = 'sparse_copy' - if not implementation in ['networkx', 'boost', 'dense_copy', 'sparse_copy']: + if implementation not in ['networkx', 'boost', 'dense_copy', 'sparse_copy']: raise ValueError("the implementation can only be 'networkx', " "'boost', 'sparse_copy', 'dense_copy' or None") @@ -19105,7 +19105,7 @@ def layout_extend_randomly(self, pos, dim=2): # Check each vertex position is in pos, add position randomly within the # plot range if none is defined for v in self: - if not v in pos: + if v not in pos: pos[v] = [xmin + dx * random(), ymin + dy * random()] return pos diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index 75fb6241f23..fe601ddeea9 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -1530,7 +1530,7 @@ def is_tree(self, certificate=False, output='vertex'): sage: G.is_tree(certificate=True, output='edge') (False, [(0, 0, None)]) """ - if not output in ['vertex', 'edge']: + if output not in ['vertex', 'edge']: raise ValueError('output must be either vertex or edge') if not self.order() or not self.is_connected(): @@ -6499,8 +6499,7 @@ def independent_set(self, algorithm="Cliquer", value_only=False, reduction_rules return self.order() - my_cover else: my_cover = set(my_cover) - return [u for u in self if not u in my_cover] - + return [u for u in self if u not in my_cover] @doc_index("Algorithmically hard stuff") @rename_keyword(deprecation=32238, verbosity='verbose') @@ -6757,7 +6756,7 @@ def vertex_cover(self, algorithm="Cliquer", value_only=False, if value_only: size_cover_g = g.order() - len(independent) else: - cover_g = set(uu for uu in g if not uu in independent) + cover_g = set(uu for uu in g if uu not in independent) elif algorithm == "MILP": diff --git a/src/sage/graphs/graph_database.py b/src/sage/graphs/graph_database.py index c7c6fe18cca..fc114c0afec 100644 --- a/src/sage/graphs/graph_database.py +++ b/src/sage/graphs/graph_database.py @@ -430,7 +430,7 @@ class located in :mod:`sage.databases.sql_db` to make the query for key in kwds: # check validity - if not key in valid_kwds: + if key not in valid_kwds: raise KeyError('%s is not a valid key for this database.'%str(key)) # designate a query_dict diff --git a/src/sage/graphs/graph_generators.py b/src/sage/graphs/graph_generators.py index 17d65711459..307c056744f 100644 --- a/src/sage/graphs/graph_generators.py +++ b/src/sage/graphs/graph_generators.py @@ -814,7 +814,7 @@ def extra_property(x): yield copyfun(gg) if copy else gg elif augment == 'edges': if vertices is None: - from sage.rings.all import Integer + from sage.rings.integer import Integer vertices = Integer(0) while True: for g in self(vertices, loops=loops, sparse=sparse): diff --git a/src/sage/graphs/graph_input.py b/src/sage/graphs/graph_input.py index 35caebb8c25..52f61775e7b 100644 --- a/src/sage/graphs/graph_input.py +++ b/src/sage/graphs/graph_input.py @@ -453,6 +453,13 @@ def from_dict_of_dicts(G, M, loops=False, multiedges=False, weighted=False, conv sage: from_dict_of_dicts(g, graphs.PetersenGraph().to_dictionary(edge_labels=True)) sage: g.is_isomorphic(graphs.PetersenGraph()) True + + TESTS: + + :trac:`32831` is fixed:: + + sage: DiGraph({0: {}, 1: {}, 2: {}, 3: {}, 4: {}}) + Digraph on 5 vertices """ if any(not isinstance(M[u], dict) for u in M): raise ValueError("input dict must be a consistent format") @@ -467,6 +474,7 @@ def from_dict_of_dicts(G, M, loops=False, multiedges=False, weighted=False, conv loops = False if weighted is None: G._weighted = False + input_multiedges = multiedges if multiedges is not False: if not all(isinstance(M[u][v], list) for u in M for v in M[u]): if multiedges: @@ -501,6 +509,8 @@ def from_dict_of_dicts(G, M, loops=False, multiedges=False, weighted=False, conv for u in M: for v in M[u]: G._backend.add_edge(u, v, relabel(M[u][v]), is_directed) + if not G.size() and input_multiedges is not True: + G.allow_multiple_edges(False, check=False) def from_dict_of_lists(G, D, loops=False, multiedges=False, weighted=False): r""" diff --git a/src/sage/graphs/isgci.py b/src/sage/graphs/isgci.py index 4ddd64d2171..99f90f76179 100644 --- a/src/sage/graphs/isgci.py +++ b/src/sage/graphs/isgci.py @@ -456,7 +456,7 @@ class represented by ``gc_id`` ?* self._name = name self._gc_id = gc_id - if not recognition_function is None: + if recognition_function is not None: self._recognition_function = recognition_function def _repr_(self): diff --git a/src/sage/graphs/pq_trees.py b/src/sage/graphs/pq_trees.py index 7dfbe72349f..6a36cfa8886 100644 --- a/src/sage/graphs/pq_trees.py +++ b/src/sage/graphs/pq_trees.py @@ -220,7 +220,7 @@ def __init__(self, seq): if isinstance(e, list): e = Set(e) - if not e in self._children: + if e not in self._children: self._children.append(e) def reverse(self): diff --git a/src/sage/graphs/spanning_tree.pyx b/src/sage/graphs/spanning_tree.pyx index 7fdfc1d50c5..7e13bdf1a6f 100644 --- a/src/sage/graphs/spanning_tree.pyx +++ b/src/sage/graphs/spanning_tree.pyx @@ -796,7 +796,7 @@ cpdef boruvka(G, wfunction=None, bint check=False, bint by_weight=True): return T -def random_spanning_tree(self, output_as_graph=False): +def random_spanning_tree(G, output_as_graph=False, by_weight=False, weight_function=None, check_weight=True): r""" Return a random spanning tree of the graph. @@ -808,11 +808,30 @@ def random_spanning_tree(self, output_as_graph=False): edge `(i, j)` to the spanning tree, where `i` is the previous vertex in the random walk. + When ``by_weight`` is ``True`` or a weight function is given, the selection + of the neighbor is done proportionaly to the edge weights. + INPUT: + - ``G`` -- an undirected graph + - ``output_as_graph`` -- boolean (default: ``False``); whether to return a list of edges or a graph + - ``by_weight`` -- boolean (default: ``False``); if ``True``, the edges in + the graph are weighted, otherwise all edges have weight 1 + + - ``weight_function`` -- function (default: ``None``); a function that takes + as input an edge ``(u, v, l)`` and outputs its weight. If not ``None``, + ``by_weight`` is automatically set to ``True``. If ``None`` and + ``by_weight`` is ``True``, we use the edge label ``l`` , if ``l`` is not + ``None``, else ``1`` as a weight. The ``weight_function`` can be used to + transform the label into a weight (note that, if the weight returned is + not convertible to a float, an error is raised) + + - ``check_weight`` -- boolean (default: ``True``); whether to check that + the ``weight_function`` outputs a number for each edge. + .. SEEALSO:: :meth:`~sage.graphs.generic_graph.GenericGraph.spanning_trees_count` @@ -846,6 +865,35 @@ def random_spanning_tree(self, output_as_graph=False): sage: T.set_pos(pos) sage: T.show(vertex_labels=False) + We can also use edge weights to change the probability of returning a + spanning tree:: + + sage: def foo(G, k): + ....: S = set() + ....: for _ in range(k): + ....: E = G.random_spanning_tree(by_weight=True) + ....: S.add(Graph(E).graph6_string()) + ....: return S + sage: K3 = graphs.CompleteGraph(3) + sage: for u, v in K3.edges(labels=False): + ....: K3.set_edge_label(u, v, randint(1, 2)) + sage: foo(K3, 100) == {'BW', 'Bg', 'Bo'} # random + True + sage: K4 = graphs.CompleteGraph(4) + sage: for u, v in K4.edges(labels=False): + ....: K4.set_edge_label(u, v, randint(1, 2)) + sage: print(len(foo(K4, 100))) # random + 16 + + Check that the spanning tree returned when using weights is a tree:: + + sage: G = graphs.RandomBarabasiAlbert(50, 2) + sage: for u, v in G.edge_iterator(labels=False): + ....: G.set_edge_label(u, v, randint(1, 10)) + sage: T = G.random_spanning_tree(by_weight=True, output_as_graph=True) + sage: T.is_tree() + True + TESTS:: sage: G = Graph() @@ -861,21 +909,43 @@ def random_spanning_tree(self, output_as_graph=False): ValueError: works only for non-empty connected graphs """ from sage.misc.prandom import randint + from sage.misc.prandom import random from sage.graphs.graph import Graph - cdef int N = self.order() + cdef int N = G.order() - if not N or not self.is_connected(): + if not N or not G.is_connected(): raise ValueError('works only for non-empty connected graphs') - s = next(self.vertex_iterator()) + if G.order() == G.size() + 1: + # G is a tree + if output_as_graph: + return G.copy() + return list(G.edge_iterator(label=False)) + + by_weight, weight_function = G._get_weight_function(by_weight=by_weight, + weight_function=weight_function, + check_weight=check_weight) + + if by_weight: + def next_neighbor(s): + p = random() * sum(weight_function(e) + for e in G.edge_iterator(s, sort_vertices=False)) + for e in G.edge_iterator(s, sort_vertices=False): + p -= weight_function(e) + if p <= 0: + break + return e[1] if e[0] == s else e[0] + else: + def next_neighbor(s): + return G.neighbors(s)[randint(0, G.degree(s) - 1)] + + s = next(G.vertex_iterator()) cdef set found = set([s]) cdef int found_nr = 1 cdef list tree_edges = [] - cdef list neighbors while found_nr < N: - neighbors = self.neighbors(s) - new_s = neighbors[randint(0, len(neighbors) - 1)] + new_s = next_neighbor(s) if new_s not in found: found.add(new_s) found_nr += 1 diff --git a/src/sage/groups/braid.py b/src/sage/groups/braid.py index a6e53f2e1a1..688ec825893 100644 --- a/src/sage/groups/braid.py +++ b/src/sage/groups/braid.py @@ -2141,8 +2141,10 @@ def eps(self, N): in parallel. """ def eps_monom(q_tuple): + r""" + Evaluate the map `\mathcal{E}_N` for a single mononial. + """ q = self.q - r"""Evaluate the map $\mathcal{E}_N$ for a single mononial.""" ret_q = q**sum((N - 1 - q_tuple[3*i + 2])*q_tuple[3*i + 1] for i in range(self._minus_begin//3)) ret_q *= q**sum((N - 1)*(-q_tuple[rj]) diff --git a/src/sage/groups/class_function.py b/src/sage/groups/class_function.py index 60d0318ac97..94abb43d5f6 100644 --- a/src/sage/groups/class_function.py +++ b/src/sage/groups/class_function.py @@ -26,7 +26,7 @@ from sage.structure.sage_object import SageObject from sage.structure.richcmp import richcmp, richcmp_method from sage.interfaces.gap import gap -from sage.rings.all import Integer +from sage.rings.integer import Integer from sage.rings.all import CyclotomicField from sage.libs.gap.element import GapElement from sage.libs.gap.libgap import libgap diff --git a/src/sage/groups/cubic_braid.py b/src/sage/groups/cubic_braid.py index 2d2b5f393be..db110b57e95 100644 --- a/src/sage/groups/cubic_braid.py +++ b/src/sage/groups/cubic_braid.py @@ -76,7 +76,7 @@ # https://www.gnu.org/licenses/ # **************************************************************************** - +from sage.categories.groups import Groups from sage.misc.cachefunc import cached_method from sage.libs.gap.element import GapElement from sage.groups.free_group import FreeGroup @@ -102,12 +102,12 @@ def _reduce_tietze(tietze_list): easily possible using the second braid relation and degree reduction. EXAMPLES:: - + sage: from sage.groups.cubic_braid import _reduce_tietze sage: _reduce_tietze((2, 2, -3, 5, 3, 1, 1, 5)) [-2, -5, -1] """ - def eleminate_item(tietze_list): + def eliminate_item(tietze_list): """ this sub method searches for an item in the Tietze expression such that it together with the first entry gives a pair which can be @@ -118,14 +118,14 @@ def eleminate_item(tietze_list): l = len(tietze_list) if l < 2: return None - first = tietze_list[0] + first = tietze_list[0] second = None for i in range(1,l): if tietze_list[i] in (first, -first): if i == 1: second = tietze_list[i] break - if min(abs(abs(tietze_list[j])-abs(first)) for j in range(1, i)) > 1: + if all(abs(abs(tietze_list[j])-abs(first)) > 1 for j in range(1, i)): # the entry on position i can be moved right to the first entry # by the second braid relation second = tietze_list[i] @@ -143,7 +143,7 @@ def eleminate_item(tietze_list): l = len(tietze_list) for i in range(l): end = tietze_list[i:l] - tietze_list_red = eleminate_item(end) + tietze_list_red = eliminate_item(end) if tietze_list_red is not None: start = tietze_list[:i] return start + _reduce_tietze(tietze_list_red) @@ -788,7 +788,11 @@ def __init__(self, names, cbg_type=None): elif cbg_type == CubicBraidGroup.type.AssionS: rels.append(b[i+2]*b[i]*t[i+1]*b[i]*ti[i+1]*t[i+2]*t[i+1]*b[i]*ti[i+1]*ti[i+2]) - FinitelyPresentedGroup.__init__(self, free_group, tuple(rels)) + if self._nstrands <= 5 or cbg_type != CubicBraidGroup.type.Coxeter: + cat = Groups().Finite() + else: + cat = Groups().Infinite() + FinitelyPresentedGroup.__init__(self, free_group, tuple(rels), category=cat) self._free_group = free_group # ------------------------------------------------------------------------------------------------ @@ -1458,16 +1462,14 @@ def as_matrix_group(self, root_bur=None, domain=None, characteristic=None, var=' ... ValueError: Burau representation does not factor through the relations """ - # ------------------------------------------------------------------------------- + # ------------------------------------------------------------------ # define matrix group by generators using the Burau representation - # ------------------------------------------------------------------------------- - + # ------------------------------------------------------------------ unitary = False if isinstance(reduced, str): if reduced == 'unitary': unitary = True - - gen_list =[] + gen_list = [] for braid_gen in self.gens(): bur_mat = braid_gen.burau_matrix(root_bur=root_bur, domain=domain, characteristic=characteristic, var=var, reduced=reduced) @@ -1482,7 +1484,7 @@ def as_matrix_group(self, root_bur=None, domain=None, characteristic=None, var=' if unitary and herm_form.is_singular(): unitary = False # since a degenerated hermitian form doesn't define a unitary group if self._classical_invariant_form is None: - self._classical_invariant_form = herm_form + self._classical_invariant_form = herm_form if unitary: from sage.rings.finite_rings.finite_field_base import is_FiniteField @@ -1496,7 +1498,7 @@ def as_matrix_group(self, root_bur=None, domain=None, characteristic=None, var=' matrix_group = base_group.subgroup(gen_list) else: from sage.groups.matrix_gps.finitely_generated import MatrixGroup - matrix_group = MatrixGroup(gen_list) + matrix_group = MatrixGroup(gen_list, category=self.category()) # ------------------------------------------------------------------------------- # check if there is a well defined group homomorphism to matrix_group @@ -1505,7 +1507,7 @@ def as_matrix_group(self, root_bur=None, domain=None, characteristic=None, var=' # here. # ------------------------------------------------------------------------------- hom_to_mat = self.hom(matrix_group.gens(), check=False) - if not all( hom_to_mat(rel).is_one() for rel in self.relations()): + if not all(hom_to_mat(rel).is_one() for rel in self.relations()): raise ValueError("Burau representation does not factor through the relations") matrix_group.register_conversion(hom_to_mat) return matrix_group @@ -1539,7 +1541,6 @@ def as_permutation_group(self, use_classical=True): sage: C3 = CubicBraidGroup(3) sage: PC3 = C3.as_permutation_group() sage: C3.is_isomorphic(PC3) - #I Forcing finiteness test True sage: PC3.degree() 8 @@ -1937,7 +1938,6 @@ def is_finite(self): from sage.rings.infinity import infinity return not self.order() is infinity - # ---------------------------------------------------------------------------------- # creating a CubicBraidGroup as subgroup of self on less strands # ---------------------------------------------------------------------------------- diff --git a/src/sage/groups/finitely_presented_named.py b/src/sage/groups/finitely_presented_named.py index fbaf8e29357..c9a534a75be 100644 --- a/src/sage/groups/finitely_presented_named.py +++ b/src/sage/groups/finitely_presented_named.py @@ -59,7 +59,7 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.rings.all import Integer +from sage.rings.integer import Integer from sage.groups.free_group import FreeGroup from sage.groups.finitely_presented import FinitelyPresentedGroup from sage.libs.gap.libgap import libgap diff --git a/src/sage/groups/libgap_mixin.py b/src/sage/groups/libgap_mixin.py index 16417aea5e0..e72b5a7aeb3 100644 --- a/src/sage/groups/libgap_mixin.py +++ b/src/sage/groups/libgap_mixin.py @@ -558,7 +558,7 @@ def character_table(self): #how gap handles these groups. G = self._gap_() cl = self.conjugacy_classes() - from sage.rings.all import Integer + from sage.rings.integer import Integer n = Integer(len(cl)) irrG = G.Irr() ct = [[irrG[i][j] for j in range(n)] for i in range(n)] diff --git a/src/sage/groups/matrix_gps/finitely_generated.py b/src/sage/groups/matrix_gps/finitely_generated.py index cef211ea07c..a1950685df7 100644 --- a/src/sage/groups/matrix_gps/finitely_generated.py +++ b/src/sage/groups/matrix_gps/finitely_generated.py @@ -294,12 +294,15 @@ def MatrixGroup(*gens, **kwds): base_ring = MS.base_ring() degree = ZZ(MS.ncols()) # == MS.nrows() from sage.libs.gap.libgap import libgap + category = kwds.get('category', None) try: gap_gens = [libgap(matrix_gen) for matrix_gen in gens] gap_group = libgap.Group(gap_gens) - return FinitelyGeneratedMatrixGroup_gap(degree, base_ring, gap_group) + return FinitelyGeneratedMatrixGroup_gap(degree, base_ring, gap_group, + category=category) except (TypeError, ValueError): - return FinitelyGeneratedMatrixGroup_generic(degree, base_ring, gens) + return FinitelyGeneratedMatrixGroup_generic(degree, base_ring, gens, + category=category) ################################################################### # @@ -1152,7 +1155,7 @@ def reynolds_operator(self, poly, chi=None): sage: R. = K[] sage: f = -K.gen()*x sage: G.reynolds_operator(f) - (t)*x + (t)*y + t*x + t*y """ if poly.parent().ngens() != self.degree(): raise TypeError("number of variables in polynomial must match size of matrices") diff --git a/src/sage/groups/matrix_gps/matrix_group.py b/src/sage/groups/matrix_gps/matrix_group.py index e82abf76246..f2ce966c9ed 100644 --- a/src/sage/groups/matrix_gps/matrix_group.py +++ b/src/sage/groups/matrix_gps/matrix_group.py @@ -212,7 +212,24 @@ def subgroup(self, generators, check=True): sage: TestSuite(G).run() sage: TestSuite(S).run() + + sage: W = CoxeterGroup(['I',7]) + sage: s = W.simple_reflections() + sage: G = W.subgroup([s[1]]) + sage: G.category() + Category of finite groups + + sage: W = WeylGroup(['A',2]) + sage: s = W.simple_reflections() + sage: G = W.subgroup([s[1]]) + sage: G.category() + Category of finite groups """ + try: + test = self.is_finite() + except NotImplementedError: + test = self in Groups().Finite() + cat = Groups().Finite() if test else Groups() # this method enlarges the method with same name of # ParentLibGAP to cases where the ambient group is not # inherited from ParentLibGAP. @@ -224,7 +241,7 @@ def subgroup(self, generators, check=True): raise ValueError("generator %s is not in the group" % (g)) from sage.groups.matrix_gps.finitely_generated import MatrixGroup - subgroup = MatrixGroup(generators, check=check) + subgroup = MatrixGroup(generators, check=check, category=cat) subgroup._ambient = self return subgroup @@ -409,12 +426,11 @@ def __init__(self, degree, base_ring, category=None): if self._deg <= 0: raise ValueError('the degree must be at least 1') - if category is None: - category = Groups() + cat = Groups() if category is None else category if base_ring in Rings().Finite(): - category = category.Finite() + cat = cat.Finite() super(MatrixGroup_generic, self).__init__(base=base_ring, - category=category) + category=cat) def degree(self): """ @@ -759,8 +775,12 @@ def _subgroup_constructor(self, libgap_subgroup): sage: G.ambient() is SL2Z True """ + cat = Groups() + if self in Groups().Finite(): + cat = cat.Finite() from sage.groups.matrix_gps.finitely_generated import FinitelyGeneratedMatrixGroup_gap return FinitelyGeneratedMatrixGroup_gap(self.degree(), self.base_ring(), - libgap_subgroup, ambient=self) + libgap_subgroup, ambient=self, + category=cat) from sage.groups.generic import structure_description diff --git a/src/sage/groups/matrix_gps/unitary.py b/src/sage/groups/matrix_gps/unitary.py index cefb9b5223b..c144e3b701b 100644 --- a/src/sage/groups/matrix_gps/unitary.py +++ b/src/sage/groups/matrix_gps/unitary.py @@ -49,7 +49,7 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.rings.all import GF +from sage.rings.finite_rings.finite_field_constructor import GF from sage.rings.finite_rings.finite_field_base import is_FiniteField from sage.misc.latex import latex from sage.misc.cachefunc import cached_method diff --git a/src/sage/groups/pari_group.py b/src/sage/groups/pari_group.py index 128fc1b217d..027bb04b321 100644 --- a/src/sage/groups/pari_group.py +++ b/src/sage/groups/pari_group.py @@ -5,7 +5,7 @@ """ from sage.libs.pari import pari -from sage.rings.all import Integer +from sage.rings.integer import Integer from sage.groups.perm_gps.permgroup_named import TransitiveGroup diff --git a/src/sage/interacts/library.py b/src/sage/interacts/library.py index 153ba021b8f..c4c57f382a5 100644 --- a/src/sage/interacts/library.py +++ b/src/sage/interacts/library.py @@ -65,13 +65,14 @@ from sage.symbolic.constants import pi from sage.symbolic.relation import solve from sage.symbolic.ring import SR -import math x = SR.var('x') # It is important that this file is lazily imported for this to work from sage.repl.user_globals import get_global +assert get_global # to suppress pyflakes warning + from sage.repl.ipython_kernel.all_jupyter import (interact, checkbox, input_box, input_grid, range_slider, selector, slider, text_control) @@ -1612,7 +1613,7 @@ def cellular_automaton( rule_number: IntSlider(value=110, description=u'Rule number', max=255) size: IntSlider(value=6, description=u'size of graphic', max=11, min=1) """ - from sage.all import Integer + from sage.rings.integer import Integer if not 0 <= rule_number <= 255: raise ValueError('Invalid rule number') binary_digits = Integer(rule_number).digits(base=2) @@ -1682,7 +1683,7 @@ def polar_prime_spiral( start, end = interval from sage.ext.fast_eval import fast_float - from math import floor, ceil + from math import ceil from sage.plot.colors import hue if start < 1 or end <= start: diff --git a/src/sage/interfaces/axiom.py b/src/sage/interfaces/axiom.py index d46b67bbb32..8819fd857fe 100644 --- a/src/sage/interfaces/axiom.py +++ b/src/sage/interfaces/axiom.py @@ -702,16 +702,15 @@ def _latex_(self): sage: a = axiom(1/2) #optional - axiom sage: latex(a) #optional - axiom \frac{1}{2} - """ self._check_valid() P = self.parent() - s = P._eval_line('outputAsTex(%s)'%self.name(), reformat=False) - if not '$$' in s: + s = P._eval_line('outputAsTex(%s)' % self.name(), reformat=False) + if '$$' not in s: raise RuntimeError("Error texing axiom object.") i = s.find('$$') j = s.rfind('$$') - s = s[i+2:j] + s = s[i + 2:j] s = multiple_replace({'\r':'', '\n':' ', ' \\sp ':'^', '\\arcsin ':'\\sin^{-1} ', diff --git a/src/sage/interfaces/expect.py b/src/sage/interfaces/expect.py index e619644f0e9..d31668974a1 100644 --- a/src/sage/interfaces/expect.py +++ b/src/sage/interfaces/expect.py @@ -1308,12 +1308,12 @@ def _synchronize(self, cmd='1+%s;\n'): if self._expect is None: return rnd = randrange(2147483647) - s = str(rnd+1) - cmd = cmd%rnd + s = str(rnd + 1) + cmd = cmd % rnd self._sendstr(cmd) try: self._expect_expr(timeout=0.5) - if not s in self._before(): + if s not in self._before(): self._expect_expr(s, timeout=0.5) self._expect_expr(timeout=0.5) except pexpect.TIMEOUT: diff --git a/src/sage/interfaces/interface.py b/src/sage/interfaces/interface.py index 7ace8e6ba03..19c6c7c8aa4 100644 --- a/src/sage/interfaces/interface.py +++ b/src/sage/interfaces/interface.py @@ -734,20 +734,20 @@ def __init__(self, parent, value, is_name=False, name=None): raise TypeError(x) def _latex_(self): -# return "\\begin{verbatim}%s\\end{verbatim}"%self + # return "\\begin{verbatim}%s\\end{verbatim}"%self string = str(self) - if not '|' in string: + if '|' not in string: delim = '|' - elif not '#' in string: + elif '#' not in string: delim = '#' - elif not '@' in string: + elif '@' not in string: delim = '@' - elif not '~' in string: + elif '~' not in string: delim = '~' - return "\\verb%s%s%s"%(delim, string, delim) + return "\\verb%s%s%s" % (delim, string, delim) def __iter__(self): - for i in range(1, len(self)+1): + for i in range(1, len(self) + 1): yield self[i] def __len__(self): diff --git a/src/sage/interfaces/mathics.py b/src/sage/interfaces/mathics.py index 2a81b23fed4..9a938ca759f 100644 --- a/src/sage/interfaces/mathics.py +++ b/src/sage/interfaces/mathics.py @@ -1062,15 +1062,15 @@ def _sage_(self, locals={}): self._check_valid() if self.is_inexact(): m = self.to_mpmath() - if not self is m and not m is None: + if self is not m and m is not None: from sage.libs.mpmath.utils import mpmath_to_sage return mpmath_to_sage(m, self.get_precision()) s = self.to_sympy() - if not self is s and not s is None: + if self is not s and s is not None: if hasattr(s, '_sage_'): return s._sage_() p = self.to_python() - if not self is p and not p is None: + if self is not p and p is not None: def conv(i): return self.parent()(i).sage() if type(p) is list: @@ -1078,7 +1078,7 @@ def conv(i): elif type(p) is tuple: return tuple([conv(i) for i in p]) elif type(p) is dict: - return {conv(k):conv(v) for k, v in p.items()} + return {conv(k): conv(v) for k, v in p.items()} else: return p return s diff --git a/src/sage/interfaces/maxima.py b/src/sage/interfaces/maxima.py index fc7f48bc052..8144d525825 100644 --- a/src/sage/interfaces/maxima.py +++ b/src/sage/interfaces/maxima.py @@ -847,13 +847,13 @@ def _synchronize(self): # The 0; *is* necessary... it comes up in certain rare cases # that are revealed by extensive testing. # Don't delete it. -- william stein - cmd = '''0;sconcat("%s",(%s+1));\n'''%(marker,r) + cmd = '''0;sconcat("%s",(%s+1));\n''' % (marker, r) self._sendstr(cmd) try: try: self._expect_expr(timeout=0.5) - if not s in self._before(): - self._expect_expr(s,timeout=0.5) + if s not in self._before(): + self._expect_expr(s, timeout=0.5) self._expect_expr(timeout=0.5) except pexpect.TIMEOUT: # Don't call self._interrupt() here, as that might send multiple @@ -944,7 +944,7 @@ def _error_check(self, cmd, out): """ r = self._error_re m = r.search(out) - if not m is None: + if m is not None: self._error_msg(cmd, out) def _error_msg(self, cmd, out): diff --git a/src/sage/interfaces/maxima_abstract.py b/src/sage/interfaces/maxima_abstract.py index 917059de0ab..af20ffddd21 100644 --- a/src/sage/interfaces/maxima_abstract.py +++ b/src/sage/interfaces/maxima_abstract.py @@ -981,7 +981,7 @@ def unit_quadratic_integer(self, n): sage: u.parent() Number Field in a with defining polynomial x^2 - 13 with a = 3.605551275463990? """ - from sage.rings.all import Integer + from sage.rings.integer import Integer from sage.rings.number_field.number_field import QuadraticField # Take square-free part so sqrt(n) doesn't get simplified # further by maxima @@ -1536,7 +1536,7 @@ def nintegral(self, var='x', a=0, b=1, sage: gp('intnum(x=0,1,exp(-sqrt(x)))') 0.52848223531423071361790491935415653021675547587292866196865279321015401702040079 """ - from sage.rings.all import Integer + from sage.rings.integer import Integer v = self.quad_qags(var, a, b, epsrel=desired_relative_error, limit=maximum_num_subintervals) return v[0], v[1], Integer(v[2]), Integer(v[3]) diff --git a/src/sage/interfaces/maxima_lib.py b/src/sage/interfaces/maxima_lib.py index 12005b269e8..e0e07c52c78 100644 --- a/src/sage/interfaces/maxima_lib.py +++ b/src/sage/interfaces/maxima_lib.py @@ -1607,18 +1607,18 @@ def sr_to_max(expr): # This should be safe if we treated all special operators above #furthermore, this should already use any _maxima_ methods on op, so use any #conversion methods that are registered in pynac. - op_max=maxima(op).ecl() + op_max = maxima(op).ecl() if op_max in max_op_dict: raise RuntimeError("Encountered operator mismatch in sr-to-maxima translation") - sage_op_dict[op]=op_max - max_op_dict[op_max]=op + sage_op_dict[op] = op_max + max_op_dict[op_max] = op return EclObject(([sage_op_dict[op]], [sr_to_max(o) for o in expr.operands()])) elif expr.is_symbol() or expr._is_registered_constant_(): - if not expr in sage_sym_dict: - sym_max=maxima(expr).ecl() - sage_sym_dict[expr]=sym_max - max_sym_dict[sym_max]=expr + if expr not in sage_sym_dict: + sym_max = maxima(expr).ecl() + sage_sym_dict[expr] = sym_max + max_sym_dict[sym_max] = expr return sage_sym_dict[expr] else: try: diff --git a/src/sage/interfaces/octave.py b/src/sage/interfaces/octave.py index 845fa0fd264..60daa33dbda 100644 --- a/src/sage/interfaces/octave.py +++ b/src/sage/interfaces/octave.py @@ -322,10 +322,10 @@ def _keyboard_interrupt(self): except pexpect.ExceptionPexpect as msg: raise RuntimeError( "THIS IS A BUG -- PLEASE REPORT. This should never happen.\n" + msg) self._start() - raise KeyboardInterrupt("Restarting %s (WARNING: all variables defined in previous session are now invalid)"%self) + raise KeyboardInterrupt("Restarting %s (WARNING: all variables defined in previous session are now invalid)" % self) else: - self._expect.send('\003') # control-c - raise KeyboardInterrupt("Ctrl-c pressed while running %s"%self) + self._expect.send('\003') # control-c + raise KeyboardInterrupt("Ctrl-c pressed while running %s" % self) def quit(self, verbose=False): """ @@ -339,7 +339,7 @@ def quit(self, verbose=False): # Don't bother, since it just hangs in some cases, and it # isn't necessary, since octave behaves well with respect # to signals. - if not self._expect is None: + if self._expect is not None: if verbose: print("Exiting spawned %s process." % self) return diff --git a/src/sage/interfaces/qepcad.py b/src/sage/interfaces/qepcad.py index 9fa2451ddd6..38d9c8c646a 100644 --- a/src/sage/interfaces/qepcad.py +++ b/src/sage/interfaces/qepcad.py @@ -1223,7 +1223,6 @@ def make_cells(self, text): return cells - def __getattr__(self, attrname): r""" Return a :class:`QepcadFunction` object for any QEPCAD command. @@ -1236,7 +1235,7 @@ def __getattr__(self, attrname): """ if attrname[:1] == "_": raise AttributeError - if not attrname in self._tab_completion(): + if attrname not in self._tab_completion(): raise AttributeError return QepcadFunction(self, attrname) diff --git a/src/sage/interfaces/singular.py b/src/sage/interfaces/singular.py index d7718b7aaf3..023b9e3d42a 100644 --- a/src/sage/interfaces/singular.py +++ b/src/sage/interfaces/singular.py @@ -1629,7 +1629,7 @@ def sage_global_ring(self): else: # it ought to be a finite field q = ZZ(charstr[0].lstrip('ZZ/')) - from sage.all import GF + from sage.rings.finite_rings.finite_field_constructor import GF if q.is_prime(): br = GF(q) else: diff --git a/src/sage/interfaces/sympy.py b/src/sage/interfaces/sympy.py index a16e3ab6aec..8fb6caf0188 100644 --- a/src/sage/interfaces/sympy.py +++ b/src/sage/interfaces/sympy.py @@ -1055,33 +1055,27 @@ def test_basics(): check_expression("x**2+y**3", "x y") check_expression("1/(x+y)**2-x**3/4", "x y") - def test_complex(): check_expression("I", "") check_expression("23+I*4", "x") - def test_complex_fail(): # Sage doesn't properly implement _sympy_ on I check_expression("I*y", "y") check_expression("x+I*y", "x y") - def test_integer(): check_expression("4*x", "x") check_expression("-4*x", "x") - def test_real(): check_expression("1.123*x", "x") check_expression("-18.22*x", "x") - - def test_functions(): # Test at least one Function without own _sage_ method from sympy import factorial - assert not "_sage_" in factorial.__dict__ + assert "_sage_" not in factorial.__dict__ check_expression("factorial(x)", "x") check_expression("sin(x)", "x") check_expression("cos(x)", "x") diff --git a/src/sage/knots/link.py b/src/sage/knots/link.py index 3ebffa134da..1b246c70fd6 100644 --- a/src/sage/knots/link.py +++ b/src/sage/knots/link.py @@ -1926,19 +1926,23 @@ def determinant(self): sage: L = Link(B([1]*16 + [2,1,2,1,2,2,2,2,2,2,2,1,2,1,2,-1,2,-2])) sage: L.determinant() 65 + sage: B = BraidGroup(3) + sage: Link(B([1, 2, 1, 1, 2])).determinant() + 4 TESTS:: + sage: B = BraidGroup(3) sage: Link(B([1, 2, 1, -2, -1])).determinant() - Traceback (most recent call last): - ... - NotImplementedError: determinant implemented only for knots - """ - if self.is_knot(): - a = self.alexander_polynomial() - return Integer(abs(a(-1))) + 0 + + REFERENCES: - raise NotImplementedError("determinant implemented only for knots") + - Definition 6.6.3 in [Cro2004]_ + """ + V = self.seifert_matrix() + m = V + V.transpose() + return Integer(abs(m.det())) def is_alternating(self): r""" diff --git a/src/sage/libs/arb/arb_hypgeom.pxd b/src/sage/libs/arb/arb_hypgeom.pxd index 627e083bdc9..fb1c40ddaa8 100644 --- a/src/sage/libs/arb/arb_hypgeom.pxd +++ b/src/sage/libs/arb/arb_hypgeom.pxd @@ -30,9 +30,9 @@ cdef extern from "arb_wrap.h": void arb_hypgeom_gamma_lower(arb_t res, const arb_t s, const arb_t z, int regularized, long prec) void _arb_hypgeom_gamma_lower_series(arb_ptr res, const arb_t s, arb_srcptr z, long zlen, int regularized, long n, long prec) void arb_hypgeom_gamma_lower_series(arb_poly_t res, const arb_t s, const arb_poly_t z, int regularized, long n, long prec) - void arb_hypgeom_beta_lower(arb_t res, const arb_t a, const arb_t b, const arb_t z, int regularized, long prec) - void _arb_hypgeom_beta_lower_series(arb_ptr res, const arb_t a, const arb_t b, arb_srcptr z, long zlen, int regularized, long n, long prec) - void arb_hypgeom_beta_lower_series(arb_poly_t res, const arb_t a, const arb_t b, const arb_poly_t z, int regularized, long n, long prec) + void arb_hypgeom_beta_lower(arb_t res, const arb_t a, const arb_t b, const arb_t z, bint regularized, long prec) + void _arb_hypgeom_beta_lower_series(arb_ptr res, const arb_t a, const arb_t b, arb_srcptr z, long zlen, bint regularized, long n, long prec) + void arb_hypgeom_beta_lower_series(arb_poly_t res, const arb_t a, const arb_t b, const arb_poly_t z, bint regularized, long n, long prec) void arb_hypgeom_expint(arb_t res, const arb_t s, const arb_t z, long prec) void arb_hypgeom_ei(arb_t res, const arb_t z, long prec) void _arb_hypgeom_ei_series(arb_ptr res, arb_srcptr z, long zlen, long len, long prec) @@ -49,9 +49,9 @@ cdef extern from "arb_wrap.h": void arb_hypgeom_chi(arb_t res, const arb_t z, long prec) void _arb_hypgeom_chi_series(arb_ptr res, arb_srcptr z, long zlen, long len, long prec) void arb_hypgeom_chi_series(arb_poly_t res, const arb_poly_t z, long len, long prec) - void arb_hypgeom_li(arb_t res, const arb_t z, int offset, long prec) - void _arb_hypgeom_li_series(arb_ptr res, arb_srcptr z, long zlen, int offset, long len, long prec) - void arb_hypgeom_li_series(arb_poly_t res, const arb_poly_t z, int offset, long len, long prec) + void arb_hypgeom_li(arb_t res, const arb_t z, bint offset, long prec) + void _arb_hypgeom_li_series(arb_ptr res, arb_srcptr z, long zlen, bint offset, long len, long prec) + void arb_hypgeom_li_series(arb_poly_t res, const arb_poly_t z, bint offset, long len, long prec) void arb_hypgeom_bessel_j(arb_t res, const arb_t nu, const arb_t z, long prec) void arb_hypgeom_bessel_y(arb_t res, const arb_t nu, const arb_t z, long prec) void arb_hypgeom_bessel_jy(arb_t res1, arb_t res2, const arb_t nu, const arb_t z, long prec) diff --git a/src/sage/libs/eclib/interface.py b/src/sage/libs/eclib/interface.py index a163cc31093..3db3fd902fc 100644 --- a/src/sage/libs/eclib/interface.py +++ b/src/sage/libs/eclib/interface.py @@ -27,7 +27,6 @@ """ import sys from sage.structure.sage_object import SageObject -from sage.rings.all import Integer from sage.rings.integer_ring import IntegerRing from .mwrank import _Curvedata, _two_descent, _mw, parse_point_list diff --git a/src/sage/libs/eclib/mwrank.pyx b/src/sage/libs/eclib/mwrank.pyx index 0c20771d558..d8f8b38c136 100644 --- a/src/sage/libs/eclib/mwrank.pyx +++ b/src/sage/libs/eclib/mwrank.pyx @@ -28,7 +28,7 @@ from cysignals.signals cimport sig_on, sig_off from sage.cpython.string cimport char_to_str, str_to_bytes from sage.cpython.string import FS_ENCODING from sage.libs.eclib cimport bigint, Curvedata, mw, two_descent -from sage.rings.all import Integer +from sage.rings.integer import Integer cdef extern from "wrap.cpp": ### misc functions ### diff --git a/src/sage/libs/singular/decl.pxd b/src/sage/libs/singular/decl.pxd index 806937ff6e1..997cb631dd1 100644 --- a/src/sage/libs/singular/decl.pxd +++ b/src/sage/libs/singular/decl.pxd @@ -127,6 +127,7 @@ cdef extern from "singular/Singular/libsingular.h": number* cfMult(number *, number *, const n_Procs_s* r) # algebraic number multiplication number* (*cfInit)(int i, const n_Procs_s* r ) # algebraic number from int + number* (*cfInitMPZ)(mpz_t i, const n_Procs_s* r) number* (*cfParameter)(int i, const n_Procs_s* r) int (*cfParDeg)(number* n, const n_Procs_s* r) int (*cfSize)(number* n, const n_Procs_s* r) @@ -1136,3 +1137,11 @@ cdef extern from "singular/kernel/GBEngine/kstd1.h": cdef extern from "singular/kernel/GBEngine/syz.h": ctypedef struct syStrategy "ssyStrategy": short references + +cdef extern from "singular/polys/ext_fields/transext.h": + ctypedef struct TransExtInfo: + ring * r + + + + diff --git a/src/sage/libs/singular/groebner_strategy.pyx b/src/sage/libs/singular/groebner_strategy.pyx index a14df93ad42..20751eafa71 100644 --- a/src/sage/libs/singular/groebner_strategy.pyx +++ b/src/sage/libs/singular/groebner_strategy.pyx @@ -341,6 +341,17 @@ cdef class NCGroebnerStrategy(SageObject): ... TypeError: First parameter must be an ideal in a g-algebra. + Check that tail reduction is applied too:: + + sage: F = PolynomialRing(QQ,'t').fraction_field() + sage: FA = FreeAlgebra(F, 6, 'x1,x2,x3,x4,x5,x6') + sage: N = FA.g_algebra({FA.gen(j)*FA.gen(i):-FA.gen(i)*FA.gen(j) for i in range(5) for j in range(i+1,6)}) + sage: I = N.ideal([g^2 for g in N.gens()],side='twosided') + sage: N.inject_variables() + Defining x1, x2, x3, x4, x5, x6 + sage: I.reduce(x1*x2*x3 + x2^2*x4) + x1*x2*x3 + """ if not isinstance(L, NCPolynomialIdeal): raise TypeError("First parameter must be an ideal in a g-algebra.") @@ -372,6 +383,7 @@ cdef class NCGroebnerStrategy(SageObject): self._strat.enterS = enterSBba #- set S self._strat.sl = -1 + self._strat.noTailReduction = False #- init local data struct initS(i, NULL, self._strat) diff --git a/src/sage/libs/singular/polynomial.pyx b/src/sage/libs/singular/polynomial.pyx index 7687de8f2d8..f6d244e79fa 100644 --- a/src/sage/libs/singular/polynomial.pyx +++ b/src/sage/libs/singular/polynomial.pyx @@ -23,6 +23,8 @@ cdef extern from *: # hack to get at cython macro import re plusminus_pattern = re.compile("([^\(^])([\+\-])") +parenthvar_pattern = re.compile(r"\(([a-zA-Z][a-zA-Z0-9]*)\)") + from sage.cpython.string cimport bytes_to_str, str_to_bytes @@ -441,6 +443,7 @@ cdef object singular_polynomial_str(poly *p, ring *r): s = bytes_to_str(p_String(p, r, r)) s = plusminus_pattern.sub("\\1 \\2 ", s) + s = parenthvar_pattern.sub("\\1", s) return s @@ -618,6 +621,9 @@ cdef int singular_polynomial_subst(poly **p, int var_index, poly *value, ring *r - ``r`` - a ring """ + if r != currRing: + rChangeCurrRing(r) + if p_IsConstant(value, r): p[0] = pSubst(p[0], var_index+1, value) return 0 @@ -625,8 +631,6 @@ cdef int singular_polynomial_subst(poly **p, int var_index, poly *value, ring *r cdef unsigned long exp = p_GetExp(p[0], var_index+1, r) * p_GetMaxExp(value, r) overflow_check(exp, r) - if r != currRing: - rChangeCurrRing(r) cdef int count = singular_polynomial_length_bounded(p[0], 15) if unlikely(count >= 15 or exp > 15): sig_on() diff --git a/src/sage/libs/singular/ring.pyx b/src/sage/libs/singular/ring.pyx index 9c3ee22c533..35955020cf5 100644 --- a/src/sage/libs/singular/ring.pyx +++ b/src/sage/libs/singular/ring.pyx @@ -6,6 +6,8 @@ AUTHORS: - Martin Albrecht (2009-07): initial implementation - Kwankyu Lee (2010-06): added matrix term order support + +- Miguel Marco (2021): added transcendental extensions over Q """ #***************************************************************************** # Copyright (C) 2009 Martin Albrecht @@ -26,7 +28,9 @@ from sage.libs.singular.decl cimport ringorder_dp, ringorder_Dp, ringorder_lp, r from sage.libs.singular.decl cimport p_Copy, prCopyR from sage.libs.singular.decl cimport n_unknown, n_Zp, n_Q, n_R, n_GF, n_long_R, n_algExt,n_transExt,n_long_C, n_Z, n_Zn, n_Znm, n_Z2m, n_CF from sage.libs.singular.decl cimport n_coeffType, cfInitCharProc -from sage.libs.singular.decl cimport rDefault, GFInfo, ZnmInfo, nInitChar, AlgExtInfo, nRegister, naInitChar +from sage.libs.singular.decl cimport rDefault, GFInfo, ZnmInfo, nInitChar, AlgExtInfo, nRegister, naInitChar, TransExtInfo + + from sage.rings.integer cimport Integer from sage.rings.integer_ring cimport IntegerRing_class @@ -40,11 +44,19 @@ from sage.rings.polynomial.term_order import TermOrder from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomial_libsingular, MPolynomialRing_libsingular from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing +from sage.rings.polynomial.polynomial_ring import PolynomialRing_field + +from sage.rings.fraction_field import FractionField_generic, FractionField_1poly_field + from cpython.object cimport Py_EQ, Py_NE from collections import defaultdict + + + + # mapping str --> SINGULAR representation order_dict = { "dp": ringorder_dp, @@ -117,6 +129,15 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: sage: P. = Zmod(25213521351515232)[]; P Multivariate Polynomial Ring in x, y, z over Ring of integers modulo 25213521351515232 + sage: K = PolynomialRing(QQ, 's,t').fraction_field() + sage: P. = K[]; P + Multivariate Polynomial Ring in x, y over Fraction Field of Multivariate Polynomial Ring in s, t over Rational Field + + sage: F = PolynomialRing(FiniteField(7),'a,b').fraction_field() + sage: R. = F[] + sage: R + Multivariate Polynomial Ring in x, y, z over Fraction Field of Multivariate Polynomial Ring in a, b over Finite Field of size 7 + TESTS: Check that ``degneglex`` and ``degrevlex`` are the same up to reversal of @@ -127,6 +148,25 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: sage: L = [v for d in (0..4) for v in IntegerVectors(d, 4)] sage: sorted([R.monomial(*e) for e in L]) == sorted([S.monomial(*e) for e in L]) True + + Check that we are using the libsingular backend instead of the pexpect one:: + + sage: F = PolynomialRing(FiniteField(7),'a,b').fraction_field() + sage: R. = F[] + sage: from sage.libs.singular.function import singular_function + sage: sing_print = singular_function('print') + sage: sing_print(R) + 'polynomial ring, over a field, global ordering\n// coefficients: ZZ/7(a, b)\n// number of vars : 3\n// block 1 : ordering dp\n// : names x y z\n// block 2 : ordering C' + + :: + + sage: F = PolynomialRing(QQ, 's,t').fraction_field() + sage: R. = F[] + sage: from sage.libs.singular.function import singular_function + sage: sing_print = singular_function('print') + sage: sing_print(R) + 'polynomial ring, over a field, global ordering\n// coefficients: QQ(s, t)\n// number of vars : 3\n// block 1 : ordering dp\n// : names x y z\n// block 2 : ordering C' + """ cdef long cexponent cdef GFInfo* _param @@ -143,10 +183,13 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: cdef int ringorder_column_pos cdef int ringorder_column_asc + cdef int ngens + cdef n_coeffType ringtype = n_unknown cdef MPolynomialRing_libsingular k cdef MPolynomial_libsingular minpoly cdef AlgExtInfo extParam + cdef TransExtInfo trextParam cdef n_coeffType _type = n_unknown #cdef cfInitCharProc myfunctionptr; @@ -249,6 +292,59 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: characteristic = 0 _ring = rDefault( characteristic ,nvars, _names, nblcks, _order, _block0, _block1, _wvhdl) + elif isinstance(base_ring, FractionField_generic) and isinstance(base_ring.base(), (MPolynomialRing_libsingular, PolynomialRing_field)) and isinstance(base_ring.base().base_ring(), RationalField): + characteristic = 1 + k = PolynomialRing(RationalField(), + names=base_ring.variable_names(), order="lex", implementation="singular") + + ngens = len(k.gens()) + + _ext_names = omAlloc0(ngens*sizeof(char*)) + for i in range(ngens): + _name = str_to_bytes(k._names[i]) + _ext_names[i] = omStrDup(_name) + + _cfr = rDefault( 0, ngens, _ext_names ) + rComplete(_cfr, 1) + + trextParam.r = _cfr + + _cf = nInitChar(n_transExt, &trextParam) + + + if (_cf is NULL): + raise RuntimeError("Failed to allocate _cf ring.") + + _ring = rDefault (_cf ,nvars, _names, nblcks, _order, _block0, _block1, _wvhdl) + + elif isinstance(base_ring, FractionField_generic) and isinstance(base_ring.base(), (MPolynomialRing_libsingular, PolynomialRing_field)) and isinstance(base_ring.base().base_ring(), FiniteField_generic): + if not base_ring.base_ring().is_prime_field(): + raise NotImplementedError("Transcental extension are not implemented for non-prime finite fields") + characteristic = int(base_ring.characteristic()) + k = PolynomialRing(base_ring.base_ring(), + names=base_ring.variable_names(), order="lex", implementation="singular") + + ngens = len(k.gens()) + + _ext_names = omAlloc0(ngens*sizeof(char*)) + for i in range(ngens): + _name = str_to_bytes(k._names[i]) + _ext_names[i] = omStrDup(_name) + + _cfr = rDefault( characteristic, ngens, _ext_names ) + rComplete(_cfr, 1) + + trextParam.r = _cfr + + _cf = nInitChar(n_transExt, &trextParam) + + + if (_cf is NULL): + raise RuntimeError("Failed to allocate _cf ring.") + + _ring = rDefault (_cf ,nvars, _names, nblcks, _order, _block0, _block1, _wvhdl) + + elif isinstance(base_ring, NumberField) and base_ring.is_absolute(): characteristic = 1 k = PolynomialRing(RationalField(), diff --git a/src/sage/libs/singular/singular.pyx b/src/sage/libs/singular/singular.pyx index 4e85f2158c5..d45de78576b 100644 --- a/src/sage/libs/singular/singular.pyx +++ b/src/sage/libs/singular/singular.pyx @@ -4,6 +4,8 @@ libSingular: Conversion Routines and Initialisation AUTHOR: - Martin Albrecht + +- Miguel Marco (2021): added transcendental extensions over Q """ # **************************************************************************** @@ -27,10 +29,15 @@ import os from libc.stdint cimport int64_t from sage.libs.singular.decl cimport * +from sage.rings.polynomial.polydict import ETuple + from sage.rings.rational_field import RationalField from sage.rings.integer_ring cimport IntegerRing_class from sage.rings.finite_rings.integer_mod_ring import IntegerModRing_generic from sage.rings.finite_rings.finite_field_base import FiniteField +from sage.rings.polynomial.polynomial_ring import PolynomialRing_field +from sage.rings.fraction_field import FractionField_generic, FractionField_1poly_field + from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn from sage.rings.finite_rings.finite_field_givaro import FiniteField_givaro from sage.rings.finite_rings.finite_field_ntl_gf2e import FiniteField_ntl_gf2e @@ -40,12 +47,32 @@ from sage.libs.gmp.all cimport * from sage.cpython.string import FS_ENCODING from sage.cpython.string cimport str_to_bytes, char_to_str, bytes_to_str -from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomial_libsingular +from sage.rings.polynomial.multi_polynomial_libsingular cimport MPolynomial_libsingular, MPolynomialRing_libsingular + +ctypedef struct fraction "fractionObject": + poly *numerator + poly *denominator + int complexity _saved_options = (int(0),0,0) cdef Rational si2sa_QQ(number *n, number **nn, ring *_ring): """ + Create a sage rational number from a singular one. + + INPUT: + + - ``n`` - a (pointer to) a singular rational number + + - ``*n`` - a pointer to a pointer like before + + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` + + OUTPUT: + + - A sage Rational + TESTS:: sage: P. = QQ[] @@ -103,6 +130,20 @@ cdef Rational si2sa_QQ(number *n, number **nn, ring *_ring): cdef Integer si2sa_ZZ(number *n, ring *_ring): """ + Create a sage integer number from a singular one. + + INPUT: + + - ``n`` - a (pointer to) a singular integer number + + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` + + OUTPUT: + + - A sage Integer + + TESTS:: sage: P. = ZZ[] @@ -124,6 +165,21 @@ cdef Integer si2sa_ZZ(number *n, ring *_ring): cdef FFgivE si2sa_GFqGivaro(number *n, ring *_ring, Cache_givaro cache): """ + Create a sage element of a small finite field from a singular one. + + INPUT: + + - ``n`` - a (pointer to) a singular number in a finite field + + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` + + - ``cache`` - A Givaro number field + + OUTPUT: + + - A sage element of ``cache`` + TESTS:: sage: K. = GF(5^3) @@ -164,6 +220,23 @@ cdef FFgivE si2sa_GFqGivaro(number *n, ring *_ring, Cache_givaro cache): cdef FFgf2eE si2sa_GFqNTLGF2E(number *n, ring *_ring, Cache_ntl_gf2e cache): """ + Create a sage element of a finite field of characteristic 2 from a + singular one. + + INPUT: + + - ``n`` - a (pointer to) a singular number in a finite field + + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` + + - ``cache`` - A ntl_gf2e number field + + OUTPUT: + + - A sage element of ``cache`` + + TESTS:: sage: K. = GF(2^20) @@ -199,6 +272,21 @@ cdef FFgf2eE si2sa_GFqNTLGF2E(number *n, ring *_ring, Cache_ntl_gf2e cache): cdef object si2sa_GFq_generic(number *n, ring *_ring, object base): """ + Create a sage element of a generic finite field from a singular one. + + INPUT: + + - ``n`` - a (pointer to) a singular number in a finite field + + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` + + - ``base`` - A sage finite field + + OUTPUT: + + - A sage element of ``base`` + TESTS:: sage: K. = GF(3^16) @@ -216,7 +304,6 @@ cdef object si2sa_GFq_generic(number *n, ring *_ring, object base): sage: R. = F[] sage: R(-1).constant_coefficient() # indirect doctest 2147483646 - """ cdef poly *z cdef long c @@ -245,8 +332,199 @@ cdef object si2sa_GFq_generic(number *n, ring *_ring, object base): z = pNext(z) return ret +cdef object si2sa_transext_QQ(number *n, ring *_ring, object base): + """ + Create a sage element of a transcendental extension of ``QQ`` from a + singular one. + + INPUT: + + - ``n`` - a (pointer to) a singular number in a transcendental extension + of the rationals + + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` + + - ``base`` - A sage FractionField + + OUTPUT: + + - A sage element of ``base`` + + TESTS:: + + sage: F = PolynomialRing(QQ,'a,b').fraction_field() + sage: F.inject_variables() + Defining a, b + sage: R. = F[] + sage: a*x + a*x + sage: I = R.ideal([a*x]) + sage: I + Ideal (a*x) of Multivariate Polynomial Ring in x, y over Fraction Field of Multivariate Polynomial Ring in a, b over Rational Field + sage: I.groebner_basis() + [x] + sage: I = R.ideal([a*x+b*y^2, (b+a)/(b-a)*x^3-3*y*x]) + sage: I.groebner_basis() + [x^3 + (3*a - 3*b)/(a + b)*x*y, y^2 + a/b*x] + sage: R.term_order() + Degree reverse lexicographic term order + """ + + cdef poly *numer + cdef poly *denom + cdef number *c + cdef int e + cdef fraction *frac + cdef object snumer + cdef object sdenom + + cdef ring *cfRing = _ring.cf.extRing + + if _ring.cf.cfIsZero(n,_ring.cf): + return base._zero_element + elif _ring.cf.cfIsOne(n,_ring.cf): + return base._one_element + + snumer = base(0) + sdenom = base(0) + + frac = n + + numer = frac.numerator + denom = frac.denominator + + while numer: + c = p_GetCoeff(numer, cfRing) + coeff = si2sa_QQ(c, &c, cfRing) + numer.coef = c + for i in range(base.ngens()): + e = p_GetExp(numer, i+1, cfRing) + if e!= 0: + coeff *= base.gen(i)**e + snumer += coeff + numer = pNext(numer) + + if not denom: + sdenom = base(1) + else: + while denom: + c = p_GetCoeff(denom, cfRing) + coeff = si2sa_QQ(c, &c, cfRing) + denom.coef = c + for i in range(base.ngens()): + e = p_GetExp(denom, i+1, cfRing) + if e!= 0: + coeff *= base.gen(i)**e + sdenom += coeff + denom = pNext(denom) + + return snumer/sdenom + + +cdef object si2sa_transext_FF(number *n, ring *_ring, object base): + """ + Create a sage element of a transcendental extension of a prime field from a + singular one. + + INPUT: + + - ``n`` - a (pointer to) a singular number in a transcendental extension + of the rationals + + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` + + - ``base`` - A sage FractionField + + OUTPUT: + + - A sage element of ``base`` + + TESTS:: + + sage: F = PolynomialRing(FiniteField(7),'a,b').fraction_field() + sage: R. = F[] + sage: n = R(5) + sage: n + -2 + sage: type(n) + + """ + + cdef poly *numer + cdef poly *denom + cdef number *c + cdef int e + cdef fraction *frac + cdef object snumer + cdef object sdenom + + cdef ring *cfRing = _ring.cf.extRing + + if _ring.cf.cfIsZero(n,_ring.cf): + return base._zero_element + elif _ring.cf.cfIsOne(n,_ring.cf): + return base._one_element + + snumer = base(0) + sdenom = base(0) + + frac = n + + numer = frac.numerator + denom = frac.denominator + + while numer: + + + + c = p_GetCoeff(numer, cfRing) + coeff = base(cfRing.cf.cfInt(c, cfRing.cf)) + numer.coef = c + for i in range(base.ngens()): + e = p_GetExp(numer, i+1, cfRing) + if e!= 0: + coeff *= base.gen(i)**e + snumer += coeff + numer = pNext(numer) + + if not denom: + sdenom = base(1) + else: + while denom: + c = p_GetCoeff(denom, cfRing) + coeff = base(cfRing.cf.cfInt(c, cfRing.cf)) + denom.coef = c + for i in range(base.ngens()): + e = p_GetExp(denom, i+1, cfRing) + if e!= 0: + coeff *= base.gen(i)**e + sdenom += coeff + denom = pNext(denom) + + return snumer/sdenom + + cdef object si2sa_NF(number *n, ring *_ring, object base): """ + Create a sage element of a number field from a singular one. + + INPUT: + + - ``n`` - a (pointer to) a singular number in an algebraic extension of + the rationals + + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` + + - ``base`` - A sage NumberField + + OUTPUT: + + - A sage element of ``base`` + + TESTS:: sage: K. = NumberField(x^2 - 2) @@ -295,6 +573,21 @@ cdef object si2sa_NF(number *n, ring *_ring, object base): cdef inline object si2sa_ZZmod(number *n, ring *_ring, object base): """ + Create a sage element of a ring of integers modulo n from a singular one. + + INPUT: + + - ``n`` - a (pointer to) a singular number in a ring of integers modulo n + + - ``_ ring`` - a (pointer to) a singular ring, in whose coefficient field + lives ``n`` + + - ``base`` - A sage IntegerModRing + + OUTPUT: + + - A sage element of ``base`` + TESTS:: sage: P. = Integers(10)[] @@ -341,6 +634,20 @@ cdef inline object si2sa_ZZmod(number *n, ring *_ring, object base): cdef number *sa2si_QQ(Rational r, ring *_ring): """ + Create a singular number from a sage rational. + + INPUT: + + - ``r`` - a sage rational number + + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + + + OUTPUT: + + - A (pointer to) a singular number + + TESTS:: sage: P. = QQ[] @@ -358,6 +665,36 @@ cdef number *sa2si_QQ(Rational r, ring *_ring): cdef number *sa2si_GFqGivaro(int quo, ring *_ring): """ + Create a singular number in a small finite field. + + INPUT: + + - ``quo`` - a sage integer + + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + + + OUTPUT: + + - A (pointer to) a singular number + + Number field elements are represented as polynomials in the number field + generator. In this case, ``quo`` is the integer resulting from evaluating + that polynomial in the characteristic of the field. + + + TESTS:: + + sage: F = FiniteField(5^2) + sage: type(F) + + sage: R. = F[] + sage: R(0) + 1 + 1 + sage: R(F.gen()) + 1 + (z2 + 1) + sage: R(F.gen()^2) + 1 + (z2 - 1) """ if _ring != currRing: rChangeCurrRing(_ring) @@ -397,6 +734,32 @@ cdef number *sa2si_GFqGivaro(int quo, ring *_ring): cdef number *sa2si_GFqNTLGF2E(FFgf2eE elem, ring *_ring): """ + Create a singular number from a sage element of a finite field of + characteristic 2. + + INPUT: + + - ``elem`` - a sage element of a ntl_gf2e finite field + + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + + + OUTPUT: + + - A (pointer to) a singular number + + TESTS:: + + sage: F = FiniteField(2^20) + sage: type(F) + + sage: R. = F[] + sage: R(0)+1 + 1 + sage: R(F.gen()) + 1 + (z20 + 1) + sage: R(F.gen()^21) + 1 + (z20^11 + z20^10 + z20^8 + z20^7 + z20^6 + z20^5 + z20^2 + z20 + 1) """ if _ring != currRing: rChangeCurrRing(_ring) cdef int i @@ -438,6 +801,31 @@ cdef number *sa2si_GFqNTLGF2E(FFgf2eE elem, ring *_ring): cdef number *sa2si_GFq_generic(object elem, ring *_ring): """ + Create a singular number from a sage element of a generic finite field. + + INPUT: + + - ``elem`` - a sage element of a generic finite field + + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + + + OUTPUT: + + - A (pointer to) a singular number + + TESTS:: + + sage: F = FiniteField(3^20) + sage: type(F) + + sage: R. = F[] + sage: R(0) + 1 + 1 + sage: R(F.gen()) + 1 + (z20 + 1) + sage: R(F.gen()^21) + 1 + (z20^14 - z20^12 - z20^11 - z20^10 - z20^9 + z20^6 + z20^5 + z20^4 - z20^2 + z20 + 1) """ cdef int i cdef number *n1 @@ -477,8 +865,294 @@ cdef number *sa2si_GFq_generic(object elem, ring *_ring): return n1 +cdef number *sa2si_transext_QQ(object elem, ring *_ring): + """ + Create a singular number from a sage element of a transcendental extension + of the rationals. + + INPUT: + + - ``elem`` - a sage element of a FractionField of polynomials over the rationals + + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + + + OUTPUT: + + - A (pointer to) a singular number + + + TESTS:: + + sage: F = PolynomialRing(QQ,'a,b').fraction_field() + sage: F.inject_variables() + Defining a, b + sage: R. = F[] + sage: a*x + a*x + sage: I = R.ideal([a*x]) + sage: I + Ideal (a*x) of Multivariate Polynomial Ring in x, y over Fraction Field of Multivariate Polynomial Ring in a, b over Rational Field + sage: I.groebner_basis() + [x] + sage: I = R.ideal([a*x+b*y^2, (b+a)/(b-a)*x^3-3*y*x]) + sage: I.groebner_basis() + [x^3 + (3*a - 3*b)/(a + b)*x*y, y^2 + a/b*x] + sage: R.term_order() + Degree reverse lexicographic term order + + :: + + sage: F = PolynomialRing(QQ,'a').fraction_field() + sage: R. = F[] + sage: F.inject_variables() + Defining a + sage: a*x + a*x + sage: I = R.ideal([a*x+5*y^2, (1+a)/(1-a)*x^3-3*y*x]) + sage: I + Ideal (5*y^2 + a*x, (-a - 1)/(a - 1)*x^3 - 3*x*y) of Multivariate Polynomial Ring in x, y over Fraction Field of Univariate Polynomial Ring in a over Rational Field + sage: I.groebner_basis() + [x^3 + (3*a - 3)/(a + 1)*x*y, y^2 + a/5*x] + + :: + + sage: F = PolynomialRing(QQ,'a,b').fraction_field() + sage: R. = PolynomialRing(F) + sage: S. = QQ[] + sage: f = x + y + 1 + sage: R(f) + x + y + 1 + """ + + cdef int j + cdef number *n1 + cdef number *a + cdef number *naCoeff + cdef number *numerator + cdef number *denominator + cdef number *cfnum + cdef number *cfden + cdef number *aux1 + cdef number *aux2 + cdef number *power + cdef int ngens + cdef int ex + cdef nMapFunc nMapFuncPtr = NULL; + + if _ring != currRing: + rChangeCurrRing(_ring) + + ngens = elem.parent().ngens() + + nMapFuncPtr = naSetMap(_ring.cf, currRing.cf) # choose correct mapping function + + if nMapFuncPtr is NULL: + raise RuntimeError("Failed to determine nMapFuncPtr") + + numerdic = elem.numerator().dict() + denomdic = elem.denominator().dict() + + if numerdic and not isinstance(list(numerdic)[0], (tuple, ETuple)): + numerdic = {(k,):b for k,b in numerdic.items()} + + if denomdic and not isinstance(list(denomdic)[0], (tuple, ETuple)): + denomdic = {(k,):b for k,b in denomdic.items()} + + if _ring != currRing: + rChangeCurrRing(_ring) + n1 = _ring.cf.cfInit(0, _ring.cf) + numerator = _ring.cf.cfInit(0, _ring.cf) + for (exponents, coef) in numerdic.items(): + numer = coef.numerator() + cfnum = _ring.cf.cfInitMPZ((numer).value, _ring.cf) + denom = coef.denominator() + cfden = _ring.cf.cfInitMPZ((denom).value, _ring.cf) + naCoeff = _ring.cf.cfDiv(cfnum, cfden, _ring.cf) + _ring.cf.cfDelete(&cfnum, _ring.cf) + _ring.cf.cfDelete(&cfden, _ring.cf) + for (j, ex) in enumerate(exponents): + a = _ring.cf.cfParameter(j+1, _ring.cf) + _ring.cf.cfPower(a, ex, &power, _ring.cf) + aux1 = naCoeff + naCoeff = _ring.cf.cfMult(aux1, power, _ring.cf) + _ring.cf.cfDelete(&aux1, _ring.cf) + _ring.cf.cfDelete(&a, _ring.cf) + _ring.cf.cfDelete(&power, _ring.cf) + aux2 = numerator + numerator = _ring.cf.cfAdd(aux2, naCoeff,_ring.cf) + _ring.cf.cfDelete(&aux2, _ring.cf) + + if elem.denominator() != 1: + denominator = _ring.cf.cfInit(0, _ring.cf) + + for (exponents, coef) in denomdic.items(): + numer = coef.numerator() + cfnum = _ring.cf.cfInitMPZ((numer).value, _ring.cf) + denom = coef.denominator() + cfden = _ring.cf.cfInitMPZ((denom).value, _ring.cf) + naCoeff = _ring.cf.cfDiv(cfnum, cfden, _ring.cf) + _ring.cf.cfDelete(&cfnum, _ring.cf) + _ring.cf.cfDelete(&cfden, _ring.cf) + for (j, ex) in enumerate(exponents): + a = _ring.cf.cfParameter(j+1, _ring.cf) + _ring.cf.cfPower(a, ex, &power, _ring.cf) + aux1 = naCoeff + naCoeff = _ring.cf.cfMult(aux1, power, _ring.cf) + _ring.cf.cfDelete(&aux1, _ring.cf) + _ring.cf.cfDelete(&a, _ring.cf) + _ring.cf.cfDelete(&power, _ring.cf) + aux2 = denominator + denominator = _ring.cf.cfAdd(aux2, naCoeff,_ring.cf) + _ring.cf.cfDelete(&aux2, _ring.cf) + + else: + denominator = _ring.cf.cfInit(1, _ring.cf) + + n1 = _ring.cf.cfDiv(numerator, denominator, _ring.cf) + + _ring.cf.cfDelete(&numerator, _ring.cf) + _ring.cf.cfDelete(&denominator, _ring.cf) + _ring.cf.cfDelete(&naCoeff, _ring.cf) + _ring.cf.cfDelete(&a, _ring.cf) + + return n1 + + + +cdef number *sa2si_transext_FF(object elem, ring *_ring): + """ + Create a singular number from a sage element of a transcendental extension + of a prime field. + + INPUT: + + - ``elem`` - a sage element of a FractionField of polynomials over the rationals + + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + + + OUTPUT: + + - A (pointer to) a singular number + + + TESTS:: + + sage: F = PolynomialRing(FiniteField(7),'a,b').fraction_field() + sage: R. = F[] + sage: n = R(5) + sage: n + n + 3 + sage: Integer(n) + 5 + """ + cdef int j + cdef number *n1 + cdef number *a + cdef number *naCoeff + cdef number *numerator + cdef number *denominator + cdef number *aux1 + cdef number *aux2 + cdef int ngens + cdef int ex + cdef nMapFunc nMapFuncPtr = NULL; + + if _ring != currRing: + rChangeCurrRing(_ring) + + ngens = elem.parent().ngens() + + nMapFuncPtr = naSetMap(_ring.cf, currRing.cf) # choose correct mapping function + + if nMapFuncPtr is NULL: + raise RuntimeError("Failed to determine nMapFuncPtr") + + numerdic = elem.numerator().dict() + denomdic = elem.denominator().dict() + + if numerdic and not isinstance(list(numerdic)[0], (tuple, ETuple)): + numerdic = {(k,):b for k,b in numerdic.items()} + + if denomdic and not isinstance(list(denomdic)[0], (tuple, ETuple)): + denomdic = {(k,):b for k,b in denomdic.items()} + + if _ring != currRing: + rChangeCurrRing(_ring) + numerator = _ring.cf.cfInit(0, _ring.cf) + for (exponents, coef) in numerdic.items(): + naCoeff = _ring.cf.cfInit(coef, _ring.cf) + for (j, ex) in enumerate(exponents): + a = _ring.cf.cfParameter(j+1, _ring.cf) + for k in range(ex): + aux1 = naCoeff + naCoeff = _ring.cf.cfMult(aux1, a ,_ring.cf) + _ring.cf.cfDelete(&aux1, _ring.cf) + _ring.cf.cfDelete(&a, _ring.cf) + aux2 = numerator + numerator = _ring.cf.cfAdd(aux2, naCoeff,_ring.cf) + _ring.cf.cfDelete(&naCoeff, _ring.cf) + _ring.cf.cfDelete(&aux2, _ring.cf) + + if elem.denominator() != 1: + denominator = _ring.cf.cfInit(0, _ring.cf) + + for (exponents, coef) in denomdic.items(): + naCoeff = _ring.cf.cfInit(coef, _ring.cf) + for (j, ex) in enumerate(exponents): + a = _ring.cf.cfParameter(j+1, _ring.cf) + for k in range(ex): + aux1 = naCoeff + naCoeff = _ring.cf.cfMult(aux1, a ,_ring.cf) + _ring.cf.cfDelete(&aux1, _ring.cf) + _ring.cf.cfDelete(&a, _ring.cf) + aux2 = denominator + denominator = _ring.cf.cfAdd(aux2, naCoeff,_ring.cf) + _ring.cf.cfDelete(&naCoeff, _ring.cf) + _ring.cf.cfDelete(&aux2, _ring.cf) + + else: + denominator = _ring.cf.cfInit(1, _ring.cf) + + n1 = _ring.cf.cfDiv(numerator, denominator, _ring.cf) + + _ring.cf.cfDelete(&numerator, _ring.cf) + _ring.cf.cfDelete(&denominator, _ring.cf) + _ring.cf.cfDelete(&a, _ring.cf) + + return n1 + + cdef number *sa2si_NF(object elem, ring *_ring): """ + Create a singular number from a sage element of a number field. + + INPUT: + + - ``elem`` - a sage element of a NumberField + + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + + + OUTPUT: + + - A (pointer to) a singular number + + TESTS:: + + sage: F = NumberField(x^3+x+1, 'a') + sage: type(F) + + sage: R. = F[] + sage: R(0) + 1 + 1 + sage: R(1) + 1 + sage: R(F.gen()) + 1 + (a + 1) + sage: R(F.gen()^5) + 1 + (-a^2 + a + 2) """ cdef int i cdef number *n1 @@ -493,7 +1167,7 @@ cdef number *sa2si_NF(object elem, ring *_ring): nMapFuncPtr = naSetMap(_ring.cf, currRing.cf) # choose correct mapping function - if (nMapFuncPtr is NULL): + if nMapFuncPtr is NULL: raise RuntimeError("Failed to determine nMapFuncPtr") elem = list(elem) @@ -518,7 +1192,6 @@ cdef number *sa2si_NF(object elem, ring *_ring): rComplete(qqr,1) qqr.ShortOut = 0 - nMapFuncPtr = naSetMap( qqr.cf , _ring.cf ) # choose correct mapping function cdef poly *_p for i from 0 <= i < len(elem): @@ -545,6 +1218,20 @@ cdef number *sa2si_NF(object elem, ring *_ring): cdef number *sa2si_ZZ(Integer d, ring *_ring): """ + Create a singular number from a sage Integer. + + INPUT: + + - ``elem`` - a sage Integer + + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + + + OUTPUT: + + - A (pointer to) a singular number + + TESTS:: sage: P. = ZZ[] @@ -564,6 +1251,14 @@ cdef number *sa2si_ZZ(Integer d, ring *_ring): cdef inline number *sa2si_ZZmod(IntegerMod_abstract d, ring *_ring): """ + Create a singular number from a sage element of a IntegerModRing. + + INPUT: + + - ``elem`` - a sage IntegerMod + + - ``_ ring`` - a (pointer to) a singular ring, where the resul will live + TESTS:: sage: P. = Integers(10)[] @@ -637,6 +1332,21 @@ cdef inline number *sa2si_ZZmod(IntegerMod_abstract d, ring *_ring): raise ValueError cdef object si2sa(number *n, ring *_ring, object base): + r""" + Create a sage number from a singular one + + INPUT: + + - ``n`` - a (pointer to) a singular number + + - ``_ring`` - a (pointer to) the singular ring where ``n`` lives + + - ``object`` - the sage parent where the result will live + + OUTPUT: + + An element of ``base`` + """ if isinstance(base, FiniteField_prime_modn): return base(_ring.cf.cfInt(n, _ring.cf)) @@ -658,6 +1368,12 @@ cdef object si2sa(number *n, ring *_ring, object base): elif isinstance(base, NumberField) and base.is_absolute(): return si2sa_NF(n, _ring, base) + elif isinstance(base, FractionField_generic) and isinstance(base.base(), (MPolynomialRing_libsingular, PolynomialRing_field)) and isinstance(base.base_ring(), RationalField): + return si2sa_transext_QQ(n, _ring, base) + + elif isinstance(base, FractionField_generic) and isinstance(base.base(), (MPolynomialRing_libsingular, PolynomialRing_field)) and isinstance(base.base_ring(), FiniteField_prime_modn): + return si2sa_transext_FF(n, _ring, base) + elif isinstance(base, IntegerModRing_generic): if _ring.cf.type == n_unknown: return base(_ring.cf.cfInt(n, _ring.cf)) @@ -667,6 +1383,20 @@ cdef object si2sa(number *n, ring *_ring, object base): raise ValueError("cannot convert from SINGULAR number") cdef number *sa2si(Element elem, ring * _ring): + r""" + Create a singular number from a sage one. + + INPUT: + + - ``elem`` - a sage element from a parent. The parent must have a + corresponding singular coefficient type. + + - ``_ring`` - a (pointer to) the singular ring where the result will live. + + OUTPUT: + + a (pointer to) a singular number + """ cdef int i = 0 if isinstance(elem._parent, FiniteField_prime_modn): return n_Init(int(elem),_ring) @@ -692,11 +1422,27 @@ cdef number *sa2si(Element elem, ring * _ring): if _ring.cf.type == n_unknown: return n_Init(int(elem),_ring) return sa2si_ZZmod(elem, _ring) - else: - raise ValueError("cannot convert to SINGULAR number") + elif isinstance(elem._parent, FractionField_generic) and isinstance(elem._parent.base(), (MPolynomialRing_libsingular, PolynomialRing_field)): + if isinstance(elem._parent.base().base_ring(), RationalField): + return sa2si_transext_QQ(elem, _ring) + elif isinstance(elem._parent.base().base_ring(), FiniteField_prime_modn): + return sa2si_transext_FF(elem, _ring) + + raise ValueError("cannot convert to SINGULAR number") cdef object si2sa_intvec(intvec *v): + r""" + create a sage tuple from a singular vector of integers + + INPUT: + + - ``v`` - a (pointer to) a singular intvec + + OUTPUT: + + a sage tuple + """ cdef int r cdef list l = list() for r in range(v.length()): diff --git a/src/sage/misc/html.py b/src/sage/misc/html.py index 7dacc5f2748..cc310888512 100644 --- a/src/sage/misc/html.py +++ b/src/sage/misc/html.py @@ -294,12 +294,13 @@ def eval(self, x, globals=None, locals=None, mode='display', combine_all=False): sage: MathJax().eval(3, mode='inline') \(\newcommand{\Bold}[1]{\mathbf{#1}}3\) sage: MathJax().eval(type(3), mode='inline') - \(\newcommand{\Bold}[1]{\mathbf{#1}}\verb||\) + \(\newcommand{\Bold}[1]{\mathbf{#1}}\verb|<class|\verb| |\verb|'sage.rings.integer.Integer'>|\) """ # Get a regular LaTeX representation of x x = latex(x, combine_all=combine_all) - # The following block, hopefully, can be removed in some future MathJax. + # The "\text{\texttt{...}}" blocks are reformed to be renderable by MathJax. + # These blocks are produced by str_function() defined in sage.misc.latex. prefix = r"\text{\texttt{" parts = x.split(prefix) for i, part in enumerate(parts): @@ -324,7 +325,6 @@ def eval(self, x, globals=None, locals=None, mode='display', combine_all=False): delimiter = "|" y = "(complicated string)" wrapper = r"\verb" + delimiter + "%s" + delimiter - spacer = r"\phantom{\verb!%s!}" y = y.replace("{ }", " ").replace("{-}", "-") for c in r"#$%&\^_{}~": char_wrapper = r"{\char`\%s}" % c @@ -336,14 +336,12 @@ def eval(self, x, globals=None, locals=None, mode='display', combine_all=False): nspaces += 1 continue if nspaces > 0: - subparts.append(spacer % ("x" * nspaces)) + subparts.append(wrapper % (" " * nspaces)) nspaces = 1 subparts.append(wrapper % subpart) - # There is a bug with omitting empty lines in arrays - if not y: - subparts.append(spacer % "x") subparts.append(part[closing + 1:]) parts[i] = "".join(subparts) + from sage.misc.latex_macros import sage_configurable_latex_macros from sage.misc.latex import _Latex_prefs latex_string = ''.join( @@ -351,15 +349,16 @@ def eval(self, x, globals=None, locals=None, mode='display', combine_all=False): [_Latex_prefs._option['macros']] + parts ) + mathjax_string = latex_string.replace('<', '<') if mode == 'display': html = r'\[{0}\]' elif mode == 'inline': html = r'\({0}\)' elif mode == 'plain': - return latex_string + return mathjax_string else: raise ValueError("mode must be either 'display', 'inline', or 'plain'") - return MathJaxExpr(html.format(latex_string)) + return MathJaxExpr(html.format(mathjax_string)) class HTMLFragmentFactory(SageObject): @@ -412,7 +411,7 @@ def __call__(self, obj, concatenate=True, strict=False): sagemath sage: html('sagemath', strict=True) - \[\newcommand{\Bold}[1]{\mathbf{#1}}\verb|sagemath|\] + \[\newcommand{\Bold}[1]{\mathbf{#1}}\verb|<a|\verb| |\verb|href="http://sagemath.org">sagemath</a>|\] """ # string obj is interpreted as an HTML in not strict mode if isinstance(obj, str) and not strict: diff --git a/src/sage/misc/misc.py b/src/sage/misc/misc.py index fbebd99b3a3..659e83b1208 100644 --- a/src/sage/misc/misc.py +++ b/src/sage/misc/misc.py @@ -759,7 +759,7 @@ def nest(f, n, x): x """ - from sage.rings.all import Integer + from sage.rings.integer import Integer n = Integer(n) if n < 0: diff --git a/src/sage/misc/persist.pyx b/src/sage/misc/persist.pyx index e19dba5db83..2a3a61fdce0 100644 --- a/src/sage/misc/persist.pyx +++ b/src/sage/misc/persist.pyx @@ -562,6 +562,14 @@ def unpickle_global(module, name): ImportError: cannot import some_old_class from sage.some_old_module, call register_unpickle_override('sage.some_old_module', 'some_old_class', ...) to fix this + + TESTS: + + Test that :func:`register_unpickle_override` calls in lazily imported modules + are respected:: + + sage: unpickle_global('sage.combinat.root_system.type_A', 'ambient_space') + """ unpickler = unpickle_override.get((module, name)) if unpickler is not None: @@ -582,6 +590,12 @@ def unpickle_global(module, name): __import__(module) except ImportError: error() + + # Importing the module may have run register_unpickle_override. + unpickler = unpickle_override.get((module, name)) + if unpickler is not None: + return unpickler[0] + mod = sys.modules[module] return getattr(mod, name) diff --git a/src/sage/modular/btquotients/pautomorphicform.py b/src/sage/modular/btquotients/pautomorphicform.py index 5668569ae85..28f1618ee2e 100644 --- a/src/sage/modular/btquotients/pautomorphicform.py +++ b/src/sage/modular/btquotients/pautomorphicform.py @@ -47,7 +47,7 @@ from sage.matrix.matrix_space import MatrixSpace from sage.structure.element import ModuleElement from sage.modules.module import Module -from sage.rings.all import Integer +from sage.rings.integer import Integer from sage.matrix.constructor import Matrix, zero_matrix from sage.rings.all import Qp, QQ, ZZ from copy import copy diff --git a/src/sage/modular/modform/ambient_R.py b/src/sage/modular/modform/ambient_R.py index 9bac23c8970..a99b080062f 100644 --- a/src/sage/modular/modform/ambient_R.py +++ b/src/sage/modular/modform/ambient_R.py @@ -109,7 +109,7 @@ def _compute_q_expansion_basis(self, prec=None): elif c.is_prime_power(): K = self.base_ring() p = K.characteristic().prime_factors()[0] - from sage.rings.all import GF + from sage.rings.finite_rings.finite_field_constructor import GF Kp = GF(p) newB = [f.change_ring(K) for f in list(self.__M.cuspidal_subspace().q_integral_basis(prec))] A = Kp**prec diff --git a/src/sage/modular/modform/defaults.py b/src/sage/modular/modform/defaults.py index 3d064931119..d2b5127cb17 100644 --- a/src/sage/modular/modform/defaults.py +++ b/src/sage/modular/modform/defaults.py @@ -8,7 +8,7 @@ # The default precision for computation and display of q-expansions of # modular forms. -from sage.rings.all import Integer +from sage.rings.integer import Integer DEFAULT_PRECISION = Integer(6) DEFAULT_VARIABLE = 'q' diff --git a/src/sage/modular/modform/eisenstein_submodule.py b/src/sage/modular/modform/eisenstein_submodule.py index a4fc4a1aa6f..ab041a78fc4 100644 --- a/src/sage/modular/modform/eisenstein_submodule.py +++ b/src/sage/modular/modform/eisenstein_submodule.py @@ -4,7 +4,7 @@ """ from sage.structure.all import Sequence -from sage.misc.all import cached_method +from sage.misc.cachefunc import cached_method import sage.rings.all as rings from sage.categories.all import Objects from sage.matrix.all import Matrix diff --git a/src/sage/modular/modform/numerical.py b/src/sage/modular/modform/numerical.py index f09aca90239..056f5ad88f1 100644 --- a/src/sage/modular/modform/numerical.py +++ b/src/sage/modular/modform/numerical.py @@ -71,21 +71,21 @@ class NumericalEigenforms(SageObject): sage: n = numerical_eigenforms(23) sage: n == loads(dumps(n)) True - sage: n.ap(2) # rel tol 2e-14 + sage: n.ap(2) # abs tol 1e-12 [3.0, -1.6180339887498947, 0.6180339887498968] - sage: n.systems_of_eigenvalues(7) # rel tol 2e-14 + sage: n.systems_of_eigenvalues(7) # abs tol 2e-12 [ [-1.6180339887498947, 2.2360679774997894, -3.2360679774997894], [0.6180339887498968, -2.236067977499788, 1.2360679774997936], [3.0, 4.0, 6.0] ] - sage: n.systems_of_abs(7) + sage: n.systems_of_abs(7) # abs tol 2e-12 [ - [0.6180339887..., 2.236067977..., 1.236067977...], - [1.6180339887..., 2.236067977..., 3.236067977...], + [0.6180339887498943, 2.2360679774997894, 1.2360679774997887], + [1.6180339887498947, 2.23606797749979, 3.2360679774997894], [3.0, 4.0, 6.0] ] - sage: n.eigenvalues([2,3,5]) # rel tol 2e-14 + sage: n.eigenvalues([2,3,5]) # rel tol 2e-12 [[3.0, -1.6180339887498947, 0.6180339887498968], [4.0, 2.2360679774997894, -2.236067977499788], [6.0, -3.2360679774997894, 1.2360679774997936]] diff --git a/src/sage/modular/modsym/manin_symbol_list.py b/src/sage/modular/modsym/manin_symbol_list.py index dc4226b5db5..187db53bd16 100644 --- a/src/sage/modular/modsym/manin_symbol_list.py +++ b/src/sage/modular/modsym/manin_symbol_list.py @@ -36,7 +36,7 @@ import sage.modular.modsym.p1list as p1list import sage.modular.modsym.g1list as g1list import sage.modular.modsym.ghlist as ghlist -from sage.rings.all import Integer +from sage.rings.integer import Integer from sage.structure.parent import Parent from sage.misc.persist import register_unpickle_override from sage.structure.richcmp import richcmp_method, richcmp diff --git a/src/sage/modules/filtered_vector_space.py b/src/sage/modules/filtered_vector_space.py index dd6608c6161..dd5784041eb 100644 --- a/src/sage/modules/filtered_vector_space.py +++ b/src/sage/modules/filtered_vector_space.py @@ -113,7 +113,7 @@ from sage.categories.fields import Fields from sage.modules.free_module import FreeModule_ambient_field, VectorSpace from sage.matrix.constructor import matrix -from sage.misc.all import cached_method +from sage.misc.cachefunc import cached_method def is_FilteredVectorSpace(X): diff --git a/src/sage/modules/free_quadratic_module_integer_symmetric.py b/src/sage/modules/free_quadratic_module_integer_symmetric.py index d09578682ea..d872452021b 100644 --- a/src/sage/modules/free_quadratic_module_integer_symmetric.py +++ b/src/sage/modules/free_quadratic_module_integer_symmetric.py @@ -1050,7 +1050,7 @@ def maximal_overlattice(self, p=None): # and trac:11940 if not self.is_even() and (p is None or p==2): raise ValueError("This lattice must be even to admit an even overlattice") - from sage.rings.all import GF + from sage.rings.finite_rings.finite_field_constructor import GF L = self if p is None: P = ZZ(self.determinant()).prime_factors() diff --git a/src/sage/modules/multi_filtered_vector_space.py b/src/sage/modules/multi_filtered_vector_space.py index 0d0e4b316e7..61e4754452e 100644 --- a/src/sage/modules/multi_filtered_vector_space.py +++ b/src/sage/modules/multi_filtered_vector_space.py @@ -43,7 +43,7 @@ from sage.rings.infinity import infinity, minus_infinity from sage.categories.fields import Fields from sage.modules.free_module import FreeModule_ambient_field, VectorSpace -from sage.misc.all import cached_method +from sage.misc.cachefunc import cached_method from sage.modules.filtered_vector_space import FilteredVectorSpace diff --git a/src/sage/monoids/automatic_semigroup.py b/src/sage/monoids/automatic_semigroup.py index b06df8af2f7..aa14bf11388 100644 --- a/src/sage/monoids/automatic_semigroup.py +++ b/src/sage/monoids/automatic_semigroup.py @@ -20,7 +20,7 @@ # **************************************************************************** import operator -from sage.misc.all import cached_method +from sage.misc.cachefunc import cached_method from sage.categories.semigroups import Semigroups from sage.categories.sets_cat import Sets from sage.categories.monoids import Monoids diff --git a/src/sage/parallel/decorate.py b/src/sage/parallel/decorate.py index 37df8188691..43dd7a8142c 100644 --- a/src/sage/parallel/decorate.py +++ b/src/sage/parallel/decorate.py @@ -4,7 +4,7 @@ import types -from sage.rings.all import Integer +from sage.rings.integer import Integer from .reference import parallel_iter as p_iter_reference from .use_fork import p_iter_fork diff --git a/src/sage/plot/colors.py b/src/sage/plot/colors.py index 0f2923aa972..6fdba0f0da0 100644 --- a/src/sage/plot/colors.py +++ b/src/sage/plot/colors.py @@ -21,7 +21,7 @@ For a list of color maps in Sage, evaluate:: sage: sorted(colormaps) - [u'Accent', u'Blues', u'BrBG', ...] + ['Accent', 'Blues', 'BrBG', ...] These are imported from matplotlib's cm_ module. @@ -290,16 +290,10 @@ def rgbcolor(c, space='rgb'): (0.25, 0.4, 0.9) sage: rgbcolor('purple') (0.5019607843137255, 0.0, 0.5019607843137255) - sage: rgbcolor(u'purple') - (0.5019607843137255, 0.0, 0.5019607843137255) sage: rgbcolor('#fa0') (1.0, 0.6666666666666666, 0.0) - sage: rgbcolor(u'#fa0') - (1.0, 0.6666666666666666, 0.0) sage: rgbcolor('#ffffff') (1.0, 1.0, 1.0) - sage: rgbcolor(u'#ffffff') - (1.0, 1.0, 1.0) sage: rgbcolor((1,1/2,1/3)) (1.0, 0.5, 0.3333333333333333) sage: rgbcolor([1,1/2,1/3]) @@ -510,8 +504,7 @@ def __eq__(self, right): """ if isinstance(right, Color): return self._rgb == right._rgb - else: - return False + return False def __ne__(self, right): """ @@ -824,7 +817,7 @@ def __int__(self): OUTPUT: - the integer `256^2 r_int + 256 g_int + b_int`, where `r_int`, `g_int`, and `b_int` - are obtained from `r`, `g`, and `b` by converting from the real interval [0.0, 1.0] + are obtained from `r`, `g`, and `b` by converting from the real interval [0.0, 1.0] to the integer range 0, 1, ..., 255. EXAMPLES:: @@ -1115,7 +1108,7 @@ def __getattr__(self, name): try: return self[name] except KeyError: - raise AttributeError("'%s' has no attribute or colormap %s"%(type(self).__name__,name)) + raise AttributeError("'%s' has no attribute or colormap %s" % (type(self).__name__, name)) def __dir__(self): """ @@ -1136,8 +1129,10 @@ def __dir__(self): methods = ['__dir__', '__getattr__'] return dir(super(ColorsDict, self)) + methods + sorted(self) + colors = ColorsDict() + # Add convenient module-scope colors. These are Color instances. for c in colors: vars()[c] = colors[c] @@ -1254,7 +1249,7 @@ def float_to_integer(r, g, b): OUTPUT: - the integer `256^2 r_int + 256 g_int + b_int`, where `r_int`, `g_int`, and `b_int` - are obtained from `r`, `g`, and `b` by converting from the real interval [0.0, 1.0] + are obtained from `r`, `g`, and `b` by converting from the real interval [0.0, 1.0] to the integer range 0, 1, ..., 255. EXAMPLES:: @@ -1337,7 +1332,7 @@ def get_cmap(cmap): and color names. For a list of map names, evaluate:: sage: sorted(colormaps) - [u'Accent', u'Blues', ...] + ['Accent', 'Blues', ...] See :func:`rgbcolor` for valid list/tuple element formats. @@ -1356,8 +1351,6 @@ def get_cmap(cmap): sage: from sage.plot.colors import get_cmap sage: get_cmap('jet') - sage: get_cmap(u'jet') - sage: get_cmap([(0,0,0), (0.5,0.5,0.5), (1,1,1)]) sage: get_cmap(['green', 'lightblue', 'blue']) @@ -1383,7 +1376,7 @@ def get_cmap(cmap): return cmap elif isinstance(cmap, str): - if not cmap in cm.datad: + if cmap not in cm.datad: raise RuntimeError("Color map %s not known (type import matplotlib.cm; matplotlib.cm.datad.keys() for valid names)" % cmap) return cm.__dict__[cmap] @@ -1431,7 +1424,7 @@ class Colormaps(MutableMapping): For a list of map names, evaluate:: sage: sorted(colormaps) - [u'Accent', u'Blues', ...] + ['Accent', 'Blues', ...] """ def __init__(self): """ @@ -1616,7 +1609,7 @@ def __getattr__(self, name): try: return self[name] except KeyError: - raise AttributeError("'%s' has no attribute or colormap %s"%(type(self).__name__,name)) + raise AttributeError("'%s' has no attribute or colormap %s" % (type(self).__name__, name)) def __repr__(self): """ @@ -1678,7 +1671,7 @@ def __delitem__(self, name): sage: maps = Colormaps() sage: count = len(maps) sage: maps.popitem() # random - (u'Spectral', ) + ('Spectral', ) sage: count - 1 == len(maps) True """ diff --git a/src/sage/plot/graphics.py b/src/sage/plot/graphics.py index 61fa25dd277..137f65016f4 100644 --- a/src/sage/plot/graphics.py +++ b/src/sage/plot/graphics.py @@ -99,7 +99,7 @@ def _parse_figsize(figsize): if len(figsize) != 2: raise ValueError("figsize should be a positive number or a list " "of two positive numbers, not {0}".format(figsize)) - figsize = (float(figsize[0]), float(figsize[1])) # floats for mpl + figsize = (float(figsize[0]), float(figsize[1])) # floats for mpl if not (figsize[0] > 0 and figsize[1] > 0): raise ValueError("figsize should be positive numbers, " "not {0} and {1}".format(figsize[0], figsize[1])) @@ -107,12 +107,12 @@ def _parse_figsize(figsize): # in this case, figsize is a single number representing the width and # should be positive try: - figsize = float(figsize) # to pass to mpl + figsize = float(figsize) # to pass to mpl except TypeError: raise TypeError("figsize should be a positive number, not {0}".format(figsize)) if figsize > 0: default_width, default_height = rcParams['figure.figsize'] - figsize = (figsize, default_height*figsize/default_width) + figsize = (figsize, default_height * figsize / default_width) else: raise ValueError("figsize should be positive, not {0}".format(figsize)) return figsize @@ -435,7 +435,6 @@ def set_legend_options(self, **kwds): else: self._legend_opts.update(kwds) - def get_axes_range(self): """ Returns a dictionary of the range of the axes for this graphics @@ -784,9 +783,9 @@ def axes_labels(self, l=None): :: sage: c = circle((0,0), 1) - sage: c.axes_labels(['axe des abscisses', u'axe des ordonnées']) + sage: c.axes_labels(['axe des abscisses', 'axe des ordonnées']) sage: c._axes_labels - ('axe des abscisses', u'axe des ordonn\xe9es') + ('axe des abscisses', 'axe des ordonnées') """ if l is None: try: @@ -852,7 +851,6 @@ def axes_label_color(self, c=None): return self._axes_label_color self._axes_label_color = rgbcolor(c) - def axes_width(self, w=None): r""" Set the axes width. Use this to draw a plot with really fat or @@ -1019,7 +1017,7 @@ def __str__(self): sage: print(S) Graphics object consisting of 1 graphics primitive """ - s = "Graphics object consisting of %s graphics primitives"%(len(self)) + s = "Graphics object consisting of %s graphics primitives" % (len(self)) if len(self) == 1: s = s[:-1] return s @@ -1193,7 +1191,7 @@ def __add__(self, other): from sage.plot.plot3d.base import Graphics3d if isinstance(other, Graphics3d): return self.plot3d() + other - raise TypeError("other (=%s) must be a Graphics objects"%other) + raise TypeError("other (=%s) must be a Graphics objects" % other) g = Graphics() g._objects = self._objects + other._objects g._show_legend = self._show_legend or other._show_legend @@ -1208,9 +1206,9 @@ def __add__(self, other): if 'flip_y' in self._extra_kwds and 'flip_y' in other._extra_kwds: g._extra_kwds['flip_y'] = (self._extra_kwds['flip_y'] or other._extra_kwds['flip_y']) - if self.aspect_ratio()=='automatic': + if self.aspect_ratio() == 'automatic': g.set_aspect_ratio(other.aspect_ratio()) - elif other.aspect_ratio()=='automatic': + elif other.aspect_ratio() == 'automatic': g.set_aspect_ratio(self.aspect_ratio()) else: g.set_aspect_ratio(max(self.aspect_ratio(), other.aspect_ratio())) @@ -1275,7 +1273,7 @@ def plot3d(self, z=0, **kwds): from sage.plot.plot3d.base import Graphics3dGroup g = Graphics3dGroup([g.plot3d(**kwds) for g in self._objects]) if z: - g = g.translate(0,0,z) + g = g.translate(0, 0, z) return g @classmethod @@ -1412,7 +1410,6 @@ def _set_scale(self, subplot, scale=None, base=None): return (xscale, yscale, basex, basey) - # This dictionary has the default values for the keywords to show(). When # show is invoked with keyword arguments, those arguments are merged with # this dictionary to create a set of keywords with the defaults filled in. @@ -2199,7 +2196,6 @@ def ymax(self, ymax=None): else: self.set_axes_range(ymax=ymax) - def get_minmax_data(self): r""" Return the x and y coordinate minimum and maximum @@ -2252,16 +2248,16 @@ def get_minmax_data(self): ymin = min(d['ymin'] for d in minmax_data) ymax = max(d['ymax'] for d in minmax_data) if isnan(xmin): - xmin=0 + xmin = 0 sage.misc.verbose.verbose("xmin was NaN (setting to 0)", level=0) if isnan(xmax): - xmax=0 + xmax = 0 sage.misc.verbose.verbose("xmax was NaN (setting to 0)", level=0) if isnan(ymin): - ymin=0 + ymin = 0 sage.misc.verbose.verbose("ymin was NaN (setting to 0)", level=0) if isnan(ymax): - ymax=0 + ymax = 0 sage.misc.verbose.verbose("ymax was NaN (setting to 0)", level=0) else: xmin = xmax = ymin = ymax = 0 @@ -2312,18 +2308,18 @@ def _limit_output_aspect_ratio(self, xmin, xmax, ymin, ymax): if aspect_ratio != 'automatic': width = xmax - xmin height = ymax - ymin - output_aspect = abs(width/height/aspect_ratio) + output_aspect = abs(width / height / aspect_ratio) if output_aspect > 1e15: height = 1e15 * width / aspect_ratio ycenter = (ymax - ymin) / 2 - ymin = ycenter - height/2 - ymax = ycenter + height/2 + ymin = ycenter - height / 2 + ymax = ycenter + height / 2 if output_aspect < 1e-15: width = 1e-15 * height * aspect_ratio xcenter = (xmax - xmin) / 2 - xmin = xcenter - width/2 - xmax = xcenter + width/2 - return {'xmin':xmin, 'xmax':xmax, 'ymin':ymin, 'ymax':ymax} + xmin = xcenter - width / 2 + xmax = xcenter + width / 2 + return {'xmin': xmin, 'xmax': xmax, 'ymin': ymin, 'ymax': ymax} def _matplotlib_tick_formatter(self, subplot, base=(10, 10), locator_options={}, scale=('linear', 'linear'), @@ -2356,45 +2352,45 @@ def _matplotlib_tick_formatter(self, subplot, base=(10, 10), MultipleLocator, NullLocator, ScalarFormatter) x_locator, y_locator = ticks - #---------------------- Location of x-ticks ---------------------# + # ---------------------- Location of x-ticks --------------------- if x_locator is None: if scale[0] == 'log': x_locator = LogLocator(base=base[0]) else: x_locator = MaxNLocator(**locator_options) - elif isinstance(x_locator,Locator): + elif isinstance(x_locator, Locator): pass elif x_locator == []: x_locator = NullLocator() - elif isinstance(x_locator,list): + elif isinstance(x_locator, list): x_locator = FixedLocator(x_locator) - else: # x_locator is a number which can be made a float + else: # x_locator is a number which can be made a float from sage.functions.other import ceil, floor - if floor(xmax/x_locator)-ceil(xmin/x_locator)>1: - x_locator=MultipleLocator(float(x_locator)) - else: # not enough room for two major ticks + if floor(xmax / x_locator) - ceil(xmin / x_locator) > 1: + x_locator = MultipleLocator(float(x_locator)) + else: # not enough room for two major ticks raise ValueError('Expand the range of the independent ' 'variable to allow two multiples of your tick locator ' '(option `ticks`).') - #---------------------- Location of y-ticks ---------------------# + # ---------------------- Location of y-ticks --------------------- if y_locator is None: if scale[1] == 'log': y_locator = LogLocator(base=base[1]) else: y_locator = MaxNLocator(**locator_options) - elif isinstance(y_locator,Locator): + elif isinstance(y_locator, Locator): pass elif y_locator == []: y_locator = NullLocator() - elif isinstance(y_locator,list): + elif isinstance(y_locator, list): y_locator = FixedLocator(y_locator) - else: # y_locator is a number which can be made a float + else: # y_locator is a number which can be made a float from sage.functions.other import ceil, floor - if floor(ymax/y_locator)-ceil(ymin/y_locator)>1: - y_locator=MultipleLocator(float(y_locator)) - else: # not enough room for two major ticks + if floor(ymax / y_locator) - ceil(ymin / y_locator) > 1: + y_locator = MultipleLocator(float(y_locator)) + else: # not enough room for two major ticks raise ValueError('Expand the range of the dependent ' 'variable to allow two multiples of your tick locator ' '(option `ticks`).') @@ -2404,7 +2400,7 @@ def _matplotlib_tick_formatter(self, subplot, base=(10, 10), from sage.misc.latex import latex from sage.symbolic.ring import SR from .misc import _multiple_of_constant - #---------------------- Formatting x-ticks ----------------------# + # ---------------------- Formatting x-ticks ---------------------- if x_formatter is None: if scale[0] == 'log': x_formatter = LogFormatterMathtext(base=base[0]) @@ -2412,16 +2408,16 @@ def _matplotlib_tick_formatter(self, subplot, base=(10, 10), x_formatter = ScalarFormatter() elif x_formatter in SR: x_const = x_formatter - x_formatter = FuncFormatter(lambda n,pos: - _multiple_of_constant(n,pos,x_const)) + x_formatter = FuncFormatter(lambda n, pos: + _multiple_of_constant(n, pos, x_const)) elif x_formatter == "latex": if scale[0] == 'log': # We need to strip out '\\mathdefault' from the string - x_formatter = FuncFormatter(lambda n,pos: - LogFormatterMathtext(base=base[0])(n,pos).replace( - "\\mathdefault","")) + x_formatter = FuncFormatter(lambda n, pos: + LogFormatterMathtext(base=base[0])(n, pos).replace( + "\\mathdefault", "")) else: - x_formatter = FuncFormatter(lambda n,pos: '$%s$'%latex(n)) + x_formatter = FuncFormatter(lambda n, pos: '$%s$' % latex(n)) elif isinstance(x_formatter, (list, tuple)): if (not isinstance(ticks[0], (list, tuple)) or len(ticks[0]) != len(x_formatter)): @@ -2429,7 +2425,7 @@ def _matplotlib_tick_formatter(self, subplot, base=(10, 10), "`tick_formatter` is a list then the first component " "of `ticks` must also be a list of equal length.") x_formatter = FixedFormatter(x_formatter) - #---------------------- Formatting y-ticks ----------------------# + # ---------------------- Formatting y-ticks ---------------------- if y_formatter is None: if scale[1] == 'log': y_formatter = LogFormatterMathtext(base=base[1]) @@ -2437,16 +2433,16 @@ def _matplotlib_tick_formatter(self, subplot, base=(10, 10), y_formatter = ScalarFormatter() elif y_formatter in SR: y_const = y_formatter - y_formatter = FuncFormatter(lambda n,pos: - _multiple_of_constant(n,pos,y_const)) + y_formatter = FuncFormatter(lambda n, pos: + _multiple_of_constant(n, pos, y_const)) elif y_formatter == "latex": if scale[1] == 'log': # We need to strip out '\\mathdefault' from the string - y_formatter = FuncFormatter(lambda n,pos: - LogFormatterMathtext(base=base[1])(n,pos).replace( - "\\mathdefault","")) + y_formatter = FuncFormatter(lambda n, pos: + LogFormatterMathtext(base=base[1])(n, pos).replace( + "\\mathdefault", "")) else: - y_formatter = FuncFormatter(lambda n,pos: '$%s$'%latex(n)) + y_formatter = FuncFormatter(lambda n, pos: '$%s$' % latex(n)) elif isinstance(y_formatter, (list, tuple)): if (not isinstance(ticks[1], (list, tuple)) or len(ticks[1]) != len(y_formatter)): @@ -2478,7 +2474,6 @@ def _matplotlib_tick_formatter(self, subplot, base=(10, 10), return (subplot, x_locator, y_locator, x_formatter, y_formatter) - def _get_vmin_vmax(self, vmin, vmax, basev, axes_pad): r""" Determine the min/max value for a variable plotted on a logarithmic @@ -2570,14 +2565,14 @@ def _get_vmin_vmax(self, vmin, vmax, basev, axes_pad): else: axes_pad = float(abs(axes_pad)) - logvmin = math.log(vmin)/math.log(basev) - logvmax = math.log(vmax)/math.log(basev) + logvmin = math.log(vmin) / math.log(basev) + logvmax = math.log(vmax) / math.log(basev) if math.floor(logvmax) - math.ceil(logvmin) < 0: vmax = basev**math.ceil(logvmax) vmin = basev**math.floor(logvmin) elif math.floor(logvmax) - math.ceil(logvmin) < 1: - if logvmax-math.floor(logvmax) > math.ceil(logvmin)-logvmin: + if logvmax - math.floor(logvmax) > math.ceil(logvmin) - logvmin: vmax = basev**math.ceil(logvmax) if axes_pad > 0: vmin -= vmin * basev**(-axes_pad) @@ -2730,15 +2725,15 @@ def matplotlib(self, filename=None, axes = self._show_axes from matplotlib.figure import Figure - if typeset == 'type1': # Requires LaTeX, dvipng, gs to be installed. + if typeset == 'type1': # Requires LaTeX, dvipng, gs to be installed. rcParams['ps.useafm'] = True rcParams['pdf.use14corefonts'] = True rcParams['text.usetex'] = True - elif typeset == 'latex': # Requires LaTeX, dvipng, gs to be installed. + elif typeset == 'latex': # Requires LaTeX, dvipng, gs to be installed. rcParams['ps.useafm'] = False rcParams['pdf.use14corefonts'] = False rcParams['text.usetex'] = True - elif typeset != 'default': # We won't change (maybe user-set) defaults + elif typeset != 'default': # We won't change (maybe user-set) defaults raise ValueError("typeset must be set to one of 'default', 'latex'," " or 'type1'; got '{}'.".format(typeset)) @@ -2772,13 +2767,13 @@ def matplotlib(self, filename=None, self._bbox_extra_artists.extend(g._bbox_extra_artists) # Set the aspect ratio if aspect_ratio is None: - aspect_ratio=self.aspect_ratio() + aspect_ratio = self.aspect_ratio() if aspect_ratio == 'automatic': subplot.set_aspect('auto', adjustable='box') else: subplot.set_aspect(aspect_ratio, adjustable='box') - #---------------- Set the axes limits and scale ------------------# + # ---------------- Set the axes limits and scale ------------------ self.set_axes_range(xmin, xmax, ymin, ymax) d = self.get_axes_range() xmin = d['xmax' if flip_x else 'xmin'] @@ -2797,7 +2792,7 @@ def matplotlib(self, filename=None, xmax, xmin = self._get_vmin_vmax(xmax, xmin, basex, axes_pad) else: xpad = 0.02 if axes_pad is None else axes_pad - xpad = (xmax - xmin)*float(xpad) + xpad = (xmax - xmin) * float(xpad) xmax += xpad xmin -= xpad @@ -2809,11 +2804,11 @@ def matplotlib(self, filename=None, ymax, ymin = self._get_vmin_vmax(ymax, ymin, basey, axes_pad) else: ypad = 0.02 if axes_pad is None else axes_pad - ypad = (ymax - ymin)*float(ypad) + ypad = (ymax - ymin) * float(ypad) ymax += ypad ymin -= ypad - #-------------------------- Set the legend -----------------------# + # -------------------------- Set the legend ----------------------- if show_legend is None: show_legend = self._show_legend @@ -2823,12 +2818,11 @@ def matplotlib(self, filename=None, lopts.update(legend_options) lopts.update(self._legend_opts) prop = FontProperties( - family = lopts.pop('font_family', 'sans-serif'), - size = lopts.pop('font_size', 'medium'), - style = lopts.pop('font_style', 'normal'), - weight = lopts.pop('font_weight', 'medium'), - variant = lopts.pop('font_variant', 'normal') - ) + family=lopts.pop('font_family', 'sans-serif'), + size=lopts.pop('font_size', 'medium'), + style=lopts.pop('font_style', 'normal'), + weight=lopts.pop('font_weight', 'medium'), + variant=lopts.pop('font_variant', 'normal')) color = lopts.pop('back_color', 'white') leg = subplot.legend(prop=prop, **lopts) if leg is None: @@ -2846,7 +2840,8 @@ def matplotlib(self, filename=None, subplot.set_xlim([xmin, xmax]) subplot.set_ylim([ymin, ymax]) - locator_options=dict(nbins=9,steps=[1,2,5,10],integer=ticks_integer) + locator_options = dict(nbins=9, steps=[1, 2, 5, 10], + integer=ticks_integer) if axes is None: axes = self._show_axes @@ -2855,7 +2850,6 @@ def matplotlib(self, filename=None, spine.set_color(self._axes_color) spine.set_linewidth(self._axes_width) - if frame: # For now, set the formatter to the old one, since that is # sort of what we are used to. We should eventually look at @@ -2863,24 +2857,24 @@ def matplotlib(self, filename=None, (subplot, x_locator, y_locator, x_formatter, y_formatter) = self._matplotlib_tick_formatter( - subplot, base=(basex, basey), - locator_options=locator_options, - scale=(xscale, yscale), - tick_formatter=tick_formatter, ticks=ticks, - xmax=xmax, xmin=xmin, ymax=ymax, ymin=ymin) + subplot, base=(basex, basey), + locator_options=locator_options, + scale=(xscale, yscale), + tick_formatter=tick_formatter, ticks=ticks, + xmax=xmax, xmin=xmin, ymax=ymax, ymin=ymin) subplot.set_frame_on(True) if axes and xscale == 'linear' and yscale == 'linear': - if (ymin<=0 and ymax>=0) or (ymax<=0 and ymin>=0): + if (ymin <= 0 and ymax >= 0) or (ymax <= 0 and ymin >= 0): subplot.axhline(color=self._axes_color, linewidth=self._axes_width) - if (xmin<=0 and xmax>=0) or (xmax<=0 and xmin>=0): + if (xmin <= 0 and xmax >= 0) or (xmax <= 0 and xmin >= 0): subplot.axvline(color=self._axes_color, linewidth=self._axes_width) elif axes: - ymiddle=False - xmiddle=False + ymiddle = False + xmiddle = False # Note that the user may specify a custom xmin and xmax which # flips the axis horizontally. Hence we need to check for both # the possibilities in the if statements below. Similar @@ -2888,68 +2882,68 @@ def matplotlib(self, filename=None, if xscale == 'log': if xmax > xmin: subplot.spines['right'].set_visible(False) - subplot.spines['left'].set_position(('outward',10)) + subplot.spines['left'].set_position(('outward', 10)) subplot.yaxis.set_ticks_position('left') subplot.yaxis.set_label_position('left') - yaxis='left' + yaxis = 'left' elif xmax < xmin: subplot.spines['left'].set_visible(False) - subplot.spines['right'].set_position(('outward',10)) + subplot.spines['right'].set_position(('outward', 10)) subplot.yaxis.set_ticks_position('right') subplot.yaxis.set_label_position('right') - yaxis='right' + yaxis = 'right' elif (xmin > 0 and xmax > xmin) or (xmax > 0 and xmin > xmax): subplot.spines['right'].set_visible(False) - subplot.spines['left'].set_position(('outward',10)) + subplot.spines['left'].set_position(('outward', 10)) subplot.yaxis.set_ticks_position('left') subplot.yaxis.set_label_position('left') - yaxis='left' + yaxis = 'left' elif (xmax < 0 and xmax > xmin) or (xmin < 0 and xmin > xmax): subplot.spines['left'].set_visible(False) - subplot.spines['right'].set_position(('outward',10)) + subplot.spines['right'].set_position(('outward', 10)) subplot.yaxis.set_ticks_position('right') subplot.yaxis.set_label_position('right') - yaxis='right' + yaxis = 'right' else: subplot.spines['left'].set_position('zero') subplot.yaxis.set_ticks_position('left') subplot.yaxis.set_label_position('left') subplot.spines['right'].set_visible(False) - ymiddle=True - yaxis='left' + ymiddle = True + yaxis = 'left' if yscale == 'log': if ymax > ymin: subplot.spines['top'].set_visible(False) - subplot.spines['bottom'].set_position(('outward',10)) + subplot.spines['bottom'].set_position(('outward', 10)) subplot.xaxis.set_ticks_position('bottom') subplot.xaxis.set_label_position('bottom') - xaxis='bottom' + xaxis = 'bottom' elif ymax < ymin: subplot.spines['bottom'].set_visible(False) - subplot.spines['top'].set_position(('outward',10)) + subplot.spines['top'].set_position(('outward', 10)) subplot.xaxis.set_ticks_position('top') subplot.xaxis.set_label_position('top') - xaxis='top' + xaxis = 'top' elif (ymin > 0 and ymax > ymin) or (ymax > 0 and ymin > ymax): subplot.spines['top'].set_visible(False) - subplot.spines['bottom'].set_position(('outward',10)) + subplot.spines['bottom'].set_position(('outward', 10)) subplot.xaxis.set_ticks_position('bottom') subplot.xaxis.set_label_position('bottom') - xaxis='bottom' + xaxis = 'bottom' elif (ymax < 0 and ymax > ymin) or (ymin < 0 and ymin > ymax): subplot.spines['bottom'].set_visible(False) - subplot.spines['top'].set_position(('outward',10)) + subplot.spines['top'].set_position(('outward', 10)) subplot.xaxis.set_ticks_position('top') subplot.xaxis.set_label_position('top') - xaxis='top' + xaxis = 'top' else: subplot.spines['bottom'].set_position('zero') subplot.xaxis.set_ticks_position('bottom') subplot.xaxis.set_label_position('bottom') subplot.spines['top'].set_visible(False) - xmiddle=True - xaxis='bottom' + xmiddle = True + xaxis = 'bottom' # For now, set the formatter to the old one, since that is # sort of what we are used to. We should eventually look at @@ -2957,11 +2951,11 @@ def matplotlib(self, filename=None, (subplot, x_locator, y_locator, x_formatter, y_formatter) = self._matplotlib_tick_formatter( - subplot, base=(basex, basey), - locator_options=locator_options, - scale=(xscale, yscale), - tick_formatter=tick_formatter, ticks=ticks, - xmax=xmax, xmin=xmin, ymax=ymax, ymin=ymin) + subplot, base=(basex, basey), + locator_options=locator_options, + scale=(xscale, yscale), + tick_formatter=tick_formatter, ticks=ticks, + xmax=xmax, xmin=xmin, ymax=ymax, ymin=ymin) # Make ticklines go on both sides of the axes # if xmiddle: @@ -2982,8 +2976,7 @@ def matplotlib(self, filename=None, # Make the zero tick labels disappear if the axes cross # inside the picture, but only if log scale is not used - if (xmiddle and ymiddle and xscale == 'linear' and - yscale == 'linear'): + if (xmiddle and ymiddle and xscale == 'linear' == yscale): from sage.plot.plot import SelectiveFormatter subplot.yaxis.set_major_formatter(SelectiveFormatter( subplot.yaxis.get_major_formatter(), skip_values=[0])) @@ -3009,20 +3002,20 @@ def matplotlib(self, filename=None, subplot.xaxis.set_minor_locator(NullLocator()) elif xscale == 'linear': subplot.xaxis.set_minor_locator(AutoMinorLocator()) - else: # log scale + else: # log scale from sage.arith.srange import srange - base_inv = 1.0/basex - subs = [float(_) for _ in srange(2*base_inv, 1, base_inv)] + base_inv = 1.0 / basex + subs = [float(_) for _ in srange(2 * base_inv, 1, base_inv)] subplot.xaxis.set_minor_locator(LogLocator(base=basex, subs=subs)) if isinstance(y_locator, (NullLocator, FixedLocator)): subplot.yaxis.set_minor_locator(NullLocator()) elif yscale == 'linear': subplot.yaxis.set_minor_locator(AutoMinorLocator()) - else: # log scale + else: # log scale from sage.arith.srange import srange - base_inv = 1.0/basey - subs = [float(_) for _ in srange(2*base_inv, 1, base_inv)] + base_inv = 1.0 / basey + subs = [float(_) for _ in srange(2 * base_inv, 1, base_inv)] subplot.yaxis.set_minor_locator(LogLocator(base=basey, subs=subs)) # Set the color and fontsize of ticks @@ -3032,121 +3025,119 @@ def matplotlib(self, filename=None, if gridlines is not None: if isinstance(gridlines, (list, tuple)): - vgridlines,hgridlines=gridlines + vgridlines, hgridlines = gridlines else: - hgridlines=gridlines - vgridlines=gridlines + hgridlines = gridlines + vgridlines = gridlines if gridlinesstyle is None: # Set up the default grid style - gridlinesstyle=dict(color='black',linestyle=':',linewidth=0.5) + gridlinesstyle = dict(color='black', linestyle=':', + linewidth=0.5) - vgridstyle=gridlinesstyle.copy() + vgridstyle = gridlinesstyle.copy() if vgridlinesstyle is not None: vgridstyle.update(vgridlinesstyle) - hgridstyle=gridlinesstyle.copy() + hgridstyle = gridlinesstyle.copy() if hgridlinesstyle is not None: hgridstyle.update(hgridlinesstyle) - if hgridlines=='minor': - hgridstyle['which']='both' - if vgridlines=='minor': - vgridstyle['which']='both' + if hgridlines == 'minor': + hgridstyle['which'] = 'both' + if vgridlines == 'minor': + vgridstyle['which'] = 'both' if not isinstance(hgridlines, str) and hasattr(hgridlines, '__iter__'): - hlines=iter(hgridlines) - hgridstyle.pop("minor",None) + hlines = iter(hgridlines) + hgridstyle.pop("minor", None) for hline in hlines: if isinstance(hline, (list, tuple)): - hl, style=hline - st=hgridstyle.copy() + hl, style = hline + st = hgridstyle.copy() st.update(style) else: - hl=hline - st=hgridstyle - subplot.axhline(hl,**st) + hl = hline + st = hgridstyle + subplot.axhline(hl, **st) else: if hgridlines not in (None, False): subplot.yaxis.grid(True, **hgridstyle) if not isinstance(vgridlines, str) and hasattr(vgridlines, '__iter__'): - vlines=iter(vgridlines) - vgridstyle.pop("minor",None) + vlines = iter(vgridlines) + vgridstyle.pop("minor", None) for vline in vlines: if isinstance(vline, (list, tuple)): - vl, style=vline - st=vgridstyle.copy() + vl, style = vline + st = vgridstyle.copy() st.update(style) else: - vl=vline - st=vgridstyle - subplot.axvline(vl,**st) + vl = vline + st = vgridstyle + subplot.axvline(vl, **st) else: if vgridlines not in (None, False): subplot.xaxis.grid(True, **vgridstyle) - - if self._axes_labels is not None: - label_options={} - label_options['color']=self._axes_label_color - label_options['size']=int(self._axes_labels_size * self._fontsize) + label_options = {} + label_options['color'] = self._axes_label_color + label_options['size'] = int(self._axes_labels_size * self._fontsize) subplot.set_xlabel(self._axes_labels[0], **label_options) subplot.set_ylabel(self._axes_labels[1], **label_options) - if axes is True and frame is False: # We set the label positions according to where we are # drawing the axes. - if xaxis=='bottom': - yaxis_labely=subplot.get_ylim()[1] - yaxis_labeloffset=8 - yaxis_vert='bottom' - xaxis_labely=0 - xaxis_vert='baseline' + if xaxis == 'bottom': + yaxis_labely = subplot.get_ylim()[1] + yaxis_labeloffset = 8 + yaxis_vert = 'bottom' + xaxis_labely = 0 + xaxis_vert = 'baseline' else: - yaxis_labely=subplot.get_ylim()[0] - yaxis_labeloffset=-8 - yaxis_vert='top' - xaxis_labely=1 - xaxis_vert='top' - - if yaxis=='left': - xaxis_labelx=subplot.get_xlim()[1] - xaxis_labeloffset=8 - xaxis_horiz='left' - yaxis_labelx=0 + yaxis_labely = subplot.get_ylim()[0] + yaxis_labeloffset = -8 + yaxis_vert = 'top' + xaxis_labely = 1 + xaxis_vert = 'top' + + if yaxis == 'left': + xaxis_labelx = subplot.get_xlim()[1] + xaxis_labeloffset = 8 + xaxis_horiz = 'left' + yaxis_labelx = 0 else: - xaxis_labelx=subplot.get_xlim()[0] - xaxis_labeloffset=-8 - xaxis_horiz='right' - yaxis_labelx=1 + xaxis_labelx = subplot.get_xlim()[0] + xaxis_labeloffset = -8 + xaxis_horiz = 'right' + yaxis_labelx = 1 from matplotlib.transforms import offset_copy - xlabel=subplot.xaxis.get_label() + xlabel = subplot.xaxis.get_label() xlabel.set_horizontalalignment(xaxis_horiz) xlabel.set_verticalalignment(xaxis_vert) - trans=subplot.spines[xaxis].get_transform() - labeltrans=offset_copy(trans, figure, x=xaxis_labeloffset, - y=0, units='points') + trans = subplot.spines[xaxis].get_transform() + labeltrans = offset_copy(trans, figure, x=xaxis_labeloffset, + y=0, units='points') subplot.xaxis.set_label_coords(x=xaxis_labelx, y=xaxis_labely, transform=labeltrans) - ylabel=subplot.yaxis.get_label() + ylabel = subplot.yaxis.get_label() ylabel.set_horizontalalignment('center') ylabel.set_verticalalignment(yaxis_vert) ylabel.set_rotation('horizontal') - trans=subplot.spines[yaxis].get_transform() - labeltrans=offset_copy(trans, figure, x=0, - y=yaxis_labeloffset, units='points') + trans = subplot.spines[yaxis].get_transform() + labeltrans = offset_copy(trans, figure, x=0, + y=yaxis_labeloffset, units='points') subplot.yaxis.set_label_coords(x=yaxis_labelx, y=yaxis_labely, transform=labeltrans) # This option makes the xlim and ylim limits not take effect # todo: figure out which limits were specified, and let the # free limits autoscale - #subplot.autoscale_view(tight=True) + # subplot.autoscale_view(tight=True) if title is not None: if title_pos is not None: if (not isinstance(title_pos, (list, tuple)) or @@ -3161,7 +3152,8 @@ def matplotlib(self, filename=None, position=title_pos) else: subplot.set_title(title, fontsize=fontsize) - else: # frame is false axes is not None, and neither is axes_labels + else: + # frame is false axes is not None, and neither is axes_labels # Then, the title is moved up to avoid overlap with axes labels if title_pos is None: title_pos = (0.5, 1.05) @@ -3195,7 +3187,6 @@ def save_image(self, filename=None, *args, **kwds): """ self.save(filename, *args, **kwds) - # filename argument is written explicitly so that it can be used as a # positional one, which is a very likely usage for this function. @@ -3304,13 +3295,13 @@ def save(self, filename, **kwds): else: from matplotlib import rcParams rc_backup = (rcParams['ps.useafm'], rcParams['pdf.use14corefonts'], - rcParams['text.usetex']) # save the rcParams + rcParams['text.usetex']) # save the rcParams figure = self.matplotlib(**options) # You can output in PNG, PS, EPS, PDF, PGF, or SVG format, depending # on the file extension. # PGF is handled by a different backend if ext == '.pgf': - from sage.features.latex import xelatex,pdflatex,lualatex + from sage.features.latex import xelatex, pdflatex, lualatex latex_implementations = [] if xelatex().is_present(): latex_implementations.append('xelatex') @@ -3325,12 +3316,10 @@ def save(self, filename, **kwds): # use pdflatex and set font encoding as per # matplotlib documentation: # https://matplotlib.org/users/pgf.html#pgf-tutorial - pgf_options= {"pgf.texsystem": "pdflatex", - "pgf.preamble": [ - r"\usepackage[utf8x]{inputenc}", - r"\usepackage[T1]{fontenc}" - ] - } + pgf_options = {"pgf.texsystem": "pdflatex", + "pgf.preamble": [ + r"\usepackage[utf8x]{inputenc}", + r"\usepackage[T1]{fontenc}"]} else: pgf_options = { "pgf.texsystem": latex_implementations[0], @@ -3348,7 +3337,7 @@ def save(self, filename, **kwds): from matplotlib.backends.backend_agg import FigureCanvasAgg figure.set_canvas(FigureCanvasAgg(figure)) # this messes up the aspect ratio! - #figure.canvas.mpl_connect('draw_event', pad_for_tick_labels) + # figure.canvas.mpl_connect('draw_event', pad_for_tick_labels) # tight_layout adjusts the *subplot* parameters so ticks aren't cut off, etc. figure.tight_layout() @@ -3363,7 +3352,7 @@ def save(self, filename, **kwds): # Restore the rcParams to the original, possibly user-set values (rcParams['ps.useafm'], rcParams['pdf.use14corefonts'], - rcParams['text.usetex']) = rc_backup + rcParams['text.usetex']) = rc_backup def _latex_(self, **kwds): """ @@ -3386,7 +3375,7 @@ def _latex_(self, **kwds): tmpfilename = tmp_filename(ext='.pgf') self.save(filename=tmpfilename, **kwds) with open(tmpfilename, "r") as tmpfile: - latex_list = tmpfile.readlines() + latex_list = tmpfile.readlines() from sage.misc.latex import latex latex.add_package_to_preamble_if_available('pgf') return ''.join(latex_list) @@ -3502,6 +3491,7 @@ def inset(self, graphics, pos=None, fontsize=None): graphics._extra_kwds['fontsize'] = 6 return MultiGraphics([(self, pos0), (graphics, pos)]) + # Deprecation notice for GraphicsArray import def GraphicsArray(*args, **kwargs): r""" diff --git a/src/sage/quadratic_forms/quadratic_form.py b/src/sage/quadratic_forms/quadratic_form.py index e53203c66d9..02df1fe76ba 100644 --- a/src/sage/quadratic_forms/quadratic_form.py +++ b/src/sage/quadratic_forms/quadratic_form.py @@ -1288,7 +1288,7 @@ def polynomial(self,names='x'): 2*a*y0^2 + 3*a*y0*y1 + (-a + 1)*y1^2 + (2*a + 4)*y2^2 sage: Q = QuadraticForm(F,4,[a, 3*a, 0, 1 - a, a - 3, 0, 2*a + 4, 4 + a, 0, 1]) sage: Q.polynomial(names='z') - (a)*z0^2 + (3*a)*z0*z1 + (a - 3)*z1^2 + (a + 4)*z2^2 + (-a + 1)*z0*z3 + (2*a + 4)*z1*z3 + z3^2 + a*z0^2 + (3*a)*z0*z1 + (a - 3)*z1^2 + (a + 4)*z2^2 + (-a + 1)*z0*z3 + (2*a + 4)*z1*z3 + z3^2 sage: B. = QuaternionAlgebra(F,-1,-1) sage: Q = QuadraticForm(B, 3, [2*a, 3*a, i, 1 - a, 0, 2*a + 4]) sage: Q.polynomial() diff --git a/src/sage/repl/rich_output/output_browser.py b/src/sage/repl/rich_output/output_browser.py index 2746e3dff8e..3d7cda599a1 100644 --- a/src/sage/repl/rich_output/output_browser.py +++ b/src/sage/repl/rich_output/output_browser.py @@ -40,10 +40,12 @@ def __init__(self, html): # pdf export of a notebook m = latex_re.match(html) if m: + mathjax_string = m.group('latex') + latex_string = mathjax_string.replace('<', '<') if m.group('mathstart') == r'\[' and m.group('mathend') == r'\]': - self.latex = OutputBuffer('$$' + m.group('latex') + '$$') + self.latex = OutputBuffer('$$' + latex_string + '$$') else: - self.latex = OutputBuffer('$' + m.group('latex') + '$') + self.latex = OutputBuffer('$' + latex_string + '$') else: self.latex = None diff --git a/src/sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py b/src/sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py index 909af780d77..7c308fd2460 100644 --- a/src/sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py +++ b/src/sage/rings/asymptotic/asymptotics_multivariate_generating_functions.py @@ -2727,7 +2727,7 @@ def smooth_critical_ideal(self, alpha): sage: F = FFPD(G, Hfac) sage: alpha = var('a1, a2') sage: F.smooth_critical_ideal(alpha) - Ideal (y^2 + 2*a1/a2*y - 1, x + ((-a2)/a1)*y + (-a1 + a2)/a1) of + Ideal (y^2 + (2*a1)/a2*y - 1, x + (-a2)/a1*y + (-a1 + a2)/a1) of Multivariate Polynomial Ring in x, y over Fraction Field of Multivariate Polynomial Ring in a1, a2 over Rational Field @@ -2737,7 +2737,7 @@ def smooth_critical_ideal(self, alpha): sage: F = FFPD(G, Hfac) sage: alpha = [7/3, var('a')] sage: F.smooth_critical_ideal(alpha) - Ideal (y^2 + 14/3/a*y - 1, x + (-3/7*a)*y + 3/7*a - 1) of Multivariate Polynomial Ring in x, y over Fraction Field of Univariate Polynomial Ring in a over Rational Field + Ideal (y^2 + 14/(3*a)*y - 1, x + (-3*a)/7*y + (3*a - 7)/7) of Multivariate Polynomial Ring in x, y over Fraction Field of Univariate Polynomial Ring in a over Rational Field """ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing diff --git a/src/sage/rings/complex_arb.pyx b/src/sage/rings/complex_arb.pyx index b18359ca151..ce9b1b19a95 100644 --- a/src/sage/rings/complex_arb.pyx +++ b/src/sage/rings/complex_arb.pyx @@ -188,6 +188,7 @@ from sage.structure.parent cimport Parent from sage.structure.unique_representation import UniqueRepresentation from sage.arith.long cimport is_small_python_int +from sage.misc.superseded import deprecated_function_alias from sage.rings.complex_mpfr import ComplexField from sage.rings.complex_interval_field import ComplexIntervalField, ComplexIntervalField_class from sage.rings.integer_ring import ZZ @@ -4175,16 +4176,21 @@ cdef class ComplexBall(RingElement): if _do_sig(prec(self)): sig_off() return res - def ei(self): + def Ei(self): """ Return the exponential integral with argument ``self``. EXAMPLES:: - sage: CBF(1, 1).ei() + sage: CBF(1, 1).Ei() [1.76462598556385 +/- ...e-15] + [2.38776985151052 +/- ...e-15]*I - sage: CBF(0).ei() + sage: CBF(0).Ei() nan + + TESTS: + + sage: CBF(Ei(I)) + [0.337403922900968 +/- 3.76e-16] + [2.51687939716208 +/- 2.01e-15]*I """ cdef ComplexBall result = self._new() if _do_sig(prec(self)): sig_on() @@ -4192,16 +4198,23 @@ cdef class ComplexBall(RingElement): if _do_sig(prec(self)): sig_off() return result - def si(self): + ei = deprecated_function_alias(32869, Ei) + + def Si(self): """ Return the sine integral with argument ``self``. EXAMPLES:: - sage: CBF(1, 1).si() + sage: CBF(1, 1).Si() [1.10422265823558 +/- ...e-15] + [0.88245380500792 +/- ...e-15]*I - sage: CBF(0).si() + sage: CBF(0).Si() 0 + + TESTS: + + sage: CBF(Si(I)) + [1.05725087537573 +/- 2.77e-15]*I """ cdef ComplexBall result = self._new() if _do_sig(prec(self)): sig_on() @@ -4209,16 +4222,25 @@ cdef class ComplexBall(RingElement): if _do_sig(prec(self)): sig_off() return result - def ci(self): + sin_integral = Si # as for the symbolic function + + si = deprecated_function_alias(32869, Si) + + def Ci(self): """ Return the cosine integral with argument ``self``. EXAMPLES:: - sage: CBF(1, 1).ci() + sage: CBF(1, 1).Ci() [0.882172180555936 +/- ...e-16] + [0.287249133519956 +/- ...e-16]*I - sage: CBF(0).ci() + sage: CBF(0).Ci() nan + nan*I + + TESTS: + + sage: CBF(Ci(I)) + [0.837866940980208 +/- 4.72e-16] + [1.570796326794897 +/- 5.54e-16]*I """ cdef ComplexBall result = self._new() if _do_sig(prec(self)): sig_on() @@ -4226,34 +4248,51 @@ cdef class ComplexBall(RingElement): if _do_sig(prec(self)): sig_off() return result - def shi(self): + cos_integral = Ci # as for the symbolic function + + ci = deprecated_function_alias(32869, Ci) + + def Shi(self): """ Return the hyperbolic sine integral with argument ``self``. EXAMPLES:: - sage: CBF(1, 1).shi() + sage: CBF(1, 1).Shi() [0.88245380500792 +/- ...e-15] + [1.10422265823558 +/- ...e-15]*I - sage: CBF(0).shi() + sage: CBF(0).Shi() 0 - """ + TESTS: + + sage: CBF(Shi(I)) + [0.946083070367183 +/- 9.22e-16]*I + """ cdef ComplexBall result = self._new() if _do_sig(prec(self)): sig_on() acb_hypgeom_shi(result.value, self.value, prec(self)) if _do_sig(prec(self)): sig_off() return result - def chi(self): + sinh_integral = Shi + + shi = deprecated_function_alias(32869, Shi) + + def Chi(self): """ Return the hyperbolic cosine integral with argument ``self``. EXAMPLES:: - sage: CBF(1, 1).chi() + sage: CBF(1, 1).Chi() [0.882172180555936 +/- ...e-16] + [1.28354719327494 +/- ...e-15]*I - sage: CBF(0).chi() + sage: CBF(0).Chi() nan + nan*I + + TESTS: + + sage: CBF(Chi(I)) + [0.337403922900968 +/- 3.25e-16] + [1.570796326794897 +/- 5.54e-16]*I """ cdef ComplexBall result = self._new() if _do_sig(prec(self)): sig_on() @@ -4261,6 +4300,10 @@ cdef class ComplexBall(RingElement): if _do_sig(prec(self)): sig_off() return result + cosh_integral = Chi + + chi = deprecated_function_alias(32869, Chi) + def li(self, bint offset=False): """ Return the logarithmic integral with argument ``self``. @@ -4279,6 +4322,13 @@ cdef class ComplexBall(RingElement): 0.000000000000000 sage: Li(0).n() -1.04516378011749 + + TESTS:: + + sage: CBF(li(0)) + 0 + sage: CBF(Li(0)) + [-1.04516378011749...] """ cdef ComplexBall result = self._new() if _do_sig(prec(self)): sig_on() @@ -4286,6 +4336,29 @@ cdef class ComplexBall(RingElement): if _do_sig(prec(self)): sig_off() return result + log_integral = li + + def Li(self): + """ + Offset logarithmic integral. + + EXAMPLES:: + + sage: CBF(0).Li() + [-1.045163780117493 +/- ...e-16] + sage: li(0).n() + 0.000000000000000 + sage: Li(0).n() + -1.04516378011749 + """ + cdef ComplexBall result = self._new() + if _do_sig(prec(self)): sig_on() + acb_hypgeom_li(result.value, self.value, True, prec(self)) + if _do_sig(prec(self)): sig_off() + return result + + log_integral_offset = Li + def jacobi_theta(self, tau): r""" Return the four Jacobi theta functions evaluated at the argument diff --git a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx index 685f9a272bd..7092888fddd 100644 --- a/src/sage/rings/finite_rings/element_ntl_gf2e.pyx +++ b/src/sage/rings/finite_rings/element_ntl_gf2e.pyx @@ -1253,30 +1253,21 @@ cdef class FiniteField_ntl_gf2eElement(FinitePolyExtElement): def log(self, base): """ - Return `x` such that `b^x = a`, where `x` is `a` and `b` - is the base. + Compute an integer `x` such that `b^x = a`, where `a` is ``self`` + and `b` is ``base``. INPUT: - - ``base`` -- finite field element that generates the multiplicative - group. + - ``base`` -- finite-field element. OUTPUT: Integer `x` such that `a^x = b`, if it exists. Raises a ``ValueError`` exception if no such `x` exists. - EXAMPLES:: + ALGORITHM: :pari:`fflog` - sage: F = GF(17) - sage: F(3^11).log(F(3)) - 11 - sage: F = GF(113) - sage: F(3^19).log(F(3)) - 19 - sage: F = GF(next_prime(10000)) - sage: F(23^997).log(F(23)) - 997 + EXAMPLES:: sage: F = FiniteField(2^10, 'a') sage: g = F.gen() @@ -1287,12 +1278,46 @@ cdef class FiniteField_ntl_gf2eElement(FinitePolyExtElement): a^8 + a^7 + a^4 + a + 1 a^8 + a^7 + a^4 + a + 1 - AUTHOR: David Joyner and William Stein (2005-11) + Big instances used to take a very long time before :trac:`32842`:: + + sage: g = GF(2^61).gen() + sage: g.log(g^7) + 1976436865040309101 + + TESTS: + + Check that non-existence is correctly detected:: + + sage: g = GF(2^50).gen() + sage: (2^50-1) % 1023 + 0 + sage: g.log(g^1023) + Traceback (most recent call last): + ... + ValueError: no logarithm of z50 exists to base z50^49 + z50^46 + z50^45 + z50^44 + z50^41 + z50^34 + z50^33 + z50^32 + z50^27 + z50^25 + z50^24 + z50^21 + z50^18 + z50^17 + z50^16 + z50^15 + z50^12 + z50^11 + z50^10 + z50^8 + z50^7 + z50^3 + z50^2 + + AUTHORS: + + - David Joyner and William Stein (2005-11) + - Lorenz Panny (2021-11): use PARI's :pari:`fflog` instead of :func:`sage.groups.generic.discrete_log` """ - from sage.groups.generic import discrete_log + base = self.parent()(base) + + # The result is undefined if the input to fflog() is invalid. + # Since the unit group is cyclic, it suffices to check orders. + cdef Integer base_order = base.multiplicative_order() + cdef Integer self_order = self.multiplicative_order() + if not self_order.divides(base_order): + raise ValueError(f'no logarithm of {self} exists to base {base}') + + # Let's pass the known factorization of the order to PARI. + fs, = self._parent.factored_unit_order() # cached + ps = pari.Col(p for p,_ in fs) + vs = pari.Col(base_order.valuation(p) for p,_ in fs) + fac = pari.matconcat((ps, vs)) - b = self.parent()(base) - return discrete_log(self, b) + x = pari.fflog(self, base, (base_order, fac)) + return Integer(x) def unpickleFiniteField_ntl_gf2eElement(parent, elem): """ diff --git a/src/sage/rings/finite_rings/integer_mod_ring.py b/src/sage/rings/finite_rings/integer_mod_ring.py index 28fb2736491..00f64ed4bd3 100644 --- a/src/sage/rings/finite_rings/integer_mod_ring.py +++ b/src/sage/rings/finite_rings/integer_mod_ring.py @@ -1366,7 +1366,7 @@ def unit_gens(self, **kwds): The choice of generators is affected by the optional keyword ``algorithm``; this can be ``'sage'`` (default) or ``'pari'``. - See :meth:`unit_group` for details. + See :meth:`unit_group` for details. :: sage: A = Zmod(55) sage: A.unit_gens(algorithm='sage') diff --git a/src/sage/rings/finite_rings/residue_field.pyx b/src/sage/rings/finite_rings/residue_field.pyx index 62bebc2303b..b04066cc738 100644 --- a/src/sage/rings/finite_rings/residue_field.pyx +++ b/src/sage/rings/finite_rings/residue_field.pyx @@ -109,7 +109,7 @@ First over a small non-prime field:: sage: R. = PolynomialRing(Rf) sage: ubar = Rf(u) sage: I = ideal([ubar*X + Y]); I - Ideal ((ubar)*X + Y) of Multivariate Polynomial Ring in X, Y over Residue field in ubar of Fractional ideal (47, 517/55860*u^5 + 235/3724*u^4 + 9829/13965*u^3 + 54106/13965*u^2 + 64517/27930*u + 755696/13965) + Ideal (ubar*X + Y) of Multivariate Polynomial Ring in X, Y over Residue field in ubar of Fractional ideal (47, 517/55860*u^5 + 235/3724*u^4 + 9829/13965*u^3 + 54106/13965*u^2 + 64517/27930*u + 755696/13965) sage: I.groebner_basis() [X + (-19*ubar^2 - 5*ubar - 17)*Y] diff --git a/src/sage/rings/fraction_field.py b/src/sage/rings/fraction_field.py index 8d8d4c49c80..d5d392efba0 100644 --- a/src/sage/rings/fraction_field.py +++ b/src/sage/rings/fraction_field.py @@ -586,7 +586,7 @@ def _element_constructor_(self, x, y=None, coerce=True): sage: B. = PolynomialRing(A,'d,e') sage: R. = PolynomialRing(B,'x') sage: (a*d*x^2+a+e+1).resultant(-4*c^2*x+1) - a*d + 16*c^4*e + 16*a*c^4 + 16*c^4 + a*d + (16*c^4)*e + (16*a*c^4 + 16*c^4) Check that :trac:`24539` is fixed:: @@ -618,6 +618,8 @@ def _element_constructor_(self, x, y=None, coerce=True): sage: F(x) -1/2/(a^2 + a) """ + if isinstance(x, (list, tuple)) and len(x) == 1: + x = x[0] if y is None: if parent(x) is self: return x diff --git a/src/sage/rings/fraction_field_FpT.pyx b/src/sage/rings/fraction_field_FpT.pyx index b81535fe5bd..58ee9bf3050 100644 --- a/src/sage/rings/fraction_field_FpT.pyx +++ b/src/sage/rings/fraction_field_FpT.pyx @@ -13,7 +13,7 @@ from cysignals.signals cimport sig_on, sig_off from sage.rings.finite_rings.stdint cimport INTEGER_MOD_INT32_LIMIT from sage.libs.gmp.mpz cimport * -from sage.rings.all import GF +from sage.rings.finite_rings.finite_field_constructor import GF from sage.libs.flint.nmod_poly cimport * from sage.libs.flint.ulong_extras cimport n_jacobi from sage.structure.element cimport Element, ModuleElement, FieldElement diff --git a/src/sage/rings/function_field/place.py b/src/sage/rings/function_field/place.py index f3400e76bdb..f53a853f70d 100644 --- a/src/sage/rings/function_field/place.py +++ b/src/sage/rings/function_field/place.py @@ -81,7 +81,7 @@ class FunctionFieldPlace(Element): INPUT: - - ``field`` -- function field + - ``parent`` -- place set of a function field - ``prime`` -- prime ideal associated with the place @@ -1188,3 +1188,16 @@ def _an_element_(self): break return p + def function_field(self): + """ + Return the function field to which this place set belongs. + + EXAMPLES:: + + sage: K. = FunctionField(GF(2)); _. = K[] + sage: L. = K.extension(Y^3 + x + x^3*Y) + sage: PS = L.place_set() + sage: PS.function_field() == L + True + """ + return self._field diff --git a/src/sage/rings/ideal.py b/src/sage/rings/ideal.py index 3a135b8f982..871ebf1aaad 100644 --- a/src/sage/rings/ideal.py +++ b/src/sage/rings/ideal.py @@ -172,6 +172,7 @@ def Ideal(*args, **kwds): first = args[0] + inferred_field = False if not isinstance(first, sage.rings.ring.Ring): if isinstance(first, Ideal_generic) and len(args) == 1: R = first.ring() @@ -183,6 +184,7 @@ def Ideal(*args, **kwds): gens = args gens = Sequence(gens) R = gens.universe() + inferred_field = isinstance(R, sage.rings.ring.Field) else: R = first gens = args[1:] @@ -190,7 +192,15 @@ def Ideal(*args, **kwds): if not isinstance(R, sage.rings.ring.CommutativeRing): raise TypeError("R must be a commutative ring") - return R.ideal(*gens, **kwds) + I = R.ideal(*gens, **kwds) + + if inferred_field and not isinstance(I, Ideal_fractional): # trac 32320 + import warnings + warnings.warn(f'Constructing an ideal in {R}, which is a field.' + ' Did you intend to take numerators first?' + ' This warning can be muted by passing the base ring to Ideal() explicitly.') + + return I def is_Ideal(x): r""" diff --git a/src/sage/rings/infinity.py b/src/sage/rings/infinity.py index 6bbacbe31e9..18adea7ca8b 100644 --- a/src/sage/rings/infinity.py +++ b/src/sage/rings/infinity.py @@ -711,9 +711,13 @@ def _element_constructor_(self, x): True """ # Lazy elements can wrap infinity or not, unwrap first - from sage.rings.real_lazy import LazyWrapper - if isinstance(x, LazyWrapper): - x = x._value + try: + from sage.rings.real_lazy import LazyWrapper + except ImportError: + pass + else: + if isinstance(x, LazyWrapper): + x = x._value # Handle all ways to represent infinity first if isinstance(x, InfinityElement): @@ -721,7 +725,7 @@ def _element_constructor_(self, x): elif isinstance(x, float): if x in [float('+inf'), float('-inf')]: return self.gen() - elif isinstance(x, sage.rings.real_mpfi.RealIntervalFieldElement): + elif isinstance(x, RingElement) and isinstance(x.parent(), sage.rings.abc.RealIntervalField): if x.upper().is_infinity() or x.lower().is_infinity(): return self.gen() else: @@ -1167,9 +1171,13 @@ def _element_constructor_(self, x): ValueError: infinite but not with +/- phase """ # Lazy elements can wrap infinity or not, unwrap first - from sage.rings.real_lazy import LazyWrapper - if isinstance(x, LazyWrapper): - x = x._value + try: + from sage.rings.real_lazy import LazyWrapper + except ImportError: + pass + else: + if isinstance(x, LazyWrapper): + x = x._value # Handle all ways to represent infinity first if isinstance(x, InfinityElement): @@ -1182,7 +1190,7 @@ def _element_constructor_(self, x): return self.gen(0) if x == float('-inf'): return self.gen(1) - elif isinstance(x, sage.rings.real_mpfi.RealIntervalFieldElement): + elif isinstance(x, RingElement) and isinstance(x.parent(), sage.rings.abc.RealIntervalField): if x.upper().is_positive_infinity(): return self.gen(0) if x.lower().is_negative_infinity(): diff --git a/src/sage/rings/invariants/invariant_theory.py b/src/sage/rings/invariants/invariant_theory.py index dddd27f784e..a0cb9566ad4 100644 --- a/src/sage/rings/invariants/invariant_theory.py +++ b/src/sage/rings/invariants/invariant_theory.py @@ -256,9 +256,9 @@ def transvectant(f, g, h=1, scale='default'): sage: S. = R[] sage: quintic = invariant_theory.binary_quintic(x^5+x^3+2*x^2+y^5, x) sage: transvectant(quintic, quintic, 2) - Binary sextic given by 1/5*x^6 + 6/5*x^5*h + (-3/25)*x^4*h^2 - + (2*y^5 - 8/25)*x^3*h^3 + (-12/25)*x^2*h^4 + 3/5*y^5*x*h^5 - + 2/5*y^5*h^6 + Binary sextic given by 1/5*x^6 + 6/5*x^5*h - 3/25*x^4*h^2 + + (50*y^5 - 8)/25*x^3*h^3 - 12/25*x^2*h^4 + (3*y^5)/5*x*h^5 + + (2*y^5)/5*h^6 """ f = f.homogenized() g = g.homogenized() diff --git a/src/sage/rings/morphism.pyx b/src/sage/rings/morphism.pyx index 6a96df172d8..b4d6596ce04 100644 --- a/src/sage/rings/morphism.pyx +++ b/src/sage/rings/morphism.pyx @@ -1255,11 +1255,21 @@ cdef class RingHomomorphism(RingMap): Traceback (most recent call last): ... NotImplementedError: base map must be trivial + + Non-commutative rings are not supported (:trac:`32824`):: + + sage: A = GradedCommutativeAlgebra(QQ, 'x,y,z') + sage: A.hom(A.gens(), A).kernel() + Traceback (most recent call last): + ... + NotImplementedError: rings are not commutative """ from .quotient_ring import is_QuotientRing from .ideal import Ideal_generic A = self.domain() B = self.codomain() + if not (A.is_commutative() and B.is_commutative()): + raise NotImplementedError("rings are not commutative") if A.base_ring() != B.base_ring(): raise NotImplementedError("base rings must be equal") try: diff --git a/src/sage/rings/multi_power_series_ring_element.py b/src/sage/rings/multi_power_series_ring_element.py index 782a6f077a3..4d85381b9df 100644 --- a/src/sage/rings/multi_power_series_ring_element.py +++ b/src/sage/rings/multi_power_series_ring_element.py @@ -462,7 +462,7 @@ def __call__(self, *x, **kwds): sage: cc = K.hom([-i]) sage: R. = PowerSeriesRing(K) sage: f = s^2 + i*s*t + (3+4*i)*s^3 + R.O(4); f - s^2 + (i)*s*t + (4*i + 3)*s^3 + O(s, t)^4 + s^2 + i*s*t + (4*i + 3)*s^3 + O(s, t)^4 sage: f(t, s, base_map=cc) (-i)*s*t + t^2 + (-4*i + 3)*t^3 + O(s, t)^4 """ diff --git a/src/sage/rings/number_field/number_field_ideal.py b/src/sage/rings/number_field/number_field_ideal.py index 1f5bca3ce33..b12d1c66613 100644 --- a/src/sage/rings/number_field/number_field_ideal.py +++ b/src/sage/rings/number_field/number_field_ideal.py @@ -46,7 +46,7 @@ import sage.misc.misc as misc from sage.rings.finite_rings.finite_field_constructor import FiniteField -from sage.rings.ideal import Ideal_generic +from sage.rings.ideal import Ideal_generic, Ideal_fractional from sage.misc.misc_c import prod from sage.misc.mrange import xmrange_iter from sage.misc.cachefunc import cached_method @@ -1734,7 +1734,7 @@ def is_NumberFieldIdeal(x): return isinstance(x, NumberFieldIdeal) -class NumberFieldFractionalIdeal(MultiplicativeGroupElement, NumberFieldIdeal): +class NumberFieldFractionalIdeal(MultiplicativeGroupElement, NumberFieldIdeal, Ideal_fractional): r""" A fractional ideal in a number field. @@ -1747,6 +1747,14 @@ class NumberFieldFractionalIdeal(MultiplicativeGroupElement, NumberFieldIdeal): sage: Jinv = I^(-2) sage: J*Jinv Fractional ideal (1) + + TESTS: + + Number-field fractional ideals are fractional ideals (:trac:`32380`):: + + sage: from sage.rings.ideal import Ideal_fractional + sage: isinstance(I, Ideal_fractional) + True """ def __init__(self, field, gens, coerce=True): """ diff --git a/src/sage/rings/padics/local_generic_element.pyx b/src/sage/rings/padics/local_generic_element.pyx index 2a1c0b32dac..da753af83c1 100644 --- a/src/sage/rings/padics/local_generic_element.pyx +++ b/src/sage/rings/padics/local_generic_element.pyx @@ -908,7 +908,7 @@ cdef class LocalGenericElement(CommutativeRingElement): from sage.categories.fields import Fields if self.parent() in Fields(): - from sage.rings.all import Integer + from sage.rings.integer import Integer return Integer(0) return self.valuation() diff --git a/src/sage/rings/padics/padic_capped_absolute_element.pyx b/src/sage/rings/padics/padic_capped_absolute_element.pyx index 387dd7c8b65..12ecdc457e8 100644 --- a/src/sage/rings/padics/padic_capped_absolute_element.pyx +++ b/src/sage/rings/padics/padic_capped_absolute_element.pyx @@ -249,7 +249,7 @@ cdef class pAdicCappedAbsoluteElement(CAElement): cdef Integer selfvalue = Integer.__new__(Integer) mpz_set(selfvalue.value, self.value) if field: - from sage.rings.finite_rings.all import GF + from sage.rings.finite_rings.finite_field_constructor import GF return GF(self.parent().prime())(selfvalue) else: return Mod(selfvalue, modulus) diff --git a/src/sage/rings/padics/padic_capped_relative_element.pyx b/src/sage/rings/padics/padic_capped_relative_element.pyx index bea6c17af19..7626d36cba5 100644 --- a/src/sage/rings/padics/padic_capped_relative_element.pyx +++ b/src/sage/rings/padics/padic_capped_relative_element.pyx @@ -353,7 +353,7 @@ cdef class pAdicCappedRelativeElement(CRElement): # Need to do this better. mpz_mul(selfvalue.value, self.prime_pow.pow_mpz_t_tmp(self.ordp), self.unit) if field: - from sage.rings.finite_rings.all import GF + from sage.rings.finite_rings.finite_field_constructor import GF return GF(self.parent().prime())(selfvalue) else: return Mod(selfvalue, modulus) diff --git a/src/sage/rings/padics/padic_fixed_mod_element.pyx b/src/sage/rings/padics/padic_fixed_mod_element.pyx index e012cbba9fc..9a663986b19 100644 --- a/src/sage/rings/padics/padic_fixed_mod_element.pyx +++ b/src/sage/rings/padics/padic_fixed_mod_element.pyx @@ -319,7 +319,7 @@ cdef class pAdicFixedModElement(FMElement): selfvalue = PY_NEW(Integer) mpz_set(selfvalue.value, self.value) if field: - from sage.rings.finite_rings.all import GF + from sage.rings.finite_rings.finite_field_constructor import GF return GF(self.parent().prime())(selfvalue) else: return Mod(selfvalue, modulus) diff --git a/src/sage/rings/padics/padic_floating_point_element.pyx b/src/sage/rings/padics/padic_floating_point_element.pyx index b3eb407918e..2111fa50934 100644 --- a/src/sage/rings/padics/padic_floating_point_element.pyx +++ b/src/sage/rings/padics/padic_floating_point_element.pyx @@ -316,7 +316,7 @@ cdef class pAdicFloatingPointElement(FPElement): # Need to do this better. mpz_mul(selfvalue.value, self.prime_pow.pow_mpz_t_tmp(self.ordp), self.unit) if field: - from sage.rings.finite_rings.all import GF + from sage.rings.finite_rings.finite_field_constructor import GF return GF(self.parent().prime())(selfvalue) else: return Mod(selfvalue, modulus) diff --git a/src/sage/rings/padics/padic_valuation.py b/src/sage/rings/padics/padic_valuation.py index 7efc8513961..f0d576cff66 100644 --- a/src/sage/rings/padics/padic_valuation.py +++ b/src/sage/rings/padics/padic_valuation.py @@ -1149,7 +1149,7 @@ def residue_ring(self): Finite Field of size 3 """ - from sage.rings.all import GF + from sage.rings.finite_rings.finite_field_constructor import GF return GF(self.p()) def _ge_(self, other): diff --git a/src/sage/rings/polynomial/flatten.py b/src/sage/rings/polynomial/flatten.py index b7dadef0b51..4ffe29f9ebe 100644 --- a/src/sage/rings/polynomial/flatten.py +++ b/src/sage/rings/polynomial/flatten.py @@ -113,7 +113,7 @@ def __init__(self, domain): sage: from sage.rings.polynomial.flatten import FlatteningMorphism sage: f = FlatteningMorphism(R) sage: f(R('v*a*x^2 + b^2 + 1/v*y')) - (v)*x^2*a + b^2 + (1/2*v^2)*y + v*x^2*a + b^2 + (1/2*v^2)*y :: diff --git a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx index 2c69227760c..5d34e62d04c 100644 --- a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx +++ b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx @@ -250,6 +250,7 @@ from sage.interfaces.macaulay2 import macaulay2 as macaulay2_default, is_Macaula from sage.misc.all import prod as mul from sage.misc.sage_eval import sage_eval + cimport cypari2.gen from . import polynomial_element @@ -558,7 +559,7 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: k. = GF(2^8) sage: P. = PolynomialRing(k,2) sage: P._coerce_(a) - (a) + a sage: z = QQ['z'].0 sage: K. = NumberField(z^2 - 2) @@ -769,6 +770,16 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: S(f) (2*abar)*y + Check that creating element from strings works for transcendental extensions:: + + sage: T. = QQ[] + sage: F = FractionField(T) + sage: R. = F[] + sage: R('d*z+x^2*y') + x^2*y + d*z + + + """ cdef poly *_p cdef poly *mon @@ -961,7 +972,11 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): # let python do the parsing d = self.gens_dict() if self.base_ring().gen() != 1: - d[str(self.base_ring().gen())]=self.base_ring().gen() + if hasattr(self.base_ring(), 'gens'): + for gen in self.base_ring().gens(): + d[str(gen)] = gen + else: + d[str(self.base_ring().gen())] = self.base_ring_gen() try: if '/' in element: element = sage_eval(element,d) @@ -1964,7 +1979,7 @@ cdef class MPolynomial_libsingular(MPolynomial): sage: F. = GF(7^2) sage: R. = F[] sage: p = a*x^2 + y + a^3; p - (a)*x^2 + y + (-2*a - 3) + a*x^2 + y + (-2*a - 3) sage: q = copy(p) sage: p == q True @@ -3504,6 +3519,19 @@ cdef class MPolynomial_libsingular(MPolynomial): ....: assert y.subs(d) == y.subs(**ds) == vy ....: assert z.subs(d) == z.subs(**ds) == vz ....: assert (x+y).subs(d) == (x+y).subs(**ds) == vx+vy + + Check that substitution doesn't crash in transcendental extensions:: + + sage: F = PolynomialRing(QQ,'c,d').fraction_field() + sage: F.inject_variables() + Defining c, d + sage: R. = F[] + sage: f = R(d*z^2 + c*y*z^2) + sage: f.subs({x:z^2,y:1}) + (c + d)*z^2 + sage: f.subs({z:x+1}) + c*x^2*y + d*x^2 + (2*c)*x*y + (2*d)*x + c*y + d + """ cdef int mi, i, need_map, try_symbolic @@ -4226,10 +4254,10 @@ cdef class MPolynomial_libsingular(MPolynomial): sage: K. = NumberField(p^3-2) sage: KXY. = K[] sage: factor(x^3 - 2*y^3) - (x + (-s)*y) * (x^2 + (s)*x*y + (s^2)*y^2) + (x + (-s)*y) * (x^2 + s*x*y + (s^2)*y^2) sage: k = (x^3-2*y^3)^5*(x+s*y)^2*(2/3 + s^2) sage: k.factor() - ((s^2 + 2/3)) * (x + (s)*y)^2 * (x + (-s)*y)^5 * (x^2 + (s)*x*y + (s^2)*y^2)^5 + ((s^2 + 2/3)) * (x + s*y)^2 * (x + (-s)*y)^5 * (x^2 + s*x*y + (s^2)*y^2)^5 This shows that ticket :trac:`2780` is fixed, i.e. that the unit part of the factorization is set correctly:: @@ -4320,7 +4348,7 @@ cdef class MPolynomial_libsingular(MPolynomial): sage: q=y^11 + (a)*y^10 + (a + 1)*x*y^3 sage: f = p*q sage: f.factor() - x * y^3 * (y^8 + (a)*y^7 + (a + 1)*x) * (x^7*y^3 + x*y^9 + (a)*x^8 + (a)*y^4) + x * y^3 * (y^8 + a*y^7 + (a + 1)*x) * (x^7*y^3 + x*y^9 + a*x^8 + a*y^4) We test several examples which were known to return wrong results in the past (see :trac:`10902`):: diff --git a/src/sage/rings/polynomial/plural.pyx b/src/sage/rings/polynomial/plural.pyx index 349871f5086..972d22049da 100644 --- a/src/sage/rings/polynomial/plural.pyx +++ b/src/sage/rings/polynomial/plural.pyx @@ -138,6 +138,8 @@ from sage.structure.parent cimport Parent from sage.structure.parent_gens cimport ParentWithGens from sage.rings.polynomial.term_order import TermOrder +from sage.misc.functional import coerce + class G_AlgFactory(UniqueFactory): """ @@ -487,6 +489,17 @@ cdef class NCPolynomialRing_plural(Ring): Traceback (most recent call last): ... ValueError: unable to construct an element of this ring + + Check that it works for rings with parameters:: + + sage: F = PolynomialRing(QQ,'t1,t2').fraction_field() + sage: A = FreeAlgebra(F, 2, 'x,y') + sage: A.inject_variables() + Defining x, y + sage: B = A.g_algebra({y*x:-x*y}) + sage: B(2) + 2 + """ if element == 0: @@ -502,6 +515,11 @@ cdef class NCPolynomialRing_plural(Ring): base_ring = self.base_ring() + try: + element = coerce(base_ring, element) + except: + pass + if(_ring != currRing): rChangeCurrRing(_ring) if isinstance(element, NCPolynomial_plural): @@ -721,7 +739,7 @@ cdef class NCPolynomialRing_plural(Ring): -x*y """ from sage.repl.rich_output.backend_base import BackendBase - from sage.repl.display.pretty_print import SagePrettyPrinter + from sage.repl.display.pretty_print import SagePrettyPrinter varstr = ", ".join(char_to_str(rRingVar(i, self._ring)) for i in range(self.__ngens)) backend = BackendBase() @@ -2254,7 +2272,7 @@ cdef class NCPolynomial_plural(RingElement): sage: phi(x*y - x^2*z) a^2*b^3 - a^2*b^2*c sage: phi(x*y - z2*x^2*z) - (z2)*a^2*b^3 - a^2*b^2*c + z2*a^2*b^3 - a^2*b^2*c sage: phi = R.hom([a*b, b, a*b*c], base_map=GF(9).frobenius_endomorphism(), check=False) sage: phi(x*y - x^2*z) a^2*b^3 - a^2*b^2*c diff --git a/src/sage/rings/polynomial/polydict.pyx b/src/sage/rings/polynomial/polydict.pyx index 98b663a029d..95785f04521 100644 --- a/src/sage/rings/polynomial/polydict.pyx +++ b/src/sage/rings/polynomial/polydict.pyx @@ -1624,11 +1624,12 @@ cdef class ETuple: sage: R. = Frac(QQ['x'])[] sage: type(y) - + sage: y^(2^32) Traceback (most recent call last): ... - OverflowError: exponent overflow (2147483648) + OverflowError: exponent overflow (...) # 64-bit + OverflowError: Python int too large to convert to C unsigned long # 32-bit """ if self._length!=other._length: raise ArithmeticError diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index 2dfcaf2c735..2edc2ab54ad 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -6421,7 +6421,8 @@ cdef class Polynomial(CommutativeAlgebraElement): sage: p = ((1/b^2*d^2+1/a)*x*y^2+a*b/c*y+e+x^2) sage: q = -4*c^2*y^3+1 sage: p.resultant(q) - 16*c^4*x^6 + 48*c^4*e*x^4 + (1/b^6*d^6 + 3/(a*b^4)*d^4 + ((-12*a^3*b*c + 3)/(a^2*b^2))*d^2 + (-12*a^3*b*c + 1)/a^3)*x^3 + 48*c^4*e^2*x^2 + (((-12*a*c)/b)*d^2*e + (-12*b*c)*e)*x + 16*c^4*e^3 + 4*a^3*b^3/c + (16*c^4)*x^6 + (48*c^4)*e*x^4 + (1/(b^6)*d^6 + 3/(a*b^4)*d^4 + (-12*a^3*b*c + 3)/(a^2*b^2)*d^2 + (-12*a^3*b*c + 1)/(a^3))*x^3 + (48*c^4)*e^2*x^2 + ((-12*a*c)/b*d^2*e + (-12*b*c)*e)*x + (16*c^4)*e^3 + (4*a^3*b^3)/c + Test for :trac:`10978`:: diff --git a/src/sage/rings/polynomial/polynomial_element_generic.py b/src/sage/rings/polynomial/polynomial_element_generic.py index a8a5065f827..275470b15fd 100644 --- a/src/sage/rings/polynomial/polynomial_element_generic.py +++ b/src/sage/rings/polynomial/polynomial_element_generic.py @@ -767,16 +767,20 @@ def quo_rem(self, other): Returns the quotient and remainder of the Euclidean division of ``self`` and ``other``. - Raises ZerodivisionError if ``other`` is zero. Raises ArithmeticError - if ``other`` has a nonunit leading coefficient. + Raises ZerodivisionError if ``other`` is zero. + + Raises ArithmeticError if ``other`` has a nonunit leading coefficient + and this causes the Euclidean division to fail. EXAMPLES:: - sage: P. = PolynomialRing(ZZ,sparse=True) - sage: R. = PolynomialRing(P,sparse=True) + sage: P. = PolynomialRing(ZZ, sparse=True) + sage: R. = PolynomialRing(P, sparse=True) sage: f = R.random_element(10) - sage: g = y^5+R.random_element(4) - sage: q,r = f.quo_rem(g) + sage: while x.divides(f.leading_coefficient()): + ....: f = R.random_element(10) + sage: g = y^5 + R.random_element(4) + sage: q, r = f.quo_rem(g) sage: f == q*g + r and r.degree() < g.degree() True sage: g = x*y^5 @@ -790,25 +794,32 @@ def quo_rem(self, other): ... ZeroDivisionError: Division by zero polynomial + If the leading coefficient of ``other`` is not a unit, Euclidean division may still work:: + + sage: f = -x*y^10 + 2*x*y^7 + y^3 - 2*x^2*y^2 - y + sage: g = x*y^5 + sage: f.quo_rem(g) + (-y^5 + 2*y^2, y^3 - 2*x^2*y^2 - y) + TESTS:: - sage: P. = PolynomialRing(ZZ,sparse=True) - sage: f = x^10-4*x^6-5 - sage: g = 17*x^22+x^15-3*x^5+1 - sage: q,r = g.quo_rem(f) + sage: P. = PolynomialRing(ZZ, sparse=True) + sage: f = x^10 - 4*x^6 - 5 + sage: g = 17*x^22 + x^15 - 3*x^5 + 1 + sage: q, r = g.quo_rem(f) sage: g == f*q + r and r.degree() < f.degree() True sage: zero = P(0) sage: zero.quo_rem(f) (0, 0) sage: Q. = IntegerModRing(14)[] - sage: f = y^10-4*y^6-5 - sage: g = 17*y^22+y^15-3*y^5+1 - sage: q,r = g.quo_rem(f) + sage: f = y^10 - 4*y^6 - 5 + sage: g = 17*y^22 + y^15 - 3*y^5 + 1 + sage: q, r = g.quo_rem(f) sage: g == f*q + r and r.degree() < f.degree() True - sage: f += 2*y^10 # 3 is invertible mod 14 - sage: q,r = g.quo_rem(f) + sage: f += 2*y^10 # 3 is invertible mod 14 + sage: q, r = g.quo_rem(f) sage: g == f*q + r and r.degree() < f.degree() True diff --git a/src/sage/rings/polynomial/polynomial_quotient_ring.py b/src/sage/rings/polynomial/polynomial_quotient_ring.py index f342447c8f0..ad567eabe7d 100644 --- a/src/sage/rings/polynomial/polynomial_quotient_ring.py +++ b/src/sage/rings/polynomial/polynomial_quotient_ring.py @@ -1056,6 +1056,23 @@ def is_field(self, proof = True): return ret def krull_dimension(self): + """ + Return the Krull dimension. + + This is the Krull dimension of the base ring, unless the + quotient is zero. + + EXAMPLES:: + + sage: R = PolynomialRing(ZZ,'x').quotient(x**6-1) + sage: R.krull_dimension() + 1 + sage: R = PolynomialRing(ZZ,'x').quotient(1) + sage: R.krull_dimension() + -1 + """ + if self.is_zero(): + return -1 return self.base_ring().krull_dimension() def modulus(self): @@ -1888,7 +1905,7 @@ def _isomorphic_ring(self): # for a finite field, we return the isomorphic simple extensions of # the underlying prime field N = self.cardinality() - from sage.rings.all import GF + from sage.rings.finite_rings.finite_field_constructor import GF isomorphic_ring = GF(N) # the map to GF(N) maps our generator to a root of our modulus in the isomorphic_ring diff --git a/src/sage/rings/real_arb.pyx b/src/sage/rings/real_arb.pyx index c616e9cd304..80a840e7868 100644 --- a/src/sage/rings/real_arb.pyx +++ b/src/sage/rings/real_arb.pyx @@ -3468,9 +3468,215 @@ cdef class RealBall(RingElement): if _do_sig(prec(self)): sig_off() return res - def gamma(self): + def erfi(self): """ - Return the image of this ball by the Euler Gamma function. + Imaginary error function + + EXAMPLES:: + + sage: RBF(1/2).erfi() + [0.614952094696511 +/- 2.22e-16] + """ + cdef RealBall res = self._new() + if _do_sig(prec(self)): sig_on() + arb_hypgeom_erfi(res.value, self.value, prec(self)) + if _do_sig(prec(self)): sig_off() + return res + + def Ei(self): + """ + Exponential integral + + EXAMPLES:: + + sage: RBF(1).Ei() + [1.89511781635594 +/- 4.94e-15] + + TESTS:: + + sage: RBF(Ei(1)) + [1.89511781635594 +/- 4.94e-15] + """ + cdef RealBall res = self._new() + if _do_sig(prec(self)): sig_on() + arb_hypgeom_ei(res.value, self.value, prec(self)) + if _do_sig(prec(self)): sig_off() + return res + + def Si(self): + """ + Sine integral + + EXAMPLES:: + + sage: RBF(1).Si() + [0.946083070367183 +/- 9.22e-16] + + TESTS:: + + sage: RBF(Si(1)) + [0.946083070367183 +/- 9.22e-16] + """ + cdef RealBall res = self._new() + if _do_sig(prec(self)): sig_on() + arb_hypgeom_si(res.value, self.value, prec(self)) + if _do_sig(prec(self)): sig_off() + return res + + sin_integral = Si + + def Ci(self): + """ + Cosine integral + + EXAMPLES:: + + sage: RBF(1).Ci() + [0.337403922900968 +/- 3.25e-16] + + TESTS:: + + sage: RBF(Ci(1)) + [0.337403922900968 +/- 3.25e-16] + """ + cdef RealBall res = self._new() + if _do_sig(prec(self)): sig_on() + arb_hypgeom_ci(res.value, self.value, prec(self)) + if _do_sig(prec(self)): sig_off() + return res + + cos_integral = Ci + + def Shi(self): + """ + Hyperbolic sine integral + + EXAMPLES:: + + sage: RBF(1).Shi() + [1.05725087537573 +/- 2.77e-15] + + TESTS:: + + sage: RBF(Shi(1)) + [1.05725087537573 +/- 2.77e-15] + """ + cdef RealBall res = self._new() + if _do_sig(prec(self)): sig_on() + arb_hypgeom_shi(res.value, self.value, prec(self)) + if _do_sig(prec(self)): sig_off() + return res + + sinh_integral = Shi + + def Chi(self): + """ + Hyperbolic cosine integral + + EXAMPLES:: + + sage: RBF(1).Chi() + [0.837866940980208 +/- 4.72e-16] + + TESTS:: + + sage: RBF(Chi(1)) + [0.837866940980208 +/- 4.72e-16] + """ + cdef RealBall res = self._new() + if _do_sig(prec(self)): sig_on() + arb_hypgeom_chi(res.value, self.value, prec(self)) + if _do_sig(prec(self)): sig_off() + return res + + cosh_integral = Chi + + def li(self): + """ + Logarithmic integral + + EXAMPLES:: + + sage: RBF(3).li() + [2.16358859466719 +/- 4.72e-15] + + TESTS:: + + sage: RBF(li(0)) + 0 + sage: RBF(Li(0)) + [-1.04516378011749 +/- 4.23e-15] + """ + cdef RealBall res = self._new() + if _do_sig(prec(self)): sig_on() + arb_hypgeom_li(res.value, self.value, False, prec(self)) + if _do_sig(prec(self)): sig_off() + return res + + log_integral = li + + def Li(self): + """ + Offset logarithmic integral + + EXAMPLES:: + + sage: RBF(3).Li() + [1.11842481454970 +/- 7.61e-15] + """ + cdef RealBall res = self._new() + if _do_sig(prec(self)): sig_on() + arb_hypgeom_li(res.value, self.value, True, prec(self)) + if _do_sig(prec(self)): sig_off() + return res + + log_integral_offset = Li + + def beta(self, a, z=1): + """ + (Incomplete) beta function + + INPUT: + + - ``a``, ``z`` (optional) -- real balls + + OUTPUT: + + The lower incomplete beta function `B(self, a, z)`. + + With the default value of ``z``, the complete beta function `B(self, a)`. + + EXAMPLES:: + + sage: RBF(sin(3)).beta(RBF(2/3).sqrt()) + [7.407661629415 +/- 1.07e-13] + sage: RealBallField(100)(7/2).beta(1) + [0.28571428571428571428571428571 +/- 5.23e-30] + sage: RealBallField(100)(7/2).beta(1, 1/2) + [0.025253813613805268728601584361 +/- 2.53e-31] + + .. TODO:: + + At the moment RBF(beta(a,b)) does not work, one needs + RBF(a).beta(b) for this to work. See :trac:`32851` + and :trac:`24641`. + """ + cdef RealBall a_ball, z_ball + cdef RealBall res = self._new() + if _do_sig(prec(self)): sig_on() + a_ball = self._parent.coerce(a) + z_ball = self._parent.coerce(z) + arb_hypgeom_beta_lower(res.value, self.value, a_ball.value, + z_ball.value, False, prec(self)) + if _do_sig(prec(self)): sig_off() + return res + + def gamma(self, a=None): + """ + Image of this ball by the (upper incomplete) Euler Gamma function + + For `a` real, return the upper incomplete Gamma function + `\Gamma(self,a)`. For integer and rational arguments, :meth:`~sage.rings.real_arb.RealBallField.gamma` may be faster. @@ -3479,13 +3685,53 @@ cdef class RealBall(RingElement): sage: RBF(1/2).gamma() [1.772453850905516 +/- ...e-16] + sage: RBF(gamma(3/2, RBF(2).sqrt())) + [0.37118875695353 +/- 3.00e-15] + sage: RBF(3/2).gamma_inc(RBF(2).sqrt()) + [0.37118875695353 +/- 3.00e-15] .. SEEALSO:: :meth:`~sage.rings.real_arb.RealBallField.gamma` + + TESTS:: + + sage: RealBallField(100).gamma(1/2) + [1.77245385090551602729816748334 +/- 1.90e-30] """ + cdef RealBall a_ball + cdef RealBall res = self._new() + if a is None: + if _do_sig(prec(self)): sig_on() + arb_gamma(res.value, self.value, prec(self)) + if _do_sig(prec(self)): sig_off() + else: + if _do_sig(prec(self)): sig_on() + a_ball = self._parent.coerce(a) + arb_hypgeom_gamma_upper(res.value, self.value, a_ball.value, 0, prec(self)) + if _do_sig(prec(self)): sig_off() + return res + + gamma_inc = gamma + + def gamma_inc_lower(self, a): + """ + Image of this ball by the lower incomplete Euler Gamma function + + For `a` real, return the lower incomplete Gamma function + of `\Gamma(self,a)`. + + EXAMPLES:: + + sage: RBF(gamma_inc_lower(1/2, RBF(2).sqrt())) + [1.608308637729248 +/- 8.14e-16] + sage: RealBallField(100)(7/2).gamma_inc_lower(5) + [2.6966551541863035516887949614 +/- 8.91e-29] + """ + cdef RealBall a_ball cdef RealBall res = self._new() if _do_sig(prec(self)): sig_on() - arb_gamma(res.value, self.value, prec(self)) + a_ball = RBF(a) + arb_hypgeom_gamma_lower(res.value, self.value, a_ball.value, 0, prec(self)) if _do_sig(prec(self)): sig_off() return res @@ -3569,6 +3815,8 @@ cdef class RealBall(RingElement): For ``a = 1`` (or ``a = None``), this computes the Riemann zeta function. + Otherwise, it computes the Hurwitz zeta function. + Use :meth:`RealBallField.zeta` to compute the Riemann zeta function of a small integer without first converting it to a real ball. diff --git a/src/sage/schemes/affine/affine_morphism.py b/src/sage/schemes/affine/affine_morphism.py index d8dae3b68a0..54c8a247309 100644 --- a/src/sage/schemes/affine/affine_morphism.py +++ b/src/sage/schemes/affine/affine_morphism.py @@ -61,7 +61,7 @@ from sage.arith.all import gcd -from sage.rings.all import Integer +from sage.rings.integer import Integer from sage.rings.finite_rings.finite_field_constructor import is_PrimeFiniteField from sage.rings.fraction_field import FractionField from sage.rings.fraction_field_element import FractionFieldElement @@ -950,7 +950,7 @@ def reduce_base_field(self): From: Affine Space of dimension 2 over Finite Field in t of size 5^4 To: Affine Space of dimension 1 over Finite Field in t of size 5^4 Defn: Defined on coordinates by sending (a, b) to - (a^2 + (t)*b) + (a^2 + t*b) :: @@ -961,7 +961,7 @@ def reduce_base_field(self): sage: g = f.reduce_base_field();g Scheme endomorphism of Affine Space of dimension 1 over Cyclotomic Field of order 4 and degree 2 Defn: Defined on coordinates by sending (x) to - (x^2 + (v)) + (x^2 + v) sage: g.base_ring() is K True @@ -1005,7 +1005,7 @@ def reduce_base_field(self): To: Affine Space of dimension 2 over Number Field in a with defining polynomial x^3 - x + 1 with a = -1.324717957244746? Defn: Defined on coordinates by sending (x) to - (x^2 + (a)*x + 3, 5*x) + (x^2 + a*x + 3, 5*x) :: diff --git a/src/sage/schemes/curves/affine_curve.py b/src/sage/schemes/curves/affine_curve.py index 2702be6f095..23312f06ed6 100644 --- a/src/sage/schemes/curves/affine_curve.py +++ b/src/sage/schemes/curves/affine_curve.py @@ -2440,7 +2440,7 @@ def places_on(self, point): Point (x + (a + 1), y + (-a + 1)), Point (x - 1, y + (a + 1)), Point (x - 1, y + (-a - 1)), - Point (x + (-a - 1), y + (a)), + Point (x + (-a - 1), y + a), Point (x + (-a - 1), y + (-a)), Point (x + 1, y + 1), Point (x + 1, y - 1)] diff --git a/src/sage/schemes/curves/closed_point.py b/src/sage/schemes/curves/closed_point.py index 718b8a20c76..d35ad60b35e 100644 --- a/src/sage/schemes/curves/closed_point.py +++ b/src/sage/schemes/curves/closed_point.py @@ -105,11 +105,11 @@ class IntegralCurveClosedPoint(CurveClosedPoint): sage: C.closed_points() [Point (x, y), Point (x, y + 1), - Point (x + (a), y + (a)), - Point (x + (a), y + (a + 1)), - Point (x + (a + 1), y + (a)), + Point (x + a, y + a), + Point (x + a, y + (a + 1)), + Point (x + (a + 1), y + a), Point (x + (a + 1), y + (a + 1)), - Point (x + 1, y + (a)), + Point (x + 1, y + a), Point (x + 1, y + (a + 1))] """ def __init__(self, curve, prime_ideal, degree): @@ -269,7 +269,7 @@ def rational_point(self): Point (x + (z2 + 1), y + (-z2 + 1)), Point (x - 1, y + (z2 + 1)), Point (x - 1, y + (-z2 - 1)), - Point (x + (-z2 - 1), y + (z2)), + Point (x + (-z2 - 1), y + z2), Point (x + (-z2 - 1), y + (-z2)), Point (x + 1, y + 1), Point (x + 1, y - 1)] @@ -356,8 +356,8 @@ def rational_point(self): [Point (x, z), Point (x, y), Point (y, z), - Point (x + (a)*z, y + (a + 1)*z), - Point (x + (a + 1)*z, y + (a)*z)] + Point (x + a*z, y + (a + 1)*z), + Point (x + (a + 1)*z, y + a*z)] sage: [p.rational_point() for p in _] [(0 : 1 : 0), (0 : 0 : 1), (1 : 0 : 0), (a : a + 1 : 1), (a + 1 : a : 1)] sage: set(_) == set(C.rational_points()) diff --git a/src/sage/schemes/curves/projective_curve.py b/src/sage/schemes/curves/projective_curve.py index ea49a181815..068ffb73146 100644 --- a/src/sage/schemes/curves/projective_curve.py +++ b/src/sage/schemes/curves/projective_curve.py @@ -2628,11 +2628,11 @@ def closed_points(self, degree=1): [Point (x0, x1), Point (x0 + (-z2 - 1)*x2, x1), Point (x0 + (z2 + 1)*x2, x1), - Point (x0 + (z2)*x2, x1 + (z2 - 1)*x2), + Point (x0 + z2*x2, x1 + (z2 - 1)*x2), Point (x0 + (-z2)*x2, x1 + (-z2 + 1)*x2), Point (x0 + (-z2 - 1)*x2, x1 + (-z2 - 1)*x2), Point (x0 + (z2 + 1)*x2, x1 + (z2 + 1)*x2), - Point (x0 + (z2 - 1)*x2, x1 + (z2)*x2), + Point (x0 + (z2 - 1)*x2, x1 + z2*x2), Point (x0 + (-z2 + 1)*x2, x1 + (-z2)*x2), Point (x0 + x2, x1 - x2), Point (x0 - x2, x1 + x2)] diff --git a/src/sage/schemes/elliptic_curves/cm.py b/src/sage/schemes/elliptic_curves/cm.py index 9556d1c8ac5..e441ab51f1b 100644 --- a/src/sage/schemes/elliptic_curves/cm.py +++ b/src/sage/schemes/elliptic_curves/cm.py @@ -41,7 +41,7 @@ is_fundamental_discriminant, PolynomialRing) -from sage.misc.all import cached_function +from sage.misc.cachefunc import cached_function @cached_function def hilbert_class_polynomial(D, algorithm=None): diff --git a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py index b91c5edabae..9783877f153 100644 --- a/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py +++ b/src/sage/schemes/elliptic_curves/ell_curve_isogeny.py @@ -2416,7 +2416,7 @@ def __init_odd_kernel_polynomial(self, E, psi): sage: R. = F[] sage: f = x + alpha^2 + 1 sage: phi._EllipticCurveIsogeny__init_odd_kernel_polynomial(E, f) - (x^3 + (alpha^2 + 1)*x + alpha^3 + alpha^2 + alpha, x^3*y + (alpha^2 + 1)*x^2*y + (alpha^2 + alpha + 1)*x^2 + (alpha^2 + 1)*x*y + (alpha^2 + alpha)*x + (alpha)*y + (alpha), alpha^2 + alpha + 1, alpha^3 + alpha^2 + alpha, 1, 3) + (x^3 + (alpha^2 + 1)*x + alpha^3 + alpha^2 + alpha, x^3*y + (alpha^2 + 1)*x^2*y + (alpha^2 + alpha + 1)*x^2 + (alpha^2 + 1)*x*y + (alpha^2 + alpha)*x + alpha*y + alpha, alpha^2 + alpha + 1, alpha^3 + alpha^2 + alpha, 1, 3) sage: E = EllipticCurve(j=-262537412640768000) sage: f = (E.isogenies_prime_degree()[0]).kernel_polynomial() @@ -2565,7 +2565,7 @@ def __compute_omega_general(self, E, psi, psi_pr, phi, phi_pr): sage: fi = phi._EllipticCurveIsogeny__phi sage: fi_pr = fi.derivative() sage: phi._EllipticCurveIsogeny__compute_omega_general(E, psi, psi_pr, fi, fi_pr) - x^3*y + (alpha^2 + 1)*x^2*y + (alpha^2 + alpha + 1)*x^2 + (alpha^2 + 1)*x*y + (alpha^2 + alpha)*x + (alpha)*y + (alpha) + x^3*y + (alpha^2 + 1)*x^2*y + (alpha^2 + alpha + 1)*x^2 + (alpha^2 + 1)*x*y + (alpha^2 + alpha)*x + alpha*y + alpha A bug fixed in :trac:`7907`:: diff --git a/src/sage/schemes/elliptic_curves/ell_generic.py b/src/sage/schemes/elliptic_curves/ell_generic.py index 965271f7241..c261b284fc6 100644 --- a/src/sage/schemes/elliptic_curves/ell_generic.py +++ b/src/sage/schemes/elliptic_curves/ell_generic.py @@ -145,7 +145,7 @@ def __init__(self, K, ainvs): self.__base_ring = K self.__ainvs = tuple(K(a) for a in ainvs) if self.discriminant() == 0: - raise ArithmeticError("invariants " + str(ainvs) + " define a singular curve") + raise ArithmeticError(self._equation_string() + " defines a singular curve") PP = projective_space.ProjectiveSpace(2, K, names='xyz') x, y, z = PP.coordinate_ring().gens() a1, a2, a3, a4, a6 = ainvs diff --git a/src/sage/schemes/elliptic_curves/padics.py b/src/sage/schemes/elliptic_curves/padics.py index 7c140199516..45d3fd9fcd2 100644 --- a/src/sage/schemes/elliptic_curves/padics.py +++ b/src/sage/schemes/elliptic_curves/padics.py @@ -39,7 +39,7 @@ sqrt = math.sqrt import sage.schemes.hyperelliptic_curves.monsky_washnitzer import sage.schemes.hyperelliptic_curves.hypellfrob -from sage.misc.all import cached_method +from sage.misc.cachefunc import cached_method def __check_padic_hypotheses(self, p): r""" diff --git a/src/sage/schemes/elliptic_curves/saturation.py b/src/sage/schemes/elliptic_curves/saturation.py index 14b172cacbb..3af4d7e712b 100644 --- a/src/sage/schemes/elliptic_curves/saturation.py +++ b/src/sage/schemes/elliptic_curves/saturation.py @@ -50,7 +50,7 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from sage.rings.finite_rings.all import GF +from sage.rings.finite_rings.finite_field_constructor import GF from sage.rings.integer_ring import ZZ from sage.arith.all import kronecker_symbol as kro from sage.structure.sage_object import SageObject diff --git a/src/sage/schemes/generic/algebraic_scheme.py b/src/sage/schemes/generic/algebraic_scheme.py index 164826d9b5a..f0d73d0dcd3 100644 --- a/src/sage/schemes/generic/algebraic_scheme.py +++ b/src/sage/schemes/generic/algebraic_scheme.py @@ -1982,7 +1982,7 @@ def weil_restriction(self): Closed subscheme of Affine Space of dimension 4 over Number Field in w with defining polynomial x^5 - 2 defined by: (-w)*z0^3 + (3*w)*z0*z1^2 + z2^2 - z3^2, - (-3*w)*z0^2*z1 + (w)*z1^3 + 2*z2*z3 - 1 + (-3*w)*z0^2*z1 + w*z1^3 + 2*z2*z3 - 1 sage: X.weil_restriction().ambient_space() is A.weil_restriction() True diff --git a/src/sage/schemes/generic/scheme.py b/src/sage/schemes/generic/scheme.py index 070fcabc715..a0fa83ce65d 100644 --- a/src/sage/schemes/generic/scheme.py +++ b/src/sage/schemes/generic/scheme.py @@ -20,7 +20,7 @@ # **************************************************************************** from sage.structure.parent import Parent -from sage.misc.all import cached_method +from sage.misc.cachefunc import cached_method from sage.rings.all import (ZZ, CommutativeRing) from sage.rings.ideal import is_Ideal from sage.structure.unique_representation import UniqueRepresentation diff --git a/src/sage/schemes/plane_conics/con_field.py b/src/sage/schemes/plane_conics/con_field.py index 1b557fcd735..57285966f19 100644 --- a/src/sage/schemes/plane_conics/con_field.py +++ b/src/sage/schemes/plane_conics/con_field.py @@ -198,7 +198,7 @@ def derivative_matrix(self): sage: P. = GF(2)[] sage: c = Conic([t, 1, t^2, 1, 1, 0]); c - Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 2 (using GF2X) defined by t*x^2 + x*y + y^2 + t^2*x*z + y*z + Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 2 (using GF2X) defined by t*x^2 + x*y + y^2 + (t^2)*x*z + y*z sage: c.is_smooth() True sage: c.derivative_matrix() @@ -339,18 +339,19 @@ def diagonalization(self, names=None): sage: (t,) = K.gens() sage: C = Conic(K, [t/2,0, 1, 2, 0, 3]) sage: C.diagonalization() - (Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by 4*t*x^2 + 2*y^2 + ((3*t + 3)/t)*z^2, + (Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (-3*t)*x^2 + 2*y^2 + (3*t + 3)/t*z^2, Scheme morphism: - From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by 4*t*x^2 + 2*y^2 + ((3*t + 3)/t)*z^2 - To: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by 4*t*x^2 + 2*y^2 + x*z + 3*z^2 + From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (-3*t)*x^2 + 2*y^2 + (3*t + 3)/t*z^2 + To: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (-3*t)*x^2 + 2*y^2 + x*z + 3*z^2 Defn: Defined on coordinates by sending (x : y : z) to - (x + 6/t*z : y : z), + (x - 1/t*z : y : z), Scheme morphism: - From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by 4*t*x^2 + 2*y^2 + x*z + 3*z^2 - To: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by 4*t*x^2 + 2*y^2 + ((3*t + 3)/t)*z^2 + From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (-3*t)*x^2 + 2*y^2 + x*z + 3*z^2 + To: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (-3*t)*x^2 + 2*y^2 + (3*t + 3)/t*z^2 Defn: Defined on coordinates by sending (x : y : z) to (x + 1/t*z : y : z)) + """ if names is None: names = self.defining_polynomial().parent().variable_names() @@ -683,7 +684,7 @@ def hom(self, x, Y=None): sage: C.hom(T, D) Scheme morphism: From: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Rational Field defined by x^2 + t*y^2 + 1/t*z^2 - To: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Rational Field defined by 1/t^2*x^2 + t*y^2 + (-2/t^2)*x*z + ((t + 1)/t^2)*z^2 + To: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Rational Field defined by 1/(t^2)*x^2 + t*y^2 - 2/(t^2)*x*z + (t + 1)/(t^2)*z^2 Defn: Defined on coordinates by sending (x : y : z) to (t*x + z : y : z) @@ -759,7 +760,7 @@ def _magma_init_(self, magma): sage: F. = GF(25) sage: C = Conic([3,0,1,4,a,2]) sage: C - Projective Conic Curve over Finite Field in a of size 5^2 defined by -2*x^2 - y^2 + x*z + (a)*y*z + 2*z^2 + Projective Conic Curve over Finite Field in a of size 5^2 defined by -2*x^2 - y^2 + x*z + a*y*z + 2*z^2 sage: magma(C) # optional - magma Conic over GF(5^2) defined by 3*X^2 + 4*Y^2 + X*Z + a*Y*Z + 2*Z^2 @@ -1076,7 +1077,7 @@ def rational_point(self, algorithm = 'default', read_cache = True): sage: F. = FiniteField(7^20) sage: C = Conic([1, a, -5]); C - Projective Conic Curve over Finite Field in a of size 7^20 defined by x^2 + (a)*y^2 + 2*z^2 + Projective Conic Curve over Finite Field in a of size 7^20 defined by x^2 + a*y^2 + 2*z^2 sage: C.rational_point() # output is random (4*a^19 + 5*a^18 + 4*a^17 + a^16 + 6*a^15 + 3*a^13 + 6*a^11 + a^9 + 3*a^8 + 2*a^7 + 4*a^6 + 3*a^5 + 3*a^4 + a^3 + a + 6 : 5*a^18 + a^17 + a^16 + 6*a^15 + 4*a^14 + a^13 + 5*a^12 + 5*a^10 + 2*a^9 + 6*a^8 + 6*a^7 + 6*a^6 + 2*a^4 + 3 : 1) diff --git a/src/sage/schemes/plane_conics/con_finite_field.py b/src/sage/schemes/plane_conics/con_finite_field.py index 82f71c815d1..86a7e168259 100644 --- a/src/sage/schemes/plane_conics/con_finite_field.py +++ b/src/sage/schemes/plane_conics/con_finite_field.py @@ -108,7 +108,7 @@ def has_rational_point(self, point=False, read_cache=True, sage: F. = FiniteField(7^20) sage: C = Conic([1, a, -5]); C - Projective Conic Curve over Finite Field in a of size 7^20 defined by x^2 + (a)*y^2 + 2*z^2 + Projective Conic Curve over Finite Field in a of size 7^20 defined by x^2 + a*y^2 + 2*z^2 sage: C.has_rational_point(point = True) # output is random (True, (a^18 + 2*a^17 + 4*a^16 + 6*a^13 + a^12 + 6*a^11 + 3*a^10 + 4*a^9 + 2*a^8 + 4*a^7 + a^6 + 4*a^4 + 6*a^2 + 3*a + 6 : 5*a^19 + 5*a^18 + 5*a^17 + a^16 + 2*a^15 + 3*a^14 + 4*a^13 + 5*a^12 + a^11 + 3*a^10 + 2*a^8 + 3*a^7 + 4*a^6 + 4*a^5 + 6*a^3 + 5*a^2 + 2*a + 4 : 1)) 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 154201f2cb2..383802d75a8 100644 --- a/src/sage/schemes/plane_conics/con_rational_function_field.py +++ b/src/sage/schemes/plane_conics/con_rational_function_field.py @@ -203,14 +203,15 @@ def has_rational_point(self, point=False, algorithm='default', 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 (5*t^2 + 4)*x^2 + ((6*t^3 + 3*t^2 + 5*t + 5)/(t + 3))*y^2 + ((6*t^6 + 3*t^5 + t^3 + 6*t^2 + 6*t + 2)/(t^4 + t^3 + 4*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 (5*t^2 + 4)*x^2 + (t^2 + 3*t + 3)*x*y + (5*t^2 + 5)*y^2 + (6*t^2 + 3*t + 2)*x*z + (4*t + 3)*y*z + (4*t^2 + t + 5)*z^2 + 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 + 5)/(t + 3))*y + ((3*t^4 + 2*t^3 + 5*t^2 + 5*t + 3)/(t^4 + t^3 + 4*t^2 + 3*t + 1))*z : y + ((6*t^3 + 6*t^2 + 3*t + 6)/(t^3 + 4*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 (5*t^3 + 6*t^2 + 3*t + 3)*x^2 + (t + 4)*y^2 + (6*t^7 + 2*t^5 + t^4 + 2*t^3 + 3*t^2 + 6*t + 6)*z^2 - To: Projective Conic Curve over Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 7 defined by (5/(t^3 + 4*t^2 + 2*t + 2))*x^2 + (1/(t^3 + 3*t^2 + 5*t + 1))*y^2 + ((6*t^6 + 3*t^5 + t^3 + 6*t^2 + 6*t + 2)/(t^9 + 5*t^8 + t^7 + 6*t^6 + 3*t^5 + 4*t^3 + t^2 + 5*t + 3))*z^2 + (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 + 4*t^2 + 2*t + 2)*x : (t^2 + 5)*y : (t^5 + 4*t^4 + t^2 + 3*t + 3)*z)) codomain + ((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:: diff --git a/src/sage/schemes/projective/projective_morphism.py b/src/sage/schemes/projective/projective_morphism.py index 9e21e494e55..e00e455843d 100644 --- a/src/sage/schemes/projective/projective_morphism.py +++ b/src/sage/schemes/projective/projective_morphism.py @@ -75,7 +75,7 @@ from sage.calculus.functions import jacobian import sage.rings.abc -from sage.rings.all import Integer +from sage.rings.integer import Integer from sage.rings.algebraic_closure_finite_field import AlgebraicClosureFiniteField_generic from sage.rings.complex_mpfr import ComplexField_class from sage.rings.complex_interval_field import ComplexIntervalField_class @@ -91,7 +91,6 @@ from sage.rings.rational_field import QQ from sage.rings.real_mpfr import RealField_class from sage.rings.real_mpfi import RealIntervalField_class -import sage.rings.abc from sage.schemes.generic.morphism import SchemeMorphism_polynomial @@ -603,7 +602,7 @@ def _matrix_times_polymap_(self, mat, h): sage: matrix([[i,0], [0,i]]) * f Scheme endomorphism of Projective Space of dimension 1 over Number Field in i with defining polynomial x^2 + 1 Defn: Defined on coordinates by sending (x : y) to - ((1/3*i)*x^2 + (1/2*i)*y^2 : (i)*y^2) + ((1/3*i)*x^2 + (1/2*i)*y^2 : i*y^2) """ from sage.modules.free_module_element import vector from sage.dynamics.arithmetic_dynamics.generic_ds import DynamicalSystem @@ -1971,7 +1970,7 @@ def reduce_base_field(self): sage: f.reduce_base_field() Scheme endomorphism of Projective Space of dimension 1 over Finite Field in t2 of size 3^2 Defn: Defined on coordinates by sending (x : y) to - (x^2 + (t2)*y^2 : y^2) + (x^2 + t2*y^2 : y^2) sage: f2 = H2([x^2 + 5*y^2,y^2, 2*x*y]) sage: f2.reduce_base_field() Scheme morphism: @@ -1985,7 +1984,7 @@ def reduce_base_field(self): From: Projective Space of dimension 2 over Finite Field in t of size 3^4 To: Projective Space of dimension 1 over Finite Field in t of size 3^4 Defn: Defined on coordinates by sending (a : b : c) to - (a^2 + (t)*b^2 : c^2) + (a^2 + t*b^2 : c^2) :: @@ -2008,7 +2007,7 @@ def reduce_base_field(self): sage: f.reduce_base_field() Scheme endomorphism of Projective Space of dimension 1 over Finite Field in z4 of size 5^4 Defn: Defined on coordinates by sending (x : y) to - ((z4^3 + z4^2 + z4 - 2)*x^2 + (z4)*y^2 : x*y) + ((z4^3 + z4^2 + z4 - 2)*x^2 + z4*y^2 : x*y) sage: f=DynamicalSystem_projective([L.gen(3)*x^2 + L.gen(2)*y^2, x*y]) sage: f.reduce_base_field() Dynamical System of Projective Space of dimension 1 over Finite Field in z6 of size 5^6 diff --git a/src/sage/schemes/projective/projective_subscheme.py b/src/sage/schemes/projective/projective_subscheme.py index ccda38ad316..7c603f6bf8c 100644 --- a/src/sage/schemes/projective/projective_subscheme.py +++ b/src/sage/schemes/projective/projective_subscheme.py @@ -663,7 +663,7 @@ def _forward_image(self, f, check = True): sage: f([t^2*y-z]) Closed subscheme of Projective Space of dimension 2 over Fraction Field of Univariate Polynomial Ring in t over Rational Field defined by: - y + (-1/t^2)*z + y - 1/(t^2)*z :: diff --git a/src/sage/schemes/toric/fano_variety.py b/src/sage/schemes/toric/fano_variety.py index 20b15e3fc66..8935197298d 100644 --- a/src/sage/schemes/toric/fano_variety.py +++ b/src/sage/schemes/toric/fano_variety.py @@ -877,7 +877,7 @@ def anticanonical_hypersurface(self, **kwds): sage: H Closed subscheme of 2-d CPR-Fano toric variety covered by 3 affine patches defined by: - t*z1^3 + (psi/(psi^2 + phi))*z0*z1*z2 + 1/t*z2^3 + t*z1^3 + psi/(phi + psi^2)*z0*z1*z2 + 1/t*z2^3 sage: R = H.ambient_space().base_ring() sage: R Fraction Field of @@ -1149,7 +1149,7 @@ def nef_complete_intersection(self, nef_partition, **kwds): Closed subscheme of 3-d CPR-Fano toric variety covered by 10 affine patches defined by: a*z1*z4^2*z5^2*z7^3 + a/e*z2*z4*z5*z6*z7^2*z8^2 - + c_i*z2*z3*z4*z7*z8 + a^2*z0*z2, + + (c_i)*z2*z3*z4*z7*z8 + (a^2)*z0*z2, 4*z1*z4*z5^2*z6^2*z7^2*z8^2 + z2*z5*z6^3*z7*z8^4 + 3*z2*z3*z6^2*z8^3 + 2*z1*z3^2*z4 + 5*z0*z1*z5*z6 diff --git a/src/sage/schemes/toric/morphism.py b/src/sage/schemes/toric/morphism.py index 7e891014a65..783a4b33a25 100644 --- a/src/sage/schemes/toric/morphism.py +++ b/src/sage/schemes/toric/morphism.py @@ -371,7 +371,7 @@ from sage.structure.sequence import Sequence from sage.rings.integer_ring import ZZ from sage.arith.all import gcd -from sage.misc.all import cached_method +from sage.misc.cachefunc import cached_method from sage.matrix.constructor import matrix, identity_matrix from sage.modules.free_module_element import vector from sage.geometry.all import Cone, Fan diff --git a/src/sage/schemes/toric/sheaf/klyachko.py b/src/sage/schemes/toric/sheaf/klyachko.py index 953bbe06d02..30d6e19bf2b 100644 --- a/src/sage/schemes/toric/sheaf/klyachko.py +++ b/src/sage/schemes/toric/sheaf/klyachko.py @@ -48,7 +48,7 @@ from sage.structure.all import SageObject from sage.structure.richcmp import richcmp_method, richcmp, richcmp_not_equal from sage.rings.integer_ring import ZZ -from sage.misc.all import cached_method +from sage.misc.cachefunc import cached_method from sage.matrix.constructor import vector, block_matrix, zero_matrix from sage.modules.multi_filtered_vector_space import MultiFilteredVectorSpace import sage.geometry.abc diff --git a/src/sage/sets/disjoint_union_enumerated_sets.py b/src/sage/sets/disjoint_union_enumerated_sets.py index 79e5954c561..7e3ff52cec1 100644 --- a/src/sage/sets/disjoint_union_enumerated_sets.py +++ b/src/sage/sets/disjoint_union_enumerated_sets.py @@ -468,12 +468,12 @@ def _element_constructor_(self): sage: U = DisjointUnionEnumeratedSets( ....: Family([1,2,3], Partitions), facade=False) sage: U._element_constructor_ - sage: U = DisjointUnionEnumeratedSets( ....: Family([1,2,3], Partitions), facade=True) sage: U._element_constructor_ - """ if not self._facade: diff --git a/src/sage/structure/category_object.pyx b/src/sage/structure/category_object.pyx index 98ab3d16a45..334ee91430d 100644 --- a/src/sage/structure/category_object.pyx +++ b/src/sage/structure/category_object.pyx @@ -782,7 +782,7 @@ cdef class CategoryObject(SageObject): its categories, that is from ``EuclideanDomains().parent_class``:: sage: ZZ._test_associativity - + sage: ZZ._test_associativity(verbose = True) sage: TestSuite(ZZ).run(verbose = True) running ._test_additive_associativity() . . . pass diff --git a/src/sage/structure/coerce.pyx b/src/sage/structure/coerce.pyx index 7dc6cbd59ff..4d9069725ae 100644 --- a/src/sage/structure/coerce.pyx +++ b/src/sage/structure/coerce.pyx @@ -484,7 +484,7 @@ cdef class CoercionModel: EXAMPLES:: sage: f = ZZ['t','x'].0 + QQ['x'].0 + CyclotomicField(13).gen(); f - t + x + (zeta13) + t + x + zeta13 sage: f.parent() Multivariate Polynomial Ring in t, x over Cyclotomic Field of order 13 and degree 12 sage: ZZ['x','y'].0 + ~Frac(QQ['y']).0 diff --git a/src/sage/structure/element.pyx b/src/sage/structure/element.pyx index 76df456113e..369d3e25f18 100644 --- a/src/sage/structure/element.pyx +++ b/src/sage/structure/element.pyx @@ -474,7 +474,7 @@ cdef class Element(SageObject): category of ``CommutativeRings()``:: sage: 1.is_idempotent - + sage: 1.is_idempotent.__module__ 'sage.categories.magmas' @@ -485,7 +485,7 @@ cdef class Element(SageObject): ... AttributeError: 'sage.rings.integer.Integer' object has no attribute 'blah_blah' sage: Semigroups().example().an_element().is_idempotent - + sage: Semigroups().example().an_element().blah_blah Traceback (most recent call last): ... diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 8c29b6c6657..843cfee7f4c 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -1793,7 +1793,20 @@ cdef class Expression(Expression_abc): Traceback (most recent call last): ... ValueError: nonzero imaginary part + + sage: from sage.symbolic.function import BuiltinFunction + sage: f = BuiltinFunction("bogus_builtin_function") + sage: RBF(f(1)) + Traceback (most recent call last): + ... + TypeError: unable to convert bogus_builtin_function(1) to a RealBall + sage: CBF(f(1)) + Traceback (most recent call last): + ... + TypeError: unable to convert bogus_builtin_function(1) to a ComplexBall """ + cdef bint progress = False + cdef int i # Note that we deliberately don't use _eval_self and don't try going # through RIF/CIF in order to avoid unsafe conversions. operator = self.operator() @@ -1827,11 +1840,18 @@ cdef class Expression(Expression_abc): # Generic case: walk through the expression. In this case, we do # not bother trying to stay in the real field. try: - res = self.operator()(*[C(a) for a in args]) + for i in range(len(args)): + if args[i].parent() is not C: + progress = True + args[i] = C(args[i]) except (TypeError, ValueError): pass - else: - return R(res) + if progress: + try: + res = self.operator()(*[C(a) for a in args]) + return R(res) + except (TypeError, ValueError): + pass # Typically more informative and consistent than the exceptions that # would propagate raise TypeError("unable to convert {!r} to a {!s}".format( diff --git a/src/sage/symbolic/expression_conversions.py b/src/sage/symbolic/expression_conversions.py index d12c5969e72..3276af869ed 100644 --- a/src/sage/symbolic/expression_conversions.py +++ b/src/sage/symbolic/expression_conversions.py @@ -1542,7 +1542,7 @@ def arithmetic(self, ex, operator): if not any(repr(v) in self.varnames for v in ex.variables()): return self.base_ring(ex) elif operator == _operator.pow: - from sage.rings.all import Integer + from sage.rings.integer import Integer base, exp = ex.operands() return self(base)**Integer(exp) if operator == add_vararg: diff --git a/src/sage/symbolic/function.pyx b/src/sage/symbolic/function.pyx index 91c66fc5eff..89cdce56d70 100644 --- a/src/sage/symbolic/function.pyx +++ b/src/sage/symbolic/function.pyx @@ -627,7 +627,7 @@ cdef class Function(SageObject): sage: airy_ai(b) airy_ai([1.500000000 +/- 1.01e-10]) sage: gamma(b, 1) - gamma([1.500000000 +/- 1.01e-10], 1) + [0.50728223 +/- 4.67e-9] sage: hurwitz_zeta(b, b) hurwitz_zeta([1.500000000 +/- 1.01e-10], [1.500000000 +/- 1.01e-10]) sage: hurwitz_zeta(1/2, b) diff --git a/src/sage/tests/books/computational-mathematics-with-sagemath/mpoly_doctest.py b/src/sage/tests/books/computational-mathematics-with-sagemath/mpoly_doctest.py index bb56738cd50..0e6cad57fee 100644 --- a/src/sage/tests/books/computational-mathematics-with-sagemath/mpoly_doctest.py +++ b/src/sage/tests/books/computational-mathematics-with-sagemath/mpoly_doctest.py @@ -93,7 +93,7 @@ sage: (x^10 + y^5).gcd(x^4 - y^2) x^2 + y sage: (x^10 + y^5).factor() - (x^2 + y) * (x^2 + (a^3)*y) * (x^2 + (a^2)*y) * (x^2 + (a)*y) * (x^2 + (-a^3 - a^2 - a - 1)*y) + (x^2 + y) * (x^2 + (a^3)*y) * (x^2 + (a^2)*y) * (x^2 + a*y) * (x^2 + (-a^3 - a^2 - a - 1)*y) Sage example in ./mpoly.tex, line 564:: diff --git a/src/sage/tests/books/computational-mathematics-with-sagemath/sol/linsolve_doctest.py b/src/sage/tests/books/computational-mathematics-with-sagemath/sol/linsolve_doctest.py index 14208cd98ba..839ad0d7ec7 100644 --- a/src/sage/tests/books/computational-mathematics-with-sagemath/sol/linsolve_doctest.py +++ b/src/sage/tests/books/computational-mathematics-with-sagemath/sol/linsolve_doctest.py @@ -19,7 +19,7 @@ Sage example in ./sol/linsolve.tex, line 84:: sage: M = (X*X-a) - sage: all(abs(M[i,j]) < 10^-14 + sage: all(abs(M[i,j]) < 10^-13 ....: for i in range(4) for j in range(4) ) True diff --git a/src/sage/version.py b/src/sage/version.py index 7785a1ebba4..60df61416a0 100644 --- a/src/sage/version.py +++ b/src/sage/version.py @@ -1,5 +1,5 @@ # Sage version information for Python scripts # This file is auto-generated by the sage-update-version script, do not edit! -version = '9.5.beta6' -date = '2021-11-12' -banner = 'SageMath version 9.5.beta6, Release Date: 2021-11-12' +version = '9.5.beta7' +date = '2021-11-18' +banner = 'SageMath version 9.5.beta7, Release Date: 2021-11-18' diff --git a/src/sage_docbuild/__init__.py b/src/sage_docbuild/__init__.py index 2368d6cbf31..f27c6cf086e 100644 --- a/src/sage_docbuild/__init__.py +++ b/src/sage_docbuild/__init__.py @@ -1231,7 +1231,7 @@ def __init__(self, path): # Write self.dir/conf.py conf = r"""# This file is automatically generated by {}, do not edit! -import sys, os +import sys, os, contextlib sys.path.append({!r}) from sage.docs.conf import * @@ -1244,8 +1244,9 @@ def __init__(self, path): html_short_title = project htmlhelp_basename = name -extensions.remove('multidocs') # see #29651 -extensions.remove('inventory_builder') +with contextlib.suppress(ValueError): + extensions.remove('multidocs') # see #29651 + extensions.remove('inventory_builder') latex_domain_indices = False latex_documents = [ diff --git a/tox.ini b/tox.ini index 540ddd20be1..6dd379b1920 100644 --- a/tox.ini +++ b/tox.ini @@ -1,39 +1,61 @@ -# Run a specific environment: -# tox -e docker-fedora-31 -# Run all in parallel: -# tox -p auto +# SAGE_ROOT/tox.ini: Environments for testing the Sage distribution +# + +# To run a specific environment: +# +# $ tox -e docker-fedora-31-standard +# +# This will do a complete build of the Sage distribution in a Docker container, which will take a while. +# +# Specific 'make' targets can be given as additional arguments after "--". +# For example, to only run the configuration phase: +# +# $ tox -e docker-debian-bullseye-standard -- config.status +# +# To build a single package (and its dependencies): +# +# $ tox -e docker-manylinux-2_24-i686-standard -- ppl +# +# It can be useful to run several of the environments in parallel. For example: +# +# $ tox -p auto -- config.status +# # with local squid: -# EXTRA_DOCKER_BUILD_ARGS="--build-arg http_proxy=http://host.docker.internal:3128 --build-arg https_proxy=http://host.docker.internal:3128" tox -p auto +# +# $ EXTRA_DOCKER_BUILD_ARGS="--build-arg http_proxy=http://host.docker.internal:3128 --build-arg https_proxy=http://host.docker.internal:3128" tox -p auto -- config.status [tox] -### Test that the system packages listed in debian.txt/fedora.txt files of standard spkg exist -### and satisfy the requirements tested by spkg-configure.m4, then compile a few packages. -### + envlist = - ##### Delegation to src/tox.ini ##### - doctest, coverage, startuptime, pycodestyle-minimal, relint, codespell, - ##### Sage-the-distribution tests ##### + + ##### + ##### Sage-the-distribution tests + ##### + check_configure, - ##### Sage-the-distribution portability tests ##### - { - { - ### "docker" toxenvs copy sources from the source tree subject to the exclusions in + + ##### + ##### Sage-the-distribution portability tests + ##### + + # See https://doc.sagemath.org/html/en/developer/portability_testing.html + + ### "docker" environments copy sources from the source tree subject to the exclusions in ### the file ".dockerignore". This should work out of non-clean source trees, and all ### "docker" toxenvs can be run in parallel. - docker-{ubuntu-{trusty,xenial,bionic,latest,rolling,focal,devel}, - debian-{jessie,stretch,buster,bullseye,sid}, - linuxmint-{17,18,19,19.1,19.2,19.3}, - fedora-{26,27,28,29,30,31,32}, - centos-{7,8}, - arch-latest, - conda-forge,conda-anaconda3 - } - -{# https://github.com/docker-library/official-images#architectures-other-than-amd64 - # architectures officially supported by Docker, Inc. for running Docker - amd64,arm32v6,arm32v7,arm64v8, - # windows-amd64 # https://hub.docker.com/u/winamd64/ - # Other architectures built by official images: - # (but not officially supported by Docker, Inc.) - arm32v5,ppc64le,s390x,i386}, + + ### Package factors: + ### + ### - minimal # Install a minimal set of system packages that supports bootstrapping and compiling Sage. + ### - standard # Install all known system packages equivalent to standard packages that have spkg-configure.m4 + ### - maximal # Install all known system packages equivalent to standard/optional packages that have spkg-configure.m4 + + docker-ubuntu-trusty-minimal, + docker-debian-bullseye-standard, + docker-fedora-34-standard, + docker-archlinux-latest-maximal, + docker-manylinux-2_24-i686-standard, + docker-conda-forge-standard, + ### "local" targets should be run from a source tree that is freshly checked out ### (for example, by 'git worktree add ...') or has been cleaned by 'make bdist-clean' -- ### because they build within the source tree (because we have no VPATH support). @@ -74,26 +96,32 @@ envlist = # instead. It may install packages or update packages. It will not remove packages. # Use at your own risk. # - local-homebrew-macos - } - -{### - ### Package factors: - ### - minimal, # Install a minimal set of system packages that supports bootstrapping and compiling Sage. - standard, # Install all known system packages equivalent to standard packages that have spkg-configure.m4 - maximal # Install all known system packages equivalent to standard/optional packages that have spkg-configure.m4 - }, - ### - ### The "local-direct" toxenv passes the whole environment on to the sage build. - ### Whatever is in PATH etc. will be used. - ### - local-direct - } - -{### - ### Configuration factors: - ### - python3_spkg - } + + ### + ### The "local-direct" toxenv passes the whole environment on to the sage build. + ### Whatever is in PATH etc. will be used. + ### + # + # $ tox -e local-direct -- openblas + + + ##### + ##### Delegation to src/tox.ini + ##### + + # included with (cd src && tox -p auto): + # + # doctest, + # coverage, + # startuptime, + # pycodestyle-minimal, + # relint, + # codespell, + # + # Also available: + # + # pycodestyle + skipsdist = true @@ -247,6 +275,7 @@ setenv = gentoo: BASE_IMAGE=sheerluck/sage-on-gentoo-stage4 gentoo-python3.7: BASE_TAG=latest-py37 gentoo-python3.9: BASE_TAG=latest-py39 + gentoo-python3.10: BASE_TAG=latest-py10 gentoo: IGNORE_MISSING_SYSTEM_PACKAGES=no # # https://hub.docker.com/_/archlinux/ @@ -309,6 +338,14 @@ setenv = # Many docker images for another architecture are named the same, in the arch prefix. # All work for Docker on Mac; but only i386 works for Linux Docker. # + # According to https://github.com/docker-library/official-images#architectures-other-than-amd64 + # architectures officially supported by Docker, Inc. for running Docker: + # - amd64,arm32v6,arm32v7,arm64v8, + # - windows-amd64 # https://hub.docker.com/u/winamd64/ + # Other architectures built by official images: + # (but not officially supported by Docker, Inc.) + # - arm32v5,ppc64le,s390x,i386 + # arm32v5: ARCH_IMAGE_PREFIX=arm32v5/ arm32v6: ARCH_IMAGE_PREFIX=arm32v6/ arm32v7: ARCH_IMAGE_PREFIX=arm32v7/ @@ -585,6 +622,8 @@ commands = ## Test that configure behaves properly whitelist_externals = bash +setenv = + HOME = {envdir} commands = ./bootstrap bash -c 'test -z "$(./configure --quiet 2>&1)" || (echo >&2 Error: "configure --quiet" is not quiet; exit 1)'