diff --git a/.github/workflows/ci-cygwin-minimal.yml b/.github/workflows/ci-cygwin-minimal.yml index 8c2a7d2213f..9e847e74740 100644 --- a/.github/workflows/ci-cygwin-minimal.yml +++ b/.github/workflows/ci-cygwin-minimal.yml @@ -84,7 +84,7 @@ jobs: cygwin-stage-i-b: env: STAGE: i-b - TARGETS: cython setuptools_scm kiwisolver dateutil cycler pyparsing nose certifi pkgconfig pplpy + TARGETS: cython setuptools_scm kiwisolver dateutil cycler pyparsing certifi pkgconfig pplpy LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} diff --git a/.github/workflows/ci-cygwin-standard.yml b/.github/workflows/ci-cygwin-standard.yml index a27118d7f17..cbbe0f46a8b 100644 --- a/.github/workflows/ci-cygwin-standard.yml +++ b/.github/workflows/ci-cygwin-standard.yml @@ -84,7 +84,7 @@ jobs: cygwin-stage-i-b: env: STAGE: i-b - TARGETS: cython setuptools_scm kiwisolver dateutil cycler pyparsing nose certifi pkgconfig pplpy + TARGETS: cython setuptools_scm kiwisolver dateutil cycler pyparsing certifi pkgconfig pplpy LOCAL_ARTIFACT_NAME: sage-local-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-cygwin-${{ matrix.pkgs }} diff --git a/.github/workflows/tox-experimental.yml b/.github/workflows/tox-experimental.yml index 7bf186ace20..554a058cdb9 100644 --- a/.github/workflows/tox-experimental.yml +++ b/.github/workflows/tox-experimental.yml @@ -48,7 +48,9 @@ jobs: TOX_ENV: docker-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-tox-docker-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} DOCKER_TARGETS: configured with-targets with-targets-optional - TARGETS_OPTIONAL: "$( echo $(PATH=build/bin:$PATH build/bin/sage-package list :experimental: | grep -v database_stein_watkins\\$ | grep -v polytopes_db_4d | grep '^[${{ matrix.targets_pattern }}]' ) )" + # Test all non-dummy experimental packages, but do not test huge packages + # and do not test packages that require external software + TARGETS_OPTIONAL: "$( echo $(export PATH=build/bin:$PATH && sage-package list :experimental: --has-file spkg-install.in && sage-package list :experimental: --has-file spkg-install && sage-package list :experimental: --has-file requirements.txt | grep -v ^_ | grep -v database_stein_watkins\\$ | grep -v polytopes_db_4d | grep -v cplex | grep -v gurobi | grep '^[${{ matrix.targets_pattern }}]' ) )" steps: - uses: actions/checkout@v2 with: @@ -147,7 +149,9 @@ jobs: env: TOX_ENV: local-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-tox-local-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }}-${{ matrix.os }}-xcode_${{ matrix.xcode_version_factor }} - TARGETS_OPTIONAL: "$( echo $(PATH=build/bin:$PATH build/bin/sage-package list :experimental: | grep -v database_stein_watkins\\$ | grep -v polytopes_db_4d | grep '^[${{ matrix.targets_pattern }}]' ) )" + # Test all non-dummy experimental packages, but do not test huge packages + # and do not test packages that require external software + TARGETS_OPTIONAL: "$( echo $(export PATH=build/bin:$PATH && sage-package list :experimental: --has-file spkg-install.in && sage-package list :experimental: --has-file spkg-install && sage-package list :experimental: --has-file requirements.txt | grep -v ^_ | grep -v database_stein_watkins\\$ | grep -v polytopes_db_4d | grep -v cplex | grep -v gurobi | grep '^[${{ matrix.targets_pattern }}]' ) )" steps: - uses: actions/checkout@v2 - name: Select Xcode version diff --git a/.github/workflows/tox-optional.yml b/.github/workflows/tox-optional.yml index 9ffc60010d3..be97ecd37a8 100644 --- a/.github/workflows/tox-optional.yml +++ b/.github/workflows/tox-optional.yml @@ -48,9 +48,9 @@ jobs: TOX_ENV: docker-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-tox-docker-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} DOCKER_TARGETS: configured with-targets with-targets-optional - # Test all optional packages, but do not test huge packages, + # Test all non-dummy optional packages, but do not test huge packages # and do not test packages that require external software - TARGETS_OPTIONAL: "$( echo $(PATH=build/bin:$PATH build/bin/sage-package list :optional: | grep -v database_stein_watkins\\$ | grep -v polytopes_db_4d | grep -v cplex | grep -v gurobi | grep '^[${{ matrix.targets_pattern }}]' ) )" + TARGETS_OPTIONAL: "$( echo $(export PATH=build/bin:$PATH && (sage-package list :optional: --has-file spkg-install.in && sage-package list :optional: --has-file spkg-install && sage-package list :optional: --has-file requirements.txt) | grep -v ^_ | grep -v database_stein_watkins\\$ | grep -v polytopes_db_4d | grep -v cplex | grep -v gurobi | grep '^[${{ matrix.targets_pattern }}]' ) )" steps: - uses: actions/checkout@v2 with: @@ -149,9 +149,9 @@ jobs: env: TOX_ENV: local-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }} LOGS_ARTIFACT_NAME: logs-commit-${{ github.sha }}-tox-local-${{ matrix.tox_system_factor }}-${{ matrix.tox_packages_factor }}-${{ matrix.os }}-xcode_${{ matrix.xcode_version_factor }} - # Test all optional packages, but do not test huge packages + # Test all non-dummy optional packages, but do not test huge packages # and do not test packages that require external software - TARGETS_OPTIONAL: "$( echo $(PATH=build/bin:$PATH build/bin/sage-package list :optional: | grep -v database_stein_watkins\\$ | grep -v polytopes_db_4d | grep -v cplex | grep -v gurobi | grep '^[${{ matrix.targets_pattern }}]' ) )" + TARGETS_OPTIONAL: "$( echo $(export PATH=build/bin:$PATH && (sage-package list :optional: --has-file spkg-install.in && sage-package list :optional: --has-file spkg-install && sage-package list :optional: --has-file requirements.txt) | grep -v ^_ | grep -v database_stein_watkins\\$ | grep -v polytopes_db_4d | grep -v cplex | grep -v gurobi | grep '^[${{ matrix.targets_pattern }}]' ) )" steps: - uses: actions/checkout@v2 - name: Select Xcode version diff --git a/.gitignore b/.gitignore index cf553895adb..91838a1627c 100644 --- a/.gitignore +++ b/.gitignore @@ -182,6 +182,7 @@ src/*.egg-info/ /src/bin/sage-src-env-config # Virtual environments +/venv src/.env src/.venv src/env/ diff --git a/.zenodo.json b/.zenodo.json index 035015bacf5..f80be3c909b 100644 --- a/.zenodo.json +++ b/.zenodo.json @@ -1,10 +1,10 @@ { "description": "Mirror of the Sage https://sagemath.org/ source tree", "license": "other-open", - "title": "sagemath/sage: 9.5.beta3", - "version": "9.5.beta3", + "title": "sagemath/sage: 9.5.beta4", + "version": "9.5.beta4", "upload_type": "software", - "publication_date": "2021-10-11", + "publication_date": "2021-10-19", "creators": [ { "affiliation": "SageMath.org", @@ -15,7 +15,7 @@ "related_identifiers": [ { "scheme": "url", - "identifier": "https://github.com/sagemath/sage/tree/9.5.beta3", + "identifier": "https://github.com/sagemath/sage/tree/9.5.beta4", "relation": "isSupplementTo" }, { diff --git a/COPYING.txt b/COPYING.txt index 1ddd77c21a1..1176a856a0d 100644 --- a/COPYING.txt +++ b/COPYING.txt @@ -85,7 +85,6 @@ mistune Modified BSD mpc LGPLv3+ mpfi COPYING is GPLv2, source files state LGPLv2.1+ mpfr LGPLv3+ -mpir LGPLv3+ mpmath Modified BSD networkx Modified BSD ntl GPLv2+ diff --git a/Makefile b/Makefile index 567bffbffd0..444e4f9e4ad 100644 --- a/Makefile +++ b/Makefile @@ -109,6 +109,7 @@ distclean: build-clean @echo "Deleting all remaining output from build system ..." rm -rf local rm -f src/bin/sage-env-config + rm -f prefix venv # Delete all auto-generated files which are distributed as part of the # source tarball diff --git a/VERSION.txt b/VERSION.txt index 88f7d68ebc9..d035bc57e4b 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -SageMath version 9.5.beta3, Release Date: 2021-10-11 +SageMath version 9.5.beta4, Release Date: 2021-10-19 diff --git a/bootstrap b/bootstrap index 1ee0c6b9ab2..0feb5191eca 100755 --- a/bootstrap +++ b/bootstrap @@ -97,8 +97,13 @@ AS_VAR_SET_IF([SAGE_ENABLE_$pkgname], [], [AS_VAR_SET([SAGE_ENABLE_$pkgname], [y case "$pkgname" in _*) ;; *) spkg_configures="$spkg_configures -AC_SUBST(SAGE_ENABLE_$pkgname, [if_installed]) -SAGE_SPKG_ENABLE([$pkgname], [$pkgtype], [$(head -n1 build/pkgs/$pkgname/SPKG.rst 2>/dev/null || echo $pkgname)])" ;; +AC_SUBST(SAGE_ENABLE_$pkgname, [if_installed])" + if [ -f build/pkgs/$pkgname/spkg-install -o -f build/pkgs/$pkgname/spkg-install.in ]; then + # Trac #31163: Not just an optional dummy package + spkg_configures="$spkg_configures +SAGE_SPKG_ENABLE([$pkgname], [$pkgtype], [$(head -n1 build/pkgs/$pkgname/SPKG.rst 2>/dev/null || echo $pkgname)])" + fi + ;; esac fi done diff --git a/build/bin/sage-print-system-package-command b/build/bin/sage-print-system-package-command index 618c88174e0..6be76bdaf5f 100755 --- a/build/bin/sage-print-system-package-command +++ b/build/bin/sage-print-system-package-command @@ -149,6 +149,9 @@ case $system:$command in pip:install) [ -n "$system_packages" ] && print_shell_command "sage -pip install $system_packages" ;; + cpan:install) + [ -n "$system_packages" ] && print_shell_command "cpan -i $system_packages" + ;; repology:install) if [ -n "$system_packages" ]; then links="" diff --git a/build/bin/sage-spkg-info b/build/bin/sage-spkg-info index e9152065dc0..79de53afbee 100755 --- a/build/bin/sage-spkg-info +++ b/build/bin/sage-spkg-info @@ -57,6 +57,7 @@ if [ $have_repology = yes ]; then systems="$systems repology" fi for system in $systems; do + system_package_file="$PKG_DISTROS"/$system.txt system_packages="$(echo $(sed 's/#.*//;' $system_package_file))" case $system in debian) diff --git a/build/bin/write-dockerfile.sh b/build/bin/write-dockerfile.sh index 05cfe124966..bd709957ef1 100755 --- a/build/bin/write-dockerfile.sh +++ b/build/bin/write-dockerfile.sh @@ -219,7 +219,7 @@ ARG NUMPROC=8 ENV MAKE="make -j\${NUMPROC}" ARG USE_MAKEFLAGS="-k V=0" ENV SAGE_CHECK=warn -ENV SAGE_CHECK_PACKAGES="!cython,!r,!python3,!python2,!nose,!pathpy,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!rpy2,!symengine_py,!sage_sws2rst" +ENV SAGE_CHECK_PACKAGES="!cython,!r,!python3,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!rpy2,!sage_sws2rst" #:toolchain: $RUN make \${USE_MAKEFLAGS} base-toolchain $ENDRUN @@ -228,7 +228,7 @@ ARG NUMPROC=8 ENV MAKE="make -j\${NUMPROC}" ARG USE_MAKEFLAGS="-k V=0" ENV SAGE_CHECK=warn -ENV SAGE_CHECK_PACKAGES="!gfan,!cython,!r,!python3,!python2,!nose,!pathpy,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!rpy2,!symengine_py,!sage_sws2rst" +ENV SAGE_CHECK_PACKAGES="!gfan,!cython,!r,!python3,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!rpy2,!sage_sws2rst" #:make: ARG TARGETS_PRE="all-sage-local" $RUN make SAGE_SPKG="sage-spkg -y -o" \${USE_MAKEFLAGS} \${TARGETS_PRE} $ENDRUN @@ -238,7 +238,7 @@ ARG NUMPROC=8 ENV MAKE="make -j\${NUMPROC}" ARG USE_MAKEFLAGS="-k V=0" ENV SAGE_CHECK=warn -ENV SAGE_CHECK_PACKAGES="!gfan,!cython,!r,!python3,!python2,!nose,!pathpy,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!rpy2,!symengine_py,!sage_sws2rst" +ENV SAGE_CHECK_PACKAGES="!gfan,!cython,!r,!python3,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!rpy2,!sage_sws2rst" ADD src src ARG TARGETS="build" $RUN make SAGE_SPKG="sage-spkg -y -o" \${USE_MAKEFLAGS} \${TARGETS} $ENDRUN @@ -248,7 +248,7 @@ ARG NUMPROC=8 ENV MAKE="make -j\${NUMPROC}" ARG USE_MAKEFLAGS="-k V=0" ENV SAGE_CHECK=warn -ENV SAGE_CHECK_PACKAGES="!gfan,!cython,!r,!python3,!python2,!nose,!pathpy,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!rpy2,!symengine_py,!sage_sws2rst" +ENV SAGE_CHECK_PACKAGES="!gfan,!cython,!r,!python3,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!rpy2,!sage_sws2rst" ARG TARGETS_OPTIONAL="ptest" $RUN make SAGE_SPKG="sage-spkg -y -o" \${USE_MAKEFLAGS} \${TARGETS_OPTIONAL} || echo "(error ignored)" $ENDRUN diff --git a/build/make/Makefile.in b/build/make/Makefile.in index 912f455c566..139935933cd 100644 --- a/build/make/Makefile.in +++ b/build/make/Makefile.in @@ -32,7 +32,7 @@ SPKG_INST_RELDIR = var/lib/sage/installed # Aliases for mutually exclusive standard packages selected at configure time TOOLCHAIN = @SAGE_TOOLCHAIN@ PYTHON = python3 -MP_LIBRARY = @SAGE_MP_LIBRARY@ +MP_LIBRARY = gmp BLAS = openblas # pkgconfig files generated/installed at build time @@ -535,8 +535,10 @@ $(1)-$(4)-no-deps: $(1)-no-deps: $(1)-$(4)-no-deps $(1)-$(4)-clean: - sage-spkg-uninstall $(if $(filter $(1),$(TOOLCHAIN_DEPS)),--keep-files) \ - $(1) '$$($(4))' + if [ -d '$$($(4))' ]; then \ + sage-spkg-uninstall $(if $(filter $(1),$(TOOLCHAIN_DEPS)),--keep-files) \ + $(1) '$$($(4))'; \ + fi $(1)-clean: $(1)-$(4)-clean @@ -630,7 +632,8 @@ $$($(4))/$(SPKG_INST_RELDIR)/$(1)-$(2): $(3) $(1): $$($(4))/$(SPKG_INST_RELDIR)/$(1)-$(2) $(1)-$(4)-no-deps: - $(AM_V_at)cd '$$(SAGE_ROOT)/build/pkgs/$(1)' && \ + @if [ -x '$$(SAGE_ROOT)/build/pkgs/$(1)/spkg-install' ]; then \ + $(AM_V_at)cd '$$(SAGE_ROOT)/build/pkgs/$(1)' && \ . '$$(SAGE_ROOT)/src/bin/sage-src-env-config' && \ . '$$(SAGE_ROOT)/src/bin/sage-env-config' && \ . '$$(SAGE_ROOT)/src/bin/sage-env' && \ @@ -638,8 +641,20 @@ $(1)-$(4)-no-deps: . '$$(SAGE_ROOT)/build/bin/sage-build-env' && \ SAGE_SPKG_WHEELS=$$($(4))/var/lib/sage/wheels \ SAGE_INST_LOCAL=$$($(4)) \ - sage-logger -p '$$(SAGE_ROOT)/build/pkgs/$(1)/spkg-install' '$$(SAGE_LOGS)/$(1)-$(2).log' - touch "$$($(4))/$(SPKG_INST_RELDIR)/$(1)-$(2)" + sage-logger -p '$$(SAGE_ROOT)/build/pkgs/$(1)/spkg-install' '$$(SAGE_LOGS)/$(1)-$(2).log' && \ + touch "$$($(4))/$(SPKG_INST_RELDIR)/$(1)-$(2)"; \ + else \ + echo; \ + echo "Error: $(1) is a dummy script package that the Sage distribution uses"; \ + echo "to provide information about equivalent system packages."; \ + echo "It cannot be installed using the Sage distribution."; \ + echo "Please install it manually, for example using the system packages"; \ + echo "recommended at the end of a run of './configure'"; \ + echo "See below for package-specific information."; \ + echo; \ + $$(SAGE_ROOT)/build/bin/sage-spkg-info $(1); \ + exit 1; \ + fi $(1)-no-deps: $(1)-$(4)-no-deps diff --git a/build/pkgs/arb/SPKG.rst b/build/pkgs/arb/SPKG.rst index 404b21eb1db..cff49ddb95b 100644 --- a/build/pkgs/arb/SPKG.rst +++ b/build/pkgs/arb/SPKG.rst @@ -25,14 +25,3 @@ Upstream Contact - https://arblib.org/ - http://github.com/fredrik-johansson/arb/ - -Dependencies ------------- - -- FLINT -- MPIR or GMP -- MPFR - - -Special Update/Build Instructions ---------------------------------- diff --git a/build/pkgs/backcall/dependencies b/build/pkgs/backcall/dependencies index 97701a95eec..35228f20368 100644 --- a/build/pkgs/backcall/dependencies +++ b/build/pkgs/backcall/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) flit_core toml +$(PYTHON) | $(PYTHON_TOOLCHAIN) flit_core tomli ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/cddlib/SPKG.rst b/build/pkgs/cddlib/SPKG.rst index 89915efe311..6ab9a303cdd 100644 --- a/build/pkgs/cddlib/SPKG.rst +++ b/build/pkgs/cddlib/SPKG.rst @@ -31,8 +31,3 @@ Upstream Contact ---------------- https://github.com/cddlib/cddlib - -Dependencies ------------- - -- gmp (or its fork mpir) diff --git a/build/pkgs/cddlib/spkg-configure.m4 b/build/pkgs/cddlib/spkg-configure.m4 index aa313498737..ad227f032ed 100644 --- a/build/pkgs/cddlib/spkg-configure.m4 +++ b/build/pkgs/cddlib/spkg-configure.m4 @@ -1,5 +1,5 @@ SAGE_SPKG_CONFIGURE([cddlib], [ - SAGE_SPKG_DEPCHECK([gmp mpir], [ + SAGE_SPKG_DEPCHECK([gmp], [ dnl The sage library uses BOTH cddexec and cddexec_gmp. dnl These two executables were introduced in cddlib-094j. AC_CHECK_PROGS([CDDEXEC], [cddexec]) diff --git a/build/pkgs/cocoalib/SPKG.rst b/build/pkgs/cocoalib/SPKG.rst index 3afd8a68286..783c6cc7126 100644 --- a/build/pkgs/cocoalib/SPKG.rst +++ b/build/pkgs/cocoalib/SPKG.rst @@ -19,14 +19,3 @@ Upstream Contact - Email: cocoa@dima.unige.it - Website: http://cocoa.dima.unige.it/ - Releases: http://cocoa.dima.unige.it/cocoalib/ - -Dependencies ------------- - -- GMP/MPIR - - -Special Update/Build Instructions ---------------------------------- - -None. diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index 95ba9591301..ce3df02bc5b 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,4 +1,4 @@ tarball=configure-VERSION.tar.gz -sha1=9c45053634b6912dd4e4e68a483b5dbd483fc47d -md5=11496f4636f7c19bb4cfbaf6e57af698 -cksum=2205302326 +sha1=1df4c487d374a7ea9eeda3a9234cc6eed81c1443 +md5=83d4327261e545f26d4ad318030823e8 +cksum=2968565921 diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index 42d10d82fec..3969244814e 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -32c0d4075fb515a073925ad1feefcc4fc349b47d +e8ab458165ec5e5832adf702099f47f4cff94596 diff --git a/build/pkgs/cvxopt/dependencies b/build/pkgs/cvxopt/dependencies index 8930227ba65..2354fdb1c1e 100644 --- a/build/pkgs/cvxopt/dependencies +++ b/build/pkgs/cvxopt/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) numpy $(BLAS) gsl glpk suitesparse | $(PYTHON_TOOLCHAIN) pkgconfig nose matplotlib +$(PYTHON) numpy $(BLAS) gsl glpk suitesparse | $(PYTHON_TOOLCHAIN) pkgconfig matplotlib $(and $(filter-out no,$(SAGE_CHECK_cvxopt)), pytest) matplotlib is needed to test cvxopt (i.e., if SAGE_CHECK=yes). See #12742. diff --git a/build/pkgs/cvxopt/spkg-check.in b/build/pkgs/cvxopt/spkg-check.in index e251b2cbb6f..8b3f5031762 100644 --- a/build/pkgs/cvxopt/spkg-check.in +++ b/build/pkgs/cvxopt/spkg-check.in @@ -1,8 +1,3 @@ cd src -if ! command -v nosetests ; then - echo >&2 'Testing cvxopt requires the package nose to be installed' - exit 1 -fi - -nosetests +pytest diff --git a/build/pkgs/e_antic/SPKG.rst b/build/pkgs/e_antic/SPKG.rst index 32dfecbef0b..005a25b7e13 100644 --- a/build/pkgs/e_antic/SPKG.rst +++ b/build/pkgs/e_antic/SPKG.rst @@ -19,10 +19,3 @@ Upstream Contact ---------------- - https://github.com/videlec/e-antic - -Dependencies ------------- - -- GMP/MPIR -- FLINT -- ARB diff --git a/build/pkgs/ecl/spkg-configure.m4 b/build/pkgs/ecl/spkg-configure.m4 index 9fd61393b31..ae1e0ac5e1a 100644 --- a/build/pkgs/ecl/spkg-configure.m4 +++ b/build/pkgs/ecl/spkg-configure.m4 @@ -3,7 +3,7 @@ SAGE_SPKG_CONFIGURE([ecl], [ # Default to installing the SPKG sage_spkg_install_ecl=yes - SAGE_SPKG_DEPCHECK([gcc gc gmp mpir], [ + SAGE_SPKG_DEPCHECK([gcc gc gmp], [ AC_PATH_PROG([ECL_CONFIG], [ecl-config]) AS_IF([test x$ECL_CONFIG != x], [ # "CPPFLAGS" is not a typo, the --cflags output from diff --git a/build/pkgs/ecm/SPKG.rst b/build/pkgs/ecm/SPKG.rst index f8d0e352e56..2d88c659ae1 100644 --- a/build/pkgs/ecm/SPKG.rst +++ b/build/pkgs/ecm/SPKG.rst @@ -19,13 +19,6 @@ Upstream Contact - ecm-discuss@lists.gforge.inria.fr (requires subscription) -Dependencies ------------- - -- GMP/MPIR (Note: Python is \*not\* required for ordinary builds.) -- GNU patch - - Special Update/Build Instructions --------------------------------- @@ -47,11 +40,10 @@ Special Update/Build Instructions Note that this doesn't affect the packages' selection of processor- specific optimized [assembly] code. 'spkg-install' already reads the settings from Sage's and also a - system-wide GMP / MPIR now, but doesn't (yet) use all of them. + system-wide GMP now, but doesn't (yet) use all of them. If SAGE_FAT_BINARY="yes", we should avoid too specific settings of "-mcpu=...", and perhaps pass a more generic "--host=..." to - 'configure'. (MPIR honors '--enable-fat' to some extent, but this - option isn't used on anything other than x86 / x86_64.) + 'configure'. - We currently work around a linker bug on MacOS X 10.5 PPC (with GCC 4.2.1) which breaks 'configure' if debug symbols are enabled. diff --git a/build/pkgs/ecm/spkg-configure.m4 b/build/pkgs/ecm/spkg-configure.m4 index ada5f34b0d9..d456f1d8f2c 100644 --- a/build/pkgs/ecm/spkg-configure.m4 +++ b/build/pkgs/ecm/spkg-configure.m4 @@ -1,12 +1,6 @@ SAGE_SPKG_CONFIGURE([ecm], [ m4_pushdef([SAGE_ECM_MINVER],[7.0.4]) - AC_REQUIRE([SAGE_SPKG_CONFIGURE_GMP]) - AC_MSG_CHECKING([installing gmp/mpir? ]) - if test x$sage_spkg_install_mpir = xyes -o x$sage_spkg_install_gmp = xyes; then - AC_MSG_RESULT([yes; install ecm as well]) - sage_spkg_install_ecm=yes - else - AC_MSG_RESULT([no. ]) + SAGE_SPKG_DEPCHECK([gmp], [ AC_CHECK_HEADER(ecm.h, [ AX_ABSOLUTE_HEADER([ecm.h]) if test x$gl_cv_absolute_ecm_h = x; then @@ -38,6 +32,6 @@ SAGE_SPKG_CONFIGURE([ecm], [ AS_IF([test -z "$ac_cv_ECM"], [sage_spkg_install_ecm=yes]) AS_IF([test -z "$ac_cv_ECMBIN"], [sage_spkg_install_ecm=yes]) ], [sage_spkg_install_ecm=yes]) - fi + ]) m4_popdef([SAGE_ECM_MINVER]) ]) diff --git a/build/pkgs/fflas_ffpack/spkg-configure.m4 b/build/pkgs/fflas_ffpack/spkg-configure.m4 index 2d3a46a1a3e..01a04713f07 100644 --- a/build/pkgs/fflas_ffpack/spkg-configure.m4 +++ b/build/pkgs/fflas_ffpack/spkg-configure.m4 @@ -1,7 +1,5 @@ SAGE_SPKG_CONFIGURE([fflas_ffpack], [ - # fflas-lapack uses whatever multi-precision library givaro uses, - # either gmp or mpir. - SAGE_SPKG_DEPCHECK([givaro gmp mpir openblas], [ + SAGE_SPKG_DEPCHECK([givaro gmp openblas], [ # If our dependencies come from the system, then we can use # the system fflas-ffpack, too. Use pkg-config to find a # recentish version, if there is one. diff --git a/build/pkgs/flint/SPKG.rst b/build/pkgs/flint/SPKG.rst index 146c6ac1c82..f91de70d1ff 100644 --- a/build/pkgs/flint/SPKG.rst +++ b/build/pkgs/flint/SPKG.rst @@ -21,10 +21,3 @@ Upstream Contact - flint-devel Gougle Group (http://groups.google.co.uk/group/flint-devel) - William Hart - -Dependencies ------------- - -- MPIR -- MPFR -- NTL diff --git a/build/pkgs/flit_core/checksums.ini b/build/pkgs/flit_core/checksums.ini index a6d2508fd40..5a0b6ecb0c1 100644 --- a/build/pkgs/flit_core/checksums.ini +++ b/build/pkgs/flit_core/checksums.ini @@ -1,5 +1,5 @@ tarball=flit_core-VERSION.tar.gz -sha1=cc89ef0fef30582845dc40d73dda7fa3bfa494cd -md5=697eb7da76b4eb5833bbf8bb97131879 -cksum=4051177318 +sha1=941603f1734b9b4af74954429ef51f97540f30e5 +md5=a4bb11b54bcf029ec2cd5cb981c07ded +cksum=2905595733 upstream_url=https://pypi.io/packages/source/f/flit_core/flit_core-VERSION.tar.gz diff --git a/build/pkgs/flit_core/package-version.txt b/build/pkgs/flit_core/package-version.txt index 15a27998172..18091983f59 100644 --- a/build/pkgs/flit_core/package-version.txt +++ b/build/pkgs/flit_core/package-version.txt @@ -1 +1 @@ -3.3.0 +3.4.0 diff --git a/build/pkgs/gcc/SPKG.rst b/build/pkgs/gcc/SPKG.rst index 6004b986078..1f5684b86b2 100644 --- a/build/pkgs/gcc/SPKG.rst +++ b/build/pkgs/gcc/SPKG.rst @@ -16,17 +16,3 @@ Upstream Contact ---------------- https://gcc.gnu.org/ - -Dependencies ------------- - -- zlib -- MPIR -- MPFR -- MPC - - -Special Update/Build Instructions ---------------------------------- - -None. diff --git a/build/pkgs/gdb/SPKG.rst b/build/pkgs/gdb/SPKG.rst index b89773fe676..0716ac53fad 100644 --- a/build/pkgs/gdb/SPKG.rst +++ b/build/pkgs/gdb/SPKG.rst @@ -19,17 +19,6 @@ Upstream Contact http://www.gnu.org/software/gdb/ -Dependencies ------------- - -- python -- mpc -- mpfr -- ppl -- gmp/mpir -- makeinfo (external) - - Special Update/Build Instructions --------------------------------- diff --git a/build/pkgs/gfan/SPKG.rst b/build/pkgs/gfan/SPKG.rst index 58faef4f8f7..d2416f4a4d0 100644 --- a/build/pkgs/gfan/SPKG.rst +++ b/build/pkgs/gfan/SPKG.rst @@ -36,13 +36,6 @@ Anders Nedergaard Jensen https://users-math.au.dk/jensen/software/gfan/gfan.html -Dependencies ------------- - -- GMP/MPIR -- CDDLIB - - Special Update/Build Instructions --------------------------------- diff --git a/build/pkgs/givaro/SPKG.rst b/build/pkgs/givaro/SPKG.rst index fe64ba38237..1dcb4e45412 100644 --- a/build/pkgs/givaro/SPKG.rst +++ b/build/pkgs/givaro/SPKG.rst @@ -28,9 +28,3 @@ Upstream Contact ---------------- - Clement Pernet - -Dependencies ------------- - -- GNU patch -- GMP/MPIR diff --git a/build/pkgs/givaro/spkg-configure.m4 b/build/pkgs/givaro/spkg-configure.m4 index 6afb9e95599..7eb91edfd00 100644 --- a/build/pkgs/givaro/spkg-configure.m4 +++ b/build/pkgs/givaro/spkg-configure.m4 @@ -1,6 +1,6 @@ SAGE_SPKG_CONFIGURE([givaro], [ m4_pushdef([SAGE_GIVARO_MINVER],["40101"]) - SAGE_SPKG_DEPCHECK([gmp mpir], [ + SAGE_SPKG_DEPCHECK([gmp], [ AC_PATH_PROG([GIVAROCONFIG], [givaro-config]) AS_IF([test x$GIVAROCONFIG = x], [ AC_MSG_NOTICE([givaro-config not found. Installing givaro]) diff --git a/build/pkgs/glpk/SPKG.rst b/build/pkgs/glpk/SPKG.rst index 75acbf1c1f2..4cabfae0ba1 100644 --- a/build/pkgs/glpk/SPKG.rst +++ b/build/pkgs/glpk/SPKG.rst @@ -36,13 +36,6 @@ GLPK is currently being maintained by: http://www.gnu.org/software/glpk/#maintainer -Dependencies ------------- - -- GMP/MPIR -- zlib - - Special Update/Build Instructions --------------------------------- diff --git a/build/pkgs/glpk/spkg-configure.m4 b/build/pkgs/glpk/spkg-configure.m4 index d23ab9cc59f..6fb7d64aa44 100644 --- a/build/pkgs/glpk/spkg-configure.m4 +++ b/build/pkgs/glpk/spkg-configure.m4 @@ -1,6 +1,6 @@ SAGE_SPKG_CONFIGURE([glpk], [ m4_pushdef([SAGE_GLPK_MINVER],["4.63"]) - SAGE_SPKG_DEPCHECK([gmp mpir zlib], [ + SAGE_SPKG_DEPCHECK([gmp zlib], [ AC_PATH_PROG([GLPSOL], [glpsol]) AS_IF([test x$GLPSOL = x], [ AC_MSG_NOTICE([glpsol not found. Installing glpk]) diff --git a/build/pkgs/gmp/spkg-configure.m4 b/build/pkgs/gmp/spkg-configure.m4 index 9f5ffea5aa2..61d7c5f3b2f 100644 --- a/build/pkgs/gmp/spkg-configure.m4 +++ b/build/pkgs/gmp/spkg-configure.m4 @@ -1,8 +1,26 @@ SAGE_SPKG_CONFIGURE([gmp], [ - AC_REQUIRE([SAGE_SPKG_CONFIGURE_MPIR]) - if test x"$with_mp" = xgmp -o x"$_sage_spkg_install_gmp" = xyes; then - if test x"$SAGE_MP_LIBRARY" = xgmp; then - sage_spkg_install_gmp=yes + sage_spkg_install_gmp=no + AC_CHECK_HEADER(gmp.h, [], [sage_spkg_install_gmp=yes]) + AC_CHECK_HEADER(gmpxx.h, [], [sage_spkg_install_gmp=yes]) + dnl mpq_cmp_z appeared in GMP 6.1.0 and is used by pynac + AC_SEARCH_LIBS([__gmpq_cmp_z], [gmp], [], + [sage_spkg_install_gmp=yes]) +], [], [], [ + if test x$sage_spkg_install_gmp = xyes; then + AC_SUBST(SAGE_GMP_PREFIX, ['$SAGE_LOCAL']) + AC_SUBST(SAGE_GMP_INCLUDE, ['$SAGE_LOCAL/include']) + else + dnl If found, we want to get the absolute path to where we + dnl found it for use with some packages (e.g. iml) that need + dnl this information at configure time + AX_ABSOLUTE_HEADER([gmp.h]) + if test x$gl_cv_absolute_gmp_h = x; then + AC_MSG_ERROR(m4_normalize([ + failed to find absolute path to gmp.h despite it being reported + found + ])) fi + AC_SUBST(SAGE_GMP_INCLUDE, [`AS_DIRNAME($gl_cv_absolute_gmp_h)`]) + AC_SUBST(SAGE_GMP_PREFIX, ['']) fi ]) diff --git a/build/pkgs/graphviz/spkg-install b/build/pkgs/graphviz/spkg-install deleted file mode 100755 index aeb51456c5d..00000000000 --- a/build/pkgs/graphviz/spkg-install +++ /dev/null @@ -1,4 +0,0 @@ -#! /usr/bin/env bash -echo Error: graphviz is not installed as a system package. -echo Please install the system package recommended by ./configure -exit 1 diff --git a/build/pkgs/igraph/spkg-configure.m4 b/build/pkgs/igraph/spkg-configure.m4 index c6c180b342e..05453681b17 100644 --- a/build/pkgs/igraph/spkg-configure.m4 +++ b/build/pkgs/igraph/spkg-configure.m4 @@ -1,8 +1,8 @@ SAGE_SPKG_CONFIGURE([igraph], [ -SAGE_SPKG_DEPCHECK([glpk openblas gmp mpir], [ + SAGE_SPKG_DEPCHECK([glpk openblas gmp], [ dnl check for igraph with pkg-config PKG_CHECK_MODULES([IGRAPH], [igraph >= 0.8.3], [], [ sage_spkg_install_igraph=yes]) - ]) + ]) ]) diff --git a/build/pkgs/iml/spkg-configure.m4 b/build/pkgs/iml/spkg-configure.m4 index ea78a6bbdcd..efab2c105c6 100644 --- a/build/pkgs/iml/spkg-configure.m4 +++ b/build/pkgs/iml/spkg-configure.m4 @@ -1,5 +1,5 @@ SAGE_SPKG_CONFIGURE([iml], [ - SAGE_SPKG_DEPCHECK([gmp mpir openblas], [ + SAGE_SPKG_DEPCHECK([gmp openblas], [ AC_CHECK_HEADER([iml.h], [ AC_SEARCH_LIBS([nonsingSolvLlhsMM], [iml], [], [sage_spkg_install_iml=yes]) diff --git a/build/pkgs/importlib_metadata/dependencies b/build/pkgs/importlib_metadata/dependencies index c136b9290b7..9fcc3b0cc65 100644 --- a/build/pkgs/importlib_metadata/dependencies +++ b/build/pkgs/importlib_metadata/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) zipp typing_extensions | $(PYTHON_TOOLCHAIN) toml +$(PYTHON) zipp typing_extensions | $(PYTHON_TOOLCHAIN) tomli ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/isl/spkg-configure.m4 b/build/pkgs/isl/spkg-configure.m4 index 9394030dbc1..db2b400b6e3 100644 --- a/build/pkgs/isl/spkg-configure.m4 +++ b/build/pkgs/isl/spkg-configure.m4 @@ -1,13 +1,7 @@ SAGE_SPKG_CONFIGURE([isl], [ - AC_REQUIRE([SAGE_SPKG_CONFIGURE_GMP]) - AC_MSG_CHECKING([installing gmp/mpir? ]) - if test x$sage_spkg_install_mpir = xyes -o x$sage_spkg_install_gmp = xyes; then - AC_MSG_RESULT([yes; install isl as well]) - sage_spkg_install_isl=yes - else - AC_MSG_RESULT([no]) + SAGE_SPKG_DEPCHECK([gmp], [ PKG_CHECK_MODULES([ISL], [isl >= 0.20], [], [ sage_spkg_install_isl=yes]) - fi + ]) ]) diff --git a/build/pkgs/latte_int/SPKG.rst b/build/pkgs/latte_int/SPKG.rst index 7f97ded201b..9bd0480ce25 100644 --- a/build/pkgs/latte_int/SPKG.rst +++ b/build/pkgs/latte_int/SPKG.rst @@ -17,8 +17,3 @@ Upstream Contact ---------------- Matthias Köppe, UC Davis, CA, USA - -Dependencies ------------- - -GMP (MPIR), 4ti2, NTL, cddlib. diff --git a/build/pkgs/libxml2/spkg-install b/build/pkgs/libxml2/spkg-install deleted file mode 100755 index f61a49e9072..00000000000 --- a/build/pkgs/libxml2/spkg-install +++ /dev/null @@ -1,4 +0,0 @@ -#! /usr/bin/env bash -echo Error: libxml2 is not installed. -echo Please install it, for example using the system packages recommended by ./configure -exit 1 diff --git a/build/pkgs/llvm/spkg-install b/build/pkgs/llvm/spkg-install deleted file mode 100755 index 4233e976c04..00000000000 --- a/build/pkgs/llvm/spkg-install +++ /dev/null @@ -1,4 +0,0 @@ -#! /usr/bin/env bash -echo Error: llvm is not installed. -echo Please install it, for example using the system packages recommended by ./configure -exit 1 diff --git a/build/pkgs/lrslib/spkg-configure.m4 b/build/pkgs/lrslib/spkg-configure.m4 index 860cca451e0..0297f7118e3 100644 --- a/build/pkgs/lrslib/spkg-configure.m4 +++ b/build/pkgs/lrslib/spkg-configure.m4 @@ -1,6 +1,6 @@ SAGE_SPKG_CONFIGURE([lrslib], [ dnl System lrslib may already be 7.x, which may be compiled with FLINT - SAGE_SPKG_DEPCHECK([gmp mpir flint], [ + SAGE_SPKG_DEPCHECK([gmp flint], [ AC_CHECK_PROGS([LRSNASH], [lrsnash]) AS_IF([test -z "$LRSNASH"], [ sage_spkg_install_lrslib=yes diff --git a/build/pkgs/memory_allocator/checksums.ini b/build/pkgs/memory_allocator/checksums.ini index f7efcd9b150..fe48843d873 100644 --- a/build/pkgs/memory_allocator/checksums.ini +++ b/build/pkgs/memory_allocator/checksums.ini @@ -1,5 +1,5 @@ tarball=memory_allocator-VERSION.tar.gz -sha1=0e9256d307957e84eaba408f190cafc04d5c246a -md5=1ce1fb6dc5972017a26ee82c4371b180 -cksum=2493862442 +sha1=7721219be84207f6112e118fc79af0c2729fca34 +md5=868753a09c44194cba303db89cca4396 +cksum=16627262 upstream_url=https://pypi.io/packages/source/m/memory_allocator/memory_allocator-VERSION.tar.gz diff --git a/build/pkgs/memory_allocator/package-version.txt b/build/pkgs/memory_allocator/package-version.txt index 6e8bf73aa55..17e51c385ea 100644 --- a/build/pkgs/memory_allocator/package-version.txt +++ b/build/pkgs/memory_allocator/package-version.txt @@ -1 +1 @@ -0.1.0 +0.1.1 diff --git a/build/pkgs/mpc/spkg-configure.m4 b/build/pkgs/mpc/spkg-configure.m4 index 32aca4ada1b..1e8c475e1ff 100644 --- a/build/pkgs/mpc/spkg-configure.m4 +++ b/build/pkgs/mpc/spkg-configure.m4 @@ -1,15 +1,9 @@ SAGE_SPKG_CONFIGURE([mpc], [ - AC_REQUIRE([SAGE_SPKG_CONFIGURE_MPFR]) - AC_MSG_CHECKING([installing mpfr? ]) - if test x$sage_spkg_install_mpfr = xyes; then - AC_MSG_RESULT([yes; install mpc as well]) - sage_spkg_install_mpc=yes - else - AC_MSG_RESULT([no]) + SAGE_SPKG_DEPCHECK([mpfr], [ AC_CHECK_HEADER(mpc.h, [], [sage_spkg_install_mpc=yes]) dnl mpc_cmp_abs appeared in MPC 1.1.0 AC_SEARCH_LIBS([mpc_cmp_abs], [mpc], [], [sage_spkg_install_mpc=yes]) - fi + ]) ], [], [], [ if test x$sage_spkg_install_mpc = xyes; then AC_SUBST(SAGE_MPC_PREFIX, ['$SAGE_LOCAL']) diff --git a/build/pkgs/mpfi/spkg-configure.m4 b/build/pkgs/mpfi/spkg-configure.m4 index 0cdb10a920e..4542dce794a 100644 --- a/build/pkgs/mpfi/spkg-configure.m4 +++ b/build/pkgs/mpfi/spkg-configure.m4 @@ -1,17 +1,7 @@ SAGE_SPKG_CONFIGURE([mpfi], [ - AC_REQUIRE([SAGE_SPKG_CONFIGURE_MPFR]) - AC_MSG_CHECKING([installing mpfr? ]) - if test x$sage_spkg_install_mpfr = xyes; then - AC_MSG_RESULT([yes; install mpfi as well]) - sage_spkg_install_mpfi=yes - else - AC_MSG_RESULT([no]) - fi - m4_pushdef(SAGE_MPFI_VERSION_MAJOR, [1]) m4_pushdef(SAGE_MPFI_VERSION_MINOR, [5]) - - if test x$sage_spkg_install_mpfi != xyes; then + SAGE_SPKG_DEPCHECK([mpfr], [ AC_CHECK_HEADER([mpfi.h], [], [sage_spkg_install_mpfi=yes]) AC_SEARCH_LIBS([mpfi_diam_abs], [mpfi], [ AC_LANG_PUSH(C) @@ -31,9 +21,8 @@ SAGE_SPKG_CONFIGURE([mpfi], [ sage_spkg_install_mpfi=yes], [AC_MSG_RESULT([cross compiling. assume yes])]) AC_LANG_POP(C)], [sage_spkg_install_mpfi=yes]) - fi + ]) m4_popdef([SAGE_MPFI_VERSION_MAJOR]) m4_popdef([SAGE_MPFI_VERSION_MINOR]) ]) - diff --git a/build/pkgs/mpfr/spkg-configure.m4 b/build/pkgs/mpfr/spkg-configure.m4 index 0c15b56df43..47056d06c09 100644 --- a/build/pkgs/mpfr/spkg-configure.m4 +++ b/build/pkgs/mpfr/spkg-configure.m4 @@ -1,15 +1,9 @@ SAGE_SPKG_CONFIGURE([mpfr], [ - AC_REQUIRE([SAGE_SPKG_CONFIGURE_GMP]) - AC_MSG_CHECKING([installing gmp/mpir? ]) - if test x$sage_spkg_install_mpir = xyes -o x$sage_spkg_install_gmp = xyes; then - AC_MSG_RESULT([yes; install mpfr as well]) - sage_spkg_install_mpfr=yes - else - AC_MSG_RESULT([no]) + SAGE_SPKG_DEPCHECK([gmp], [ AC_CHECK_HEADER(mpfr.h, [], [sage_spkg_install_mpfr=yes]) dnl mpfr_free_pool appeared in r11922 (Dec 2017) on MPFR svn AC_SEARCH_LIBS([mpfr_free_pool], [mpfr], [], [sage_spkg_install_mpfr=yes]) - fi + ]) ], [], [], [ if test x$sage_spkg_install_mpfr = xyes; then AC_SUBST(SAGE_MPFR_PREFIX, ['$SAGE_LOCAL']) diff --git a/build/pkgs/mpir/SPKG.rst b/build/pkgs/mpir/SPKG.rst deleted file mode 100644 index a03133b1f6c..00000000000 --- a/build/pkgs/mpir/SPKG.rst +++ /dev/null @@ -1,44 +0,0 @@ -mpir: Multiple precision integers and rationals (fork of GMP) -============================================================= - -Description ------------ - -Multiple Precision Integers and Rationals. - -MPIR is an open source multiprecision integer library derived from -version 5.0.1 of the GMP (GNU Multi Precision) project (which was -licensed LGPL v2+). - -See http://www.mpir.org - -License -------- - -- LGPL V3+ - - -Upstream Contact ----------------- - -- The Google group mpir-devel -- thempirteam@googlemail.com - -Dependencies ------------- - -- iconv -- GNU patch - - -Special Update/Build Instructions ---------------------------------- - -- TODO: -- Perhaps also modify CXXFLAGS (and/or CPPFLAGS). -- We currently don't use anything of GMP's/MPIR's CC setting, and - matching with the current compiler (``$CC``) is perhaps suboptimal. -- Remove some files / directories not needed for Sage from upstream: -- build.vc\* directories (Microsoft Visual C build files) -- 3.0.0-644faf502c56f97d9accd301965fc57d6ec70868 - was created by running the spkg-src script. diff --git a/build/pkgs/mpir/checksums.ini b/build/pkgs/mpir/checksums.ini deleted file mode 100644 index d482fd960d9..00000000000 --- a/build/pkgs/mpir/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=mpir-VERSION.tar.bz2 -sha1=30044be9f48ce15ddfc8871bde14e363fe2f46ea -md5=55e9e31d6371b30dd046f16333c84499 -cksum=1799000157 diff --git a/build/pkgs/mpir/dependencies b/build/pkgs/mpir/dependencies deleted file mode 100644 index 8ca2e8756c8..00000000000 --- a/build/pkgs/mpir/dependencies +++ /dev/null @@ -1,5 +0,0 @@ -| yasm - ----------- -All lines of this file are ignored except the first. -It is copied by SAGE_ROOT/build/make/install into SAGE_ROOT/build/make/Makefile. diff --git a/build/pkgs/mpir/distros/conda.txt b/build/pkgs/mpir/distros/conda.txt deleted file mode 100644 index bef94785573..00000000000 --- a/build/pkgs/mpir/distros/conda.txt +++ /dev/null @@ -1 +0,0 @@ -mpir diff --git a/build/pkgs/mpir/distros/freebsd.txt b/build/pkgs/mpir/distros/freebsd.txt deleted file mode 100644 index 75bf5706674..00000000000 --- a/build/pkgs/mpir/distros/freebsd.txt +++ /dev/null @@ -1 +0,0 @@ -math/mpir diff --git a/build/pkgs/mpir/distros/homebrew.txt b/build/pkgs/mpir/distros/homebrew.txt deleted file mode 100644 index bef94785573..00000000000 --- a/build/pkgs/mpir/distros/homebrew.txt +++ /dev/null @@ -1 +0,0 @@ -mpir diff --git a/build/pkgs/mpir/distros/opensuse.txt b/build/pkgs/mpir/distros/opensuse.txt deleted file mode 100644 index 16b5b660968..00000000000 --- a/build/pkgs/mpir/distros/opensuse.txt +++ /dev/null @@ -1 +0,0 @@ -libmpir-devel diff --git a/build/pkgs/mpir/distros/repology.txt b/build/pkgs/mpir/distros/repology.txt deleted file mode 100644 index bef94785573..00000000000 --- a/build/pkgs/mpir/distros/repology.txt +++ /dev/null @@ -1 +0,0 @@ -mpir diff --git a/build/pkgs/mpir/package-version.txt b/build/pkgs/mpir/package-version.txt deleted file mode 100644 index 27bffd152e1..00000000000 --- a/build/pkgs/mpir/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -3.0.0-644faf502c56f97d9accd301965fc57d6ec70868.p0 diff --git a/build/pkgs/mpir/patches/ticket-25858.patch b/build/pkgs/mpir/patches/ticket-25858.patch deleted file mode 100644 index e4aa2fd0db4..00000000000 --- a/build/pkgs/mpir/patches/ticket-25858.patch +++ /dev/null @@ -1,144 +0,0 @@ -Add support for Celeron/Pentium CPUs that use the Haswell microarchitecture but -without various extended instruction sets -https://trac.sagemath.org/ticket/25858 -diff -ru a/configure b/configure ---- a/configure 2018-07-13 14:49:36.839366500 +0200 -+++ b/configure 2018-07-13 15:08:51.229370000 +0200 -@@ -4585,7 +4585,7 @@ - # mode, in case -m32 has failed not because it's an old gcc, but because - # it's a dual 32/64-bit gcc without a 32-bit libc, or whatever. - # -- i?86*-*-* | k[5-8]*-*-* | pentium*-*-* | prescott-*-* | core-*-* | athlon-*-* | viac3*-*-* | x86_64-*-* | netburst-*-* | netburstlahf-*-* | k8-*-* | k10-*-* | k102-*-* | k103-*-* | core2-*-* | penryn-*-* | nehalem-*-* | westmere-*-* | sandybridge-*-* | atom-*-* | nano-*-* | bobcat-*-* | bulldozer-*-* | piledriver-*-* | ivybridge-*-* | haswell-*-* | broadwell-*-* | skylake-*-* | skylakeavx-*-*) -+ i?86*-*-* | k[5-8]*-*-* | pentium*-*-* | prescott-*-* | core-*-* | athlon-*-* | viac3*-*-* | x86_64-*-* | netburst-*-* | netburstlahf-*-* | k8-*-* | k10-*-* | k102-*-* | k103-*-* | core2-*-* | penryn-*-* | nehalem-*-* | westmere-*-* | sandybridge-*-* | atom-*-* | nano-*-* | bobcat-*-* | bulldozer-*-* | piledriver-*-* | ivybridge-*-* | haswell-*-* | haswellavx-*-* | broadwell-*-* | skylake-*-* | skylakeavx-*-*) - abilist="32" - cclist="gcc icc cc" - gcc_cflags="-O2 $fomit_frame_pointer" -@@ -4761,7 +4761,11 @@ - gcc_cflags_cpu="-mtune=corei7 -mtune=core2 -mtune=nocona -mtune=pentium3 -mcpu=pentiumpro -mcpu=i486 -m486" - gcc_cflags_arch="-march=corei7 -march=core2 -march=nocona -march=pentium3 -march=pentiumpro -march=pentium" - ;; -- sandybridge | ivybridge | haswell) -+ haswell) -+ gcc_cflags_cpu="-mtune=corei7 -mtune=corei7 -mtune=core2 -mtune=nocona -mtune=pentium3 -mcpu=pentiumpro -mcpu=i486 -m486" -+ gcc_cflags_arch="-march=corei7 -march=corei7 -march=core2 -march=nocona -march=pentium3 -march=pentiumpro -march=pentium" -+ ;; -+ sandybridge | ivybridge | haswellavx) - gcc_cflags_cpu="-mtune=corei7-avx -mtune=corei7 -mtune=core2 -mtune=nocona -mtune=pentium3 -mcpu=pentiumpro -mcpu=i486 -m486" - gcc_cflags_arch="-march=corei7-avx -march=corei7 -march=core2 -march=nocona -march=pentium3 -march=pentiumpro -march=pentium" - ;; -@@ -4800,7 +4804,7 @@ - k8 | bobcat) path="x86/k7/mmx/k8 x86/k7/mmx x86/k7 x86" ;; - core2 | penryn) path="x86/core2 x86" ;; - i786 | pentium4) path="x86/pentium4/sse2 x86/pentium4/mmx x86/pentium4 x86" ;; -- nehalem | westmere | sandybridge | ivybridge | haswell | skylake | skylakeavx | broadwell) path="x86/nehalem x86" ;; -+ nehalem | westmere | sandybridge | ivybridge | haswell | haswellavx | skylake | skylakeavx | broadwell) path="x86/nehalem x86" ;; - prescott | netburst | netburstlahf) path="x86/pentium4/sse2 x86/pentium4/mmx x86/pentium4 x86" ;; - # VIA/Centaur processors, sold as CyrixIII and C3. - nano | viac32) path="x86/p6/p3mmx x86/p6/mmx x86/p6 x86";; -@@ -4842,7 +4846,7 @@ - fi - - case $host in -- x86_64-*-* | netburst-*-* | netburstlahf-*-* | k8-*-* | k10-*-* | k102-*-* | k103-*-* | core2-*-* | penryn-*-* | nehalem-*-* | westmere-*-* | sandybridge-*-* | atom-*-* | nano-*-* | bobcat-*-* | bulldozer-*-* | piledriver-*-* | ivybridge-*-* | haswell-*-* | broadwell-*-* | skylake-*-* | skylakeavx-*-*) -+ x86_64-*-* | netburst-*-* | netburstlahf-*-* | k8-*-* | k10-*-* | k102-*-* | k103-*-* | core2-*-* | penryn-*-* | nehalem-*-* | westmere-*-* | sandybridge-*-* | atom-*-* | nano-*-* | bobcat-*-* | bulldozer-*-* | piledriver-*-* | ivybridge-*-* | haswell-*-* | haswellavx-*-* | broadwell-*-* | skylake-*-* | skylakeavx-*-*) - abilist="64 32" - cclist_64="gcc cc" - gcc_64_cflags="-m64" -@@ -4901,10 +4905,12 @@ - path_64="x86_64w/sandybridge/ivybridge x86_64w/sandybridge x86_64w" ;; - haswell-pc-msys|haswell-w64-mingw*|haswell-*-cygwin*) - path_64="x86_64w/haswell x86_64w/sandybridge x86_64w" ;; -+ haswellavx-pc-msys|haswellavx-w64-mingw*|haswellavx-*-cygwin*) -+ path_64="x86_64w/haswell/avx x86_64w/haswell x86_64w/sandybridge x86_64w" ;; - skylake-pc-msys|skylake-w64-mingw*|skylake-*-cygwin*) - path_64="x86_64w/skylake x86_64w/sandybridge x86_64w" ;; - skylakeavx-pc-msys|skylakeavx-w64-mingw*|skylakeavx-*-cygwin*) -- path_64="x86_64w/skylakeavx x86_64w/skylake x86_64w/haswell x86_64w/sandybridge x86_64w" ;; -+ path_64="x86_64w/skylake/avx x86_64w/skylake x86_64w/haswell x86_64w/sandybridge x86_64w" ;; - broadwell-pc-msys|broadwell-w64-mingw*|broadwell-*-cygwin*) - path_64="x86_64w/haswell/broadwell x86_64w/haswell/avx x86_64w/haswell x86_64w/sandybridge x86_64w" ;; - atom-pc-msys|atom-w64-mingw*|atom-*-cygwin*) -@@ -4945,6 +4951,8 @@ - ivybridge-*-*) - path_64="x86_64/sandybridge/ivybridge x86_64/sandybridge x86_64/nehalem x86_64/core2 x86_64" ;; - haswell-*-*) -+ path_64="x86_64/haswell x86_64/sandybridge x86_64" ;; -+ haswellavx-*-*) - path_64="x86_64/haswell/avx x86_64/haswell x86_64/sandybridge x86_64" ;; - broadwell-*-*) - path_64="x86_64/haswell/broadwell x86_64/haswell/avx x86_64/haswell x86_64/sandybridge x86_64" ;; -@@ -10775,7 +10783,7 @@ - # enough assembler. - # - case $host in -- i?86*-*-* | k[5-8]*-*-* | pentium*-*-* | prescott-*-* | core-*-* | athlon-*-* | viac3*-*-* | x86_64-*-* | netburst-*-* | netburstlahf-*-* | k8-*-* | k10-*-* | k102-*-* | k103-*-* | core2-*-* | penryn-*-* | nehalem-*-* | westmere-*-* | sandybridge-*-* | atom-*-* | nano-*-* | bobcat-*-* | bulldozer-*-* | piledriver-*-* | ivybridge-*-* | haswell-*-* | broadwell-*-* | skylake-*-* | skylakeavx-*-*) -+ i?86*-*-* | k[5-8]*-*-* | pentium*-*-* | prescott-*-* | core-*-* | athlon-*-* | viac3*-*-* | x86_64-*-* | netburst-*-* | netburstlahf-*-* | k8-*-* | k10-*-* | k102-*-* | k103-*-* | core2-*-* | penryn-*-* | nehalem-*-* | westmere-*-* | sandybridge-*-* | atom-*-* | nano-*-* | bobcat-*-* | bulldozer-*-* | piledriver-*-* | ivybridge-*-* | haswell-*-* | haswellavx-*-* | broadwell-*-* | skylake-*-* | skylakeavx-*-*) - if test "$ABI" = 32; then - case "$path $fat_path" in - *mmx*) { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the assembler knows about MMX instructions" >&5 -@@ -25885,7 +25867,7 @@ - ;; - esac - ;; -- i?86*-*-* | k[5-8]*-*-* | pentium*-*-* | prescott-*-* | core-*-* | athlon-*-* | viac3*-*-* | x86_64-*-* | netburst-*-* | netburstlahf-*-* | k8-*-* | k10-*-* | k102-*-* | k103-*-* | core2-*-* | penryn-*-* | nehalem-*-* | westmere-*-* | sandybridge-*-* | atom-*-* | nano-*-* | bobcat-*-* | bulldozer-*-* | piledriver-*-* | ivybridge-*-* | haswell-*-* | broadwell-*-* | skylake-*-* | skylakeavx-*-*) -+ i?86*-*-* | k[5-8]*-*-* | pentium*-*-* | prescott-*-* | core-*-* | athlon-*-* | viac3*-*-* | x86_64-*-* | netburst-*-* | netburstlahf-*-* | k8-*-* | k10-*-* | k102-*-* | k103-*-* | core2-*-* | penryn-*-* | nehalem-*-* | westmere-*-* | sandybridge-*-* | atom-*-* | nano-*-* | bobcat-*-* | bulldozer-*-* | piledriver-*-* | ivybridge-*-* | haswell-*-* | haswellavx-*-* | broadwell-*-* | skylake-*-* | skylakeavx-*-*) - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking if the .align directive accepts an 0x90 fill in .text" >&5 - $as_echo_n "checking if the .align directive accepts an 0x90 fill in .text... " >&6; } -diff -ru a/cpuid.c b/cpuid.c ---- a/cpuid.c 2018-07-13 14:49:31.111368100 +0200 -+++ b/cpuid.c 2018-07-13 15:08:45.680372700 +0200 -@@ -174,12 +174,16 @@ CPUVEC_SETUP_x86_64; - if (model == 54){ CPUIS(atom);break;}//DualCore Intel Atom D2700, 2133 MHz (16 x 133) (Cedarview, Saltwell core) 32nm - if (model == 55){ CPUIS(atom);break;} - if (model == 58){ CPUIS(ivybridge);break;} -- if (model == 60){ CPUIS(haswell);break;} -+ if (model == 60){ -+ int feat = ((int *)features)[2]; -+ if (feat & FEAT_HAS_AVX) { CPUIS(haswellavx);break; } /* Core i Haswell */ -+ else { CPUIS(haswell);break; } /* Celeron/Pentium Haswell without AVX */ -+ } - if (model == 61){ CPUIS(broadwell);break;} - if (model == 62){ CPUIS(ivybridge);break;} -- if (model == 63){ CPUIS(haswell);break;} -- if (model == 69){ CPUIS(haswell);break;} -- if (model == 70){ CPUIS(haswell);break;} -+ if (model == 63){ CPUIS(haswellavx);break;} -+ if (model == 69){ CPUIS(haswellavx);break;} -+ if (model == 70){ CPUIS(haswellavx);break;} - if (model == 71){ CPUIS(broadwell);break;} - if (model == 78){ CPUIS(skylakeavx);break;} - if (model == 79){ CPUIS(broadwell);break;} -diff -ru a/mpn/x86/fat/fat.c b/mpn/x86/fat/fat.c ---- a/mpn/x86/fat/fat.c 2018-07-13 14:49:31.111368100 +0200 -+++ b/mpn/x86/fat/fat.c 2018-07-13 15:08:45.680372700 +0200 -@@ -109,6 +109,7 @@ - #define CPUSETUP_sandybridge CPUVEC_SETUP_nehalem - #define CPUSETUP_ivybridge CPUVEC_SETUP_nehalem - #define CPUSETUP_haswell CPUVEC_SETUP_nehalem -+#define CPUSETUP_haswellavx CPUVEC_SETUP_nehalem - #define CPUSETUP_broadwell CPUVEC_SETUP_nehalem - #define CPUSETUP_skylake CPUVEC_SETUP_nehalem - #define CPUSETUP_skylakeavx CPUVEC_SETUP_nehalem -diff -ru a/mpn/x86_64/fat/fat.c b/mpn/x86_64/fat/fat.c ---- a/mpn/x86_64/fat/fat.c 2018-07-13 14:49:32.356372900 +0200 -+++ b/mpn/x86_64/fat/fat.c 2018-07-13 15:08:46.992374500 +0200 -@@ -103,6 +103,7 @@ - #define CPUSETUP_sandybridge CPUVEC_SETUP_sandybridge - #define CPUSETUP_ivybridge CPUVEC_SETUP_sandybridge;CPUVEC_SETUP_sandybridge_ivybridge - #define CPUSETUP_haswell CPUVEC_SETUP_haswell -+#define CPUSETUP_haswellavx CPUVEC_SETUP_haswell;CPUVEC_SETUP_haswell_avx - #define CPUSETUP_broadwell CPUVEC_SETUP_haswell;CPUVEC_SETUP_haswell_broadwell - #define CPUSETUP_skylake CPUVEC_SETUP_skylake - #define CPUSETUP_skylakeavx CPUVEC_SETUP_skylake;CPUVEC_SETUP_skylake_avx -diff -ru a/mpn/x86_64w/fat/fat.c b/mpn/x86_64w/fat/fat.c ---- a/mpn/x86_64w/fat/fat.c 2018-07-13 14:49:28.284367600 +0200 -+++ b/mpn/x86_64w/fat/fat.c 2018-07-13 15:08:43.058372800 +0200 -@@ -103,6 +103,7 @@ - #define CPUSETUP_sandybridge CPUVEC_SETUP_sandybridge - #define CPUSETUP_ivybridge CPUVEC_SETUP_sandybridge - #define CPUSETUP_haswell CPUVEC_SETUP_haswell -+#define CPUSETUP_haswellavx CPUVEC_SETUP_haswell;CPUVEC_SETUP_haswell_avx - #define CPUSETUP_broadwell CPUVEC_SETUP_haswell;CPUVEC_SETUP_haswell_broadwell - #define CPUSETUP_skylake CPUVEC_SETUP_skylake - #define CPUSETUP_skylakeavx CPUVEC_SETUP_skylake;CPUVEC_SETUP_skylake_avx diff --git a/build/pkgs/mpir/spkg-check.in b/build/pkgs/mpir/spkg-check.in deleted file mode 100644 index 4727de00ffe..00000000000 --- a/build/pkgs/mpir/spkg-check.in +++ /dev/null @@ -1,6 +0,0 @@ -cd src - -# We don't have to set up any environment variables here since the -# Makefiles already have them from 'configure'. - -$MAKE check diff --git a/build/pkgs/mpir/spkg-configure.m4 b/build/pkgs/mpir/spkg-configure.m4 deleted file mode 100644 index fd167864ee7..00000000000 --- a/build/pkgs/mpir/spkg-configure.m4 +++ /dev/null @@ -1,74 +0,0 @@ -SAGE_SPKG_CONFIGURE([mpir], [ -dnl Implement cases for what to do on different options here - _sage_spkg_install_gmp=no - case "$with_mp" in - system) - AC_CHECK_HEADER(gmp.h, [], [_sage_spkg_install_gmp=yes]) - AC_CHECK_HEADER(gmpxx.h, [], [_sage_spkg_install_gmp=yes]) - dnl mpq_cmp_z appeared in GMP 6.1.0 and is used by pynac - AC_SEARCH_LIBS([__gmpq_cmp_z], [gmp], [], - [_sage_spkg_install_gmp=yes]) - SAGE_MP_LIBRARY=gmp - ;; - mpir) - sage_spkg_install_mpir=yes - SAGE_MP_LIBRARY=mpir - ;; - gmp) - _sage_spkg_install_gmp=yes - SAGE_MP_LIBRARY=gmp - ;; - esac -], [], [ - AC_ARG_WITH([mp], - [AS_HELP_STRING([--with-mp=system], - [use the system GMP as multiprecision library, if possible (default)]) -dnl Not indented because whitespace ends up in the help text -AS_HELP_STRING([--with-mp=mpir], - [use the Sage SPKG for MPIR as multiprecision library]) -AS_HELP_STRING([--with-mp=gmp], - [use the Sage SPKG for GMP as multiprecision library])]) - -dnl Just parse the options here - case "$with_mp" in - system) ;; - MPIR|mpir) with_mp=mpir;; - GMP|gmp) with_mp=gmp;; - "") with_mp=system;; - *) - AC_MSG_ERROR([allowed values for --with-mp are system, mpir, or gmp]);; - esac - -dnl Set SAGE_MP_LIBRARY depending on the with_mp option - case "$with_mp" in - mpir) - SAGE_MP_LIBRARY=mpir - ;; - gmp|system) - SAGE_MP_LIBRARY=gmp - ;; - esac - - AC_SUBST([SAGE_MP_LIBRARY], [$SAGE_MP_LIBRARY]) -], [ - if test x$sage_spkg_install_mpir = xyes -o x$_sage_spkg_install_gmp = xyes; then - AC_SUBST(SAGE_GMP_PREFIX, ['$SAGE_LOCAL']) - AC_SUBST(SAGE_GMP_INCLUDE, ['$SAGE_LOCAL/include']) - AC_MSG_RESULT([using $SAGE_MP_LIBRARY SPKG (via --with-mp=$SAGE_MP_LIBRARY)]) - else - dnl If found, we want to get the absolute path to where we - dnl found it for use with some packages (e.g. iml) that need - dnl this information at configure time - AX_ABSOLUTE_HEADER([gmp.h]) - if test x$gl_cv_absolute_gmp_h = x; then - AC_MSG_ERROR(m4_normalize([ - failed to find absolute path to gmp.h despite it being reported - found - ])) - fi - AC_SUBST(SAGE_GMP_INCLUDE, [`AS_DIRNAME($gl_cv_absolute_gmp_h)`]) - AC_SUBST(SAGE_GMP_PREFIX, ['']) - AC_MSG_RESULT([using GMP-compatible library from the system]) - fi -]) - diff --git a/build/pkgs/mpir/spkg-install.in b/build/pkgs/mpir/spkg-install.in deleted file mode 100644 index 01070d1dc3e..00000000000 --- a/build/pkgs/mpir/spkg-install.in +++ /dev/null @@ -1,322 +0,0 @@ -cd src - -############################################################################### -# Previous MPIR installations are only removed after a *successful* (re)build, -# before installing the new one. (Done below.) -############################################################################### - -############################################################################### -# Find out the machine type -############################################################################### - -MACHINE_TYPE_MPIR=$(bash ./config.guess) -if [ $? -ne 0 ]; then - echo >&2 "Error: failed to determine the machine type (mpir-extended)" - exit 1 -fi - -# This is the vanilla config.guess (renamed to configfsf.guess in -# MPIR) file instead of MPIR's version. It is used when -# SAGE_FAT_BINARY is set. -MACHINE_TYPE_DEFAULT=$(bash ./configfsf.guess) -if [ $? -ne 0 ]; then - echo >&2 "Error: failed to determine the machine type (default)" - exit 1 -fi - -echo "Machine type (default): $MACHINE_TYPE_DEFAULT" -echo "Machine type (mpir): $MACHINE_TYPE_MPIR" - -############################################################################### -# Set up environment variables: -############################################################################### - -user_cflags=$CFLAGS # Save them. 'sage-env' sets CC, but not CFLAGS. -required_cflags="" # Additional mandatory settings required by Sage, accumulated below. -user_ldflags=$LDFLAGS # Save them. -required_ldflags="" # Additional mandatory settings required by Sage, accumulated below. -user_abi=$ABI # Just save it. -# In case we changed CPPFLAGS or CXXFLAGS, too, we should save the user's here as well. -# We don't have to add (e.g.) '-m64' to CFLAGS/CPPFLAGS/CXXFLAGS/LDFLAGS, since -# MPIR's 'configure' is smart enough to add it if necessary or appropriate. - - -if [ -z "$CFLAG32" ]; then - CFLAG32="-m32" # Only used in this script, no need to export it. -fi -if [ -z "$CFLAG64" ]; then - CFLAG64="-m64" # Only used in this script, no need to export it. -fi - - -case "$UNAME" in - SunOS) - true;; # Auto-detect ABI - Darwin) - # In some cases (see SAGE_ROOT/spkg/bin/sage-env), on Darwin, - # CC might be set to clang, but MPIR doesn't seem to build - # with clang. - CLANG=`command -v clang` - GCC=`command -v gcc` - if [ -n "$CC" ] && [ "$CC" = "$CLANG" ] && [ -n "$GCC" ] ; then - export CC="$GCC" - fi - # Do not set ABI=32 on MacOS X 10.6 (Darwin 10) and later, since - # there everything defaults to 64-bit: - if [ "`uname -r | sed 's/\..*//'`" -lt 10 ]; then - # Assume MacOS X 10.4 or 10.5 (Darwin 8 or 9); also, PPC CPUs - # are only supported by these, not later versions. - echo "Building a 32-bit version of MPIR, which is the only supported option." - ABI=32 - case "`uname -m`" in - ppc|ppc64|[Pp]ower*) # Apple's 'uname' returns strange strings - # The Darwin assembler rejects code using an - # extended instruction set by default (cf. #8664): - required_cflags="$required_cflags -Wa,-force_cpusubtype_ALL" - ;; - esac - else - # Darwin 10 (MacOS X 10.6) or later. - # We don't have to set ABI here. - echo "Building a 64-bit version of MPIR, which is the default." - fi - ;; # Darwin - Linux) - # MPIR fails to build on 32-bit operating systems running on - # 64-bit CPUs if CFLAGS happen to contain '-m32' and ABI is - # *not* set, so we set it here if necessary: - # (Cf. http://groups.google.com/group/mpir-devel/browse_thread/thread/46ccdc5dfc3485cd#) - # Note: This code snippet could in principle be moved out of the - # Linux branch, but since we already set ABI for other - # OSs above (and print an according message), it's here. - if [ -z "$ABI" ]; then - echo "int main(){return 0;}" > foo.c - # Try building and running a 64-bit executable: - # (Building usually succeeds even on 32-bit systems, unless e.g. a 32-bit - # CPU is explicitly selected by CFLAGS, while running does not.) - if $CC $CFLAGS $CFLAG64 -o foo foo.c 2>/dev/null && ./foo 2>/dev/null; then - # We can run 64-bit executables. - # Setting ABI=64 shouldn't be necessary, but shouldn't hurt either. - echo "Building a 64-bit version of MPIR." - case "`uname -m`" in - ppc*) ABI=mode64;; - *) ABI=64;; - esac - elif $CC $CFLAGS $CFLAG32 -o foo foo.c 2>/dev/null && ./foo 2>/dev/null; then - # We're on a 32-bit OS which cannot run 64-bit executables. - echo "Building a 32-bit version of MPIR." - ABI=32 - else - # It seems the compiler does not support -m32 nor -m64 (e.g. - # GCC on Itanium rejects both); do not set ABI at all. - echo "Your compiler does not support '$CFLAG32' nor '$CFLAG64'. Leaving ABI unset." - fi - rm -f foo foo.c - fi - ;; # Linux - CYGWIN) - if uname -a | grep x86_64 ; then - ABI=64 - else - ABI=32 - fi - ;; - *) # e.g. AIX or HP-UX - echo >&2 "Warning: Your platform ($UNAME) isn't yet explicitly supported" \ - "by this MPIR spkg, i.e., by Sage's part of it." -esac - -# MPIR 2.7.2 does not know about ppc64le and confuses it with plain -# ppc64. We need to disable specific powerpc64 assembly. -if [ "`uname -m`" = ppc64le ]; then - export MPN_PATH=generic -fi - -# Workaround old GNU as version by disabling assembly use. -if [ "$UNAME" = Linux ]; then - as_version=`$AS --version | head -1 | awk 'NF>1{print $NF}'` - as_version_major=${as_version%%.*} - as_version_rest=${as_version#*.} - as_version_minor=${as_version_rest%%.*} - if [ $as_version_major -lt 2 ] || \ - [ $as_version_major -eq 2 -a $as_version_minor -lt 24 ]; then - echo "Disable use of assembly because of GNU as <= 2.23." - export MPN_PATH=generic - if [ "$SAGE_FAT_BINARY" = "yes" ]; then - echo "Cannot build with SAGE_FAT_BINARY=yes." - exit 1 - fi - fi -fi - -# Work around a bug in GCC 4.7.0 which breaks the build on Itanium CPUs. -# See #12765, #12751, and http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48496 -if [ "`uname -m`" = ia64 ] && [ "`testcc.sh $CC`" = GCC ] ; then - gcc_version=`$CC -dumpversion` - case "$gcc_version" in - 4.7.0) - required_cflags="$required_cflags -O0 -finline-functions -fschedule-insns" - echo >&2 "Warning: Disabling almost all optimization due to a bug in GCC 4.7.0" - echo >&2 " on Itanium, which otherwise would break the build." - echo >&2 " See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=48496" - echo >&2 " for current status and further details." - ;; - esac -fi - -export ABI CFLAGS CXXFLAGS LDFLAGS # Partially redundant, but safe(r). -# We don't export CPPFLAGS here, since we don't (have to) modify them. - -############################################################################### -# Now configure MPIR, eventually modifying CFLAGS [further]: -############################################################################### - -MPIR_CONFIGURE="--enable-shared $MPIR_CONFIGURE" -MPIR_CONFIGURE="--enable-gmpcompat $MPIR_CONFIGURE" - -# Fake yasm installation on non-x86[_64] system. -# It is not installed but not needed. -case `uname -m` in - i[3456]86|x86_64|amd64) - ;; - *) # Anything else - echo "Disabling check for yasm on non-x86[_64] system." - MPIR_CONFIGURE="--with-yasm=/bin/true $MPIR_CONFIGURE" - ;; -esac - -# Also build the static library to be used by e.g. ECM -# unless we are on Cygwin where we can only build a shared -# or a static library but not both: -if [ "$UNAME" = "CYGWIN" ]; then - echo "Building MPIR with the C++ interface and (only) shared libraries." - MPIR_CONFIGURE="--enable-cxx $MPIR_CONFIGURE --disable-static" -else - echo "Building MPIR with the C++ interface and (also) static libraries." - MPIR_CONFIGURE="--enable-cxx --enable-static $MPIR_CONFIGURE" -fi - -# If SAGE_FAT_BINARY is enabled, then add --enable-fat to configure -# options on Linux x86 systems. On other systems, fat binaries are not -# supported. There, we specify a build architecture which doesn't -# have a CPU name in it. -if [ "$SAGE_FAT_BINARY" = "yes" ]; then - case "$UNAME-`uname -m`" in - Linux-i[3456]86) - echo "** Building with \"fat binary\" support for 32-bit CPUs **" - MPIR_CONFIGURE="--enable-fat $MPIR_CONFIGURE" - ;; - Linux-x86_64|Linux-amd64) - echo "** Building with \"fat binary\" support for 64-bit CPUs **" - MPIR_CONFIGURE="--enable-fat $MPIR_CONFIGURE" - ;; - *) # Anything else - echo "** Building a generic binary (not assuming any specific CPU) **" - MPIR_CONFIGURE="--build=$MACHINE_TYPE_DEFAULT $MPIR_CONFIGURE" - ;; - esac -fi - - -# Pre-configure MPIR to get the settings it would use if CFLAGS were empty: -echo "------------------------------------------------------------------------" -echo "Configuring MPIR with empty CFLAGS to determine the defaults:" -(unset CFLAGS CPPFLAGS CXXFLAGS && ./configure $MPIR_CONFIGURE) -if [ $? -ne 0 ]; then - echo >&2 "Error configuring MPIR (with CFLAGS unset)." - echo >&2 "Consult `pwd`/config.log for for details." - exit 1 -fi - - -# Read MPIR-selected flags from Makefile -mpir_cc=`sed -n 's/^CC *= *//p' Makefile` -mpir_cflags=`sed -n 's/^CFLAGS *= *//p' Makefile` -if [ -z "$mpir_cc" ]; then - echo >&2 "Error: failed to determine \$CC from Makefile" - echo >&2 "Please report this to " - exit 1 -fi -echo "------------------------------------------------------------------------" -echo "Settings chosen by MPIR when configuring with CFLAGS unset:" -echo " CC: $mpir_cc" -echo " CFLAGS: $mpir_cflags" -echo "Settings added by Sage to build MPIR, taking into account SAGE_DEBUG etc.:" -echo " CFLAGS: $required_cflags" # Might be empty. -echo " LDFLAGS: $required_ldflags" # Might be empty. -echo " ABI: $ABI" # Might be empty, or the one specified by the user. -echo "Settings from the \"global\" environment:" -echo " CC: $CC" # Set by Sage, maybe overridden by the user. -echo " CFLAGS: $user_cflags" -echo " LDFLAGS: $user_ldflags" -echo " ABI: $user_abi" -echo " (CPP, CPPFLAGS, CXX and CXXFLAGS are listed below; these don't get modified.)" - -# Finally: use MPIR's flags, plus those required by Sage for the -# package to build properly, plus those specified by the user. -CFLAGS="$mpir_cflags $required_cflags $user_cflags" -LDFLAGS="$required_ldflags $user_ldflags" - -echo "Finally using the following settings:" -echo " CC=$CC" -echo " CFLAGS=$CFLAGS" -echo " CPP=$CPP" -echo " CPPFLAGS=$CPPFLAGS" -echo " CXX=$CXX" -echo " CXXFLAGS=$CXXFLAGS" -echo " LDFLAGS=$LDFLAGS" -echo " ABI=$ABI" -echo "(These settings may still get overridden by 'configure' or Makefiles.)" - -############################################################################### -# Now really configure MPIR with proper settings: -############################################################################### - -# We also add '--libdir="$SAGE_LOCAL/lib"' below, since newer autotools may -# otherwise put the libraries into .../lib64 on 64-bit systems (cf. #12131). - -echo "------------------------------------------------------------------------" -echo "Configuring MPIR with the following options:" -echo " --prefix=\"$SAGE_LOCAL\" --libdir=\"$SAGE_LOCAL/lib\" $MPIR_CONFIGURE" -echo "You can set MPIR_CONFIGURE to pass additional parameters." - -# Clear the cache of the previous configure run -find . -name config.cache -exec rm -f {} \; - -sdh_configure $MPIR_CONFIGURE - -############################################################################### -# Now build MPIR: -############################################################################### - -sdh_make -echo "Build succeeded." - -############################################################################### -# Remove previous installation (if any), *after* a successful build: -############################################################################### - -echo "Removing old GMP/MPIR headers..." -rm -f "$SAGE_LOCAL"/include/{gmp,mpir}*.h - -# Do NOT delete old GMP/MPIR shared libraries as Sage's versions of libraries -# used by GCC might still refer to them, such that their deletion would break -# GCC inside Sage. (We could perhaps remove libmpir* though.) -if false; then - echo "Removing old GMP/MPIR libraries..." - rm -f "$SAGE_LOCAL"/lib/lib{gmp,mpir}* -else - echo "Not removing old GMP/MPIR shared libraries, as other libraries" - echo "and executables might still refer to them:" - ls -l "$SAGE_LOCAL"/lib/lib{gmp,mpir}* - echo "(Libraries with the same version number will get updated though.)" -fi - -# Mark GMP as not installed (since we will overwrite it) -rm -f "$SAGE_SPKG_INST"/gmp-* - -############################################################################### -# Now install MPIR: -############################################################################### - -sdh_make_install diff --git a/build/pkgs/mpir/spkg-src b/build/pkgs/mpir/spkg-src deleted file mode 100755 index 8dde1a84941..00000000000 --- a/build/pkgs/mpir/spkg-src +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/env bash - -set -e - -if [ -z "$SAGE_DISTFILES" ]; then - echo >&2 "SAGE_DISTFILES undefined ... exiting" - echo >&2 "Maybe run 'sage --sh'?" - exit 1 -fi - -set -e - -PACKAGEVERSION=`cat $SAGE_ROOT/build/pkgs/mpir/package-version.txt` -MPIRVERSION=mpir-`echo $PACKAGEVERSION | sed 's/-.*//'` -TARBALLVERSION="mpir-$PACKAGEVERSION" - -# Get the sources -cd "$SAGE_DISTFILES" -rm -rf mpir -git clone https://github.com/wbhart/mpir.git mpir -cd mpir -git checkout 644faf502c56f97d9accd301965fc57d6ec70868 - -# Add auto-generated files -./autogen.sh - -# Create the tarball -./configure -make dist-bzip2 - -# Unpack the tarball, remove some unwanted stuff -tar xjf $MPIRVERSION.tar.bz2 -find $MPIRVERSION -name 'build.vc*' -prune -exec rm -r {} \; - -# Repackage the tarball and put it in SAGE_DISTFILES -mv $MPIRVERSION $TARBALLVERSION -tar c $TARBALLVERSION | bzip2 --best >../$TARBALLVERSION.tar.bz2 -sage-package fix-checksum mpir - -# Cleanup -cd "$SAGE_DISTFILES" -rm -rf mpir -echo "New MPIR tarball is ready in $SAGE_DISTFILES/$TARBALLVERSION.tar.bz2" diff --git a/build/pkgs/mpir/type b/build/pkgs/mpir/type deleted file mode 100644 index a6a7b9cd726..00000000000 --- a/build/pkgs/mpir/type +++ /dev/null @@ -1 +0,0 @@ -standard diff --git a/build/pkgs/networkx/dependencies b/build/pkgs/networkx/dependencies index 3d0462a6697..2a20cb459ba 100644 --- a/build/pkgs/networkx/dependencies +++ b/build/pkgs/networkx/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) decorator | $(PYTHON_TOOLCHAIN) scipy $(and $(filter-out no,$(SAGE_CHECK_networkx)), nose pytest) +$(PYTHON) decorator | $(PYTHON_TOOLCHAIN) scipy $(and $(filter-out no,$(SAGE_CHECK_networkx)), pytest) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/networkx/spkg-check.in b/build/pkgs/networkx/spkg-check.in index 60868aaefc5..8b3f5031762 100644 --- a/build/pkgs/networkx/spkg-check.in +++ b/build/pkgs/networkx/spkg-check.in @@ -1,8 +1,3 @@ cd src -if ! command -v nosetests ; then - echo >&2 'Testing networkx requires the package nose to be installed' - exit 1 -fi - -nosetests networkx -v +pytest diff --git a/build/pkgs/nose/SPKG.rst b/build/pkgs/nose/SPKG.rst deleted file mode 100644 index 49f74660ac7..00000000000 --- a/build/pkgs/nose/SPKG.rst +++ /dev/null @@ -1,34 +0,0 @@ -nose: Python unit testing framework -=================================== - -Description ------------ - -nose extends the test loading and running features of unittest, making -it easier to write, find and run tests. - -License -------- - -GNU LGPL - - -Upstream Contact ----------------- - -Author: Jason Pellerin Home Page: http://readthedocs.org/docs/nose/ - - see also https://github.com/nose-devs/nose - -Dependencies ------------- - -- setuptools / distribute -- Python -- GNU patch (shipped with Sage) - - -Special Update/Build Instructions ---------------------------------- - -None. diff --git a/build/pkgs/nose/checksums.ini b/build/pkgs/nose/checksums.ini deleted file mode 100644 index b9477e8524b..00000000000 --- a/build/pkgs/nose/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=nose-VERSION.tar.gz -sha1=97f2a04c9d43b29ddf4794a1a1d1ba803f1074c6 -md5=4d3ad0ff07b61373d2cefc89c5d0b20b -cksum=3318391794 diff --git a/build/pkgs/nose/dependencies b/build/pkgs/nose/dependencies deleted file mode 100644 index 15df0c4d6d8..00000000000 --- a/build/pkgs/nose/dependencies +++ /dev/null @@ -1,5 +0,0 @@ -$(PYTHON) | $(PYTHON_TOOLCHAIN) - ----------- -All lines of this file are ignored except the first. -It is copied by SAGE_ROOT/build/make/install into SAGE_ROOT/build/make/Makefile. diff --git a/build/pkgs/nose/distros/conda.txt b/build/pkgs/nose/distros/conda.txt deleted file mode 100644 index f3c7e8e6ffb..00000000000 --- a/build/pkgs/nose/distros/conda.txt +++ /dev/null @@ -1 +0,0 @@ -nose diff --git a/build/pkgs/nose/distros/macports.txt b/build/pkgs/nose/distros/macports.txt deleted file mode 100644 index a29026eec2b..00000000000 --- a/build/pkgs/nose/distros/macports.txt +++ /dev/null @@ -1 +0,0 @@ -py-nose diff --git a/build/pkgs/nose/distros/repology.txt b/build/pkgs/nose/distros/repology.txt deleted file mode 100644 index 4ebae104fde..00000000000 --- a/build/pkgs/nose/distros/repology.txt +++ /dev/null @@ -1,2 +0,0 @@ -nose -python:nose diff --git a/build/pkgs/nose/install-requires.txt b/build/pkgs/nose/install-requires.txt deleted file mode 100644 index 2e10ae2a3b2..00000000000 --- a/build/pkgs/nose/install-requires.txt +++ /dev/null @@ -1 +0,0 @@ -nose >=1.3.7 diff --git a/build/pkgs/nose/package-version.txt b/build/pkgs/nose/package-version.txt deleted file mode 100644 index 3336003dccd..00000000000 --- a/build/pkgs/nose/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -1.3.7 diff --git a/build/pkgs/nose/spkg-check.in b/build/pkgs/nose/spkg-check.in deleted file mode 100644 index 9bfbe9f31ab..00000000000 --- a/build/pkgs/nose/spkg-check.in +++ /dev/null @@ -1,5 +0,0 @@ -cd src - -python3 setup.py build_tests - -python3 selftest.py diff --git a/build/pkgs/nose/spkg-install.in b/build/pkgs/nose/spkg-install.in deleted file mode 100644 index fe7461d2f8b..00000000000 --- a/build/pkgs/nose/spkg-install.in +++ /dev/null @@ -1,6 +0,0 @@ -cd src - -# Install new version -echo "Installing nose..." -sdh_pip_install . -echo diff --git a/build/pkgs/nose/type b/build/pkgs/nose/type deleted file mode 100644 index a6a7b9cd726..00000000000 --- a/build/pkgs/nose/type +++ /dev/null @@ -1 +0,0 @@ -standard diff --git a/build/pkgs/ntl/spkg-configure.m4 b/build/pkgs/ntl/spkg-configure.m4 index ba019d712de..f27ebc1bba7 100644 --- a/build/pkgs/ntl/spkg-configure.m4 +++ b/build/pkgs/ntl/spkg-configure.m4 @@ -1,7 +1,7 @@ SAGE_SPKG_CONFIGURE([ntl], [ m4_pushdef(SAGE_NTL_VERSION_MAJOR, [10]) m4_pushdef(SAGE_NTL_VERSION_MINOR, [3]) - SAGE_SPKG_DEPCHECK([gmp mpir gcc], [ + SAGE_SPKG_DEPCHECK([gmp gcc], [ AC_CHECK_HEADER([NTL/ZZ.h], [], [sage_spkg_install_ntl=yes]) AC_MSG_CHECKING([whether we can link a program using NTL]) NTL_SAVED_LIBS=$LIBS diff --git a/build/pkgs/pandoc/spkg-install b/build/pkgs/pandoc/spkg-install deleted file mode 100755 index 45fa6a3e0a9..00000000000 --- a/build/pkgs/pandoc/spkg-install +++ /dev/null @@ -1,5 +0,0 @@ -#! /usr/bin/env bash -echo Error: pandoc, a prerequisite of rst2ipynb, is not installed. -echo Please install it manually, for example using the system packages -echo recommended by ./configure. -exit 1 diff --git a/build/pkgs/pari/spkg-configure.m4 b/build/pkgs/pari/spkg-configure.m4 index 0baf6e427b6..9721849e7ba 100644 --- a/build/pkgs/pari/spkg-configure.m4 +++ b/build/pkgs/pari/spkg-configure.m4 @@ -1,7 +1,7 @@ SAGE_SPKG_CONFIGURE([pari], [ dnl See gp_version below on how the version is computed from MAJV.MINV.PATCHV m4_pushdef([SAGE_PARI_MINVER],["134401"]) - SAGE_SPKG_DEPCHECK([gmp mpir readline], [ + SAGE_SPKG_DEPCHECK([gmp readline], [ AC_PATH_PROG([GP], [gp]) if test x$GP = x; then dnl GP test AC_MSG_NOTICE([gp is not found]) diff --git a/build/pkgs/perl_cpan_polymake_prereq/distros/cpan.txt b/build/pkgs/perl_cpan_polymake_prereq/distros/cpan.txt index fbd93fc89a2..131aebf6d3d 100644 --- a/build/pkgs/perl_cpan_polymake_prereq/distros/cpan.txt +++ b/build/pkgs/perl_cpan_polymake_prereq/distros/cpan.txt @@ -4,3 +4,4 @@ XML::LibXSLT File::Slurp JSON SVG +Term::ReadKey diff --git a/build/pkgs/perl_cpan_polymake_prereq/distros/fedora.txt b/build/pkgs/perl_cpan_polymake_prereq/distros/fedora.txt index 89a8a7622bf..c7390e63993 100644 --- a/build/pkgs/perl_cpan_polymake_prereq/distros/fedora.txt +++ b/build/pkgs/perl_cpan_polymake_prereq/distros/fedora.txt @@ -2,6 +2,7 @@ perl-ExtUtils-Embed perl-File-Slurp perl-JSON perl-Term-ReadLine-Gnu +perl-Term-ReadKey perl-XML-Writer perl-XML-LibXML perl-XML-LibXSLT diff --git a/build/pkgs/perl_cpan_polymake_prereq/distros/freebsd.txt b/build/pkgs/perl_cpan_polymake_prereq/distros/freebsd.txt index 9b2b62bccd9..43a596433c9 100644 --- a/build/pkgs/perl_cpan_polymake_prereq/distros/freebsd.txt +++ b/build/pkgs/perl_cpan_polymake_prereq/distros/freebsd.txt @@ -4,3 +4,4 @@ textproc/p5-XML-LibXSLT devel/p5-File-Slurp converters/p5-JSON textproc/p5-SVG +devel/p5-Term-ReadKey diff --git a/build/pkgs/perl_cpan_polymake_prereq/distros/gentoo.txt b/build/pkgs/perl_cpan_polymake_prereq/distros/gentoo.txt index 67835e72530..b4803c6fdac 100644 --- a/build/pkgs/perl_cpan_polymake_prereq/distros/gentoo.txt +++ b/build/pkgs/perl_cpan_polymake_prereq/distros/gentoo.txt @@ -3,5 +3,6 @@ XML-LibXML XML-LibXSLT File-Slurp dev-perl/Term-ReadLine-Gnu +dev-perl/TermReadKey JSON SVG diff --git a/build/pkgs/perl_cpan_polymake_prereq/spkg-install b/build/pkgs/perl_cpan_polymake_prereq/spkg-install deleted file mode 100755 index 44bb1e1a6ef..00000000000 --- a/build/pkgs/perl_cpan_polymake_prereq/spkg-install +++ /dev/null @@ -1,6 +0,0 @@ -#! /usr/bin/env bash -echo Error: The Perl prerequisites of the package polymake are not installed. -echo Please install CPAN packages $(cat distros/cpan.txt) -echo manually, either using the system packages recommended by ./configure -echo or directly from CPAN. -exit 1 diff --git a/build/pkgs/perl_mongodb/spkg-install b/build/pkgs/perl_mongodb/spkg-install deleted file mode 100755 index 7f087781bb9..00000000000 --- a/build/pkgs/perl_mongodb/spkg-install +++ /dev/null @@ -1,6 +0,0 @@ -#! /usr/bin/env bash -echo Error: The optional prerequisite perl_mongodb of the package polymake are not installed. -echo Please install CPAN package $(cat distros/cpan.txt) -echo manually, either using the system package recommended by ./configure -echo or directly from CPAN. -exit 1 diff --git a/build/pkgs/perl_term_readline_gnu/type b/build/pkgs/perl_term_readline_gnu/type index 9839eb20815..134d9bc32d5 100644 --- a/build/pkgs/perl_term_readline_gnu/type +++ b/build/pkgs/perl_term_readline_gnu/type @@ -1 +1 @@ -experimental +optional diff --git a/build/pkgs/pkgconfig/SPKG.rst b/build/pkgs/pkgconfig/SPKG.rst index cd737e14763..3c5d61a167a 100644 --- a/build/pkgs/pkgconfig/SPKG.rst +++ b/build/pkgs/pkgconfig/SPKG.rst @@ -17,16 +17,3 @@ Upstream Contact ---------------- https://github.com/matze/pkgconfig - -Dependencies ------------- - -- Python 2.6+ - - -Special Update/Build Instructions ---------------------------------- - -Standard setup.py - -- remove_nose.patch: Remove the nose dependency (not actually used) diff --git a/build/pkgs/polymake/checksums.ini b/build/pkgs/polymake/checksums.ini index e059b0e2bbd..081ea86bc52 100644 --- a/build/pkgs/polymake/checksums.ini +++ b/build/pkgs/polymake/checksums.ini @@ -1,5 +1,5 @@ tarball=polymake-VERSION-minimal.tar.bz2 -sha1=5370b16300ff8aed4eb5fa6bb5232d25935e6303 -md5=8f6a8e87e3b8bf5ccf22f26790a4dd1a -cksum=1398515202 +sha1=d50dff3f2124a22563cc468f104c360b81a2c59d +md5=8785d6fca67ef7becad6600dad0fefaf +cksum=1451222436 upstream_url=https://polymake.org/lib/exe/fetch.php/download/polymake-VERSION-minimal.tar.bz2 diff --git a/build/pkgs/polymake/package-version.txt b/build/pkgs/polymake/package-version.txt index 515be8f918d..4caecc733e6 100644 --- a/build/pkgs/polymake/package-version.txt +++ b/build/pkgs/polymake/package-version.txt @@ -1 +1 @@ -4.4 +4.5 diff --git a/build/pkgs/polymake/type b/build/pkgs/polymake/type index 9839eb20815..134d9bc32d5 100644 --- a/build/pkgs/polymake/type +++ b/build/pkgs/polymake/type @@ -1 +1 @@ -experimental +optional diff --git a/build/pkgs/ppl/SPKG.rst b/build/pkgs/ppl/SPKG.rst index 90f9f264b8e..53f1e8df54e 100644 --- a/build/pkgs/ppl/SPKG.rst +++ b/build/pkgs/ppl/SPKG.rst @@ -41,20 +41,3 @@ Core Development Team - Roberto Bagnara (University of Parma) - Patricia M. Hill (University of Parma) - Enea Zaffanella (University of Parma) - -Dependencies ------------- - -- gmp (or mpir) - - -Special Update/Build Instructions ---------------------------------- - -Patches -~~~~~~~ - -- ptrdiff_t-ppl-1.1.patch: Fixes to compile with gcc 4.9; C++ name - lookup issue. - -- weak.patch: disable use of weak symbols on Cygwin64. diff --git a/build/pkgs/ppl/spkg-configure.m4 b/build/pkgs/ppl/spkg-configure.m4 index d2538903714..2f986f12168 100644 --- a/build/pkgs/ppl/spkg-configure.m4 +++ b/build/pkgs/ppl/spkg-configure.m4 @@ -1,5 +1,5 @@ SAGE_SPKG_CONFIGURE([ppl], [ - SAGE_SPKG_DEPCHECK([gcc glpk gmp mpir], [ + SAGE_SPKG_DEPCHECK([gcc glpk gmp], [ # If our dependencies come from the system, then we can use the # system ppl, too. This macro works sort-of like the # PKG_CHECK_MODULES macro, defining e.g. PPL_CFLAGS when a diff --git a/build/pkgs/ppl/spkg-install.in b/build/pkgs/ppl/spkg-install.in index aed909ced26..bc570b95cfc 100644 --- a/build/pkgs/ppl/spkg-install.in +++ b/build/pkgs/ppl/spkg-install.in @@ -1,4 +1,4 @@ -# Make sure that we prefer Sage's mpir library over system-wide gmp/mpir installs +# Make sure that we prefer Sage's gmp library over system-wide gmp installs export CXXFLAGS="$CXXFLAGS -I$SAGE_LOCAL/include" cd src diff --git a/build/pkgs/python3/spkg-build.in b/build/pkgs/python3/spkg-build.in index c8c02917cbc..e45e4805ff6 100644 --- a/build/pkgs/python3/spkg-build.in +++ b/build/pkgs/python3/spkg-build.in @@ -84,8 +84,24 @@ sdh_configure --enable-shared $PYTHON_CONFIGURE # Make sure -L. is placed before -L$SAGE_LOCAL/lib so that python and extension # modules are linked with the right libpython; we pass this in at make time # only, since we don't want -L. to be saved as one of the default LDFLAGS -# used for building third-party extension modules -sdh_make LDFLAGS="-L. $LDFLAGS" +# used for building third-party extension modules. +# +# Trac #32442: As we now install python in SAGE_VENV, not SAGE_LOCAL, +# we need to provide paths into $SAGE_LOCAL, so that setup.py finds +# the libraries needed for the extension modules - in particular sqlite3. +# (The search code there does not know about CPATH and LIBRARY_PATH.) +make_LDFLAGS="-L. -L$SAGE_LOCAL/lib $LDFLAGS" +make_CPPFLAGS="-I$SAGE_LOCAL/include $CPPFLAGS" + +# Also, we need to add an rpath, like we do for SAGE_LOCAL in src/bin/sage-env. +# SAGE_INST_LOCAL is the installation hierarchy for the current package +# -- for python3, this is SAGE_VENV. +make_LDFLAGS="-Wl,-rpath,$SAGE_INST_LOCAL/lib $make_LDFLAGS" +if [ "$UNAME" = "Linux" ]; then + make_LDFLAGS="-Wl,-rpath-link,$SAGE_INST_LOCAL/lib $make_LDFLAGS" +fi + +sdh_make LDFLAGS="$make_LDFLAGS" CPPFLAGS="$make_CPPFLAGS" if [ "$UNAME" = "Darwin" ]; then export DYLD_LIBRARY_PATH="." diff --git a/build/pkgs/python3/spkg-configure.m4 b/build/pkgs/python3/spkg-configure.m4 index 9cb396d0c81..df740192aca 100644 --- a/build/pkgs/python3/spkg-configure.m4 +++ b/build/pkgs/python3/spkg-configure.m4 @@ -119,6 +119,17 @@ To build Sage with a different system python, use ./configure --with-python=/pat ]) AC_SUBST([PYTHON_FOR_VENV]) + AS_VAR_IF([SAGE_VENV], [auto], [SAGE_VENV=$SAGE_VENV_AUTO]) + AS_CASE([$SAGE_VENV], + [no], [SAGE_VENV='${SAGE_LOCAL}'],dnl Quoted so that it is resolved at build time by shell/Makefile + [yes], [AS_IF([test -n "$PYTHON_FOR_VENV"], [ + PYTHON_VERSION=$("$PYTHON_FOR_VENV" -c "import sysconfig; print(sysconfig.get_python_version())") + ], [ + PYTHON_VERSION=$(echo $(cat build/pkgs/python3/package-version.txt)) + ]) + SAGE_VENV='${SAGE_LOCAL}'/var/lib/sage/venv-python$PYTHON_VERSION] + ) + dnl These temporary directories are created by the check above dnl and need to be cleaned up to prevent the "rm -f conftest*" dnl (that a bunch of other checks do) from emitting warnings about diff --git a/build/pkgs/ratpoints/SPKG.rst b/build/pkgs/ratpoints/SPKG.rst index 34616de3437..6607094bec9 100644 --- a/build/pkgs/ratpoints/SPKG.rst +++ b/build/pkgs/ratpoints/SPKG.rst @@ -19,16 +19,6 @@ Upstream Contact - Email: Michael.Stoll@uni-bayreuth.de - Website: http://www.mathe2.uni-bayreuth.de/stoll/programs/ -Dependencies ------------- - -- GMP/MPIR -- (GNU) patch - - -Special Update/Build Instructions ---------------------------------- - Note on SSE2 instructions ~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/build/pkgs/sagelib/package-version.txt b/build/pkgs/sagelib/package-version.txt index 173833eaf87..3fe69eb5038 100644 --- a/build/pkgs/sagelib/package-version.txt +++ b/build/pkgs/sagelib/package-version.txt @@ -1 +1 @@ -9.5.beta3 +9.5.beta4 diff --git a/build/pkgs/setuptools_scm/checksums.ini b/build/pkgs/setuptools_scm/checksums.ini index 10f9425e48f..a5c492c3e2f 100644 --- a/build/pkgs/setuptools_scm/checksums.ini +++ b/build/pkgs/setuptools_scm/checksums.ini @@ -1,5 +1,5 @@ tarball=setuptools_scm-VERSION.tar.gz -sha1=6d793de55ec500f7516802830f903cbc460a7999 -md5=7e17d25fd5bc5b128cfe2964a2e4cd5b -cksum=1288889703 +sha1=a4f02fddae697614e356cadfddb6241cc7737f38 +md5=32918d8ac566360c21411e0b3556c695 +cksum=1450556136 upstream_url=https://pypi.io/packages/source/s/setuptools_scm/setuptools_scm-VERSION.tar.gz diff --git a/build/pkgs/setuptools_scm/package-version.txt b/build/pkgs/setuptools_scm/package-version.txt index dc0208aba8e..91e4a9f2622 100644 --- a/build/pkgs/setuptools_scm/package-version.txt +++ b/build/pkgs/setuptools_scm/package-version.txt @@ -1 +1 @@ -6.3.1 +6.3.2 diff --git a/build/pkgs/singular/SPKG.rst b/build/pkgs/singular/SPKG.rst index eed2b57980d..f8bf274b4e2 100644 --- a/build/pkgs/singular/SPKG.rst +++ b/build/pkgs/singular/SPKG.rst @@ -20,16 +20,6 @@ libsingular-devel@mathematik.uni-kl.de https://www.singular.uni-kl.de/ -Dependencies ------------- - -- GNU patch -- readline -- GMP/MPIR -- MPFR -- NTL -- FLINT - Special Update/Build Instructions --------------------------------- diff --git a/build/pkgs/sphinx/install-requires.txt b/build/pkgs/sphinx/install-requires.txt index 2d146f2fe48..0c661b6c6c1 100644 --- a/build/pkgs/sphinx/install-requires.txt +++ b/build/pkgs/sphinx/install-requires.txt @@ -1 +1 @@ -sphinx >=4, <4.2 +sphinx >=4, <4.3 diff --git a/build/pkgs/sqlite/checksums.ini b/build/pkgs/sqlite/checksums.ini index 72262b7523c..5cb33394ab3 100644 --- a/build/pkgs/sqlite/checksums.ini +++ b/build/pkgs/sqlite/checksums.ini @@ -1,4 +1,5 @@ -tarball=sqlite-autoconf-VERSION.tar.gz -sha1=053d8237eb9741b0e297073810668c2611a8e38e -md5=8f3dfe83387e62ecb91c7c5c09c688dc -cksum=1918823569 +tarball=sqlite-autoconf-3360000.tar.gz +sha1=a4bcf9e951bfb9745214241ba08476299fc2dc1e +md5=f5752052fc5b8e1b539af86a3671eac7 +cksum=763219165 +upstream_url=https://www.sqlite.org/2021/sqlite-autoconf-3360000.tar.gz diff --git a/build/pkgs/sqlite/package-version.txt b/build/pkgs/sqlite/package-version.txt index b4456b4138a..0b477b458f2 100644 --- a/build/pkgs/sqlite/package-version.txt +++ b/build/pkgs/sqlite/package-version.txt @@ -1 +1 @@ -3290000 +3.36.0 diff --git a/build/pkgs/sqlite/spkg-install.in b/build/pkgs/sqlite/spkg-install.in index f20e4ecdb23..d13df2ba1b8 100644 --- a/build/pkgs/sqlite/spkg-install.in +++ b/build/pkgs/sqlite/spkg-install.in @@ -2,17 +2,10 @@ rm -f "$SAGE_LOCAL/bin/sqlite3" cd src -# Use newer version of config.guess and config.sub (see Trac #19711) -cp "$SAGE_ROOT"/config/config.* . - - export CPPFLAGS="$CPPFLAGS -I$SAGE_LOCAL/include" -# Old OS X systems need -DSQLITE_WITHOUT_ZONEMALLOC -if uname -sr |grep 'Darwin [0-8][.]' >/dev/null; then - export CPPFLAGS="$CPPFLAGS -DSQLITE_WITHOUT_ZONEMALLOC" -fi - +# Trac #32646: configure script does not have --disable-maintainer-mode +touch configure */configure Makefile.in sdh_configure sdh_make diff --git a/build/pkgs/symengine/checksums.ini b/build/pkgs/symengine/checksums.ini index b5600d35000..712c4eddb90 100644 --- a/build/pkgs/symengine/checksums.ini +++ b/build/pkgs/symengine/checksums.ini @@ -1,5 +1,5 @@ tarball=symengine-VERSION.tar.gz -sha1=a4d30b3c417c3939383384b95c8b3c248e4e413e -md5=72b8f1442fd3084c96e59d9fe87eec1a -cksum=3356860163 +sha1=87a0104d8682cb2f192d8b4bf3435a514bdb6f4c +md5=967b913b365eda9fb30ecb3f1ded46f2 +cksum=2359123828 upstream_url=https://github.com/symengine/symengine/releases/download/vVERSION/symengine-VERSION.tar.gz diff --git a/build/pkgs/symengine/package-version.txt b/build/pkgs/symengine/package-version.txt index faef31a4357..6f4eebdf6f6 100644 --- a/build/pkgs/symengine/package-version.txt +++ b/build/pkgs/symengine/package-version.txt @@ -1 +1 @@ -0.7.0 +0.8.1 diff --git a/build/pkgs/symengine/patches/1749.patch b/build/pkgs/symengine/patches/1749.patch deleted file mode 100644 index 40ff66b1856..00000000000 --- a/build/pkgs/symengine/patches/1749.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 713c096527291b24a8bee47895859f202b6eaa92 Mon Sep 17 00:00:00 2001 -From: Isuru Fernando -Date: Sat, 20 Mar 2021 13:33:17 -0500 -Subject: [PATCH] Check for flint-arb - ---- - cmake/FindARB.cmake | 2 +- - cmake/LibFindMacros.cmake | 4 ++-- - 2 files changed, 3 insertions(+), 3 deletions(-) - -diff --git a/cmake/FindARB.cmake b/cmake/FindARB.cmake -index 770da3133..281c5beae 100644 ---- a/cmake/FindARB.cmake -+++ b/cmake/FindARB.cmake -@@ -1,7 +1,7 @@ - include(LibFindMacros) - - libfind_include(arb.h arb) --libfind_library(arb arb) -+libfind_library(arb arb flint-arb) - - set(ARB_LIBRARIES ${ARB_LIBRARY}) - set(ARB_INCLUDE_DIRS ${ARB_INCLUDE_DIR}) -diff --git a/cmake/LibFindMacros.cmake b/cmake/LibFindMacros.cmake -index 68fcaa426..06aa3f5ba 100644 ---- a/cmake/LibFindMacros.cmake -+++ b/cmake/LibFindMacros.cmake -@@ -28,7 +28,7 @@ function (libfind_library libname pkg) - - find_library(${LIBNAME}_LIBRARY - NAMES -- ${libname} -+ ${libname} ${ARGN} - ) - - if (NOT TARGET ${libname}) -@@ -42,6 +42,6 @@ function (libfind_include HEADER pkg) - - find_path(${PKG}_INCLUDE_DIR - NAMES -- ${HEADER} -+ ${HEADER} ${ARGN} - ) - endfunction() diff --git a/build/pkgs/symengine_py/checksums.ini b/build/pkgs/symengine_py/checksums.ini index 00b39b8e687..3b0db282ffa 100644 --- a/build/pkgs/symengine_py/checksums.ini +++ b/build/pkgs/symengine_py/checksums.ini @@ -1,5 +1,5 @@ tarball=symengine.py-VERSION.tar.gz -sha1=8535fea222d85c5afefc5122dd5d43d91aa4ebb0 -md5=0167a0081410be856edc8ee245005576 -cksum=4011943203 +sha1=16da67020baf6ab95cd517f58618fa7af1c8fc5e +md5=1c365dd039f8568b732c39fa4c9a7cf4 +cksum=3244910588 upstream_url=https://github.com/symengine/symengine.py/archive/vVERSION.tar.gz diff --git a/build/pkgs/symengine_py/dependencies b/build/pkgs/symengine_py/dependencies index 1b773295978..a48b85c68e8 100644 --- a/build/pkgs/symengine_py/dependencies +++ b/build/pkgs/symengine_py/dependencies @@ -1,4 +1,4 @@ -symengine $(PYTHON) | cmake cython $(PYTHON_TOOLCHAIN) $(and $(filter-out no,$(SAGE_CHECK_symengine_py)), nose) +symengine $(PYTHON) | cmake cython $(PYTHON_TOOLCHAIN) $(and $(filter-out no,$(SAGE_CHECK_symengine_py)), pytest) ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/symengine_py/package-version.txt b/build/pkgs/symengine_py/package-version.txt index 5d8391e20f4..25329dc9cba 100644 --- a/build/pkgs/symengine_py/package-version.txt +++ b/build/pkgs/symengine_py/package-version.txt @@ -1 +1 @@ -0.7.0.post2 +0.8.1.p0 diff --git a/build/pkgs/symengine_py/patches/0001-Fix-getting-string-representation-of-sage-objects.patch b/build/pkgs/symengine_py/patches/0001-Fix-getting-string-representation-of-sage-objects.patch new file mode 100644 index 00000000000..78c71610b53 --- /dev/null +++ b/build/pkgs/symengine_py/patches/0001-Fix-getting-string-representation-of-sage-objects.patch @@ -0,0 +1,118 @@ +From 68c90c14ae3e779b88a513195cc89db599d10efb Mon Sep 17 00:00:00 2001 +From: Isuru Fernando +Date: Fri, 1 Oct 2021 19:25:07 -0700 +Subject: [PATCH] Fix getting string representation of sage objects + +--- + symengine/lib/pywrapper.cpp | 17 ++++++----------- + symengine/lib/symengine_wrapper.pyx | 9 ++++++--- + symengine/tests/test_sage.py | 10 +++------- + symengine/tests/test_sympy_conv.py | 1 + + 4 files changed, 16 insertions(+), 21 deletions(-) + +diff --git a/symengine/lib/pywrapper.cpp b/symengine/lib/pywrapper.cpp +index ca7b7c1..c321ea3 100644 +--- a/symengine/lib/pywrapper.cpp ++++ b/symengine/lib/pywrapper.cpp +@@ -175,17 +175,12 @@ RCP PyNumber::eval(long bits) const { + } + + std::string PyNumber::__str__() const { +- PyObject* temp; +- std::string str; +-#if PY_MAJOR_VERSION > 2 +- temp = PyUnicode_AsUTF8String(pyobject_); +- str = std::string(PyBytes_AsString(temp)); +-#else +- temp = PyObject_Str(pyobject_); +- str = std::string(PyString_AsString(temp)); +-#endif +- Py_XDECREF(temp); +- return str; ++ Py_ssize_t size; ++ PyObject *pystr = PyObject_Str(pyobject_); ++ const char* data = PyUnicode_AsUTF8AndSize(pystr, &size); ++ std::string result = std::string(data, size); ++ Py_XDECREF(pystr); ++ return result; + } + + // PyFunctionClass +diff --git a/symengine/lib/symengine_wrapper.pyx b/symengine/lib/symengine_wrapper.pyx +index d178afe..d18c058 100644 +--- a/symengine/lib/symengine_wrapper.pyx ++++ b/symengine/lib/symengine_wrapper.pyx +@@ -2690,7 +2690,7 @@ class FunctionSymbol(Function): + def _sage_(self): + import sage.all as sage + name = self.get_name() +- return sage.function(name, *self.args_as_sage()) ++ return sage.function(name)(*self.args_as_sage()) + + def func(self, *values): + name = self.get_name() +@@ -2711,7 +2711,7 @@ cdef rcp_const_basic pynumber_to_symengine(PyObject* o1): + + cdef PyObject* symengine_to_sage(rcp_const_basic o1): + import sage.all as sage +- t = sage.SR(c2py(o1)._sage_()) ++ t = c2py(o1)._sage_() + Py_XINCREF(t) + return (t) + +@@ -2765,7 +2765,10 @@ cdef class PyNumber(Number): + + def _sage_(self): + import sage.all as sage +- return sage.SR(self.pyobject()) ++ res = self.pyobject() ++ if hasattr(res, '_sage_'): ++ return res._sage_() ++ return res + + def pyobject(self): + return deref(symengine.rcp_static_cast_PyNumber(self.thisptr)).get_py_object() +diff --git a/symengine/tests/test_sage.py b/symengine/tests/test_sage.py +index 3b994ab..e364bd6 100644 +--- a/symengine/tests/test_sage.py ++++ b/symengine/tests/test_sage.py +@@ -66,9 +66,9 @@ def test_sage_conversions(): + assert cos(x1)._sage_() == sage.cos(x) + assert cos(x1) == sympify(sage.cos(x)) + +- assert function_symbol('f', x1, y1)._sage_() == sage.function('f', x, y) ++ assert function_symbol('f', x1, y1)._sage_() == sage.function('f')(x, y) + assert (function_symbol('f', 2 * x1, x1 + y1).diff(x1)._sage_() == +- sage.function('f', 2 * x, x + y).diff(x)) ++ sage.function('f')(2 * x, x + y).diff(x)) + + assert LambertW(x1) == LambertW(x) + assert LambertW(x1)._sage_() == sage.lambert_w(x) +@@ -142,11 +142,7 @@ def test_sage_conversions(): + b = b + 8 + assert isinstance(b, PyNumber) + assert b._sage_() == a +- +- a = a + x +- b = b + x +- assert isinstance(b, Add) +- assert b._sage_() == a ++ assert str(a) == str(b) + + # Sage Function + e = x1 + wrap_sage_function(sage.log_gamma(x)) +diff --git a/symengine/tests/test_sympy_conv.py b/symengine/tests/test_sympy_conv.py +index 3f8b152..ee070a8 100644 +--- a/symengine/tests/test_sympy_conv.py ++++ b/symengine/tests/test_sympy_conv.py +@@ -760,6 +760,7 @@ def test_pynumber(): + assert isinstance(b, PyNumber) + assert b == a # Check equality via SymEngine + assert a == b # Check equality via SymPy ++ assert str(a) == str(b) + + a = 1 - a + b = 1 - b +-- +2.7.4 + diff --git a/build/pkgs/symengine_py/spkg-check.in b/build/pkgs/symengine_py/spkg-check.in index fba8e388486..5ead50de889 100644 --- a/build/pkgs/symengine_py/spkg-check.in +++ b/build/pkgs/symengine_py/spkg-check.in @@ -1,3 +1,7 @@ cd src -nosetests symengine/tests -v +# since the module is not built in place, go to a new directory +mkdir empty +cd empty + +python3 ../bin/test_python.py diff --git a/build/pkgs/toml/spkg-configure.m4 b/build/pkgs/toml/spkg-configure.m4 new file mode 100644 index 00000000000..0dbc722cde5 --- /dev/null +++ b/build/pkgs/toml/spkg-configure.m4 @@ -0,0 +1,7 @@ +SAGE_SPKG_CONFIGURE([toml], [ + sage_spkg_install_toml=yes + ], [dnl REQUIRED-CHECK + AC_REQUIRE([SAGE_SPKG_CONFIGURE_TOX]) + dnl toml is only needed when we cannot use system tox. + AS_VAR_SET([SPKG_REQUIRE], [$sage_spkg_install_tox]) + ]) diff --git a/build/pkgs/tomli/dependencies b/build/pkgs/tomli/dependencies index 31b6d3bd71c..7cd1e28759d 100644 --- a/build/pkgs/tomli/dependencies +++ b/build/pkgs/tomli/dependencies @@ -1,4 +1,4 @@ -$(PYTHON) | pip flit_core toml +$(PYTHON) | pip flit_core ---------- All lines of this file are ignored except the first. diff --git a/build/pkgs/tomli/spkg-install.in b/build/pkgs/tomli/spkg-install.in index 37ac1a53437..e62010cea1e 100644 --- a/build/pkgs/tomli/spkg-install.in +++ b/build/pkgs/tomli/spkg-install.in @@ -1,2 +1,4 @@ cd src +# tomli's build system, flit_core, has a runtime dependency on tomli. +export PYTHONPATH="$(pwd)" sdh_pip_install . diff --git a/build/pkgs/yasm/SPKG.rst b/build/pkgs/yasm/SPKG.rst deleted file mode 100644 index 0e1de168678..00000000000 --- a/build/pkgs/yasm/SPKG.rst +++ /dev/null @@ -1,41 +0,0 @@ -yasm: An assembler for the x86 and AMD64 instruction sets -========================================================= - -Description ------------ - -Yasm is a complete rewrite of the NASM assembler under the “new” BSD -License (some portions are under other licenses, see COPYING for -details). - -Yasm currently supports the x86 and AMD64 instruction sets, accepts NASM -and GAS assembler syntaxes, outputs binary, ELF32, ELF64, 32 and 64-bit -Mach-O, RDOFF2, COFF, Win32, and Win64 object formats, and generates -source debugging information in STABS, DWARF 2, and CodeView 8 formats. - -Yasm can be easily integrated into Visual Studio 2005/2008 and 2010 for -assembly of NASM or GAS syntax code into Win32 or Win64 object files. - -See https://yasm.tortall.net - -License -------- - -Yasm is licensed under the 2-clause and 3-clause “revised” BSD licenses, -with one exception: the Bit::Vector module used by the mainline version -of Yasm to implement its large integer and machine-independent floating -point support is triple-licensed under the Artistic license, GPL, and -LGPL. The “yasm-nextgen” codebase uses a different BSD-licensed -implementation and is thus entirely under BSD-equivalent licenses. The -full text of the licenses are provided in the Yasm source distribution. - - -Upstream Contact ----------------- - -- https://yasm.tortall.net - -Dependencies ------------- - -- none diff --git a/build/pkgs/yasm/checksums.ini b/build/pkgs/yasm/checksums.ini deleted file mode 100644 index 5889d0ce114..00000000000 --- a/build/pkgs/yasm/checksums.ini +++ /dev/null @@ -1,4 +0,0 @@ -tarball=yasm-VERSION.tar.gz -sha1=b7574e9f0826bedef975d64d3825f75fbaeef55e -md5=fc9e586751ff789b34b1f21d572d96af -cksum=3388492465 diff --git a/build/pkgs/yasm/dependencies b/build/pkgs/yasm/dependencies deleted file mode 100644 index 2f9f3849682..00000000000 --- a/build/pkgs/yasm/dependencies +++ /dev/null @@ -1 +0,0 @@ -# no dependencies diff --git a/build/pkgs/yasm/distros/alpine.txt b/build/pkgs/yasm/distros/alpine.txt deleted file mode 100644 index eff8d5c7abd..00000000000 --- a/build/pkgs/yasm/distros/alpine.txt +++ /dev/null @@ -1 +0,0 @@ -yasm diff --git a/build/pkgs/yasm/distros/conda.txt b/build/pkgs/yasm/distros/conda.txt deleted file mode 100644 index eff8d5c7abd..00000000000 --- a/build/pkgs/yasm/distros/conda.txt +++ /dev/null @@ -1 +0,0 @@ -yasm diff --git a/build/pkgs/yasm/distros/cygwin.txt b/build/pkgs/yasm/distros/cygwin.txt deleted file mode 100644 index eff8d5c7abd..00000000000 --- a/build/pkgs/yasm/distros/cygwin.txt +++ /dev/null @@ -1 +0,0 @@ -yasm diff --git a/build/pkgs/yasm/distros/debian.txt b/build/pkgs/yasm/distros/debian.txt deleted file mode 100644 index eff8d5c7abd..00000000000 --- a/build/pkgs/yasm/distros/debian.txt +++ /dev/null @@ -1 +0,0 @@ -yasm diff --git a/build/pkgs/yasm/distros/fedora.txt b/build/pkgs/yasm/distros/fedora.txt deleted file mode 100644 index eff8d5c7abd..00000000000 --- a/build/pkgs/yasm/distros/fedora.txt +++ /dev/null @@ -1 +0,0 @@ -yasm diff --git a/build/pkgs/yasm/distros/freebsd.txt b/build/pkgs/yasm/distros/freebsd.txt deleted file mode 100644 index d04eee4fbc4..00000000000 --- a/build/pkgs/yasm/distros/freebsd.txt +++ /dev/null @@ -1 +0,0 @@ -devel/yasm diff --git a/build/pkgs/yasm/distros/homebrew.txt b/build/pkgs/yasm/distros/homebrew.txt deleted file mode 100644 index eff8d5c7abd..00000000000 --- a/build/pkgs/yasm/distros/homebrew.txt +++ /dev/null @@ -1 +0,0 @@ -yasm diff --git a/build/pkgs/yasm/distros/macports.txt b/build/pkgs/yasm/distros/macports.txt deleted file mode 100644 index eff8d5c7abd..00000000000 --- a/build/pkgs/yasm/distros/macports.txt +++ /dev/null @@ -1 +0,0 @@ -yasm diff --git a/build/pkgs/yasm/distros/opensuse.txt b/build/pkgs/yasm/distros/opensuse.txt deleted file mode 100644 index eff8d5c7abd..00000000000 --- a/build/pkgs/yasm/distros/opensuse.txt +++ /dev/null @@ -1 +0,0 @@ -yasm diff --git a/build/pkgs/yasm/distros/repology.txt b/build/pkgs/yasm/distros/repology.txt deleted file mode 100644 index eff8d5c7abd..00000000000 --- a/build/pkgs/yasm/distros/repology.txt +++ /dev/null @@ -1 +0,0 @@ -yasm diff --git a/build/pkgs/yasm/distros/slackware.txt b/build/pkgs/yasm/distros/slackware.txt deleted file mode 100644 index eff8d5c7abd..00000000000 --- a/build/pkgs/yasm/distros/slackware.txt +++ /dev/null @@ -1 +0,0 @@ -yasm diff --git a/build/pkgs/yasm/distros/void.txt b/build/pkgs/yasm/distros/void.txt deleted file mode 100644 index eff8d5c7abd..00000000000 --- a/build/pkgs/yasm/distros/void.txt +++ /dev/null @@ -1 +0,0 @@ -yasm diff --git a/build/pkgs/yasm/package-version.txt b/build/pkgs/yasm/package-version.txt deleted file mode 100644 index 05749212e36..00000000000 --- a/build/pkgs/yasm/package-version.txt +++ /dev/null @@ -1 +0,0 @@ -1.3.0.p0 diff --git a/build/pkgs/yasm/spkg-check.in b/build/pkgs/yasm/spkg-check.in deleted file mode 100644 index ae888d81474..00000000000 --- a/build/pkgs/yasm/spkg-check.in +++ /dev/null @@ -1,5 +0,0 @@ -cd src - -# -j1 needed to avoid a possible race condition in the tests -# see https://trac.sagemath.org/ticket/23217 -$MAKE -j1 check diff --git a/build/pkgs/yasm/spkg-configure.m4 b/build/pkgs/yasm/spkg-configure.m4 deleted file mode 100644 index bc85c7ce45c..00000000000 --- a/build/pkgs/yasm/spkg-configure.m4 +++ /dev/null @@ -1,20 +0,0 @@ -SAGE_SPKG_CONFIGURE( - [yasm], - # Yasm is only needed on x86(_64) systems; check also for system yasm which - # must support "adox" (new Skylake instruction) - [AC_MSG_CHECKING([for yasm supporting the adox instruction]) - AC_PATH_PROGS_FEATURE_CHECK([YASM], [yasm], - [[{ echo "BITS 64"; echo "adox rax, rax"; } | ${ac_path_YASM} - -o /dev/null >/dev/null 2>/dev/null && - ac_cv_path_YASM=${ac_path_YASM} && - ac_path_YASM_found=: - ]], - [sage_spkg_install_yasm=yes; ac_cv_path_YASM=no]) - AC_MSG_RESULT($ac_cv_path_YASM)], - [dnl REQUIRED-CHECK - AS_CASE("$host_cpu", [i@<:@0-9@:>@86|x86_64|amd64], [], [sage_require_yasm=no]) - AC_REQUIRE([SAGE_SPKG_CONFIGURE_MPIR]) - AS_IF([test x$sage_spkg_install_mpir = xno], [ - sage_require_yasm=no - ]) - ] -) diff --git a/build/pkgs/yasm/spkg-install.in b/build/pkgs/yasm/spkg-install.in deleted file mode 100644 index a863950189e..00000000000 --- a/build/pkgs/yasm/spkg-install.in +++ /dev/null @@ -1,5 +0,0 @@ -cd src - -sdh_configure -sdh_make -sdh_make_install diff --git a/build/pkgs/yasm/type b/build/pkgs/yasm/type deleted file mode 100644 index a6a7b9cd726..00000000000 --- a/build/pkgs/yasm/type +++ /dev/null @@ -1 +0,0 @@ -standard diff --git a/build/pkgs/zn_poly/spkg-configure.m4 b/build/pkgs/zn_poly/spkg-configure.m4 index ba3fd95a96a..c3e47c7621b 100644 --- a/build/pkgs/zn_poly/spkg-configure.m4 +++ b/build/pkgs/zn_poly/spkg-configure.m4 @@ -1,5 +1,5 @@ SAGE_SPKG_CONFIGURE([zn_poly], [ - SAGE_SPKG_DEPCHECK([gmp mpir], [ + SAGE_SPKG_DEPCHECK([gmp], [ AC_CHECK_HEADER([zn_poly/zn_poly.h], [ AC_SEARCH_LIBS([zn_mod_init], [zn_poly], [ ], [sage_spkg_install_zn_poly=yes]) diff --git a/configure.ac b/configure.ac index 0e092a93853..42d6afdc8f6 100644 --- a/configure.ac +++ b/configure.ac @@ -70,15 +70,24 @@ SAGE_LOCAL="$prefix" # This is nonstandard. if test "$SAGE_LOCAL" = NONE; then SAGE_LOCAL=local + if test -x "$SAGE_LOCAL"/bin/python3; then + # Incremental build with an existing installation of python3 spkg + # in SAGE_LOCAL or venv in SAGE_LOCAL. Keep old behavior. + SAGE_VENV_AUTO=no + else + SAGE_VENV_AUTO=yes + fi +else + SAGE_VENV_AUTO=no fi SAGE_SRC="$SAGE_ROOT/src" SAGE_SPKG_INST="$SAGE_LOCAL/var/lib/sage/installed" AC_ARG_WITH([sage-venv], - [AS_HELP_STRING([--with-sage-venv=SAGE_VENV], + [AS_HELP_STRING([--with-sage-venv={auto (default),yes,no,SAGE_VENV}], [put Python packages into an installation hierarchy separate from prefix])], [SAGE_VENV="$withval"], - [SAGE_VENV='${SAGE_LOCAL}'])dnl Quoted so that it is resolved at build time by shell/Makefile + [SAGE_VENV="auto"]) AC_SUBST([SAGE_VENV]) #--------------------------------------------------------- @@ -493,6 +502,29 @@ AC_CONFIG_COMMANDS(mkdirs, SAGE_INST="$SAGE_SPKG_INST" ]) +AC_CONFIG_COMMANDS(links, [ + dnl Create links for the convenience of users + SYMLINK="${ac_top_build_prefix}prefix" + AS_IF([test -L "$SYMLINK" -o ! -e "$SYMLINK"], [ + AC_MSG_NOTICE([creating convenience symlink $SYMLINK -> $SAGE_LOCAL]) + rm -f "$SYMLINK" + ln -sf "$SAGE_LOCAL" "$SYMLINK" + ], [ + AC_MSG_NOTICE([cannot create convenience symlink $SYMLINK -> $SAGE_LOCAL because the file exists and is not a symlink; this is harmless]) + ]) + SYMLINK="${ac_top_build_prefix}venv" + AS_IF([test -L "$SYMLINK" -o ! -e "$SYMLINK"], [ + AC_MSG_NOTICE([creating convenience symlink $SYMLINK -> $SAGE_VENV]) + rm -f "$SYMLINK" + ln -sf "$SAGE_VENV" "$SYMLINK" + ], [ + AC_MSG_NOTICE([cannot create convenience symlink $SYMLINK -> $SAGE_VENV because the file exists and is not a symlink; this is harmless]) + ]) +], [ + SAGE_LOCAL="$SAGE_LOCAL" + eval SAGE_VENV="$SAGE_VENV"dnl eval so as to evaluate the embedded ${SAGE_LOCAL} +]) + AC_OUTPUT() SAGE_SYSTEM_PACKAGE_NOTICE() diff --git a/m4/sage_spkg_collect.m4 b/m4/sage_spkg_collect.m4 index 70e0a70d12a..e6dcecdd24c 100644 --- a/m4/sage_spkg_collect.m4 +++ b/m4/sage_spkg_collect.m4 @@ -144,7 +144,36 @@ for DIR in $SAGE_ROOT/build/pkgs/*; do SPKG_NAME=$(basename $DIR) SPKG_VERSION=$(newest_version $SPKG_NAME) - in_sdist=no + in_sdist=yes + + dnl Determine package source + dnl + if test -f "$DIR/requirements.txt"; then + SPKG_SOURCE=pip + # Since pip packages are downloaded and installed by pip, we don't + # include them in the source tarball. At the time of this writing, + # all pip packages are optional. + in_sdist=no + elif test ! -f "$DIR/checksums.ini"; then + if test -f "$DIR/spkg-install"; then + SPKG_SOURCE=script + else + dnl a dummy script package + SPKG_SOURCE=none + fi + # We assume that either (a) the sources for an optional script + # package will be downloaded by the script, or (b) that a + # standard script package's sources are already a part of the + # sage repository (and thus the release tarball). As a result, + # we don't need to download the sources, which is what + # "in_sdist" really means. At the time of this writing, the + # only standard script packages are sage_conf and sagelib. + # The sources of these packages are in subdirectories of + # $SAGE_ROOT/pkgs. + in_sdist=no + else + SPKG_SOURCE=normal + fi dnl Write out information about the installation tree, using the name of the tree prefix dnl variable (SAGE_LOCAL or SAGE_VENV). The makefile variable of SPKG is called "trees_SPKG", @@ -153,8 +182,8 @@ for DIR in $SAGE_ROOT/build/pkgs/*; do dnl Jupyter notebook, then packages such as jupyter_core would have to be installed into dnl two trees. SPKG_TREE_VAR=SAGE_LOCAL - if test -f "$DIR/requirements.txt" -o -f "$DIR/install-requires.txt"; then - dnl A Python package + if test -f "$DIR/requirements.txt" -o -f "$DIR/install-requires.txt" -o "$SPKG_NAME" = python3; then + dnl A Python package or spkg installation of python3 itself SPKG_TREE_VAR=SAGE_VENV fi SAGE_PACKAGE_TREES="${SAGE_PACKAGE_TREES}$(printf '\ntrees_')${SPKG_NAME} = ${SPKG_TREE_VAR}" @@ -177,7 +206,11 @@ for DIR in $SAGE_ROOT/build/pkgs/*; do AS_VAR_IF([SAGE_ENABLE_]${SPKG_NAME}, [yes], [ message="$SPKG_TYPE, will be installed as an SPKG" ], [ - message="$SPKG_TYPE, use \"$srcdir/configure --enable-$SPKG_NAME\" to install" + message="$SPKG_TYPE" + AS_VAR_IF([SPKG_SOURCE], [none], [], [ + dnl Non-dummy optional/experimental package, advertise how to install + message="$message, use \"$srcdir/configure --enable-$SPKG_NAME\" to install" + ]) SAGE_NEED_SYSTEM_PACKAGES_VAR=SAGE_NEED_SYSTEM_PACKAGES_OPTIONAL ]) ;; @@ -188,9 +221,9 @@ for DIR in $SAGE_ROOT/build/pkgs/*; do case "$SPKG_TYPE" in standard) - in_sdist=yes ;; optional|experimental) + in_sdist=no uninstall_message=", use \"$srcdir/configure --disable-$SPKG_NAME\" to uninstall" stampfile="" for f in "$SAGE_SPKG_INST/$SPKG_NAME"-*; do @@ -228,8 +261,12 @@ for DIR in $SAGE_ROOT/build/pkgs/*; do AS_VAR_IF([sage_spkg_install], [no], [ dnl We will use the system package (or not required for this platform.) SAGE_DUMMY_PACKAGES="${SAGE_DUMMY_PACKAGES} \\$(printf '\n ')${SPKG_NAME}" - AS_VAR_IF([sage_require], [yes], [ message="using system package; SPKG will not be installed" - ], [ message="not required on your platform; SPKG will not be installed" + AS_VAR_IF([sage_require], [yes], [ message="using system package" + ], [ message="not required on your platform" + ]) + dnl Trac #31163: Only talk about the SPKG if there is an SPKG + AS_VAR_IF([SPKG_SOURCE], [none], [], [ + message="$message; SPKG will not be installed" ]) ], [ dnl We will not use the system package. @@ -262,38 +299,6 @@ for DIR in $SAGE_ROOT/build/pkgs/*; do AS_VAR_POPDEF([sage_require])dnl AS_VAR_POPDEF([sage_spkg_install])dnl - # Packages that should be included in the source distribution - # This includes all standard packages and two special cases - case "$SPKG_NAME" in - mpir) - in_sdist=yes - ;; - esac - - # Determine package source - # - if test -f "$DIR/requirements.txt"; then - SPKG_SOURCE=pip - # Since pip packages are downloaded and installed by pip, we don't - # include them in the source tarball. At the time of this writing, - # all pip packages are optional. - in_sdist=no - elif test ! -f "$DIR/checksums.ini"; then - SPKG_SOURCE=script - # We assume that either (a) the sources for an optional script - # package will be downloaded by the script, or (b) that a - # standard script package's sources are already a part of the - # sage repository (and thus the release tarball). As a result, - # we don't need to download the sources, which is what - # "in_sdist" really means. At the time of this writing, the - # only standard script packages are sage_conf and sagelib. - # The sources of these packages are in subdirectories of - # $SAGE_ROOT/pkgs. - in_sdist=no - else - SPKG_SOURCE=normal - fi - if test "$in_sdist" = yes; then SAGE_SDIST_PACKAGES="${SAGE_SDIST_PACKAGES} \\$(printf '\n ')${SPKG_NAME}" fi @@ -341,7 +346,7 @@ for DIR in $SAGE_ROOT/build/pkgs/*; do pip) SAGE_PIP_PACKAGES="${SAGE_PIP_PACKAGES} \\$(printf '\n ')${SPKG_NAME}" ;; - script) + script|none) SAGE_SCRIPT_PACKAGES="${SAGE_SCRIPT_PACKAGES} \\$(printf '\n ')${SPKG_NAME}" ;; normal) diff --git a/m4/sage_spkg_configure.m4 b/m4/sage_spkg_configure.m4 index 968e6077134..e6aa0f3ca72 100644 --- a/m4/sage_spkg_configure.m4 +++ b/m4/sage_spkg_configure.m4 @@ -29,8 +29,8 @@ # # - REQUIRED-CHECK - this checks whether or not the package is a required # dependency of Sage at all, depending typically on the platform. Some -# packages (e.g. yasm, among others) are only dependencies on certain -# platforms, and otherwise do not need to be checked for at all. If +# packages (e.g. sqlite) are only dependencies in some circumstances +# and otherwise do not need to be checked for at all. If # a REQUIRED-CHECK determines that the package is not required it sets # sage_require_="no". # diff --git a/src/.relint.yml b/src/.relint.yml index cb1a1e5eac2..9d12054b982 100644 --- a/src/.relint.yml +++ b/src/.relint.yml @@ -8,13 +8,14 @@ # ifilter, imap, izip # __metaclass__ Hint: # update raise statements # except Exception, var Hint: # sagenb # six is no longer allowed - pattern: '(import.*[, ]ifilter|import.*[, ]imap|import.*[, ]izip|^\s*raise\s*[A-Za-z]*Error\s*,|__metaclass__|except\s*[A-Za-z]\s*,|sagenb|import six|from six import)' + pattern: '(import.*[, ]ifilter|import.*[, ]imap|import.*[, ]izip|^\s*raise\s*[A-Za-z]*Error\s*,|__metaclass__|except\s*[A-Za-z]\s*,|[^_]sagenb|import six|from six import)' filePattern: .*[.](py|pyx|rst) - name: 'foreign_latex: foreign commands in LaTeX' hint: | use equivalent LaTeX commands instead of plain TeX commands such as \over, \choose, etc. - pattern: '(\\choose|\\over[^l]|\\atop|\\above|\\overwithdelims|\\atopwithdelims|\\abovewithdelims)' + pattern: '(\\choose|\\atop|\\above|\\overwithdelims|\\atopwithdelims|\\abovewithdelims)' + # \over appears in bad latex code coming from Fricas and Maxima - name: 'blocks: wrong syntax for blocks (INPUT, OUTPUT, EXAMPLES, NOTE, etc.)' hint: | diff --git a/src/VERSION.txt b/src/VERSION.txt index 173833eaf87..3fe69eb5038 100644 --- a/src/VERSION.txt +++ b/src/VERSION.txt @@ -1 +1 @@ -9.5.beta3 +9.5.beta4 diff --git a/src/bin/sage b/src/bin/sage index 8a5bfafd8e2..fcd263029d0 100755 --- a/src/bin/sage +++ b/src/bin/sage @@ -466,7 +466,7 @@ usage_advanced() { echo " labeled \"# optional\" or labeled" echo " \"# optional tag\" for any of the tags given." echo " --randorder[=seed] -- randomize order of tests" - echo " --random-seed[=seed] -- random seed for fuzzing doctests" + echo " --random-seed[=seed] -- random seed (integer) for fuzzing doctests" echo " --new -- only test files modified since last commit" echo " --initial -- only show the first failure per block" echo " --debug -- drop into PDB after an unexpected error" diff --git a/src/bin/sage-runtests b/src/bin/sage-runtests index 4fc2062b152..d7a416185f8 100755 --- a/src/bin/sage-runtests +++ b/src/bin/sage-runtests @@ -56,7 +56,7 @@ if __name__ == "__main__": 'if "build" is listed, will also run tests specific to Sage\'s build/packaging system; ' 'if set to "all", then all tests will be run') parser.add_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 for fuzzing doctests") + parser.add_argument("--random-seed", dest="random_seed", type=int, metavar="SEED", help="random seed (integer) for fuzzing doctests") 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 750e10d31e0..1fa6283f152 100644 --- a/src/bin/sage-version.sh +++ b/src/bin/sage-version.sh @@ -1,5 +1,5 @@ # Sage version information for shell scripts # This file is auto-generated by the sage-update-version script, do not edit! -SAGE_VERSION='9.5.beta3' -SAGE_RELEASE_DATE='2021-10-11' -SAGE_VERSION_BANNER='SageMath version 9.5.beta3, Release Date: 2021-10-11' +SAGE_VERSION='9.5.beta4' +SAGE_RELEASE_DATE='2021-10-19' +SAGE_VERSION_BANNER='SageMath version 9.5.beta4, Release Date: 2021-10-19' diff --git a/src/doc/de/thematische_anleitungen/sage_gymnasium.rst b/src/doc/de/thematische_anleitungen/sage_gymnasium.rst index fa556752f01..95cc42478f5 100644 --- a/src/doc/de/thematische_anleitungen/sage_gymnasium.rst +++ b/src/doc/de/thematische_anleitungen/sage_gymnasium.rst @@ -315,13 +315,13 @@ Ausdruck:: sage: var('x') x sage: type(x*2) - + Auch eine Funktion (siehe unten) ist ein symbolischer Ausdruck:: sage: f(x) = x + 1 sage: type(f) - + Benutzen wir jedoch eine Variable, um etwas zu speichern und nicht als symbolischen Parameter, so ist ein Ausdruck, welcher sie enthält, nicht mehr ein symbolischer @@ -329,7 +329,7 @@ Ausdruck:: sage: x = 3 sage: type(x*2) - + Terme können auch in Variablen gespeichert werden. Dazu benutzen wir wie bei Zahlenwerten den Operator ``=`` für die Zuordnung:: diff --git a/src/doc/de/tutorial/interactive_shell.rst b/src/doc/de/tutorial/interactive_shell.rst index a95e8e83b53..869029fa70e 100644 --- a/src/doc/de/tutorial/interactive_shell.rst +++ b/src/doc/de/tutorial/interactive_shell.rst @@ -410,7 +410,7 @@ Zum Beispiel: Automatic pdb calling has been turned ON sage: EllipticCurve([1,infinity]) --------------------------------------------------------------------------- - Traceback (most recent call last) + Traceback (most recent call last) ... ipdb> @@ -519,7 +519,7 @@ Funktionsnamen ein ``?`` an, um die Dokumentation dazu aufzurufen. sage: V = QQ^3 sage: V.coordinates? Type: instancemethod - Base Class: + Base Class: String Form: Namespace: Interactive diff --git a/src/doc/de/tutorial/interfaces.rst b/src/doc/de/tutorial/interfaces.rst index 68e4ea2994f..edb4f383363 100644 --- a/src/doc/de/tutorial/interfaces.rst +++ b/src/doc/de/tutorial/interfaces.rst @@ -61,7 +61,7 @@ mehr referenziert wird. Die Objekte haben außerdem verschiedene Typen: sage: type(gp('znprimroot(10007)')) sage: type(pari('znprimroot(10007)')) - + Welche Variante sollten Sie also nutzen? Das kommt darauf an was Sie tun. Die GP-Schnittstelle kann alles was ein normales @@ -98,7 +98,7 @@ Zuerst erstellen wir eine PARI-Liste aus einer Python-Liste. sage: v [1, 2, 3, 4, 5] sage: type(v) - + Jedes PARI-Objekt ist vom Typ ``Gen``. Den PARI Typ des vorliegenden Objekts können Sie mit der ``type`` Unterfunktion herausfinden. diff --git a/src/doc/de/tutorial/programming.rst b/src/doc/de/tutorial/programming.rst index 236fb8e9c29..7d86c01e30b 100644 --- a/src/doc/de/tutorial/programming.rst +++ b/src/doc/de/tutorial/programming.rst @@ -396,7 +396,7 @@ Folge haben einen gemeinsamen Obertyp, der das Folgenuniversum genannt wird. sage: type(v) sage: type(v[1]) - + sage: v.universe() Rational Field sage: v.is_immutable() diff --git a/src/doc/de/tutorial/tour_advanced.rst b/src/doc/de/tutorial/tour_advanced.rst index b36e8ae8fff..7ee92b357df 100644 --- a/src/doc/de/tutorial/tour_advanced.rst +++ b/src/doc/de/tutorial/tour_advanced.rst @@ -405,6 +405,7 @@ Räumen von Modulformen zur Verfügung. Zum Beispiel, :: + sage: from sage.modular.dims import dimension_cusp_forms sage: dimension_cusp_forms(Gamma0(11),2) 1 sage: dimension_cusp_forms(Gamma0(1),12) diff --git a/src/doc/de/tutorial/tour_assignment.rst b/src/doc/de/tutorial/tour_assignment.rst index e406ab4621c..2bc72cae3e1 100644 --- a/src/doc/de/tutorial/tour_assignment.rst +++ b/src/doc/de/tutorial/tour_assignment.rst @@ -91,10 +91,10 @@ beliebigen Python-Typs innerhalb eines Sichtbarkeitsbereich aufnehmen. sage: a = 5 # a ist eine ganze Zahl sage: type(a) - + sage: a = 5/3 # jetzt ist a eine rationale Zahl sage: type(a) - + sage: a = 'hello' # jetzt ist a ein String sage: type(a) <... 'str'> diff --git a/src/doc/de/tutorial/tour_functions.rst b/src/doc/de/tutorial/tour_functions.rst index 501a2f9dbd9..18cbbf00ced 100644 --- a/src/doc/de/tutorial/tour_functions.rst +++ b/src/doc/de/tutorial/tour_functions.rst @@ -61,7 +61,7 @@ können geplottet, differenziert und integriert werden. sage: Dg(3) 6 sage: type(g) - + sage: plot(g, 0, 2) Graphics object consisting of 1 graphics primitive @@ -78,7 +78,7 @@ Erläuterung zu erhalten. sage: g(x) x^2 sage: type(g(x)) - + sage: g(x).derivative() 2*x sage: plot(g(x), 0, 2) @@ -95,7 +95,7 @@ werden. sage: plot(sin, 0, 2) Graphics object consisting of 1 graphics primitive sage: type(sin(x)) - + sage: plot(sin(x), 0, 2) Graphics object consisting of 1 graphics primitive @@ -143,7 +143,7 @@ wird, was wiederum bedeutet, dass ``x<2`` ausgewertet wird. :: sage: type(x<2) - + Wenn eine symbolische Gleichung ausgewertet wird, wie in der Definition von ``h``, wird falls sie nicht offensichtlicherweise wahr @@ -176,9 +176,9 @@ Das Problem: ``g(3)``, zum Beispiel, gibt folgenden Fehler zurück: :: sage: type(f) - + sage: type(g) - + ``g`` ist keine Funktion, es ist eine Konstante, hat also keine zugehörigen Variablen, und man kann in sie nichts einsetzen. @@ -196,7 +196,7 @@ Die Lösung: Es gibt mehrere Möglichkeiten. sage: g(3) 1 sage: type(g) - + - Oder mit der ursprünglichen Definition von ``f``, definieren Sie ``g`` als symbolischen Ausdruck. @@ -210,7 +210,7 @@ Die Lösung: Es gibt mehrere Möglichkeiten. sage: g(3) 1 sage: type(g) - + - Oder mit den ursprünglichen Definitionen von ``f`` and ``g``, geben Sie die Variable an, in diese Sie den Wert einsetzen. diff --git a/src/doc/en/constructions/interface_issues.rst b/src/doc/en/constructions/interface_issues.rst index e6cb1c30da6..efe93c7edbc 100644 --- a/src/doc/en/constructions/interface_issues.rst +++ b/src/doc/en/constructions/interface_issues.rst @@ -382,7 +382,7 @@ help interface to find the file name: sage: PermutationGroup.center? Type: instancemethod - Base Class: + Base Class: String Form: Namespace: Interactive File: /home/wdj/sage/local/lib/python2.4/site-packages/sage/groups/permgroup.py diff --git a/src/doc/en/constructions/modular_forms.rst b/src/doc/en/constructions/modular_forms.rst index 34ab41622db..7979214859d 100644 --- a/src/doc/en/constructions/modular_forms.rst +++ b/src/doc/en/constructions/modular_forms.rst @@ -4,7 +4,7 @@ Modular forms ************* -One of 's computational specialities is (the very technical field +One of SageMath's computational specialities is (the very technical field of) modular forms and can do a lot more than is even suggested in this very brief introduction. @@ -19,6 +19,7 @@ section "Modular forms" in the Tutorial: :: + sage: from sage.modular.dims import dimension_cusp_forms sage: dimension_cusp_forms(Gamma0(11),2) 1 sage: dimension_cusp_forms(Gamma0(1),12) @@ -31,8 +32,6 @@ dimensions of newforms), ``dimension_modular_forms`` (for modular forms), and ``dimension_eis`` (for Eisenstein series). The syntax is similar - see the Reference Manual for examples. -In future versions of Sage, more related commands will be added. - .. index:: cosets of Gamma_0 Coset representatives @@ -115,6 +114,7 @@ and related curves. Here are some examples of the syntax: :: + sage: from sage.modular.dims import dimension_cusp_forms sage: dimension_cusp_forms(Gamma0(22)) 2 sage: dimension_cusp_forms(Gamma0(30)) diff --git a/src/doc/en/developer/coding_basics.rst b/src/doc/en/developer/coding_basics.rst index 7830c674573..b264bcf3c0c 100644 --- a/src/doc/en/developer/coding_basics.rst +++ b/src/doc/en/developer/coding_basics.rst @@ -1121,9 +1121,10 @@ framework. Here is a comprehensive list: .. NOTE:: - Any words after ``# optional`` are interpreted as a list of - package names, separated by spaces. + package (spkg) names or other feature tags, separated by spaces. - - Any punctuation (periods, commas, hyphens, semicolons, ...) after the + - Any punctuation other than underscores (``_``) and periods (``.``), + that is, commas, hyphens, semicolons, ..., after the first word ends the list of packages. Hyphens or colons between the word ``optional`` and the first package name are allowed. Therefore, you should not write ``optional: needs package CHomP`` but simply diff --git a/src/doc/en/developer/coding_in_python.rst b/src/doc/en/developer/coding_in_python.rst index 1d8b7c1d3bf..aa98cbb614c 100644 --- a/src/doc/en/developer/coding_in_python.rst +++ b/src/doc/en/developer/coding_in_python.rst @@ -261,7 +261,7 @@ replacements are made: <... 'int'> sage: b = 393939 sage: type(b) - + sage: a == b True @@ -465,6 +465,33 @@ Note that the syntax in ``except`` is to list all the exceptions that are caught as a tuple, followed by an error message. +Integer Return Values +===================== + +Many functions and methods in Sage return integer values. +Those should usually be returned as Sage integers of class +:class:`Integer ` rather than +as Python integers of class :class:`int`, as users may want +to explore the resulting integers' number-theoretic properties +such as prime factorization. Exceptions should be made when +there are good reasons such as performance or compatibility +with Python code, for instance in methods such as +``__hash__``, ``__len__``, and ``__int__``. + +To return a Python integer ``i`` as a Sage integer, use: + +.. CODE-BLOCK:: python + + from sage.rings.integer import Integer + return Integer(i) + +To return a Sage integer ``i`` as a Python ineger, use: + +.. CODE-BLOCK:: python + + return int(i) + + Importing ========= diff --git a/src/doc/en/developer/doctesting.rst b/src/doc/en/developer/doctesting.rst index f5fec4590f3..e26d7329095 100644 --- a/src/doc/en/developer/doctesting.rst +++ b/src/doc/en/developer/doctesting.rst @@ -803,7 +803,33 @@ You can also pass in an explicit amount of time:: Finally, you can disable any warnings about long tests with ``--warn-long 0``. -Doctests may start from a random seed:: +Doctests start from a random seed:: + + [kliem@sage sage-9.2]$ sage -t src/sage/doctest/tests/random_seed.rst + Running doctests with ID 2020-06-23-23-22-59-49f37a55. + ... + Doctesting 1 file. + sage -t --warn-long 89.5 --random-seed=112986622569797306072457879734474628454 src/sage/doctest/tests/random_seed.rst + ********************************************************************** + File "src/sage/doctest/tests/random_seed.rst", line 3, in sage.doctest.tests.random_seed + Failed example: + randint(5, 10) + Expected: + 9 + Got: + 8 + ********************************************************************** + 1 item had failures: + 1 of 2 in sage.doctest.tests.random_seed + [1 test, 1 failure, 0.00 s] + ---------------------------------------------------------------------- + sage -t --warn-long 89.5 --random-seed=112986622569797306072457879734474628454 src/sage/doctest/tests/random_seed.rst # 1 doctest failed + ---------------------------------------------------------------------- + Total time for all tests: 0.0 seconds + cpu time: 0.0 seconds + cumulative wall time: 0.0 seconds + +This seed can be set explicitly to reproduce possible failures:: [kliem@sage sage-9.2]$ sage -t --warn-long 89.5 --random-seed=112986622569797306072457879734474628454 src/sage/doctest/tests/random_seed.rst Running doctests with ID 2020-06-23-23-24-28-14a52269. diff --git a/src/doc/en/developer/portability_testing.rst b/src/doc/en/developer/portability_testing.rst index 204c173dc52..e6a61ebeb58 100644 --- a/src/doc/en/developer/portability_testing.rst +++ b/src/doc/en/developer/portability_testing.rst @@ -220,10 +220,10 @@ Using Sage's database of equivalent distribution packages At the end of the ``./configure`` run, Sage issued a message like the following:: - configure: notice: the following SPKGs did not find equivalent system packages: arb boost boost_cropped bzip2 ... yasm zeromq zlib + configure: notice: the following SPKGs did not find equivalent system packages: arb boost_cropped bzip2 ... zeromq zlib checking for the package system in use... debian configure: hint: installing the following system packages is recommended and may avoid building some of the above SPKGs from source: - configure: $ sudo apt-get install libflint-arb-dev ... yasm libzmq3-dev libz-dev + configure: $ sudo apt-get install libflint-arb-dev ... libzmq3-dev libz-dev configure: After installation, re-run configure using: configure: $ ./config.status --recheck && ./config.status @@ -248,7 +248,7 @@ system, in particular a list of installed packages and their versions. Let us install a subset of these packages:: - root@39d693b2a75d:/sage# apt-get install libbz2-dev bzip2 yasm libz-dev + root@39d693b2a75d:/sage# apt-get install libbz2-dev bzip2 libz-dev Reading package lists... Done ... Setting up zlib1g-dev:amd64 (1:1.2.11.dfsg-0ubuntu2) ... @@ -285,8 +285,8 @@ have no access to the worktree:: root@73987568712c:/# cd sage root@73987568712c:/sage# command -v gcc /usr/bin/gcc - root@73987568712c:/sage# command -v yasm - /usr/bin/yasm + root@73987568712c:/sage# command -v bunzip2 + /usr/bin/bunzip2 root@73987568712c:/sage# ^D [mkoeppe@sage worktree-ubuntu-latest]$ @@ -337,7 +337,7 @@ image...:: Then, to install system packages...:: ... - RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -qqq --no-install-recommends --yes binutils make m4 perl python3 ... yasm libzmq3-dev libz-dev && apt-get clean + RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -qqq --no-install-recommends --yes binutils make m4 perl python3 ... libzmq3-dev libz-dev && apt-get clean Then, to bootstrap and configure...:: @@ -852,10 +852,10 @@ an isolated copy of Homebrew with all prerequisites for bootstrapping:: checking for a BSD-compatible install... /usr/bin/install -c checking whether build environment is sane... yes ... - configure: notice: the following SPKGs did not find equivalent system packages: arb cbc cliquer ... tachyon xz yasm zeromq + configure: notice: the following SPKGs did not find equivalent system packages: arb cbc cliquer ... tachyon xz zeromq checking for the package system in use... homebrew configure: hint: installing the following system packages is recommended and may avoid building some of the above SPKGs from source: - configure: $ brew install cmake gcc gsl mpfi ninja openblas gpatch r readline xz yasm zeromq + configure: $ brew install cmake gcc gsl mpfi ninja openblas gpatch r readline xz zeromq ... sage-logger -p 'sage-spkg -y -o lrslib-062+autotools-2017-03-03.p1' '.../worktree-local/logs/pkgs/lrslib-062+autotools-2017-03-03.p1.log' [lrslib-062+autotools-2017-03-03.p1] installing. Log file: .../worktree-local/logs/pkgs/lrslib-062+autotools-2017-03-03.p1.log diff --git a/src/doc/en/faq/faq-general.rst b/src/doc/en/faq/faq-general.rst index ebc04f45144..462fe69e617 100644 --- a/src/doc/en/faq/faq-general.rst +++ b/src/doc/en/faq/faq-general.rst @@ -22,10 +22,10 @@ number theory, but throughout the mathematical sciences. Sage builds upon and extends functionalities of many underlying packages. Even from early on, when Sage was primarily used for number theory, this included -`Givaro `_, -`MPIR `_, -`NTL `_, -`Pari/GP `_, +`Givaro `_, +`GMP `_, +`NTL `_, +`Pari/GP `_, and many others too numerous to list here. Students, teachers, professors, researchers throughout the world use Sage because they require a comprehensive free open source mathematics package that @@ -197,7 +197,7 @@ functionalities are made possible through FOSS projects such as * `NumPy and SciPy `_ --- numerical linear algebra and other numerical computing capabilities for Python. * `OpenBLAS `_ --- an optimized BLAS library. -* `Pari/GP `_ --- a computer algebra +* `Pari/GP `_ --- a computer algebra system for fast computations in number theory. * `Pynac `_ --- a modified version of GiNaC that replaces the dependency on CLN by Python. diff --git a/src/doc/en/installation/source.rst b/src/doc/en/installation/source.rst index 5ccd5fc7a83..0d789336e5e 100644 --- a/src/doc/en/installation/source.rst +++ b/src/doc/en/installation/source.rst @@ -1124,8 +1124,8 @@ Here are some of the more commonly used variables affecting the build process: An entry ``package-name`` means to run the test suite for the named package regardless of the setting of :envvar:`SAGE_CHECK`. An entry ``!package-name`` means to skip its test suite. - So if this is set to ``mpir,!python3``, then always run the test suite for - MPIR, but always skip the test suite for Python 3. + So if this is set to ``ppl,!python3``, then always run the test suite for + PPL, but always skip the test suite for Python 3. .. note:: @@ -1282,11 +1282,6 @@ Here are some of the more commonly used variables affecting the build process: Environment variables dealing with specific Sage packages: -- :envvar:`SAGE_MP_LIBRARY` - to use an alternative library in place of ``MPIR`` - for multiprecision integer arithmetic. Supported values are - - ``MPIR`` (default choice), ``GMP``. - - :envvar:`SAGE_MATPLOTLIB_GUI` - if set to anything non-empty except ``no``, then Sage will attempt to build the graphical backend when it builds the matplotlib package. diff --git a/src/doc/en/prep/Programming.rst b/src/doc/en/prep/Programming.rst index d74ed1e9f42..f495c872f48 100644 --- a/src/doc/en/prep/Programming.rst +++ b/src/doc/en/prep/Programming.rst @@ -524,12 +524,12 @@ Luckily, it's possible to restore symbolic constants. :: sage: type(e) - + :: sage: type(pi) - + Variables are another thing to keep in mind. As mentioned briefly in earlier tutorials, in order to maintain maximum flexibility while not @@ -539,7 +539,7 @@ nothing else. :: sage: type(x) - + :: diff --git a/src/doc/en/prep/Quickstarts/Linear-Algebra.rst b/src/doc/en/prep/Quickstarts/Linear-Algebra.rst index 666e4b48765..58cb44edd3c 100644 --- a/src/doc/en/prep/Quickstarts/Linear-Algebra.rst +++ b/src/doc/en/prep/Quickstarts/Linear-Algebra.rst @@ -192,7 +192,7 @@ for our purposes. sage: type( ring_vec ) sage: type( field_vec ) - + Left\-Handed or Right\-handed? ------------------------------- diff --git a/src/doc/en/prep/Quickstarts/Number-Theory.rst b/src/doc/en/prep/Quickstarts/Number-Theory.rst index 5b1f73d8138..aa46ee12a86 100644 --- a/src/doc/en/prep/Quickstarts/Number-Theory.rst +++ b/src/doc/en/prep/Quickstarts/Number-Theory.rst @@ -31,7 +31,7 @@ For instance, we can create a number in :math:`\ZZ/11\ZZ`. The sage: a = mod(2,11); a; type(a); a^10; a^1000000 2 - + 1 1 diff --git a/src/doc/en/reference/coercion/index.rst b/src/doc/en/reference/coercion/index.rst index 04666bda51b..d8d7c2ade79 100644 --- a/src/doc/en/reference/coercion/index.rst +++ b/src/doc/en/reference/coercion/index.rst @@ -74,9 +74,9 @@ There is an important distinction between Parents and types:: sage: a = GF(5).random_element() sage: b = GF(7).random_element() sage: type(a) - + sage: type(b) - + sage: type(a) == type(b) True sage: parent(a) diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index 2916ebcaf05..cecda8a5ef3 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -3064,6 +3064,10 @@ REFERENCES: .. [Hutz2015] \B. Hutz. Determination of all rational preperiodic points for morphisms of PN. Mathematics of Computation, 84:291 (2015), 289-308. +.. [Hutz2019] \B. Hutz. Multipliers and invariants of endomorphisms of projective + space in dimension greater than 1, Journal de Théorie des Nombres de + Bordeaux, Tome 32 (2020) no. 2, pp. 439-469. + .. [Huy2005] \D. Huybrechts : *Complex Geometry*, Springer (Berlin) (2005). diff --git a/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/level_one_forms.rst b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/level_one_forms.rst index 42841173aa0..e2777d45512 100644 --- a/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/level_one_forms.rst +++ b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/level_one_forms.rst @@ -52,6 +52,7 @@ rather nice diagonal shape. q + 195660*q^3 + 12080128*q^4 + 44656110*q^5 + O(q^6), q^2 - 48*q^3 + 1080*q^4 - 15040*q^5 + O(q^6) ] + sage: from sage.modular.dims import dimension_modular_forms sage: dimension_modular_forms(1,200) 17 sage: B = victor_miller_basis(200, 18) #5 seconds @@ -64,7 +65,7 @@ rather nice diagonal shape. ] Note: Craig Citro has made the above computation an order of -magnitude faster in code he hasn't quite got into Sage yet. +magnitude faster in code he has not quite got into Sage yet. "I'll clean those up and submit them soon, since I need them for something I'm working on ... I'm currently in the process of making diff --git a/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/modular_forms_and_hecke_operators.rst b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/modular_forms_and_hecke_operators.rst index e9cf689d171..4d223f282d3 100644 --- a/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/modular_forms_and_hecke_operators.rst +++ b/src/doc/en/thematic_tutorials/explicit_methods_in_number_theory/modular_forms_and_hecke_operators.rst @@ -164,14 +164,14 @@ dimension formulas. sage: ModularForms(Gamma1(949284), 456).dimension() 11156973844800 + sage: from sage.modular.dims import dimension_cusp_forms sage: a = [dimension_cusp_forms(Gamma0(N),2) for N in [1..25]]; a [0, 0, ..., 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 2, 2, 1, 0] sage: oeis(a) # optional - internet 0: A001617: Genus of modular group Gamma_0(n). Or, genus of modular curve X_0(n). -Sage doesn't have simple formulas for dimensions of spaces of -modular forms of weight :math:`1`, since such formulas perhaps do -not exist. +Sage does not have simple formulas for dimensions of spaces of modular +forms of weight :math:`1`, since such formulas perhaps do not exist. Diamond Bracket Operators ~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/src/doc/en/thematic_tutorials/sandpile.rst b/src/doc/en/thematic_tutorials/sandpile.rst index 7dd7091415a..ad8744a1f52 100644 --- a/src/doc/en/thematic_tutorials/sandpile.rst +++ b/src/doc/en/thematic_tutorials/sandpile.rst @@ -4988,7 +4988,7 @@ Other [ 0 -1 1650 -1649] [ 0 0 -1658 1658] - NOTES: + NOTE: The algorithm is due to John Wilmes. @@ -5002,7 +5002,7 @@ Documentation for each method is available through the Sage online help system: :: sage: SandpileConfig.fire_vertex? - Base Class: + Base Class: String Form: Namespace: Interactive File: /usr/local/sage-4.7/local/lib/python2.6/site-packages/sage/sandpiles/sandpile.py diff --git a/src/doc/en/thematic_tutorials/tutorial-objects-and-classes.rst b/src/doc/en/thematic_tutorials/tutorial-objects-and-classes.rst index cbaff12746b..a295508e0ab 100644 --- a/src/doc/en/thematic_tutorials/tutorial-objects-and-classes.rst +++ b/src/doc/en/thematic_tutorials/tutorial-objects-and-classes.rst @@ -314,7 +314,7 @@ http://docs.python.org/library/ for a complete list. :: sage: e = Integer(9) sage: type(e) - + sage: e.__dict__ Traceback (most recent call last): ... @@ -322,7 +322,7 @@ http://docs.python.org/library/ for a complete list. :: sage: id4 = SymmetricGroup(4).one() sage: type(id4) - + sage: id4.__dict__ Traceback (most recent call last): ... diff --git a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_cartesian.rst b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_cartesian.rst index d7eed347d92..978aa129395 100644 --- a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_cartesian.rst +++ b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_cartesian.rst @@ -38,7 +38,7 @@ Thanks to the notation ```` in the above declaration, the coordinates sage: z is E.cartesian_coordinates()[3] True sage: type(z) - + Besides, `\mathbb{E}^3` is endowed with the *orthonormal vector frame* `(e_x, e_y, e_z)` associated with Cartesian coordinates:: diff --git a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_change.rst b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_change.rst index 188b65ed596..d7164e7c363 100644 --- a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_change.rst +++ b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_change.rst @@ -59,7 +59,7 @@ type ``x, y, z = var('x y z')``; they are immediately available:: sage: y is cartesian[2] True sage: type(y) - + Each of the Cartesian coordinates spans the entire real line:: diff --git a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_curvilinear.rst b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_curvilinear.rst index a244b427839..96617135972 100644 --- a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_curvilinear.rst +++ b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_curvilinear.rst @@ -36,7 +36,7 @@ type ``r, th, ph = var('r th ph')``):: sage: (r, th, ph) == E.spherical_coordinates()[:] True sage: type(r) - + Moreover, the coordinate LaTeX symbols are already set:: diff --git a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_plane.rst b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_plane.rst index 0286c70c467..d5e35cc552d 100644 --- a/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_plane.rst +++ b/src/doc/en/thematic_tutorials/vector_calculus/vector_calc_plane.rst @@ -32,7 +32,7 @@ the Cartesian coordinates (there is no need to declare them via :func:`var`, i.e. to type ``x, y = var('x y')``):: sage: type(y) - + Instead of using the variables ``x`` and ``y``, one may also access to the coordinates by their indices in the chart of Cartesian coordinates:: diff --git a/src/doc/en/tutorial/interactive_shell.rst b/src/doc/en/tutorial/interactive_shell.rst index 0ca57bfaf5a..3029ad8b6b5 100644 --- a/src/doc/en/tutorial/interactive_shell.rst +++ b/src/doc/en/tutorial/interactive_shell.rst @@ -488,7 +488,7 @@ execution stack. For example, Automatic pdb calling has been turned ON sage: EllipticCurve([1,infinity]) --------------------------------------------------------------------------- - Traceback (most recent call last) + Traceback (most recent call last) ... ipdb> @@ -597,7 +597,7 @@ followed by ? for the documentation for that function. sage: V = QQ^3 sage: V.coordinates? Type: instancemethod - Base Class: + Base Class: String Form: Namespace: Interactive diff --git a/src/doc/en/tutorial/interfaces.rst b/src/doc/en/tutorial/interfaces.rst index 4ddbb146db3..b0e55345669 100644 --- a/src/doc/en/tutorial/interfaces.rst +++ b/src/doc/en/tutorial/interfaces.rst @@ -64,7 +64,7 @@ objects have different types: sage: type(gp('znprimroot(10007)')) sage: type(pari('znprimroot(10007)')) - + So which should you use? It depends on what you're doing. The GP interface can do absolutely anything you could do in the usual @@ -100,7 +100,7 @@ First we create a PARI list from a Python list. sage: v [1, 2, 3, 4, 5] sage: type(v) - + Every PARI object is of type ``Gen``. The PARI type of the underlying object can be obtained using the ``type`` member diff --git a/src/doc/en/tutorial/programming.rst b/src/doc/en/tutorial/programming.rst index e7ce161cc4f..56ecb369559 100644 --- a/src/doc/en/tutorial/programming.rst +++ b/src/doc/en/tutorial/programming.rst @@ -378,7 +378,7 @@ a common parent, called the sequences universe. sage: type(v) sage: type(v[1]) - + sage: v.universe() Rational Field sage: v.is_immutable() diff --git a/src/doc/en/tutorial/tour_advanced.rst b/src/doc/en/tutorial/tour_advanced.rst index db8f363d5bc..a34bb01f5e4 100644 --- a/src/doc/en/tutorial/tour_advanced.rst +++ b/src/doc/en/tutorial/tour_advanced.rst @@ -402,6 +402,7 @@ spaces of modular forms. For example, :: + sage: from sage.modular.dims import dimension_cusp_forms sage: dimension_cusp_forms(Gamma0(11),2) 1 sage: dimension_cusp_forms(Gamma0(1),12) diff --git a/src/doc/en/tutorial/tour_assignment.rst b/src/doc/en/tutorial/tour_assignment.rst index b7194a7d81d..6d863b15893 100644 --- a/src/doc/en/tutorial/tour_assignment.rst +++ b/src/doc/en/tutorial/tour_assignment.rst @@ -89,10 +89,10 @@ hold values of any Python type within a given scope: sage: a = 5 # a is an integer sage: type(a) - + sage: a = 5/3 # now a is a rational number sage: type(a) - + sage: a = 'hello' # now a is a string sage: type(a) <... 'str'> diff --git a/src/doc/en/tutorial/tour_coercion.rst b/src/doc/en/tutorial/tour_coercion.rst index 0ee15f3c808..65b28fa0968 100644 --- a/src/doc/en/tutorial/tour_coercion.rst +++ b/src/doc/en/tutorial/tour_coercion.rst @@ -55,9 +55,9 @@ providing different implementations of the same mathematical structure sage: Q. = PolynomialRing(ZZ, sparse=True) sage: R. = PolynomialRing(ZZ, implementation='NTL') sage: type(a); type(b); type(c) - + - + That poses two problems: On the one hand, if one has elements that are two instances of the same class, then one may expect that their diff --git a/src/doc/en/tutorial/tour_functions.rst b/src/doc/en/tutorial/tour_functions.rst index 6c006f5180a..f00991813c2 100644 --- a/src/doc/en/tutorial/tour_functions.rst +++ b/src/doc/en/tutorial/tour_functions.rst @@ -59,7 +59,7 @@ differentiated, and integrated. sage: Dg(3) 6 sage: type(g) - + sage: plot(g, 0, 2) Graphics object consisting of 1 graphics primitive @@ -75,7 +75,7 @@ illustration. sage: g(x) x^2 sage: type(g(x)) - + sage: g(x).derivative() 2*x sage: plot(g(x), 0, 2) @@ -91,7 +91,7 @@ and with a little help, differentiated, and integrated. sage: plot(sin, 0, 2) Graphics object consisting of 1 graphics primitive sage: type(sin(x)) - + sage: plot(sin(x), 0, 2) Graphics object consisting of 1 graphics primitive @@ -174,9 +174,9 @@ The problem: ``g(3)``, for example, returns an error, saying :: sage: type(f) - + sage: type(g) - + ``g`` is not a function, it's a constant, so it has no variables associated to it, and you can't plug anything into it. @@ -194,7 +194,7 @@ The solution: there are several options. sage: g(3) 1 sage: type(g) - + - Or with ``f`` as defined originally, define ``g`` to be a symbolic expression. @@ -208,7 +208,7 @@ The solution: there are several options. sage: g(3) 1 sage: type(g) - + - Or with ``f`` and ``g`` as defined originally, specify the variable for which you are substituting. diff --git a/src/doc/es/tutorial/tour_assignment.rst b/src/doc/es/tutorial/tour_assignment.rst index d5144f74e29..12297921cc2 100644 --- a/src/doc/es/tutorial/tour_assignment.rst +++ b/src/doc/es/tutorial/tour_assignment.rst @@ -88,10 +88,10 @@ contener valores de cualquier tipo Python dentro de un ámbito dado: sage: a = 5 # a es un entero sage: type(a) - + sage: a = 5/3 # ahora es un número racional sage: type(a) - + sage: a = 'hello' # ahora es una cadena sage: type(a) <... 'str'> diff --git a/src/doc/fr/tutorial/interactive_shell.rst b/src/doc/fr/tutorial/interactive_shell.rst index bebb972e6d2..c38140f781b 100644 --- a/src/doc/fr/tutorial/interactive_shell.rst +++ b/src/doc/fr/tutorial/interactive_shell.rst @@ -495,7 +495,7 @@ pile d'exécution. Par exemple : Automatic pdb calling has been turned ON sage: EllipticCurve([1,infinity]) --------------------------------------------------------------------------- - Traceback (most recent call last) + Traceback (most recent call last) ... ipdb> @@ -604,7 +604,7 @@ d'une fonction, tapez son nom suivi d'un point d'interrogation. sage: V = QQ^3 sage: V.coordinates? Type: instancemethod - Base Class: + Base Class: String Form: Namespace: Interactive diff --git a/src/doc/fr/tutorial/interfaces.rst b/src/doc/fr/tutorial/interfaces.rst index 647189f65d7..1cd662f3083 100644 --- a/src/doc/fr/tutorial/interfaces.rst +++ b/src/doc/fr/tutorial/interfaces.rst @@ -64,7 +64,7 @@ commandes sont de types différents : sage: type(gp('znprimroot(10007)')) sage: type(pari('znprimroot(10007)')) - + Alors, laquelle des interfaces utiliser ? Tout dépend de ce que vous cherchez à faire. L'interface GP permet de faire absolument tout ce que @@ -102,7 +102,7 @@ Commençons par créer une liste PARI à partir d'une liste Python. sage: v [1, 2, 3, 4, 5] sage: type(v) - + En Sage, les objets PARI sont de type ``Gen``. Le type PARI de l'objet sous-jacent est donné par la méthode ``type``. diff --git a/src/doc/fr/tutorial/programming.rst b/src/doc/fr/tutorial/programming.rst index 4e1b372a070..69b4182508e 100644 --- a/src/doc/fr/tutorial/programming.rst +++ b/src/doc/fr/tutorial/programming.rst @@ -391,7 +391,7 @@ l'univers de la séquence. sage: type(v) sage: type(v[1]) - + sage: v.universe() Rational Field sage: v.is_immutable() diff --git a/src/doc/fr/tutorial/tour_advanced.rst b/src/doc/fr/tutorial/tour_advanced.rst index d9ec556934a..c6a0f2078e8 100644 --- a/src/doc/fr/tutorial/tour_advanced.rst +++ b/src/doc/fr/tutorial/tour_advanced.rst @@ -402,6 +402,7 @@ d'espaces de formes modulaires. Par exemple, :: + sage: from sage.modular.dims import dimension_cusp_forms sage: dimension_cusp_forms(Gamma0(11),2) 1 sage: dimension_cusp_forms(Gamma0(1),12) diff --git a/src/doc/fr/tutorial/tour_assignment.rst b/src/doc/fr/tutorial/tour_assignment.rst index 70e0767586a..6607ebc5a62 100644 --- a/src/doc/fr/tutorial/tour_assignment.rst +++ b/src/doc/fr/tutorial/tour_assignment.rst @@ -93,10 +93,10 @@ sein d'une même portée : sage: a = 5 # a est un entier sage: type(a) - + sage: a = 5/3 # a est maintenant un rationnel... sage: type(a) - + sage: a = 'hello' # ...et maintenant une chaîne sage: type(a) <... 'str'> diff --git a/src/doc/fr/tutorial/tour_coercion.rst b/src/doc/fr/tutorial/tour_coercion.rst index 72846896985..9d666684313 100644 --- a/src/doc/fr/tutorial/tour_coercion.rst +++ b/src/doc/fr/tutorial/tour_coercion.rst @@ -57,9 +57,9 @@ contre matrices creuses par exemple). sage: Q. = PolynomialRing(ZZ, sparse=True) sage: R. = PolynomialRing(ZZ, implementation='NTL') sage: type(a); type(b); type(c) - + - + Deux problèmes se posent alors. D'une part, si deux éléments sont instances de la même classe, on s'attend à ce que leur méthode ``__add__`` soit capable de diff --git a/src/doc/fr/tutorial/tour_functions.rst b/src/doc/fr/tutorial/tour_functions.rst index 4465b92413c..cc88b77a071 100644 --- a/src/doc/fr/tutorial/tour_functions.rst +++ b/src/doc/fr/tutorial/tour_functions.rst @@ -59,7 +59,7 @@ et que l'on peut aussi dériver ou intégrer symboliquement :: sage: Dg(3) 6 sage: type(g) - + sage: plot(g, 0, 2) Graphics object consisting of 1 graphics primitive @@ -76,7 +76,7 @@ illustrées dans le point 5 ci-dessous. sage: g(x) x^2 sage: type(g(x)) - + sage: g(x).derivative() 2*x sage: plot(g(x), 0, 2) @@ -90,7 +90,7 @@ servir à tracer des courbes, et, indirectement, être dérivées ou intégrées sage: plot(sin, 0, 2) Graphics object consisting of 1 graphics primitive sage: type(sin(x)) - + sage: plot(sin(x), 0, 2) Graphics object consisting of 1 graphics primitive @@ -132,7 +132,7 @@ est donc évaluée. :: sage: type(x < 2) - + Or, l'évaluation d'une inégalité symbolique renvoie ``False`` quand la condition n'est pas clairement vraie. Ainsi, ``h(x)`` s'évalue en @@ -167,9 +167,9 @@ the number of arguments must be less than or equal to 0 ». :: sage: type(f) - + sage: type(g) - + En effet, ``g`` n'est pas une fonction, mais une constante, sans variable en laquelle on peut l'évaluer. @@ -185,7 +185,7 @@ Solution : il y a plusieurs possibilités. sage: g(3) 1 sage: type(g) - + - Ou, sans changer la définition de ``f``, définir ``g`` comme une expression symbolique fonctionnelle :: @@ -197,7 +197,7 @@ Solution : il y a plusieurs possibilités. sage: g(3) 1 sage: type(g) - + - Ou encore, avec ``f`` et ``g`` définies comme dans l'exemple de départ, donner explicitement la variable à remplacer par sa valeur :: diff --git a/src/doc/it/faq/faq-general.rst b/src/doc/it/faq/faq-general.rst index 5f9234d57c8..39ae0070bf9 100644 --- a/src/doc/it/faq/faq-general.rst +++ b/src/doc/it/faq/faq-general.rst @@ -21,10 +21,10 @@ dei Numeri, ma da ricercatori in tutte le scienze matematiche. Sage si avvale ed estende le funzionalità di molti dei pacchetti inglobati. Anche dal principio, quando Sage veiniva usato principalmente per la Teoria dei Numeri, includeva: -`Givaro `_, -`MPIR `_, -`NTL `_, -`Pari/GP `_, +`Givaro `_, +`GMP `_, +`NTL `_, +`Pari/GP `_, e molti altri troppo numerosi per essere elencati qui. Studenti, insegnanti, professori universitari, ricercatori di tutto il mondo usano Sage perché vogliono un pacchetto open-source comprensivo per la matematica che offra calcolo sia @@ -185,7 +185,7 @@ realizzate attraverso progetti FOSS come * `NumPy `_ --- algebra lineare numerica ed altre funzioni di calcolo numerico per Python. -* `Pari/GP `_ --- software matematico per +* `Pari/GP `_ --- software matematico per calcolo veloce in Teoria dei Numeri. * `Pynac `_ --- versione modificata di GiNaC che diff --git a/src/doc/ja/tutorial/interactive_shell.rst b/src/doc/ja/tutorial/interactive_shell.rst index eae3aeaaafc..452914bd12a 100644 --- a/src/doc/ja/tutorial/interactive_shell.rst +++ b/src/doc/ja/tutorial/interactive_shell.rst @@ -442,7 +442,7 @@ IPythonのクイック レファレンスガイドを見たければ, ``%quick Automatic pdb calling has been turned ON sage: EllipticCurve([1,infinity]) --------------------------------------------------------------------------- - Traceback (most recent call last) + Traceback (most recent call last) ... ipdb> @@ -542,7 +542,7 @@ Sageの特長の一つは,総合的なヘルプ機能の装備である. sage: V = QQ^3 sage: V.coordinates? Type: instancemethod - Base Class: + Base Class: String Form: Namespace: Interactive diff --git a/src/doc/ja/tutorial/interfaces.rst b/src/doc/ja/tutorial/interfaces.rst index 1254d297be7..9c16b2eba08 100644 --- a/src/doc/ja/tutorial/interfaces.rst +++ b/src/doc/ja/tutorial/interfaces.rst @@ -55,7 +55,7 @@ GPは送られて来た文字列を評価し,結果を変数に格納する( sage: type(gp('znprimroot(10007)')) sage: type(pari('znprimroot(10007)')) - + では,どちらの方法を選ぶべきだろうか? 答は目的による、としか言えない. @@ -84,7 +84,7 @@ PARI Cライブラリ インターフェイスについて言うと,こちら sage: v [1, 2, 3, 4, 5] sage: type(v) - + PARIのオブジェクトは全て ``Gen`` 型になる. diff --git a/src/doc/ja/tutorial/programming.rst b/src/doc/ja/tutorial/programming.rst index 245dee89b3f..9edd5f80a6d 100644 --- a/src/doc/ja/tutorial/programming.rst +++ b/src/doc/ja/tutorial/programming.rst @@ -357,7 +357,7 @@ Sageで使われる第三のリスト類似データ型が,シーケンスで sage: type(v) sage: type(v[1]) - + sage: v.universe() Rational Field sage: v.is_immutable() diff --git a/src/doc/ja/tutorial/tour_advanced.rst b/src/doc/ja/tutorial/tour_advanced.rst index 431cb2a8a16..a2b53ffc07a 100644 --- a/src/doc/ja/tutorial/tour_advanced.rst +++ b/src/doc/ja/tutorial/tour_advanced.rst @@ -383,6 +383,7 @@ Sageを使ってモジュラー空間の次元,モジュラー・シンポル :: + sage: from sage.modular.dims import dimension_cusp_forms sage: dimension_cusp_forms(Gamma0(11),2) 1 sage: dimension_cusp_forms(Gamma0(1),12) diff --git a/src/doc/ja/tutorial/tour_assignment.rst b/src/doc/ja/tutorial/tour_assignment.rst index be04ba7f6f1..ea8673689cc 100644 --- a/src/doc/ja/tutorial/tour_assignment.rst +++ b/src/doc/ja/tutorial/tour_assignment.rst @@ -79,10 +79,10 @@ Pythonのデータはダイナミックに型付けされ,変数を通して sage: a = 5 # aは整数 sage: type(a) - + sage: a = 5/3 # aは有理数になった sage: type(a) - + sage: a = 'hello' # ここでaは文字列 sage: type(a) <... 'str'> diff --git a/src/doc/ja/tutorial/tour_coercion.rst b/src/doc/ja/tutorial/tour_coercion.rst index 15c3ce07c3d..fd125a81987 100644 --- a/src/doc/ja/tutorial/tour_coercion.rst +++ b/src/doc/ja/tutorial/tour_coercion.rst @@ -42,9 +42,9 @@ Pythonは(ダイナミックではあっても)強い型付けがなされる言 sage: Q. = PolynomialRing(ZZ, sparse=True) sage: R. = PolynomialRing(ZZ, implementation='NTL') sage: type(a); type(b); type(c) - + - + 以上から,解決すべき問題は二系統あることが分る. diff --git a/src/doc/ja/tutorial/tour_functions.rst b/src/doc/ja/tutorial/tour_functions.rst index 159ffca4c51..2c210a9da7d 100644 --- a/src/doc/ja/tutorial/tour_functions.rst +++ b/src/doc/ja/tutorial/tour_functions.rst @@ -59,7 +59,7 @@ Sageで「関数」と呼ばれるべきものを定義する方法は何通り sage: Dg(3) 6 sage: type(g) - + sage: plot(g, 0, 2) Graphics object consisting of 1 graphics primitive @@ -74,7 +74,7 @@ Sageで「関数」と呼ばれるべきものを定義する方法は何通り sage: g(x) x^2 sage: type(g(x)) - + sage: g(x).derivative() 2*x sage: plot(g(x), 0, 2) @@ -92,7 +92,7 @@ Sageで「関数」と呼ばれるべきものを定義する方法は何通り sage: plot(sin, 0, 2) Graphics object consisting of 1 graphics primitive sage: type(sin(x)) - + sage: plot(sin(x), 0, 2) Graphics object consisting of 1 graphics primitive @@ -142,7 +142,7 @@ Sageで「関数」と呼ばれるべきものを定義する方法は何通り :: sage: type(x<2) - + シンボリック式が評価される際, ``h`` の定義の場合と同じように,その式が明らかに真でないかぎり戻り値は偽になる. @@ -181,9 +181,9 @@ Sageで「関数」と呼ばれるべきものを定義する方法は何通り :: sage: type(f) - + sage: type(g) - + ``g`` は関数ではなく定数になっているので,変数を持たないから何も値を受けつけない. @@ -202,7 +202,7 @@ Sageで「関数」と呼ばれるべきものを定義する方法は何通り sage: g(3) 1 sage: type(g) - + - または ``f`` の定義は元のまま ``g`` をシンボリック表式として定義する. @@ -216,7 +216,7 @@ Sageで「関数」と呼ばれるべきものを定義する方法は何通り sage: g(3) 1 sage: type(g) - + - または ``f`` と ``g`` の定義は元のまま,代入すべき変数を特定する. diff --git a/src/doc/pt/tutorial/interactive_shell.rst b/src/doc/pt/tutorial/interactive_shell.rst index 64ef511d7e4..1b3ec525c89 100644 --- a/src/doc/pt/tutorial/interactive_shell.rst +++ b/src/doc/pt/tutorial/interactive_shell.rst @@ -475,7 +475,7 @@ cima e para baixo. Por exemplo, Automatic pdb calling has been turned ON sage: EllipticCurve([1,infinity]) --------------------------------------------------------------------------- - Traceback (most recent call last) + Traceback (most recent call last) ... ipdb> @@ -582,7 +582,7 @@ seguido de ? para ver informações sobre a função. sage: V = QQ^3 sage: V.coordinates? Type: instancemethod - Base Class: + Base Class: String Form: Namespace: Interactive diff --git a/src/doc/pt/tutorial/interfaces.rst b/src/doc/pt/tutorial/interfaces.rst index 8515f18a74c..3c080cc3cfc 100644 --- a/src/doc/pt/tutorial/interfaces.rst +++ b/src/doc/pt/tutorial/interfaces.rst @@ -63,7 +63,7 @@ diferentes: sage: type(gp('znprimroot(10007)')) sage: type(pari('znprimroot(10007)')) - + Então qual eu devo usar? Depende do que você está fazendo. A interface GP pode fazer absolutamente tudo o que você poderia fazer na linha de @@ -101,7 +101,7 @@ Primeiro criamos uma lista do PARI a partir de uma lista do Python. sage: v [1, 2, 3, 4, 5] sage: type(v) - + Cada objeto do PARI é do tipo ``Gen``. O tipo PARI do objeto subjacente pode ser obtido usando a função ``type``. diff --git a/src/doc/pt/tutorial/programming.rst b/src/doc/pt/tutorial/programming.rst index 7e65233dead..fd082952410 100644 --- a/src/doc/pt/tutorial/programming.rst +++ b/src/doc/pt/tutorial/programming.rst @@ -407,7 +407,7 @@ sequência possuem um parente comum, chamado o universo da sequência. sage: type(v) sage: type(v[1]) - + sage: v.universe() Rational Field sage: v.is_immutable() diff --git a/src/doc/pt/tutorial/tour_advanced.rst b/src/doc/pt/tutorial/tour_advanced.rst index dcd0969fb8e..075b3b1551e 100644 --- a/src/doc/pt/tutorial/tour_advanced.rst +++ b/src/doc/pt/tutorial/tour_advanced.rst @@ -402,6 +402,7 @@ de formas modulares. Por exemplo, :: + sage: from sage.modular.dims import dimension_cusp_forms sage: dimension_cusp_forms(Gamma0(11),2) 1 sage: dimension_cusp_forms(Gamma0(1),12) diff --git a/src/doc/pt/tutorial/tour_assignment.rst b/src/doc/pt/tutorial/tour_assignment.rst index 5ba8651dc07..001856d1349 100644 --- a/src/doc/pt/tutorial/tour_assignment.rst +++ b/src/doc/pt/tutorial/tour_assignment.rst @@ -89,10 +89,10 @@ variável pode possuir valores de qualquer tipo em determinado escopo: sage: a = 5 # a is an integer sage: type(a) - + sage: a = 5/3 # now a is a rational number sage: type(a) - + sage: a = 'hello' # now a is a string sage: type(a) <... 'str'> diff --git a/src/doc/pt/tutorial/tour_functions.rst b/src/doc/pt/tutorial/tour_functions.rst index dc3ebe3fa9c..2a7cac13969 100644 --- a/src/doc/pt/tutorial/tour_functions.rst +++ b/src/doc/pt/tutorial/tour_functions.rst @@ -61,7 +61,7 @@ integradas. sage: Dg(3) 6 sage: type(g) - + sage: plot(g, 0, 2) Graphics object consisting of 1 graphics primitive @@ -77,7 +77,7 @@ embora com algumas ressalvas: veja o item 5 abaixo. sage: g(x) x^2 sage: type(g(x)) - + sage: g(x).derivative() 2*x sage: plot(g(x), 0, 2) @@ -93,7 +93,7 @@ gráfico, e com uma pequena ajuda, diferenciadas e integradas. sage: plot(sin, 0, 2) Graphics object consisting of 1 graphics primitive sage: type(sin(x)) - + sage: plot(sin(x), 0, 2) Graphics object consisting of 1 graphics primitive @@ -140,7 +140,7 @@ na função ``h``, o que significa que ``x<2`` é calculado. :: sage: type(x<2) - + Quando uma equação simbólica é calculada, como na definição de ``h``, se ela não é obviamente verdadeira, então ela retorna False. Logo @@ -173,9 +173,9 @@ number of arguments must be less than or equal to 0." :: sage: type(f) - + sage: type(g) - + ``g`` não é uma função, é uma constante, logo não possui variáveis associadas, e você não pode substituir nenhum valor em ``g``. @@ -193,7 +193,7 @@ Solução: existem vária opções. sage: g(3) 1 sage: type(g) - + - Ou com ``f`` como definida originalmente, defina ``g`` como uma expressão simbólica. @@ -207,7 +207,7 @@ Solução: existem vária opções. sage: g(3) 1 sage: type(g) - + - Ou com ``f`` e ``g`` como definidas originalmente, especifique a variável para a qual você está substituindo. diff --git a/src/doc/ru/tutorial/interactive_shell.rst b/src/doc/ru/tutorial/interactive_shell.rst index 7abfe99fe53..9129eeee005 100644 --- a/src/doc/ru/tutorial/interactive_shell.rst +++ b/src/doc/ru/tutorial/interactive_shell.rst @@ -392,7 +392,7 @@ Wall time. Однако, если существует существенная Automatic pdb calling has been turned ON sage: EllipticCurve([1,infinity]) --------------------------------------------------------------------------- - Traceback (most recent call last) + Traceback (most recent call last) ... ipdb> @@ -498,7 +498,7 @@ Sage обладает встроенной справочной системой sage: V = QQ^3 sage: V.coordinates? Type: instancemethod - Base Class: + Base Class: String Form: Namespace: Interactive diff --git a/src/doc/ru/tutorial/interfaces.rst b/src/doc/ru/tutorial/interfaces.rst index 2210f9c0a5b..ea84527f478 100644 --- a/src/doc/ru/tutorial/interfaces.rst +++ b/src/doc/ru/tutorial/interfaces.rst @@ -59,7 +59,7 @@ GP, и результат записывается в переменную в GP sage: type(gp('znprimroot(10007)')) sage: type(pari('znprimroot(10007)')) - + Так какой же способ использовать? Это зависит от того, что вы делаете. Интерфейс GP может делать все, что может делать программа GP/PARI, запускаемая @@ -92,7 +92,7 @@ Sage использует С-библиотеку PARI, чтобы поддер sage: v [1, 2, 3, 4, 5] sage: type(v) - + Каждый объект PARI является объектом типа ``Gen``. Тип PARI может быть получен с помощью функции-члена ``type``. diff --git a/src/doc/ru/tutorial/programming.rst b/src/doc/ru/tutorial/programming.rst index e0a58e26071..4550f32717a 100644 --- a/src/doc/ru/tutorial/programming.rst +++ b/src/doc/ru/tutorial/programming.rst @@ -367,7 +367,7 @@ Python, сработает нормально. sage: type(v) sage: type(v[1]) - + sage: v.universe() Rational Field sage: v.is_immutable() diff --git a/src/doc/ru/tutorial/tour_advanced.rst b/src/doc/ru/tutorial/tour_advanced.rst index 6d1d3bbb34c..69eb42dfd4c 100644 --- a/src/doc/ru/tutorial/tour_advanced.rst +++ b/src/doc/ru/tutorial/tour_advanced.rst @@ -364,6 +364,7 @@ Sage может выполнять вычисления, связанные с :: + sage: from sage.modular.dims import dimension_cusp_forms sage: dimension_cusp_forms(Gamma0(11),2) 1 sage: dimension_cusp_forms(Gamma0(1),12) diff --git a/src/doc/ru/tutorial/tour_assignment.rst b/src/doc/ru/tutorial/tour_assignment.rst index 7f8612cac9b..9ad9b1d715d 100644 --- a/src/doc/ru/tutorial/tour_assignment.rst +++ b/src/doc/ru/tutorial/tour_assignment.rst @@ -87,10 +87,10 @@ Python имеет динамический контроль типов, так sage: a = 5 # a - целое число sage: type(a) - + sage: a = 5/3 # теперь a - рациональное число sage: type(a) - + sage: a = 'hello' # теперь a - строка sage: type(a) <... 'str'> diff --git a/src/doc/ru/tutorial/tour_functions.rst b/src/doc/ru/tutorial/tour_functions.rst index 6cc4d9c73c2..1f87c843415 100644 --- a/src/doc/ru/tutorial/tour_functions.rst +++ b/src/doc/ru/tutorial/tour_functions.rst @@ -58,7 +58,7 @@ sage: Dg(3) 6 sage: type(g) - + sage: plot(g, 0, 2) Graphics object consisting of 1 graphics primitive @@ -73,7 +73,7 @@ sage: g(x) x^2 sage: type(g(x)) - + sage: g(x).derivative() 2*x sage: plot(g(x), 0, 2) @@ -90,7 +90,7 @@ sage: plot(sin, 0, 2) Graphics object consisting of 1 graphics primitive sage: type(sin(x)) - + sage: plot(sin(x), 0, 2) Graphics object consisting of 1 graphics primitive @@ -135,7 +135,7 @@ :: sage: type(x<2) - + Решение: Не используйте ``plot(h(x), 0, 4)``; используйте: @@ -163,9 +163,9 @@ :: sage: type(f) - + sage: type(g) - + ``g`` не является функцией, это константа, поэтому она не имеет переменных, и вы можете вставлять что угодно в нее. @@ -183,7 +183,7 @@ sage: g(3) 1 sage: type(g) - + - Либо вместе с ``f``, определенной выше, определить ``g`` как символьное выражение. @@ -196,7 +196,7 @@ sage: g(3) 1 sage: type(g) - + - Либо с ``f`` и ``g``, заданными, как показано выше, создать переменную, под которую подставляются значения. diff --git a/src/sage/algebras/commutative_dga.py b/src/sage/algebras/commutative_dga.py index 87dc61cb7a4..040c2193913 100644 --- a/src/sage/algebras/commutative_dga.py +++ b/src/sage/algebras/commutative_dga.py @@ -99,7 +99,6 @@ from sage.rings.quotient_ring import QuotientRing_nc from sage.rings.quotient_ring_element import QuotientRingElement from sage.misc.cachefunc import cached_function -from sage.misc.superseded import deprecated_function_alias def sorting_keys(element): @@ -1535,8 +1534,6 @@ def homogeneous_parts(self): res[deg] = term return {i: res[i] for i in sorted(res.keys())} - homogenous_parts = deprecated_function_alias(30585, homogeneous_parts) - def dict(self): r""" A dictionary that determines the element. diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index 023d66931b5..5dde1e17330 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -8,6 +8,11 @@ - Brant Jones, Travis Scrimshaw, Andrew Mathas (2013): Moved into the category framework and implemented the Kazhdan-Lusztig `C` and `C^{\prime}` bases + +- Chase Meadors, Tianyuan Xu (2021): + Implemented direct computation of products in the + `C^{\prime}` basis using du Cloux's Coxeter3 package + """ # **************************************************************************** # Copyright (C) 2013 Brant Jones @@ -30,7 +35,7 @@ from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing from sage.arith.all import is_square from sage.combinat.root_system.coxeter_group import CoxeterGroup -from sage.combinat.family import Family +from sage.sets.family import Family from sage.combinat.free_module import CombinatorialFreeModule @@ -1856,9 +1861,9 @@ class Cp(_KLHeckeBasis): .. MATH:: \begin{aligned} - \overline{ C^{\prime}_w } &= C^{\prime}_w\\ + \overline{ C^{\prime}_w } &= C^{\prime}_w, \\ C^{\prime}_w &= q^{-\ell(w)/2} - \sum_{v \leq w} P_{v,w}(q) T_v + \sum_{v \leq w} P_{v,w}(q) T_v, \end{aligned} where `\leq` is the Bruhat order on the underlying Coxeter group and @@ -1876,6 +1881,18 @@ class Cp(_KLHeckeBasis): See [KL1979]_ for more details. + If the optional ``coxeter3`` package is available and the + Iwahori--Hecke algebra was initialized in the "standard" presentation + where `\{q_1,q_2\} = \{v^2,1\}` as sets or the "normalized" + presentation where `\{q_1,q_2\} = \{v,-v^{-1}\}` as sets, the function + :func::`product_on_basis` in this class computes products in the + `C^{\prime}`-basis directly in the basis itself, using ``coxeter3`` to + calculate certain `\mu`-coefficients quickly. If the above conditions + are not all met, the function computes such products indirectly, by + converting elements to the `T`-basis, computing products there, and + converting back. The indirect method can be prohibitively slow for + more complex calculations; the direct method is faster. + EXAMPLES:: sage: R = LaurentPolynomialRing(QQ, 'v') @@ -1907,9 +1924,46 @@ class Cp(_KLHeckeBasis): (v^-1+v)*Cp[1] sage: Cp(s1)*Cp(s2)*Cp(s1) Cp[1,2,1] + Cp[1] - sage: Cp(s1)*Cp(s2)*Cp(s3)*Cp(s1)*Cp(s2) # long time + sage: Cp(s1)*Cp(s2)*Cp(s3)*Cp(s1)*Cp(s2) # long time Cp[1,2,3,1,2] + Cp[1,2,1] + Cp[3,1,2] + In the following product computations, whether ``coxeter3`` is + installed makes a big difference: without ``coxeter3`` the product in + type `H_4` takes about 5 seconds to compute and the product in type + `A_9` seems infeasible, while with ``coxeter3`` both the computations + are instant:: + + sage: H = IwahoriHeckeAlgebra('H4', v**2) # optional - coxeter3 + sage: Cp = H.Cp() # optional - coxeter3 + sage: Cp[3,4,3]*Cp[3,4,3,4]*Cp[1,2,3,4] # optional - coxeter3 + (v^-2+2+v^2)*Cp[3,4,3,4,1,2,3,4,2] + + (v^-2+2+v^2)*Cp[3,4,3,4,3,1,2] + + (v^-3+3*v^-1+3*v+v^3)*Cp[3,4,3,4,3,1] + + (v^-1+v)*Cp[3,4,1,2,3,4] + + (v^-1+v)*Cp[3,4,1,2] + + sage: H = IwahoriHeckeAlgebra('A9', v**2) # optional - coxeter3 + sage: Cp = H.Cp() # optional - coxeter3 + sage: Cp[1,2,1,8,9,8]*Cp[1,2,3,7,8,9] # optional - coxeter3 + (v^-2+2+v^2)*Cp[7,8,9,7,8,7,1,2,3,1] + + (v^-2+2+v^2)*Cp[8,9,8,7,1,2,3,1] + + (v^-3+3*v^-1+3*v+v^3)*Cp[8,9,8,1,2,3,1] + + To use ``coxeter3`` for product computations most efficiently, we + recommend creating the Iwahori-Hecke algebra from a Coxeter group + implemented with ``coxeter3`` to avoid unnecessary conversions, as in + the following example with the same product computed in the last one:: + + sage: R = LaurentPolynomialRing(QQ, 'v') # optional - coxeter3 + sage: v = R.gen(0) # optional - coxeter3 + sage: W = CoxeterGroup('A9', implementation='coxeter3') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, v**2) # optional - coxeter3 + sage: Cp = H.Cp() # optional - coxeter3 + sage: Cp[1,2,1,8,9,8]*Cp[1,2,3,7,8,9] # optional - coxeter3 + (v^-2+2+v^2)*Cp[1,2,1,3,7,8,7,9,8,7] + + (v^-2+2+v^2)*Cp[1,2,1,3,8,9,8,7] + + (v^-3+3*v^-1+3*v+v^3)*Cp[1,2,1,3,8,9,8] + TESTS:: sage: R. = LaurentPolynomialRing(QQ, 'v') @@ -1925,6 +1979,47 @@ class Cp(_KLHeckeBasis): """ _basis_name = 'Cp' # this is used, for example, by specialize_to and is the default prefix + def __init__(self, IHAlgebra, prefix=None): + r""" + TESTS:: + + sage: R. = LaurentPolynomialRing(QQ) # optional - coxeter3 + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, v**2) # optional - coxeter3 + sage: Cp = H.Cp() # optional - coxeter3 + sage: Cp._delta == v + ~v # optional - coxeter3 + True + sage: Cp._W_Coxeter3 == H._W # optional - coxeter3 + True + sage: H = IwahoriHeckeAlgebra(W, QQ(1)) # optional - coxeter3 + sage: Cp = H.Cp() # optional - coxeter3 + sage: Cp._W_Coxeter3 is None # optional - coxeter3 + True + """ + super().__init__(IHAlgebra, prefix) + + self._W_Coxeter3 = None + + # See if we meet the conditions to use the direct product_on_basis algorithm. + # To use v + ~v as the value delta, we need the standard or + # normalized presentations of the Hecke algebra. + v = IHAlgebra.base_ring().gen(0) + parameters = {IHAlgebra.q1(), IHAlgebra.q2()} + if v == IHAlgebra.base_ring().one() or (parameters != {v**2, -1} and parameters != {v, -1/v}): + return + + # check if products can be computed directly using ``coxeter3`` + try: + from sage.libs.coxeter3.coxeter_group import CoxeterGroup as Coxeter3Group + except ImportError: + return + + self._delta = v + ~v + if isinstance(IHAlgebra._W, Coxeter3Group): + self._W_Coxeter3 = IHAlgebra._W + else: + self._W_Coxeter3 = CoxeterGroup(IHAlgebra._W.coxeter_type(), implementation='coxeter3') + def hash_involution_on_basis(self, w): r""" Return the effect of applying the hash involution to the basis @@ -1946,6 +2041,283 @@ def hash_involution_on_basis(self, w): """ return (-1)**w.length() * self(self.realization_of().C().monomial(w)) + def product_on_basis(self, w1, w2): + r""" + Return the expansion of `C^{\prime}_{w_1} \cdot C^{\prime}_{w_2}` + in the `C^{\prime}`-basis. + + If ``coxeter3`` is installed and the Iwahori--Hecke algebra is in + the standard or normalized presentation, the product is computed + directly using the method described in ALGORITHM. If not, the + product is computed indirectly by converting the factors to the + `T`-basis, computing the product there, and converting back. + + The following formulas for products of the forms `C^{\prime}_s + \cdot C^{\prime}_w` and `C^{\prime}_w \cdot C^{\prime}_s`, where + `s` is a generator of the Coxeter group and `w` an arbitrary + element, are key to the direct computation method. The formulas are + valid for both the standard and normalized presentation of the + Hecke algebra. + + .. MATH:: + + C^{\prime}_s \cdot C^{\prime}_w = \begin{cases} + (q+q^{-1})C^{\prime}_{w}, & \text{if } \ell(sw) = \ell(w)-1,\\ + C^{\prime}_{sw}+\sum_{v\leq w, sv \leq v} \mu(v,w)C^{\prime}_v, + & \text{if } \ell(sw) = \ell(w)+1. + \end{cases} + + \qquad\qquad + + C^{\prime}_w \cdot C^{\prime}_s = \begin{cases} + (q+q^{-1})C^{\prime}_{w}, & \text{if } \ell(ws) = \ell(w)-1,\\ + C^{\prime}_{ws}+\sum_{v\leq w, vs \leq v} \mu(v,w)C^{\prime}_v, + & \text{if } \ell(ws) = \ell(w)+1. + \end{cases} + + In the above, `\leq` is the Bruhat order on the Coxeter group and + `\mu(v,w)` is the "leading coefficient of Kazhdan-Lusztig + polynomials"; see [KL1979]_ and [Lus2013]_ for more details. The + method designates the computation of the `\mu`-coefficients to + Sage's interface to Fokko du Cloux's ``coxeter3`` package, which is + why the method requires the creation of the Coxeter group using the + ``'coxeter3'`` implementation. + + ALGORITHM: + + The direct algorithm for computing `C^{\prime}_x \cdot + C^{\prime}_y` runs in two steps as follows. + + If `\ell(x) \leq \ell(y)`, we first decompose `C^{\prime}_x` into + a polynomial in the generators `C^{\prime}_s (s\in S)` and then + multiply that polynomial with `C^{\prime}_y`. If `\ell(x) > + \ell(y)`, we decompose `C^{\prime}_y` into a polynomial in + `C^{\prime}_s (s\in S)` and multiply that polynomial with + `C^{\prime}_x`. The second step (multiplication) is done by + repeatedly applying the formulas displayed earlier directly. The + first step (decomposition) is done by induction on the Bruhat order + as follows: for every element `u\in W` with length `\ell(u)>1`, + pick a left descent `s` of `u` and write `u=sw` (so `w=su`), then + note that + + .. MATH:: + + C^{\prime}_u = C^{\prime}_s \cdot C^{\prime}_{w} + - \sum_{v \le u; sv < v} \mu(v,w) C^{\prime}_v + + by the earlier formulas, where the element `w` and all elements + `v`'s on the right side are lower than `u` in the Bruhat order; + this allows us to finish the computation by decomposing the lower + order terms `C^{\prime}_w` and each `C^{\prime}_v`. For example, + for `u=121, s=1, w=21` in type `A_3` we have `C^{\prime}_{121} = + C^{\prime}_1 C^{\prime}_{21} - C^{\prime}_1`, where the lower + order term `C^{\prime}_{21}` further decomposes into `C^{\prime}_2 + C^{\prime}_1`, therefore + + .. MATH:: + + C^{\prime}_{121} = C^{\prime}_1 C^{\prime}_2 C^{\prime}_1 + - C^{\prime}_1. + + We note that the base cases `\ell(x)=1` or `\ell(x)=0` of the above + induction occur when `x` is itself a Coxeter generator `s` or the + group identity, respectively. The decomposition is trivial in these + cases (we have `C^{\prime}_x=C^{\prime}_s` or `C^{\prime}_x=1`, the + unit of the Hecke algebra). + + EXAMPLES:: + + sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp() # optional - coxeter3 + sage: Cp.product_on_basis(W([1,2,1]), W([3,1])) # optional - coxeter3 + (v^-1+v)*Cp[1,2,1,3] + sage: Cp.product_on_basis(W([1,2,1]), W([3,1,2])) # optional - coxeter3 + (v^-1+v)*Cp[1,2,1,3,2] + (v^-1+v)*Cp[1,2,1] + """ + if self._W_Coxeter3 is None: + # We do not meet the conditions to use the direct product + # algorithm; fall back to conversion to/from the T-basis. + return super().product_on_basis(w1, w2) + + # If self._W_Coxeter3 is not the underlying Coxeter group, we need + # to convert elements first for this algorithm. + if self._W_Coxeter3 != self.realization_of()._W: + w1 = self._W_Coxeter3.from_reduced_word(w1.reduced_word()) + w2 = self._W_Coxeter3.from_reduced_word(w2.reduced_word()) + + # Decomposition: write one of C'_{w1} and C'_{w2} as a polynomial in the + # generators C'_{s}. + if len(w1) <= len(w2): + side = 'left' + gen_expression = self._decompose_into_generators(w1) + other_element = self.monomial(w2) + else: + side = 'right' + gen_expression = self._decompose_into_generators(w2) + other_element = self.monomial(w1) + + # Multiplication: multiply the generators in each term of the above + # polynomial onto other_element and add that summand onto result. + result = self.zero() + for (p, coeff) in gen_expression.items(): + summand = coeff * other_element + if side == 'right': + for s in p: + summand = self._product_with_generator(s, summand, side) + else: + for s in reversed(p): + summand = self._product_with_generator(s, summand, side) + result += summand + + # Again, if self._W_Coxeter3 is not the underlying Coxeter group, + # we need to convert the result. Specifically, make sure basis + # elements appearing therein are actually indexed by elements of + # the original underlying Coxeter group. + if self._W_Coxeter3 != self.realization_of()._W: + _W = self.realization_of()._W + result = self._from_dict({_W.from_reduced_word(w.reduced_word()): c + for (w, c) in result}, remove_zeros=False) + + return result + + def _product_with_generator_on_basis(self, s, w, side='left'): + r""" + Compute the product of `C^{\prime}_s` and `C^{\prime}_w`, putting + `C^{\prime}_s` on the given ``side``. + + INPUT: + + - ``s`` -- integer in ``self.index_set()`` + - ``w`` -- a word in ``self.coxeter_group()`` + - ``side`` -- string; ``'left'`` or ``'right'`` + + EXAMPLES:: + + sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, v**2); Cp = H.Cp() # optional - coxeter3 + sage: Cp._product_with_generator_on_basis(1, W([2,1]), 'left') # optional - coxeter3 + Cp[1,2,1] + Cp[1] + sage: Cp._product_with_generator_on_basis(1, W([2,1]), 'right') # optional - coxeter3 + (v^-1+v)*Cp[2,1] + sage: Cp._product_with_generator_on_basis(2, W([1,3,2,1,3]), 'right') # optional - coxeter3 + Cp[1,2,1,3,2,1] + Cp[1,2,3,2] + Cp[1,3,2,1] + """ + # use the product formula described in the class' documentation + if w.has_descent(s, side=side): + return self._from_dict({w: self._delta}, remove_zeros=False) + + element = {} + between = self._W_Coxeter3.bruhat_interval([], w) + R = self.base_ring() + for x in between: + # Get (coxeter3-implemented) group element corresponding to x + x_elt = self._W_Coxeter3(x) + if x_elt.has_descent(s, side=side): + # Compute mu-coefficient via coxeter3 + coeff = R(x.mu_coefficient(w)) + if coeff: + element[x_elt] = coeff + longer_word = self._W_Coxeter3([s]) * w if side == 'left' else w * self._W_Coxeter3([s]) + element[longer_word] = R.one() + return self._from_dict(element, remove_zeros=False) + + def _product_with_generator(self, s, x, side='left'): + r""" + Compute the product of `C^{\prime}_s` with any linear + combination of `C^{\prime}`-basis elements. + + INPUT: + + - ``s`` -- integer in ``self.index_set()`` + - ``x`` -- any element of ``self`` + - ``side`` -- string; ``'left'`` or ``'right'`` + + EXAMPLES:: + + sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, v**2); Cp = H.Cp() # optional - coxeter3 + sage: Cp._product_with_generator(1, Cp[1]+Cp[2], 'left') # optional - coxeter3 + Cp[1,2] + (v^-1+v)*Cp[1] + sage: Cp._product_with_generator(1, Cp[1]+Cp[2], 'right') # optional - coxeter3 + Cp[2,1] + (v^-1+v)*Cp[1] + """ + return self.linear_combination((self._product_with_generator_on_basis(s, w, side), coeff) for (w, coeff) in x) + + def _decompose_into_generators(self, u): + r""" + Decompose `C^{\prime}_u` into a polynomial in the KL generators + `C^{\prime}_s`; see the ALGORITHM section of + :func:`product_on_basis`. + + OUTPUT: + + A dictionary keyed by tuples with integer values. Each entry + represents a term, where the tuple represents a monomial term + in the KL generators and the value represents the coefficient + of that term. For example, an item `(1,2): 3` stands for + `3 \cdot C^{\prime}_1 C^{\prime}_2`. + + EXAMPLES:: + + sage: R. = LaurentPolynomialRing(ZZ, 'v') # optional - coxeter3 + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: H = IwahoriHeckeAlgebra(W, v**2); Cp=H.Cp() # optional - coxeter3 + + When `u` is itself a generator `s`, the decomposition is trivial:: + + sage: Cp._decompose_into_generators(W([1])) # optional - coxeter3 + {(1,): 1} + + Another example, where `C^{\prime}_u` happens to be a monomial + (e.g., `C'_{21} = C'_2 C'_1`):: + + sage: Cp._decompose_into_generators(W([2,1])) # optional - coxeter3 + {(2, 1): 1} + + In more general situations the sum is a polynomial (e.g., + `C'_{121} = C'_1 C'_2 C'_1 - C'_1)`:: + + sage: Cp._decompose_into_generators(W([1,2,1])) # optional - coxeter3 + {(1,): -1, (1, 2, 1): 1} + sage: Cp._decompose_into_generators(W([1,2,3,1,2])) # optional - coxeter3 + {(1,): 1, (1, 2, 1): -1, (1, 2, 1, 3, 2): 1, (1, 3, 2): -1} + """ + # l(y) = 0 or 1 + if not u: + return {(): 1} + if len(u) == 1: + return {(u[0],): 1} + + # l(y) > 1, use the recursive method described in product_on_basis + s = u[0] + w = u[1:] # so CpC_s * CpC_w = CpC_u + lower order terms + + # get the lower order terms ("sum_term") + sum_term = {} + between = self._W_Coxeter3.bruhat_interval([], w) + R = self.base_ring() + for v in between: + # Get (coxeter3-implemented) group element corresponding to v + v_elt = self._W_Coxeter3(v) + if v_elt.has_left_descent(s): + # Compute mu-coefficient via coxeter3 + coeff = R(v.mu_coefficient(w)) + if coeff: + sum_term[v_elt] = coeff + + # recursion: decompose C'_s * C'_w and the lower order terms + result = {(s,) + gens: coeff for (gens, coeff) in self._decompose_into_generators(w).items()} + zero = R.zero() + for (z, c1) in sum_term.items(): + # Subtract off each term from sum_term. + for (gens, c2) in self._decompose_into_generators(z).items(): + result[gens] = result.get(gens, zero) - c1 * c2 + + return result + C_prime = Cp class C(_KLHeckeBasis): diff --git a/src/sage/algebras/lie_algebras/verma_module.py b/src/sage/algebras/lie_algebras/verma_module.py index 9c9fdca0147..730714b0bb3 100644 --- a/src/sage/algebras/lie_algebras/verma_module.py +++ b/src/sage/algebras/lie_algebras/verma_module.py @@ -31,7 +31,8 @@ from sage.modules.free_module_element import vector from sage.sets.family import Family from sage.structure.richcmp import richcmp -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ class VermaModule(CombinatorialFreeModule): diff --git a/src/sage/algebras/quantum_matrix_coordinate_algebra.py b/src/sage/algebras/quantum_matrix_coordinate_algebra.py index f93f147758b..588dc76bcf8 100644 --- a/src/sage/algebras/quantum_matrix_coordinate_algebra.py +++ b/src/sage/algebras/quantum_matrix_coordinate_algebra.py @@ -238,9 +238,8 @@ def quantum_determinant(self): raise ValueError("undefined for non-square quantum matrices") from sage.combinat.permutation import Permutations q = self._q - return self.sum(self.term(self._indices({(i, p(i)): 1 for i in range(1, self._n + 1)}), - (-q) ** p.length()) - for p in Permutations(self._n)) + return self._from_dict({self._indices({(i, p(i)): 1 for i in range(1, self._n + 1)}): + (-q) ** p.length() for p in Permutations(self._n)}) def product_on_basis(self, a, b): """ @@ -515,6 +514,16 @@ def __init__(self, m, n, q, bar, R): sage: O = algebras.QuantumMatrixCoordinate(4) sage: TestSuite(O).run() + + sage: O = algebras.QuantumMatrixCoordinate(10) + sage: O.variable_names() + ('x0101', ..., 'x1010') + sage: O = algebras.QuantumMatrixCoordinate(11,3) + sage: O.variable_names() + ('x011', ..., 'x113') + sage: O = algebras.QuantumMatrixCoordinate(3,11) + sage: O.variable_names() + ('x101', ..., 'x311') """ gp_indices = [(i, j) for i in range(1, m + 1) for j in range(1, n + 1)] @@ -526,7 +535,10 @@ def __init__(self, m, n, q, bar, R): self._m = m QuantumMatrixCoordinateAlgebra_abstract.__init__(self, gp_indices, n, q, bar, R, cat) # Set the names - names = ['x{}{}'.format(*k) for k in gp_indices] + mb = len(str(m)) + nb = len(str(n)) + base = 'x{{:0>{}}}{{:0>{}}}'.format(mb,nb) + names = [base.format(*k) for k in gp_indices] self._assign_names(names) def _repr_(self): @@ -992,3 +1004,4 @@ def _generator_key(t): if isinstance(t, tuple): return t return () + diff --git a/src/sage/algebras/schur_algebra.py b/src/sage/algebras/schur_algebra.py index 2d7af71b6f6..08b921ea160 100644 --- a/src/sage/algebras/schur_algebra.py +++ b/src/sage/algebras/schur_algebra.py @@ -45,7 +45,8 @@ from sage.matrix.constructor import Matrix from sage.misc.cachefunc import cached_method from sage.misc.flatten import flatten -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ def _schur_I_nr_representatives(n, r): diff --git a/src/sage/algebras/steenrod/all.py b/src/sage/algebras/steenrod/all.py index 77a93db16ed..134b2b032cf 100644 --- a/src/sage/algebras/steenrod/all.py +++ b/src/sage/algebras/steenrod/all.py @@ -1,7 +1,8 @@ """ The Steenrod algebra """ - from .steenrod_algebra import SteenrodAlgebra, Sq -from .steenrod_algebra_bases import steenrod_algebra_basis - +from sage.misc.lazy_import import lazy_import +lazy_import('sage.algebras.steenrod.steenrod_algebra_bases', + 'steenrod_algebra_basis', + deprecation=(32647, 'removed from namespace')) diff --git a/src/sage/algebras/steenrod/steenrod_algebra.py b/src/sage/algebras/steenrod/steenrod_algebra.py index f289d4fd86d..3eb15efd811 100644 --- a/src/sage/algebras/steenrod/steenrod_algebra.py +++ b/src/sage/algebras/steenrod/steenrod_algebra.py @@ -2037,7 +2037,8 @@ def _coerce_map_from_(self, S): sage: B3._coerce_map_from_(A31) False """ - from sage.rings.all import ZZ, GF + from sage.rings.integer_ring import ZZ + from sage.rings.finite_rings.finite_field_constructor import GF from sage.rings.infinity import Infinity p = self.prime() if S == ZZ or S == GF(p): @@ -2099,7 +2100,8 @@ def _element_constructor_(self, x): sage: A1({(2,): 1, (1,): 13}) Sq(1) + Sq(2) """ - from sage.rings.all import ZZ, GF + from sage.rings.integer_ring import ZZ + from sage.rings.finite_rings.finite_field_constructor import GF if x in GF(self.prime()) or x in ZZ: return self.from_base_ring_from_one_basis(x) diff --git a/src/sage/all.py b/src/sage/all.py index 954b0c0972d..2414b7bf4bf 100644 --- a/src/sage/all.py +++ b/src/sage/all.py @@ -31,13 +31,6 @@ sage: [inspect.getmodule(f).__name__ for f in frames if is_not_allowed(f)] [] -Check that the Sage Notebook is not imported at startup (see :trac:`15335`):: - - sage: sagenb - Traceback (most recent call last): - ... - NameError: name 'sagenb' is not defined - Check lazy import of ``interacts``:: sage: type(interacts) @@ -280,7 +273,7 @@ def quit_sage(verbose=True): import sage.libs.flint.flint sage.libs.flint.flint.free_flint_stack() - # Free globally allocated mpir integers. + # Free globally allocated gmp integers. import sage.rings.integer sage.rings.integer.free_integer_pool() import sage.algebras.quatalg.quaternion_algebra_element diff --git a/src/sage/arith/misc.py b/src/sage/arith/misc.py index 651dfb8917d..9a2aa40819d 100644 --- a/src/sage/arith/misc.py +++ b/src/sage/arith/misc.py @@ -19,10 +19,6 @@ from sage.misc.misc import powerset from sage.misc.misc_c import prod -from sage.libs.pari.all import pari -from sage.libs.flint.arith import (bernoulli_number as flint_bernoulli, - dedekind_sum as flint_dedekind_sum) - from sage.structure.element import parent from sage.structure.coerce import py_scalar_to_element @@ -30,8 +26,7 @@ from sage.rings.integer_ring import ZZ from sage.rings.integer import Integer, GCD_list from sage.rings.rational import Rational -from sage.rings.real_mpfr import RealNumber -from sage.rings.complex_mpfr import ComplexNumber +from sage.rings.abc import RealField, ComplexField from sage.rings.fast_arith import arith_int, arith_llong, prime_range @@ -207,7 +202,7 @@ def algdep(z, degree, known_bits=None, use_bits=None, known_digits=None, return None return z.denominator()*x - z.numerator() - if isinstance(z, (RealNumber, ComplexNumber)): + if isinstance(z.parent(), (RealField, ComplexField)): log2_10 = math.log(10,2) @@ -221,7 +216,7 @@ def algdep(z, degree, known_bits=None, use_bits=None, known_digits=None, if use_bits is not None: prec = int(use_bits) - is_complex = isinstance(z, ComplexNumber) + is_complex = isinstance(z.parent(), ComplexField) n = degree+1 from sage.matrix.constructor import matrix M = matrix(ZZ, n, n+1+int(is_complex)) @@ -266,6 +261,7 @@ def norm(v): raise NotImplementedError("proof and height bound only implemented for real and complex numbers") else: + from sage.libs.pari.all import pari y = pari(z) f = y.algdep(degree) @@ -366,8 +362,10 @@ def bernoulli(n, algorithm='default', num_threads=1): if n >= 100000: from warnings import warn warn("flint is known to not be accurate for large Bernoulli numbers") + from sage.libs.flint.arith import bernoulli_number as flint_bernoulli return flint_bernoulli(n) elif algorithm == 'pari': + from sage.libs.pari.all import pari x = pari(n).bernfrac() # Use the PARI C library return Rational(x) elif algorithm == 'gap': @@ -465,6 +463,7 @@ def factorial(n, algorithm='gmp'): if algorithm == 'gmp': return ZZ(n).factorial() elif algorithm == 'pari': + from sage.libs.pari.all import pari return pari.factorial(n) else: raise ValueError('unknown algorithm') @@ -1785,7 +1784,7 @@ def gcd(a, b=None, **kwargs): from sage.structure.sequence import Sequence seq = Sequence(py_scalar_to_element(el) for el in a) if seq.universe() is ZZ: - return GCD_list(a) + return GCD_list(seq) else: return __GCD_sequence(seq, **kwargs) @@ -2243,7 +2242,7 @@ def rational_reconstruction(a, m, algorithm='fast'): - ``algorithm`` -- (default: 'fast') - - ``'fast'`` - a fast implementation using direct MPIR calls + - ``'fast'`` - a fast implementation using direct GMP library calls in Cython. OUTPUT: @@ -3031,6 +3030,7 @@ def __call__(self, n): return ZZ(0) if n<=2: return ZZ(1) + from sage.libs.pari.all import pari return ZZ(pari(n).eulerphi()) def plot(self, xmin=1, xmax=50, pointsize=30, rgbcolor=(0,0,1), join=True, @@ -3434,10 +3434,10 @@ def binomial(x, m, **kwds): 1/6*x^3 - 1/2*x^2 + 1/3*x If `x \in \ZZ`, there is an optional 'algorithm' parameter, which - can be 'mpir' (faster for small values) or 'pari' (faster for - large values):: + can be 'gmp' (faster for small values; alias: 'mpir') or + 'pari' (faster for large values):: - sage: a = binomial(100, 45, algorithm='mpir') + sage: a = binomial(100, 45, algorithm='gmp') sage: b = binomial(100, 45, algorithm='pari') sage: a == b True @@ -3609,7 +3609,7 @@ def binomial(x, m, **kwds): return P(x.binomial(m, **kwds)) # case 3: rational, real numbers, complex numbers -> use pari - if isinstance(x, (Rational, RealNumber, ComplexNumber)): + if isinstance(x, Rational) or isinstance(P, (RealField, ComplexField)): return P(x.__pari__().binomial(m)) # case 4: naive method @@ -4101,6 +4101,7 @@ def primitive_root(n, check=True): sage: primitive_root(mpz(-46)) 5 """ + from sage.libs.pari.all import pari if not check: return ZZ(pari(n).znprimroot()) n = ZZ(n).abs() @@ -4160,6 +4161,7 @@ def nth_prime(n): """ if n <= 0: raise ValueError("nth prime meaningless for non-positive n (=%s)" % n) + from sage.libs.pari.all import pari return ZZ(pari.prime(n)) @@ -4278,6 +4280,7 @@ def __call__(self, n): # Use fast PARI algorithm if n == 0: return ZZ.zero() + from sage.libs.pari.all import pari return ZZ(pari(n).moebius()) @@ -4363,6 +4366,8 @@ def range(self, start, stop=None, step=None): return self.range(start, 0, step) + [ZZ.zero()] +\ self.range(step, stop, step) + from sage.libs.pari.all import pari + if step == 1: v = pari('vector(%s, i, moebius(i-1+%s))'%( stop-start, start)) @@ -4492,6 +4497,7 @@ def number_of_divisors(n): m = ZZ(n) if m.is_zero(): raise ValueError("input must be nonzero") + from sage.libs.pari.all import pari return ZZ(pari(m).numdiv()) @@ -4566,6 +4572,7 @@ def hilbert_symbol(a, b, p, algorithm="pari"): if algorithm == "pari": if p == -1: p = 0 + from sage.libs.pari.all import pari return ZZ(pari(a).hilbert(b, p)) elif algorithm == 'direct': @@ -5660,12 +5667,25 @@ def sort_complex_numbers_for_display(nums): ....: RDF.random_element())) sage: shuffle(nums) sage: nums = sort_c(nums) - sage: nums[:3] - [0.0, 1.0, 2.0] - sage: for i in range(3, len(nums)-1): - ....: assert nums[i].real() <= nums[i+1].real() + 1e-10 - ....: if abs(nums[i].real() - nums[i+1].real()) < 1e-10: - ....: assert nums[i].imag() <= nums[i+1].imag() + 1e-10 + sage: for i in range(len(nums)): + ....: if nums[i].imag(): + ....: first_non_real = i + ....: break + ....: else: + ....: first_non_real = len(nums) + sage: assert first_non_real >= 3 + sage: for i in range(first_non_real - 1): + ....: assert nums[i].real() <= nums[i + 1].real() + + sage: def truncate(n): + ....: if n.real() < 1e-10: + ....: return 0 + ....: else: + ....: return n.real().n(digits=9) + sage: for i in range(first_non_real, len(nums)-1): + ....: assert truncate(nums[i]) <= truncate(nums[i + 1]) + ....: if truncate(nums[i]) == truncate(nums[i + 1]): + ....: assert nums[i].imag() <= nums[i+1].imag() """ if not nums: return nums @@ -5872,6 +5892,7 @@ def dedekind_sum(p, q, algorithm='default'): - :wikipedia:`Dedekind\_sum` """ if algorithm == 'default' or algorithm == 'flint': + from sage.libs.flint.arith import dedekind_sum as flint_dedekind_sum return flint_dedekind_sum(p, q) if algorithm == 'pari': diff --git a/src/sage/calculus/all.py b/src/sage/calculus/all.py index fe463d63bae..bc93e3f62a7 100644 --- a/src/sage/calculus/all.py +++ b/src/sage/calculus/all.py @@ -58,8 +58,8 @@ def symbolic_expression(x): 2*x^2 + 3 sage: type(a) - sage: from sage.symbolic.expression import is_Expression - sage: is_Expression(a) + sage: from sage.structure.element import Expression + sage: isinstance(a, Expression) True sage: a in SR True diff --git a/src/sage/calculus/calculus.py b/src/sage/calculus/calculus.py index 19966cfb8b6..d3a035e2a36 100644 --- a/src/sage/calculus/calculus.py +++ b/src/sage/calculus/calculus.py @@ -1462,10 +1462,17 @@ def mma_free_limit(expression, v, a, dir=None): """ Limit using Mathematica's online interface. + INPUT: + + - ``expression`` -- symbolic expression + - ``v`` -- variable + - ``a`` -- value where the variable goes to + - ``dir`` -- ``'+'``, ``'-'`` or ``None`` (optional, default:``None``) + EXAMPLES:: sage: from sage.calculus.calculus import mma_free_limit - sage: mma_free_limit(sin(x)/x, x=0) # optional - internet + sage: mma_free_limit(sin(x)/x, x, a=0) # optional - internet 1 Another simple limit:: diff --git a/src/sage/calculus/integration.pyx b/src/sage/calculus/integration.pyx index 7d624bf7528..694dcdb2f71 100644 --- a/src/sage/calculus/integration.pyx +++ b/src/sage/calculus/integration.pyx @@ -245,6 +245,14 @@ def numerical_integral(func, a, b=None, Traceback (most recent call last): ... ValueError: integral does not converge at -infinity + + Symbolic functions can be integrated as conveniently as symbolic + expressions, as in :trac:`15219`:: + + sage: h(x) = x + sage: numerical_integral(h,0,1)[0] # abs tol 1e-8 + 0.5 + """ cdef double abs_err # step size cdef double result @@ -605,8 +613,8 @@ def monte_carlo_integral(func, xl, xu, size_t calls, algorithm='plain', "more items in upper and lower limits" ).format(len(vars), tuple(vars), target_dim)) - from sage.symbolic.expression import is_Expression - if is_Expression(func): + from sage.structure.element import Expression + if isinstance(func, Expression): if params: to_sub = dict(zip(vars[-len(params):], params)) func = func.subs(to_sub) diff --git a/src/sage/categories/coxeter_groups.py b/src/sage/categories/coxeter_groups.py index a2a6a44b5b8..70a20541ed7 100644 --- a/src/sage/categories/coxeter_groups.py +++ b/src/sage/categories/coxeter_groups.py @@ -22,7 +22,10 @@ from sage.categories.generalized_coxeter_groups import GeneralizedCoxeterGroups from sage.structure.element import have_same_parent, parent from sage.misc.flatten import flatten +from sage.graphs.digraph import DiGraph +from sage.rings.integer_ring import ZZ from copy import copy +from collections import deque class CoxeterGroups(Category_singleton): @@ -686,6 +689,139 @@ def simple_projection(self, i, side='right', length_increasing=True): return lambda x: x.apply_simple_projection(i, side=side, length_increasing=length_increasing) + def kazhdan_lusztig_cells(self, side='left'): + r""" + Compute the left, right, or two-sided Kazhdan-Lusztig cells of + ``self`` if ``self`` is finite. + + The cells are computed by using :func:`kazhdan_lusztig_cell() + `. + + As detailed there, installation of the optional package ``coxeter3`` + is recommended (though not required) before using this function + as it speeds up the computation. + + INPUT: + + - ``side`` -- (default: ``'left'``) either ``'left'``, + ``'right'``, or ``'two-sided'`` + + EXAMPLES: + + We compute the right cells in the Coxeter group of type `A_2` + below. Note that each Coxeter group may be created with multiple + implementations, namely, 'reflection' (default), 'permutation', + 'matrix', or 'coxeter3'. The choice of implementation affects the + representation of elements in the output cells but not the method + used for the cell computation:: + + sage: W = CoxeterGroup('A2') + sage: KL_cells = W.kazhdan_lusztig_cells(side='right') + sage: set([tuple(sorted(C, key=lambda w: w.reduced_word())) + ....: for C in KL_cells]) + {( + [-1 1] [ 0 -1] + [ 0 1], [ 1 -1] + ), + ( + [ 0 -1] + [-1 0] + ), + ( + [1 0] + [0 1] + ), + ( + [ 1 0] [-1 1] + [ 1 -1], [-1 0] + )} + sage: len(KL_cells) + 4 + + sage: W = CoxeterGroup('A2', implementation='permutation') + sage: len(W.kazhdan_lusztig_cells(side='right')) + 4 + + We compute the left cells in the Coxeter group of type `A_3` + below. If the optional package ``coxeter3`` is installed, it + runs in the background even if the group is not created with + the ``'coxeter3'`` implementation:: + + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: KL_cells = W.kazhdan_lusztig_cells() # optional - coxeter3 + sage: set([tuple(sorted(C)) for C in KL_cells]) # optional - coxeter3 + {([],), + ([1], [2, 1], [3, 2, 1]), + ([1, 2], [2], [3, 2]), + ([1, 2, 1], [1, 3, 2, 1], [2, 1, 3, 2, 1]), + ([1, 2, 1, 3], [1, 2, 3, 2, 1], [2, 3, 2, 1]), + ([1, 2, 1, 3, 2], [1, 2, 3, 2], [2, 3, 2]), + ([1, 2, 1, 3, 2, 1],), + ([1, 2, 3], [2, 3], [3]), + ([1, 3], [2, 1, 3]), + ([1, 3, 2], [2, 1, 3, 2])} + sage: len(KL_cells) # optional - coxeter3 + 10 + + sage: W = CoxeterGroup('A3', implementation='permutation') # optional - coxeter3 + sage: len(W.kazhdan_lusztig_cells()) # optional - coxeter3 + 10 + + Computing the two sided cells in `B_3`:: + + sage: W = CoxeterGroup('B3', implementation='coxeter3') # optional - coxeter3 + sage: b3_cells = W.kazhdan_lusztig_cells('two-sided') # optional - coxeter3 + sage: len(b3_cells) # optional - coxeter3 + 6 + sage: set([tuple(sorted(C)) for C in W.kazhdan_lusztig_cells()]) # optional - coxeter3 + {([],), + ([1], [1, 2, 3, 2, 1], [2, 1], [2, 3, 2, 1], [3, 2, 1]), + ([1, 2], [1, 2, 3, 2], [2], [2, 3, 2], [3, 2]), + ([1, 2, 3], [2, 3], [3], [3, 2, 3]), + ([2, 1, 2], [2, 3, 2, 1, 2], [3, 2, 1, 2]), + ([2, 1, 2, 3], [2, 3, 2, 1, 2, 3], [3, 2, 1, 2, 3]), + ([2, 1, 2, 3, 2], [2, 3, 2, 1, 2, 3, 2], [3, 2, 1, 2, 3, 2]), + ([2, 1, 2, 3, 2, 1], + [2, 3, 2, 1, 2, 3, 2, 1], + [3, 2, 1, 2, 3, 2, 1], + [3, 2, 3, 2, 1, 2]), + ([2, 3, 1], [3, 1], [3, 2, 3, 1]), + ([2, 3, 1, 2], [3, 1, 2], [3, 2, 3, 1, 2]), + ([2, 3, 1, 2, 3], [3, 1, 2, 3], [3, 2, 3, 1, 2, 3]), + ([2, 3, 1, 2, 3, 2], + [3, 1, 2, 3, 2], + [3, 2, 3, 1, 2, 3, 2], + [3, 2, 3, 2], + [3, 2, 3, 2, 1, 2, 3, 2]), + ([2, 3, 1, 2, 3, 2, 1], + [3, 1, 2, 3, 2, 1], + [3, 2, 3, 1, 2, 3, 2, 1], + [3, 2, 3, 2, 1], + [3, 2, 3, 2, 1, 2, 3]), + ([3, 2, 3, 2, 1, 2, 3, 2, 1],)} + + TESTS:: + + sage: W = CoxeterGroup(['A', 2, 1]) + sage: W.kazhdan_lusztig_cells() + Traceback (most recent call last): + ... + ValueError: the Coxeter group must be finite to compute Kazhdan--Lusztig cells + """ + if not self.coxeter_type().is_finite(): + raise ValueError('the Coxeter group must be finite to compute Kazhdan--Lusztig cells') + + # The identity is its own left-, right-, and two-sided- cell. + identity = frozenset([self.one()]) + cells = {identity} + + for w in self: + if not any(w in c for c in cells): + cell = w.kazhdan_lusztig_cell(side=side) + cells.add(frozenset(cell)) + + return cells + @cached_method def simple_projections(self, side='right', length_increasing=True): r""" @@ -751,7 +887,7 @@ def sign_representation(self, base_ring=None, side="twosided"): sage: W = WeylGroup(["A", 1, 1]) sage: W.sign_representation() Sign representation of Weyl Group of type ['A', 1, 1] (as a matrix group acting on the root space) over Integer Ring - + """ if base_ring is None: from sage.rings.integer_ring import ZZ @@ -2683,3 +2819,130 @@ def upper_covers(self, side='right', index_set=None): """ return self.weak_covers(side=side, index_set=index_set, positive=True) + + def kazhdan_lusztig_cell(self, side='left'): + r""" + Compute the left, right, or two-sided Kazhdan-Lusztig cell + containing the element ``self`` depending on the specified ``side``. + + Let `C'` denote the Kazhdan-Lusztig `C^{\prime}`-basis of the + Iwahori-Hecke algebra `H` of a Coxeter system `(W,S)`. Two elements + `x,y` of the Coxeter group `W` are said to lie in the same left + Kazhdan-Lusztig cell if there exist sequences `x = w_1, w_2, \ldots, + w_k = y` and `y = u_1, u_2, \ldots, u_l = x` such that for all + `1 \leq i < k` and all `1 \leq j < l`, there exist some Coxeter + generators `s,t \in S` for which `C'_{w_{i+1}}` appears in + `C'_s C'_{w_i}` and `C'_{u_{j+1}}` appears in `C'_s C'_{u_j}` + in `H`. Right and two-sided Kazhdan-Lusztig cells of `W` are + defined similarly; see [Lus2013]_. + + In this function, we compute products in the `C^{\prime}` basis by + using :class:`IwahoriHeckeAlgebra.Cp`. As mentioned in that class, + installing the optional package ``coxeter3`` is recommended + (though not required) before using this function because the + package speeds up product computations that are sometimes + computationally infeasible without it. + + INPUT: + + - ``w`` -- an element of ``self`` + + - ``side`` -- (default: ``'left'``) the kind of cell to compute; + must be either ``'left'``, ``'right'``, or ``'two-sided'`` + + EXAMPLES: + + We compute the left cell of the generator `s_1` in type `A_3` in + three different implementations of the Coxeter group. Note that the + choice of implementation affects the representation of elements in + the output cell but not the method used for the cell computation:: + + sage: W = CoxeterGroup('A3', implementation='permutation') + sage: s1,s2,s3 = W.simple_reflections() + sage: s1.kazhdan_lusztig_cell() + {(1,2,3,12)(4,5,10,11)(6,7,8,9), + (1,2,10)(3,6,5)(4,7,8)(9,12,11), + (1,7)(2,4)(5,6)(8,10)(11,12)} + + The cell computation uses the optional package ``coxeter3`` in + the background if available to speed up the computation, + even in the different implementations implementations:: + + sage: W = WeylGroup('A3', prefix='s') # optional - coxeter3 + sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 + sage: s1.kazhdan_lusztig_cell() # optional - coxeter3 + {s3*s2*s1, s2*s1, s1} + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 + sage: s1.kazhdan_lusztig_cell() # optional - coxeter3 + {[1], [2, 1], [3, 2, 1]} + + Next, we compute a right cell and a two-sided cell in `A_3`:: + + sage: W = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: s1,s2,s3 = W.simple_reflections() # optional - coxeter3 + sage: w = s1 * s3 # optional - coxeter3 + sage: w.kazhdan_lusztig_cell(side='right') # optional - coxeter3 + {[1, 3], [1, 3, 2]} + sage: w.kazhdan_lusztig_cell(side='two-sided') # optional - coxeter3 + {[1, 3], [1, 3, 2], [2, 1, 3], [2, 1, 3, 2]} + + Some slightly longer computations in `B_4`:: + + sage: W = CoxeterGroup('B4', implementation='coxeter3') # optional - coxeter3 + sage: s1,s2,s3,s4 = W.simple_reflections() # optional - coxeter3 + sage: s1.kazhdan_lusztig_cell(side='right') # long time (4 seconds) # optional - coxeter3 + {[1], + [1, 2], + [1, 2, 3], + [1, 2, 3, 4], + [1, 2, 3, 4, 3], + [1, 2, 3, 4, 3, 2], + [1, 2, 3, 4, 3, 2, 1]} + sage: (s4*s2*s3*s4).kazhdan_lusztig_cell(side='two-sided') # long time (8 seconds) # optional - coxeter3 + {[2, 3, 1], + [2, 3, 1, 2], + [2, 3, 4, 1], + [2, 3, 4, 1, 2], + [2, 3, 4, 1, 2, 3], + [2, 3, 4, 1, 2, 3, 4], + [2, 3, 4, 3, 1], + [2, 3, 4, 3, 1, 2], + ... + [4, 3, 4, 2, 3, 4, 1, 2, 3, 4]} + """ + from sage.algebras.iwahori_hecke_algebra import IwahoriHeckeAlgebra + from sage.rings.polynomial.laurent_polynomial_ring import LaurentPolynomialRing + + R = LaurentPolynomialRing(ZZ, 'v') + v = R.gen(0) + H = IwahoriHeckeAlgebra(self.parent(), v**2) + Cp = H.Cp() + + w = self.parent()(self) + + vertices, edges = {w}, set() + queue = deque([w]) + + while queue: + x = queue.pop() + cp_x = Cp(x) + for s in self.parent().simple_reflections(): + cp_s = Cp(s) + terms = [] + # Determine the Cp basis elements appearing in the product of Cp_s and Cp_w + if side == 'left' or side == 'two-sided': + terms.extend(list(cp_s * cp_x)) + if side == 'right' or side == 'two-sided': + terms.extend(list(cp_x * cp_s)) + for (y, coeff) in terms: + # the result of multiplication will always have coeff != 0 + if y != x: + edges.add((x, y)) + if y not in vertices: + vertices.add(y) + queue.appendleft(y) + + g = DiGraph([list(vertices), list(edges)]) + return set(g.strongly_connected_component_containing_vertex(w)) + diff --git a/src/sage/categories/enumerated_sets.py b/src/sage/categories/enumerated_sets.py index 4ca5747f04e..68bebd0f84f 100644 --- a/src/sage/categories/enumerated_sets.py +++ b/src/sage/categories/enumerated_sets.py @@ -146,7 +146,7 @@ def _call_(self, X): """ import sage.sets.set if isinstance(X, (tuple, list, set, range, sage.sets.set.Set_object_enumerated)): - return sage.sets.all.FiniteEnumeratedSet(X) + return sage.sets.finite_enumerated_set.FiniteEnumeratedSet(X) raise NotImplementedError class ParentMethods: diff --git a/src/sage/categories/modules_with_basis.py b/src/sage/categories/modules_with_basis.py index bb1dd2d4bbf..6cd291e4c91 100644 --- a/src/sage/categories/modules_with_basis.py +++ b/src/sage/categories/modules_with_basis.py @@ -219,7 +219,7 @@ def basis(self): sage: list(QS3.basis()) [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]] """ - from sage.combinat.family import Family + from sage.sets.family import Family return Family(self._indices, self.monomial) def module_morphism(self, on_basis=None, matrix=None, function=None, @@ -1155,7 +1155,7 @@ def _apply_module_morphism(self, x, on_basis, codomain=False): """ if x == self.zero(): if not codomain: - from sage.combinat.family import Family + from sage.sets.family import Family B = Family(self.basis()) try: z = B.first() diff --git a/src/sage/categories/pushout.py b/src/sage/categories/pushout.py index 7a15885b609..10e17140849 100644 --- a/src/sage/categories/pushout.py +++ b/src/sage/categories/pushout.py @@ -2584,7 +2584,7 @@ def merge(self, other): True """ if self == other: # both are Completion functors with the same p - from sage.all import Infinity + from sage.rings.infinity import Infinity if self.p == Infinity: new_prec = min(self.prec, other.prec) new_type = self._real_types[min(self._real_types.index(self.type), @@ -2773,7 +2773,7 @@ def _apply_functor(self, R): if not I.is_zero(): from sage.categories.fields import Fields if R in Fields(): - from sage.all import Integers + from sage.rings.finite_rings.integer_mod_ring import Integers return Integers(1) if I.ring() != R: if I.ring().has_coerce_map_from(R): @@ -3153,8 +3153,10 @@ def _apply_functor(self, R): 3-adic Eisenstein Extension Field in a defined by a^2 - 3 """ - from sage.all import QQ, ZZ, CyclotomicField + from sage.rings.rational_field import QQ + from sage.rings.integer_ring import ZZ if self.cyclotomic: + from sage.rings.number_field.number_field import CyclotomicField if R == QQ: return CyclotomicField(self.cyclotomic) if R == ZZ: @@ -3325,7 +3327,7 @@ def merge(self, other): # return other # ... or we may use the given embeddings: if self.embeddings != [None] and other.embeddings != [None]: - from sage.all import QQ + from sage.rings.rational_field import QQ KS = self(QQ) KO = other(QQ) if KS.has_coerce_map_from(KO): @@ -3566,7 +3568,7 @@ def merge(self, other): """ if self.__class__ != other.__class__: return None - from sage.sets.all import FiniteEnumeratedSet + from sage.sets.finite_enumerated_set import FiniteEnumeratedSet new_domain = set(self._domain).union(set(other._domain)) try: diff --git a/src/sage/combinat/abstract_tree.py b/src/sage/combinat/abstract_tree.py index 90b278a05ef..65fec9cacdd 100644 --- a/src/sage/combinat/abstract_tree.py +++ b/src/sage/combinat/abstract_tree.py @@ -62,6 +62,7 @@ - Florent Hivert (2010-2011): initial revision - Frédéric Chapoton (2011): contributed some methods """ +import itertools from sage.structure.list_clone import ClonableArray from sage.rings.integer import Integer @@ -195,15 +196,8 @@ def pre_order_traversal_iter(self): if self.is_empty(): return yield self - # TODO:: PYTHON 3 - # import itertools - # yield from itertools.chain(map( - # lambda c: c.pre_order_traversal_iter(), - # self - # )) - for children in self: - for node in children.pre_order_traversal_iter(): - yield node + yield from itertools.chain(*[c.pre_order_traversal_iter() + for c in self]) def iterative_pre_order_traversal(self, action=None): r""" @@ -275,7 +269,8 @@ def iterative_pre_order_traversal(self, action=None): if self.is_empty(): return if action is None: - action = lambda x: None + def action(x): + return None stack = [] stack.append(self) while stack: @@ -390,7 +385,8 @@ def pre_order_traversal(self, action=None): 7 """ if action is None: - action = lambda x: None + def action(x): + return None for node in self.pre_order_traversal_iter(): action(node) @@ -484,15 +480,8 @@ def post_order_traversal_iter(self): """ if self.is_empty(): return - # TODO:: PYTHON 3 - # import itertools - # yield from itertools.chain(map( - # lambda c: c.post_order_traversal_iter(), - # self - # )) - for children in self: - for node in children.post_order_traversal_iter(): - yield node + yield from itertools.chain(*[c.post_order_traversal_iter() + for c in self]) yield self def post_order_traversal(self, action=None): @@ -563,7 +552,8 @@ def post_order_traversal(self, action=None): 7 """ if action is None: - action = lambda x: None + def action(x): + return None for node in self.post_order_traversal_iter(): action(node) @@ -638,7 +628,8 @@ def iterative_post_order_traversal(self, action=None): if self.is_empty(): return if action is None: - action = lambda x: None + def action(x): + return None stack = [self] while stack: node = stack[-1] @@ -725,7 +716,8 @@ def breadth_first_order_traversal(self, action=None): if self.is_empty(): return if action is None: - action = lambda x: None + def action(x): + return None queue = [] queue.append(self) while queue: @@ -1179,10 +1171,10 @@ def node_to_str(t): return t_repr if len(self) == 1: repr_child = self[0]._ascii_art_() - sep = AsciiArt([" "*(repr_child._root-1)]) + sep = AsciiArt([" " * (repr_child._root - 1)]) t_repr = AsciiArt([node_to_str(self)]) t_repr._root = 1 - repr_root = (sep + t_repr)*(sep + AsciiArt(["|"])) + repr_root = (sep + t_repr) * (sep + AsciiArt(["|"])) t_repr = repr_root * repr_child t_repr._root = repr_child._root t_repr._baseline = t_repr._h - 1 @@ -1190,9 +1182,9 @@ def node_to_str(t): # General case l_repr = [subtree._ascii_art_() for subtree in self] acc = l_repr.pop(0) - whitesep = acc._root+1 - lf_sep = " "*(acc._root+1) + "_"*(acc._l-acc._root) - ls_sep = " "*(acc._root) + "/" + " "*(acc._l-acc._root) + whitesep = acc._root + 1 + lf_sep = " " * (acc._root + 1) + "_" * (acc._l - acc._root) + ls_sep = " " * (acc._root) + "/" + " " * (acc._l - acc._root) while l_repr: t_repr = l_repr.pop(0) acc += AsciiArt([" "]) + t_repr @@ -1200,10 +1192,10 @@ def node_to_str(t): lf_sep += "_" * (t_repr._root + 1) else: lf_sep += "_" * (t_repr._l + 1) - ls_sep += " "*(t_repr._root) + "/" + " "*(t_repr._l-t_repr._root) + ls_sep += " " * (t_repr._root) + "/" + " " * (t_repr._l - t_repr._root) mid = whitesep + (len(lf_sep) - whitesep) // 2 node = node_to_str(self) - t_repr = AsciiArt([lf_sep[:mid-1] + node + lf_sep[mid+len(node)-1:], ls_sep]) * acc + t_repr = AsciiArt([lf_sep[:mid - 1] + node + lf_sep[mid + len(node) - 1:], ls_sep]) * acc t_repr._root = mid t_repr._baseline = t_repr._h - 1 return t_repr @@ -1485,7 +1477,7 @@ def _latex_(self): new_cmd4 = "$}\n;}" # some variables to simplify code sep = "\\&" - space = " "*9 + space = " " * 9 sepspace = sep + space spacesep = space + sep @@ -1952,7 +1944,7 @@ def __setitem_rec__(self, idx, i, value): self._setitem(idx[-1], value) else: with self[idx[i]].clone() as child: - child.__setitem_rec__(idx, i+1, value) + child.__setitem_rec__(idx, i + 1, value) self[idx[i]] = child def __getitem__(self, idx): diff --git a/src/sage/combinat/backtrack.py b/src/sage/combinat/backtrack.py index 60df7b7eb05..2ec84286ea3 100644 --- a/src/sage/combinat/backtrack.py +++ b/src/sage/combinat/backtrack.py @@ -41,7 +41,7 @@ class GenericBacktracker(object): A generic backtrack tool for exploring a search space organized as a tree, with branch pruning, etc. - See also :class:`RecursivelyEnumeratedSet_forest` and :class:`TransitiveIdeal` for + See also :class:`RecursivelyEnumeratedSet_forest` for handling simple special cases. """ def __init__(self, initial_data, initial_state): diff --git a/src/sage/combinat/chas/fsym.py b/src/sage/combinat/chas/fsym.py index 5a3fe04b921..d618f44d3fd 100644 --- a/src/sage/combinat/chas/fsym.py +++ b/src/sage/combinat/chas/fsym.py @@ -284,7 +284,7 @@ def basis(self, degree=None): sage: TG.basis(degree=3).list() [G[123], G[13|2], G[12|3], G[1|2|3]] """ - from sage.combinat.family import Family + from sage.sets.family import Family if degree is None: return Family(self._indices, self.monomial) else: diff --git a/src/sage/combinat/cluster_algebra_quiver/quiver_mutation_type.py b/src/sage/combinat/cluster_algebra_quiver/quiver_mutation_type.py index ef3eb1e6d5d..f697451a99c 100644 --- a/src/sage/combinat/cluster_algebra_quiver/quiver_mutation_type.py +++ b/src/sage/combinat/cluster_algebra_quiver/quiver_mutation_type.py @@ -15,7 +15,7 @@ # Distributed under the terms of the GNU General Public License (GPL) # https://www.gnu.org/licenses/ # *************************************************************************** - +from __future__ import annotations import os import pickle @@ -62,12 +62,12 @@ def __call__(self, *args): _mutation_type_error(data) # check for reducible types - if all( type( data_component ) in [list,tuple,QuiverMutationType_Irreducible] for data_component in data ): + if all(type(data_component) in [list, tuple, QuiverMutationType_Irreducible] for data_component in data): if len(data) == 1: return QuiverMutationType(data[0]) else: - data = tuple( QuiverMutationType(comp) for comp in data ) - return QuiverMutationType_Reducible( *data ) + data = tuple(QuiverMutationType(comp) for comp in data) + return QuiverMutationType_Reducible(*data) # check for irreducible types if len(data) == 2: @@ -83,114 +83,114 @@ def __call__(self, *args): data = (data[0], tuple(data[1]), data[2]) # mutation type casting - if data == ('D',2,None): - return QuiverMutationType( ('A',1,None), ('A',1,None) ) - elif data == ('D',3,None): - data = ('A',3,None) - elif data == ('C',2,None): - data = ('B',2,None) - elif data == ('E',9,None): - data = ('E',8,1) + if data == ('D', 2, None): + return QuiverMutationType(('A', 1, None), ('A', 1, None)) + elif data == ('D', 3, None): + data = ('A', 3, None) + elif data == ('C', 2, None): + data = ('B', 2, None) + elif data == ('E', 9, None): + data = ('E', 8, 1) elif data[0] == 'A' and data[2] == 1 and isinstance(data[1], tuple) and len(data[1]) == 2 and min(data[1]) == 0: if max(data[1]) == 0: pass elif max(data[1]) == 1: - data = ('A', 1,None) + data = ('A', 1, None) elif max(data[1]) == 2: - return QuiverMutationType( ('A',1,None), ('A',1,None) ) + return QuiverMutationType(('A', 1, None), ('A', 1, None)) elif max(data[1]) == 3: - data = ('A',3,None) + data = ('A', 3, None) else: - data = ('D',max(data[1]),None) + data = ('D', max(data[1]), None) elif data[0] == 'GR' and data[2] is None and isinstance(data[1], tuple) and len(data[1]) == 2 and data[1][1] > data[1][0]: - if min(data[1]) > max(data[1])/2 and max(data[1]) != min(data[1])+1: - data = (data[0],(max(data[1])-min(data[1]),max(data[1])),data[2]) + if min(data[1]) > max(data[1]) / 2 and max(data[1]) != min(data[1]) + 1: + data = (data[0], (max(data[1]) - min(data[1]), max(data[1])), data[2]) if min(data[1]) == 2 and max(data[1]) > 3: - data = ('A',max(data[1])-3,None) - elif data[1] == (3,6): - data = ('D',4,None) - elif data[1] == (3,7): - data = ('E',6,None) - elif data[1] == (3,8): - data = ('E',8,None) - elif data[1] == (3,9): - data = ('E',8,[1,1]) - elif data[1] == (4,8): - data = ('E',7,[1,1]) - elif data == ('TR',1,None): - data = ('A',1,None) - elif data == ('TR',2,None): - data = ('A',3,None) - elif data == ('TR',3,None): - data = ('D',6,None) - elif data == ('TR',4,None): - data = ('E',8,(1,1)) + data = ('A', max(data[1]) - 3, None) + elif data[1] == (3, 6): + data = ('D', 4, None) + elif data[1] == (3, 7): + data = ('E', 6, None) + elif data[1] == (3, 8): + data = ('E', 8, None) + elif data[1] == (3, 9): + data = ('E', 8, [1, 1]) + elif data[1] == (4, 8): + data = ('E', 7, [1, 1]) + elif data == ('TR', 1, None): + data = ('A', 1, None) + elif data == ('TR', 2, None): + data = ('A', 3, None) + elif data == ('TR', 3, None): + data = ('D', 6, None) + elif data == ('TR', 4, None): + data = ('E', 8, (1, 1)) # mutation type casting from Kac conventions - elif data == ('A',1,1): - data = ('A',(1,1),1) + elif data == ('A', 1, 1): + data = ('A', (1, 1), 1) elif data[0] == 'B' and data[2] == 1: if data[1] == 2: - data = ('CC',2,1) + data = ('CC', 2, 1) elif data[1] > 2: - data = ('BD',data[1],1) + data = ('BD', data[1], 1) elif data[0] == 'B' and data[2] == -1: if data[1] == 2: - data = ('BB',2,1) + data = ('BB', 2, 1) elif data[1] > 2: data = ('CD', data[1], 1) elif data[0] == 'C' and data[1] > 1 and data[2] == 1: - data = ('CC', data[1],1) + data = ('CC', data[1], 1) elif data[0] == 'C' and data[1] > 1 and data[2] == -1: data = ('BB', data[1], 1) - elif data == ('A',2,2): + elif data == ('A', 2, 2): data = ('BC', 1, 1) elif data[0] == 'A' and data[1] in ZZ and data[1] > 1 and data[1] % 2 == 0 and data[2] == 2: data = ('BC', data[1] // 2, 1) elif data[0] == 'A' and data[1] in ZZ and data[1] > 3 and data[1] % 2 and data[2] == 2: data = ('CD', (data[1] + 1) // 2, 1) - # We think of ('A',3,2) as ('D',3,2) - elif data == ('A',3,2): - data = ('BB',2,1) + # We think of ('A',3, 2) as ('D',3, 2) + elif data == ('A', 3, 2): + data = ('BB', 2, 1) elif data[0] == 'D' and data[1] in ZZ and data[1] > 2 and data[2] == 2: - data = ('BB',data[1]-1,1) - elif data == ('E',6,2): - data = ('F',4,-1) - elif data == ('D',4,3): - data = ('G',2,-1) - elif data == ('F',4,(2,1)): - data = ('F',4,(1,2)) - elif data == ('G',2,(3,1)): - data = ('G',2,(1,3)) + data = ('BB', data[1] - 1, 1) + elif data == ('E', 6, 2): + data = ('F', 4, -1) + elif data == ('D', 4, 3): + data = ('G', 2, -1) + elif data == ('F', 4, (2, 1)): + data = ('F', 4, (1, 2)) + elif data == ('G', 2, (3, 1)): + data = ('G', 2, (1, 3)) elif data[0] == 'T' and data[2] is None: - data = (data[0],tuple(sorted(data[1])),data[2]) - r,p,q = data[1] + data = (data[0], tuple(sorted(data[1])), data[2]) + r, p, q = data[1] if r == 1: - data = ('A',p+q-1,None) + data = ('A', p + q - 1, None) elif r == p == 2: - data = ('D',q+2,None) + data = ('D', q + 2, None) elif r == 2 and p == 3: - if q in (3,4,5): - data = ('E',q+3,None) + if q in (3, 4, 5): + data = ('E', q + 3, None) elif q == 6: - data = ('E',8,1) + data = ('E', 8, 1) else: - data = ('E',q+3,None) + data = ('E', q + 3, None) elif r == 2 and p == q == 4: - data = ('E',7,1) + data = ('E', 7, 1) elif r == p == q == 3: - data = ('E',6,1) - elif data[0] == 'R2' and data[2] is None and all(data[1][i] in ZZ and data[1][i] > 0 for i in [0,1]): + data = ('E', 6, 1) + elif data[0] == 'R2' and data[2] is None and all(data[1][i] in ZZ and data[1][i] > 0 for i in [0, 1]): data = (data[0], tuple(sorted(data[1])), data[2]) - if data[1] == (1,1): - data = ('A',2,None) - elif data[1] == (1,2): - data = ('B',2,None) - elif data[1] == (1,3): - data = ('G',2,None) - elif data[1] == (1,4): - data = ('BC',1,1) - elif data[1] == (2,2): - data = ('A',(1,1),1) + if data[1] == (1, 1): + data = ('A', 2, None) + elif data[1] == (1, 2): + data = ('B', 2, None) + elif data[1] == (1, 3): + data = ('G', 2, None) + elif data[1] == (1, 4): + data = ('BC', 1, 1) + elif data[1] == (2, 2): + data = ('A', (1, 1), 1) # setting the parameters and returning the mutation type letter, rank, twist = data @@ -200,9 +200,9 @@ def __call__(self, *args): rank = tuple(rank) if isinstance(twist, list): twist = tuple(twist) - return QuiverMutationType_Irreducible(letter,rank,twist) + return QuiverMutationType_Irreducible(letter, rank, twist) - def _repr_(self): + def _repr_(self) -> str: """ Return the string representation of ``self``. @@ -284,13 +284,13 @@ def _samples(self): ["E", 6], ["E", 7], ["E", 8], ["F", 4], ["G", 2]]] affine_types = \ - [QuiverMutationType(t) for t in [['A', [1,1], 1], ['A', [4,5], 1], ['D', 4, 1], ['BB', 5, 1]]] + [QuiverMutationType(t) for t in [['A', [1, 1], 1], ['A', [4, 5], 1], ['D', 4, 1], ['BB', 5, 1]]] elliptic_types = \ - [QuiverMutationType(t) for t in [['E', 6, [1,1]], ['E', 7, [1,1]]]] + [QuiverMutationType(t) for t in [['E', 6, [1, 1]], ['E', 7, [1, 1]]]] mutation_finite_types = \ - [QuiverMutationType(t) for t in [['R2',(1,5)], ['R2',(3,5)]]] + [QuiverMutationType(t) for t in [['R2', (1, 5)], ['R2', (3, 5)]]] mutation_infinite_types = \ - [QuiverMutationType(t) for t in [['E',10], ['BE',5], ['GR',(3,10)], ['T',(3,3,4)]]] + [QuiverMutationType(t) for t in [['E', 10], ['BE', 5], ['GR', (3, 10)], ['T', (3, 3, 4)]]] return finite_types + affine_types + elliptic_types + mutation_finite_types + mutation_infinite_types @@ -299,7 +299,7 @@ def _samples(self): QuiverMutationType.__doc__ = \ -r""" + r""" *Quiver mutation types* can be seen as a slight generalization of *generalized Cartan types*. @@ -358,7 +358,7 @@ def _samples(self): ``BC`` and ``rank=1``. * Macdonald notation: for the dual of an untwisted affine type - (such as ['C', 6,1]), we accept a twist of -1 (i.e., + (such as ['C', 6, 1]), we accept a twist of -1 (i.e., ['C',6,-1]). - Elliptic type -- ``letter`` is a Dynkin type, ``rank`` is the rank @@ -417,22 +417,22 @@ def _samples(self): Finite types:: - sage: QuiverMutationType('A',1) + sage: QuiverMutationType('A', 1) ['A', 1] sage: QuiverMutationType('A',5) ['A', 5] - sage: QuiverMutationType('B',2) + sage: QuiverMutationType('B', 2) ['B', 2] sage: QuiverMutationType('B',5) ['B', 5] - sage: QuiverMutationType('C',2) + sage: QuiverMutationType('C', 2) ['B', 2] sage: QuiverMutationType('C',5) ['C', 5] - sage: QuiverMutationType('D',2) + sage: QuiverMutationType('D', 2) [ ['A', 1], ['A', 1] ] sage: QuiverMutationType('D',3) ['A', 3] @@ -442,111 +442,111 @@ def _samples(self): sage: QuiverMutationType('E',6) ['E', 6] - sage: QuiverMutationType('G',2) + sage: QuiverMutationType('G', 2) ['G', 2] - sage: QuiverMutationType('A',(1,0),1) + sage: QuiverMutationType('A',(1,0), 1) ['A', 1] - sage: QuiverMutationType('A',(2,0),1) + sage: QuiverMutationType('A',(2,0), 1) [ ['A', 1], ['A', 1] ] - sage: QuiverMutationType('A',(7,0),1) + sage: QuiverMutationType('A',(7,0), 1) ['D', 7] Affine types:: - sage: QuiverMutationType('A',(1,1),1) + sage: QuiverMutationType('A',(1, 1), 1) ['A', [1, 1], 1] - sage: QuiverMutationType('A',(2,4),1) + sage: QuiverMutationType('A',(2,4), 1) ['A', [2, 4], 1] - sage: QuiverMutationType('BB',2,1) + sage: QuiverMutationType('BB', 2, 1) ['BB', 2, 1] - sage: QuiverMutationType('BB',4,1) + sage: QuiverMutationType('BB',4, 1) ['BB', 4, 1] - sage: QuiverMutationType('CC',2,1) + sage: QuiverMutationType('CC', 2, 1) ['CC', 2, 1] - sage: QuiverMutationType('CC',4,1) + sage: QuiverMutationType('CC',4, 1) ['CC', 4, 1] - sage: QuiverMutationType('BC',1,1) + sage: QuiverMutationType('BC', 1, 1) ['BC', 1, 1] - sage: QuiverMutationType('BC',5,1) + sage: QuiverMutationType('BC',5, 1) ['BC', 5, 1] - sage: QuiverMutationType('BD',3,1) + sage: QuiverMutationType('BD',3, 1) ['BD', 3, 1] - sage: QuiverMutationType('BD',5,1) + sage: QuiverMutationType('BD',5, 1) ['BD', 5, 1] - sage: QuiverMutationType('CD',3,1) + sage: QuiverMutationType('CD',3, 1) ['CD', 3, 1] - sage: QuiverMutationType('CD',5,1) + sage: QuiverMutationType('CD',5, 1) ['CD', 5, 1] - sage: QuiverMutationType('D',4,1) + sage: QuiverMutationType('D',4, 1) ['D', 4, 1] - sage: QuiverMutationType('D',6,1) + sage: QuiverMutationType('D',6, 1) ['D', 6, 1] - sage: QuiverMutationType('E',6,1) + sage: QuiverMutationType('E',6, 1) ['E', 6, 1] - sage: QuiverMutationType('E',7,1) + sage: QuiverMutationType('E',7, 1) ['E', 7, 1] - sage: QuiverMutationType('E',8,1) + sage: QuiverMutationType('E',8, 1) ['E', 8, 1] - sage: QuiverMutationType('F',4,1) + sage: QuiverMutationType('F',4, 1) ['F', 4, 1] sage: QuiverMutationType('F',4,-1) ['F', 4, -1] - sage: QuiverMutationType('G',2,1) + sage: QuiverMutationType('G', 2, 1) ['G', 2, 1] - sage: QuiverMutationType('G',2,-1) + sage: QuiverMutationType('G', 2,-1) ['G', 2, -1] - sage: QuiverMutationType('A',3,2) == QuiverMutationType('D',3,2) + sage: QuiverMutationType('A',3, 2) == QuiverMutationType('D',3, 2) True Affine types using Kac's Notation:: - sage: QuiverMutationType('A',1,1) + sage: QuiverMutationType('A', 1, 1) ['A', [1, 1], 1] - sage: QuiverMutationType('B',5,1) + sage: QuiverMutationType('B',5, 1) ['BD', 5, 1] - sage: QuiverMutationType('C',5,1) + sage: QuiverMutationType('C',5, 1) ['CC', 5, 1] - sage: QuiverMutationType('A',2,2) + sage: QuiverMutationType('A', 2, 2) ['BC', 1, 1] - sage: QuiverMutationType('A',7,2) + sage: QuiverMutationType('A',7, 2) ['CD', 4, 1] - sage: QuiverMutationType('A',8,2) + sage: QuiverMutationType('A',8, 2) ['BC', 4, 1] - sage: QuiverMutationType('D',6,2) + sage: QuiverMutationType('D',6, 2) ['BB', 5, 1] - sage: QuiverMutationType('E',6,2) + sage: QuiverMutationType('E',6, 2) ['F', 4, -1] sage: QuiverMutationType('D',4,3) ['G', 2, -1] Elliptic types:: - sage: QuiverMutationType('E',6,[1,1]) + sage: QuiverMutationType('E',6,[1, 1]) ['E', 6, [1, 1]] - sage: QuiverMutationType('F',4,[2,1]) + sage: QuiverMutationType('F',4,[2, 1]) ['F', 4, [1, 2]] - sage: QuiverMutationType('G',2,[3,3]) + sage: QuiverMutationType('G', 2,[3,3]) ['G', 2, [3, 3]] Mutation finite types: Rank 2 cases:: - sage: QuiverMutationType('R2',(1,1)) + sage: QuiverMutationType('R2',(1, 1)) ['A', 2] - sage: QuiverMutationType('R2',(1,2)) + sage: QuiverMutationType('R2',(1, 2)) ['B', 2] sage: QuiverMutationType('R2',(1,3)) ['G', 2] @@ -554,7 +554,7 @@ def _samples(self): ['BC', 1, 1] sage: QuiverMutationType('R2',(1,5)) ['R2', [1, 5]] - sage: QuiverMutationType('R2',(2,2)) + sage: QuiverMutationType('R2',(2, 2)) ['A', [1, 1], 1] sage: QuiverMutationType('R2',(3,5)) ['R2', [3, 5]] @@ -571,9 +571,9 @@ def _samples(self): sage: QuiverMutationType('E',9) ['E', 8, 1] - sage: QuiverMutationType('E',10) + sage: QuiverMutationType('E', 10) ['E', 10] - sage: QuiverMutationType('E',12) + sage: QuiverMutationType('E', 12) ['E', 12] sage: QuiverMutationType('AE',(2,3)) @@ -597,12 +597,12 @@ def _samples(self): ['E', 6] sage: QuiverMutationType('GR',(3,8)) ['E', 8] - sage: QuiverMutationType('GR',(3,10)) + sage: QuiverMutationType('GR',(3, 10)) ['GR', [3, 10]] Triangular types:: - sage: QuiverMutationType('TR',2) + sage: QuiverMutationType('TR', 2) ['A', 3] sage: QuiverMutationType('TR',3) ['D', 6] @@ -613,15 +613,15 @@ def _samples(self): T types:: - sage: QuiverMutationType('T',(1,1,1)) + sage: QuiverMutationType('T',(1, 1, 1)) ['A', 1] - sage: QuiverMutationType('T',(1,1,4)) + sage: QuiverMutationType('T',(1, 1,4)) ['A', 4] sage: QuiverMutationType('T',(1,4,4)) ['A', 7] - sage: QuiverMutationType('T',(2,2,2)) + sage: QuiverMutationType('T',(2, 2, 2)) ['D', 4] - sage: QuiverMutationType('T',(2,2,4)) + sage: QuiverMutationType('T',(2, 2,4)) ['D', 6] sage: QuiverMutationType('T',(2,3,3)) ['E', 6] @@ -664,7 +664,7 @@ def _repr_(self): EXAMPLES:: - sage: QuiverMutationType(['A',2]) # indirect doctest + sage: QuiverMutationType(['A', 2]) # indirect doctest ['A', 2] """ return self._description @@ -706,7 +706,7 @@ def show(self, circular=False, directed=True): sage: QMT = QuiverMutationType(['A',5]) sage: QMT.show() # long time """ - self.plot( circular=circular, directed=directed ).show() + self.plot(circular=circular, directed=directed).show() def letter(self): """ @@ -719,7 +719,7 @@ def letter(self): sage: mut_type.letter() 'A' - sage: mut_type = QuiverMutationType( ['BC',5,1] ); mut_type + sage: mut_type = QuiverMutationType( ['BC',5, 1] ); mut_type ['BC', 5, 1] sage: mut_type.letter() 'BC' @@ -749,12 +749,12 @@ def rank(self): sage: mut_type.rank() 5 - sage: mut_type = QuiverMutationType( ['A',[4,5],1] ); mut_type + sage: mut_type = QuiverMutationType( ['A',[4,5], 1] ); mut_type ['A', [4, 5], 1] sage: mut_type.rank() 9 - sage: mut_type = QuiverMutationType( ['BC',5,1] ); mut_type + sage: mut_type = QuiverMutationType( ['BC',5, 1] ); mut_type ['BC', 5, 1] sage: mut_type.rank() 6 @@ -814,7 +814,7 @@ def standard_quiver(self): sage: mut_type.standard_quiver() Quiver on 5 vertices of type ['A', 5] - sage: mut_type = QuiverMutationType( ['A',[5,3],1] ); mut_type + sage: mut_type = QuiverMutationType( ['A',[5,3], 1] ); mut_type ['A', [3, 5], 1] sage: mut_type.standard_quiver() Quiver on 8 vertices of type ['A', [3, 5], 1] @@ -884,7 +884,7 @@ def is_irreducible(self): EXAMPLES:: - sage: mt = QuiverMutationType(['A',2]) + sage: mt = QuiverMutationType(['A', 2]) sage: mt.is_irreducible() True """ @@ -899,7 +899,7 @@ def is_mutation_finite(self): EXAMPLES:: - sage: mt = QuiverMutationType(['D',5,1]) + sage: mt = QuiverMutationType(['D',5, 1]) sage: mt.is_mutation_finite() True """ @@ -914,15 +914,15 @@ def is_simply_laced(self): EXAMPLES:: - sage: mt = QuiverMutationType(['A',2]) + sage: mt = QuiverMutationType(['A', 2]) sage: mt.is_simply_laced() True - sage: mt = QuiverMutationType(['B',2]) + sage: mt = QuiverMutationType(['B', 2]) sage: mt.is_simply_laced() False - sage: mt = QuiverMutationType(['A',(1,1),1]) + sage: mt = QuiverMutationType(['A',(1, 1), 1]) sage: mt.is_simply_laced() False """ @@ -934,15 +934,15 @@ def is_skew_symmetric(self): EXAMPLES:: - sage: mt = QuiverMutationType(['A',2]) + sage: mt = QuiverMutationType(['A', 2]) sage: mt.is_skew_symmetric() True - sage: mt = QuiverMutationType(['B',2]) + sage: mt = QuiverMutationType(['B', 2]) sage: mt.is_skew_symmetric() False - sage: mt = QuiverMutationType(['A',(1,1),1]) + sage: mt = QuiverMutationType(['A',(1, 1), 1]) sage: mt.is_skew_symmetric() True """ @@ -957,11 +957,11 @@ def is_finite(self): EXAMPLES:: - sage: mt = QuiverMutationType(['A',2]) + sage: mt = QuiverMutationType(['A', 2]) sage: mt.is_finite() True - sage: mt = QuiverMutationType(['A',[4,2],1]) + sage: mt = QuiverMutationType(['A',[4, 2], 1]) sage: mt.is_finite() False """ @@ -973,11 +973,11 @@ def is_affine(self): EXAMPLES:: - sage: mt = QuiverMutationType(['A',2]) + sage: mt = QuiverMutationType(['A', 2]) sage: mt.is_affine() False - sage: mt = QuiverMutationType(['A',[4,2],1]) + sage: mt = QuiverMutationType(['A',[4, 2], 1]) sage: mt.is_affine() True """ @@ -992,11 +992,11 @@ def is_elliptic(self): EXAMPLES:: - sage: mt = QuiverMutationType(['A',2]) + sage: mt = QuiverMutationType(['A', 2]) sage: mt.is_elliptic() False - sage: mt = QuiverMutationType(['E',6,[1,1]]) + sage: mt = QuiverMutationType(['E',6,[1, 1]]) sage: mt.is_elliptic() True """ @@ -1039,7 +1039,7 @@ def properties(self): - affine: False - elliptic: False - sage: mut_type = QuiverMutationType(['B',3,1]); mut_type + sage: mut_type = QuiverMutationType(['B',3, 1]); mut_type ['BD', 3, 1] sage: mut_type.properties() ['BD', 3, 1] has rank 4 and the following properties: @@ -1051,7 +1051,7 @@ def properties(self): - affine: True - elliptic: False - sage: mut_type = QuiverMutationType(['E',6,[1,1]]); mut_type + sage: mut_type = QuiverMutationType(['E',6,[1, 1]]); mut_type ['E', 6, [1, 1]] sage: mut_type.properties() ['E', 6, [1, 1]] has rank 8 and the following properties: @@ -1103,6 +1103,7 @@ class QuiverMutationType_Irreducible(QuiverMutationType_abstract): The mutation type for a cluster algebra or a quiver. Should not be called directly, but through QuiverMutationType. """ + def __init__(self, letter, rank, twist=None): """ Should not be called directly but through QuiverMutationType. @@ -1118,10 +1119,10 @@ def __init__(self, letter, rank, twist=None): sage: QuiverMutationType('A',5) ['A', 5] - sage: QuiverMutationType('A',[4,5],1) + sage: QuiverMutationType('A',[4,5], 1) ['A', [4, 5], 1] - sage: QuiverMutationType('BB',5,1) + sage: QuiverMutationType('BB',5, 1) ['BB', 5, 1] sage: QuiverMutationType('X',6) @@ -1155,7 +1156,7 @@ def __init__(self, letter, rank, twist=None): self._letter = letter self._twist = twist - data = [letter,rank,twist] + data = [letter, rank, twist] # type A (finite and affine) if letter == 'A': @@ -1167,11 +1168,11 @@ def __init__(self, letter, rank, twist=None): self._info['finite'] = True elif twist == 1 and isinstance(rank, list) and len(rank) == 2 and all(ri in ZZ and ri >= 0 for ri in rank) and rank != [0, 0]: if isinstance(rank, tuple): - rank = list( rank ) + rank = list(rank) data[1] = rank rank = sorted(rank) self._bi_rank = rank - self._rank = sum( self._bi_rank ) + self._rank = sum(self._bi_rank) self._info['mutation_finite'] = True if self._rank > 2: self._info['simply_laced'] = True @@ -1182,24 +1183,24 @@ def __init__(self, letter, rank, twist=None): self._info['finite'] = True else: _mutation_type_error(data) - # types ['A',1] and ['A',[0,1],1] need to be treated on + # types ['A', 1] and ['A',[0, 1], 1] need to be treated on # itself (as there is no edge) if twist is None and self._rank == 1 or twist == 1 and self._rank == 1: - self._graph.add_vertex( 0 ) - # type ['A',[1,1],1] needs to be treated on itself as well + self._graph.add_vertex(0) + # type ['A',[1, 1], 1] needs to be treated on itself as well # (as there is a double edge) elif twist == 1 and self._bi_rank[0] == 1 and self._bi_rank[1] == 1: - self._graph.add_edge( 0,1,2 ) + self._graph.add_edge(0, 1, 2) else: - for i in range( self._rank - 1 ): - self._graph.add_edge( i, i+1, 1 ) + for i in range(self._rank - 1): + self._graph.add_edge(i, i + 1, 1) if twist == 1: - self._digraph.add_edge( self._rank - 1, 0, 1 ) - for i in range( self._rank - 1 ): + self._digraph.add_edge(self._rank - 1, 0, 1) + for i in range(self._rank - 1): if i < (2 * self._bi_rank[0]) and i % 2 == 0: - self._digraph.add_edge( i+1, i, 1 ) + self._digraph.add_edge(i + 1, i, 1) else: - self._digraph.add_edge( i, i+1, 1 ) + self._digraph.add_edge(i, i + 1, 1) # type B (finite) elif letter == 'B': @@ -1209,12 +1210,12 @@ def __init__(self, letter, rank, twist=None): self._info['finite'] = True else: _mutation_type_error(data) - for i in range( rank - 2 ): - self._graph.add_edge( i, i+1, 1 ) + for i in range(rank - 2): + self._graph.add_edge(i, i+1, 1) if (rank % 2 == 0): - self._graph.add_edge( rank-2, rank-1, (1,-2) ) + self._graph.add_edge(rank-2, rank-1, (1, -2)) else: - self._graph.add_edge( rank-2, rank-1, (2,-1) ) + self._graph.add_edge(rank-2, rank-1, (2, -1)) # type C (finite) elif letter == 'C': @@ -1224,12 +1225,12 @@ def __init__(self, letter, rank, twist=None): self._info['finite'] = True else: _mutation_type_error(data) - for i in range( rank - 2 ): - self._graph.add_edge( i, i+1, 1 ) + for i in range(rank - 2): + self._graph.add_edge(i, i+1, 1) if (rank % 2 == 0): - self._graph.add_edge( rank-2, rank-1, (2,-1) ) + self._graph.add_edge(rank-2, rank-1, (2, -1)) else: - self._graph.add_edge( rank-2, rank-1, (1,-2) ) + self._graph.add_edge(rank-2, rank-1, (1, -2)) # type BB (affine) elif letter == 'BB': @@ -1239,12 +1240,12 @@ def __init__(self, letter, rank, twist=None): self._info['affine'] = True else: _mutation_type_error(data) - for i in range( rank - 2 ): - self._graph.add_edge( i, i+1, 1 ) + for i in range(rank - 2): + self._graph.add_edge(i, i+1, 1) if rank % 2 == 0: - self._graph.add_edge( rank-2, rank-1, (1, -2) ) + self._graph.add_edge(rank-2, rank-1, (1, -2)) else: - self._graph.add_edge( rank-2, rank-1, (2, -1) ) + self._graph.add_edge(rank-2, rank-1, (2, -1)) self._graph.add_edge(rank, 0, (1, -2)) # type CC (affine) @@ -1255,12 +1256,12 @@ def __init__(self, letter, rank, twist=None): self._info['affine'] = True else: _mutation_type_error(data) - for i in range( rank - 2 ): - self._graph.add_edge( i, i+1, 1 ) + for i in range(rank - 2): + self._graph.add_edge(i, i+1, 1) if rank % 2 == 0: - self._graph.add_edge( rank-2, rank-1, (2,-1) ) + self._graph.add_edge(rank-2, rank-1, (2, -1)) else: - self._graph.add_edge( rank-2, rank-1, (1,-2) ) + self._graph.add_edge(rank-2, rank-1, (1, -2)) self._graph.add_edge(rank, 0, (2, -1)) # type BC (affine) @@ -1272,14 +1273,14 @@ def __init__(self, letter, rank, twist=None): else: _mutation_type_error(data) if rank == 1: - self._graph.add_edge( 0,1,(1,-4) ) + self._graph.add_edge(0, 1, (1, -4)) else: - for i in range( rank - 2 ): - self._graph.add_edge( i, i+1, 1 ) + for i in range(rank - 2): + self._graph.add_edge(i, i+1, 1) if (rank % 2 == 0): - self._graph.add_edge( rank-2, rank-1, (2,-1) ) + self._graph.add_edge(rank-2, rank-1, (2, -1)) else: - self._graph.add_edge( rank-2, rank-1, (1,-2) ) + self._graph.add_edge(rank-2, rank-1, (1, -2)) if twist == 1: self._graph.add_edge(rank, 0, (1, -2)) @@ -1291,12 +1292,12 @@ def __init__(self, letter, rank, twist=None): self._info['affine'] = True else: _mutation_type_error(data) - for i in range( rank - 2 ): - self._graph.add_edge( i, i+1, 1 ) + for i in range(rank - 2): + self._graph.add_edge(i, i+1, 1) if (rank % 2 == 0): - self._graph.add_edge( rank-2, rank-1, (1,-2) ) + self._graph.add_edge(rank-2, rank-1, (1, -2)) else: - self._graph.add_edge( rank-2, rank-1, (2,-1) ) + self._graph.add_edge(rank-2, rank-1, (2, -1)) if twist == 1: self._graph.add_edge(rank, 1, 1) @@ -1308,12 +1309,12 @@ def __init__(self, letter, rank, twist=None): self._info['affine'] = True else: _mutation_type_error(data) - for i in range( rank - 2 ): - self._graph.add_edge( i, i+1, 1 ) + for i in range(rank - 2): + self._graph.add_edge(i, i+1, 1) if (rank % 2 == 0): - self._graph.add_edge( rank-2, rank-1, (2,-1) ) + self._graph.add_edge(rank-2, rank-1, (2, -1)) else: - self._graph.add_edge( rank-2, rank-1, (1,-2) ) + self._graph.add_edge(rank-2, rank-1, (1, -2)) if twist == 1: self._graph.add_edge(rank, 1, 1) @@ -1333,10 +1334,10 @@ def __init__(self, letter, rank, twist=None): self._info['affine'] = True else: _mutation_type_error(data) - for i in range( rank - 2 ): - self._graph.add_edge( i, i+1, 1 ) + for i in range(rank - 2): + self._graph.add_edge(i, i+1, 1) - self._graph.add_edge( rank-3, rank-1, 1 ) + self._graph.add_edge(rank-3, rank-1, 1) if twist is not None: self._graph.add_edge(rank, 1, 1) @@ -1349,63 +1350,65 @@ def __init__(self, letter, rank, twist=None): self._info['skew_symmetric'] = True self._info['finite'] = True if rank == 6: - self._graph.add_edges( [ (0,1),(1,2),(2,3),(3,4),(2,5) ] ) + self._graph.add_edges([(0, 1), (1, 2), (2, 3), (3, 4), (2, 5)]) elif rank == 7: self._graph.add_edges([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (2, 6)]) elif rank == 8: self._graph.add_edges([(0, 1), (1, 2), (2, 3), - (3, 4), (4, 5), (5, 6),(2, 7)]) - elif rank in [6,7,8] and twist == 1: + (3, 4), (4, 5), (5, 6), (2, 7)]) + elif rank in [6, 7, 8] and twist == 1: self._rank = rank + 1 self._info['mutation_finite'] = True self._info['simply_laced'] = True self._info['skew_symmetric'] = True self._info['affine'] = True if rank == 6: - self._graph.add_edges( [ (0,1),(1,2),(2,3),(3,4),(2,5),(5,6) ] ) + self._graph.add_edges([(0, 1), (1, 2), (2, 3), (3, 4), (2, 5), (5, 6)]) elif rank == 7: - self._graph.add_edges( [ (0,1),(1,2),(2,3),(3,4),(4,5),(5,6),(3,7) ] ) + self._graph.add_edges([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (3, 7)]) elif rank == 8: - self._graph.add_edges( [ (0,1),(1,2),(2,3),(3,4),(4,5),(5,6),(6,7),(2,8) ] ) - elif rank in [6,7,8] and twist == [1,1]: + self._graph.add_edges([(0, 1), (1, 2), (2, 3), (3, 4), (4, 5), (5, 6), (6, 7), (2, 8)]) + elif rank in [6, 7, 8] and twist == [1, 1]: self._rank = rank + 2 self._info['mutation_finite'] = True self._info['skew_symmetric'] = True self._info['elliptic'] = True if rank == 6: - self._digraph.add_edges( [ (0,1,1),(1,2,1),(3,2,1),(3,4,1),(5,6,1),(6,7,1),(5,1,1),(2,5,2),(5,3,1),(6,2,1) ] ) + self._digraph.add_edges([(0, 1, 1), (1, 2, 1), (3, 2, 1), (3, 4, 1), (5, 6, 1), (6, 7, 1), (5, 1, 1), (2, 5, 2), (5, 3, 1), (6, 2, 1)]) elif rank == 7: - self._digraph.add_edges( [ (1,0,1),(1,2,1),(2,3,1),(4,3,1),(4,5,1),(6,5,1),(7,8,1),(3,7,2),(7,2,1),(7,4,1),(8,3,1) ] ) + self._digraph.add_edges([(1, 0, 1), (1, 2, 1), (2, 3, 1), (4, 3, 1), (4, 5, 1), + (6, 5, 1), (7, 8, 1), (3, 7, 2), (7, 2, 1), (7, 4, 1), (8, 3, 1)]) elif rank == 8: - self._digraph.add_edges( [ (0,1,1),(1,9,1),(3,9,1),(3,4,1),(2,8,1),(2,1,1),(9,2,2),(2,3,1),(8,9,1),(5,4,1),(5,6,1),(7,6,1) ] ) + self._digraph.add_edges([(0, 1, 1), (1, 9, 1), (3, 9, 1), (3, 4, 1), (2, 8, 1), (2, 1, 1), + (9, 2, 2), (2, 3, 1), (8, 9, 1), (5, 4, 1), (5, 6, 1), (7, 6, 1)]) # type E (mutation infinite) elif rank > 9 and twist is None: self._info['simply_laced'] = True self._info['skew_symmetric'] = True self._rank = rank for i in range(rank-2): - self._graph.add_edge( i, i+1, 1 ) - self._graph.add_edge( 2, rank-1 ) + self._graph.add_edge(i, i+1, 1) + self._graph.add_edge(2, rank-1) else: _mutation_type_error(data) # type AE (mutation infinite) elif letter == 'AE': - if isinstance(rank, list) and len(rank) == 2 and all( rank[i] in ZZ and rank[i] > 0 for i in [0,1] ) and twist is None: + if isinstance(rank, list) and len(rank) == 2 and all(rank[i] in ZZ and rank[i] > 0 for i in [0, 1]) and twist is None: if isinstance(rank, tuple): - rank = list( rank ) + rank = list(rank) data[1] = rank rank = sorted(rank) self._bi_rank = rank - self._rank = sum( self._bi_rank ) + 1 + self._rank = sum(self._bi_rank) + 1 if self._rank > 3: self._info['simply_laced'] = True self._info['skew_symmetric'] = True - if self._bi_rank == [1,1]: - self._graph.add_edges( [(0,1,2),(1,2,None)] ) + if self._bi_rank == [1, 1]: + self._graph.add_edges([(0, 1, 2), (1, 2, None)]) else: - self._digraph.add_edge( self._rank - 2, 0 ) + self._digraph.add_edge(self._rank - 2, 0) for i in range(self._rank-2): if i < (2 * self._bi_rank[0]) and i % 2 == 0: self._digraph.add_edge(i + 1, i) @@ -1420,12 +1423,12 @@ def __init__(self, letter, rank, twist=None): if rank > 4 and twist is None: self._rank = rank for i in range(rank-3): - self._graph.add_edge( i, i+1 ) - self._graph.add_edge( 2, rank-1 ) + self._graph.add_edge(i, i+1) + self._graph.add_edge(2, rank-1) if rank % 2 == 0: - self._graph.add_edge( rank-3,rank-2,(2,-1) ) + self._graph.add_edge(rank-3, rank-2, (2, -1)) else: - self._graph.add_edge( rank-3,rank-2,(1,-2) ) + self._graph.add_edge(rank-3, rank-2, (1, -2)) else: _mutation_type_error(data) @@ -1434,12 +1437,12 @@ def __init__(self, letter, rank, twist=None): if rank > 4 and twist is None: self._rank = rank for i in range(rank-3): - self._graph.add_edge( i, i+1 ) - self._graph.add_edge( 2, rank-1 ) + self._graph.add_edge(i, i+1) + self._graph.add_edge(2, rank-1) if rank % 2 == 0: - self._graph.add_edge( rank-3,rank-2,(1,-2) ) + self._graph.add_edge(rank-3, rank-2, (1, -2)) else: - self._graph.add_edge( rank-3,rank-2,(2,-1) ) + self._graph.add_edge(rank-3, rank-2, (2, -1)) else: _mutation_type_error(data) @@ -1450,9 +1453,9 @@ def __init__(self, letter, rank, twist=None): self._info['simply_laced'] = True self._info['skew_symmetric'] = True for i in range(rank-3): - self._graph.add_edge( i, i+1 ) - self._graph.add_edge( 2, rank-2 ) - self._graph.add_edge( rank-4, rank-1 ) + self._graph.add_edge(i, i+1) + self._graph.add_edge(2, rank-2) + self._graph.add_edge(rank-4, rank-1) else: _mutation_type_error(data) @@ -1462,48 +1465,48 @@ def __init__(self, letter, rank, twist=None): self._rank = rank self._info['mutation_finite'] = True self._info['finite'] = True - self._graph.add_edges( [ (0,1,None),(1,2,(2,-1)),(2,3,None) ] ) + self._graph.add_edges([(0, 1, None), (1, 2, (2, -1)), (2, 3, None)]) elif rank == 4 and twist == 1: self._rank = rank + 1 self._info['mutation_finite'] = True self._info['affine'] = True - self._graph.add_edges( [ (0,1,None), (1,2,None), - (2,3,(1,-2)),(3,4,None) ] ) + self._graph.add_edges([(0, 1, None), (1, 2, None), + (2, 3, (1, -2)), (3, 4, None)]) elif rank == 4 and twist == -1: self._rank = rank + 1 self._info['mutation_finite'] = True self._info['affine'] = True - self._graph.add_edges( [ (0,1,None), (1,2,None), - (2,3,(2,-1)),(3,4,None) ] ) - elif rank == 4 and (twist == [1,2]): + self._graph.add_edges([(0, 1, None), (1, 2, None), + (2, 3, (2, -1)), (3, 4, None)]) + elif rank == 4 and (twist == [1, 2]): self._rank = rank + 2 self._info['mutation_finite'] = True self._info['elliptic'] = True - self._digraph.add_edges( [ (0,1,None), (1,2,None), - (2,3,(2,-1)), (4,2,(1,-2)), - (3,4,2), (4,5,None), (5,3,None) ]) - elif rank == 4 and (twist == [2,1]): + self._digraph.add_edges([(0, 1, None), (1, 2, None), + (2, 3, (2, -1)), (4, 2, (1, -2)), + (3, 4, 2), (4, 5, None), (5, 3, None)]) + elif rank == 4 and (twist == [2, 1]): self._rank = rank + 2 self._info['mutation_finite'] = True self._info['elliptic'] = True - self._digraph.add_edges( [ (0,1,None), (1,2,None), - (2,3,(1,-2)), (4,2,(2,-1)), - (3,4,2), (4,5,None), (5,3,None) ]) - elif rank == 4 and twist == [2,2]: + self._digraph.add_edges([(0, 1, None), (1, 2, None), + (2, 3, (1, -2)), (4, 2, (2, -1)), + (3, 4, 2), (4, 5, None), (5, 3, None)]) + elif rank == 4 and twist == [2, 2]: self._rank = rank + 2 self._info['mutation_finite'] = True self._info['elliptic'] = True - self._digraph.add_edges( [ (0,1,None), (1,2,None), - (3,1,None), (2,3,2), - (4,2,(2,-1)), (3,4,(1,-2)), - (5,4,None) ] ) - elif rank == 4 and twist == [1,1]: + self._digraph.add_edges([(0, 1, None), (1, 2, None), + (3, 1, None), (2, 3, 2), + (4, 2, (2, -1)), (3, 4, (1, -2)), + (5, 4, None)]) + elif rank == 4 and twist == [1, 1]: self._rank = rank + 2 self._info['mutation_finite'] = True self._info['elliptic'] = True - self._digraph.add_edges( [ (0,1,None), (1,2,None), - (3,1,None), (2,3,2), (4,2,(1,-2)), - (3,4,(2,-1)), (5,4,None) ] ) + self._digraph.add_edges([(0, 1, None), (1, 2, None), + (3, 1, None), (2, 3, 2), (4, 2, (1, -2)), + (3, 4, (2, -1)), (5, 4, None)]) else: _mutation_type_error(data) @@ -1513,109 +1516,109 @@ def __init__(self, letter, rank, twist=None): self._rank = rank self._info['mutation_finite'] = True self._info['finite'] = True - self._graph.add_edges( [ (0,1,(1,-3)) ] ) + self._graph.add_edges([(0, 1, (1, -3))]) elif rank == 2 and twist == -1: self._rank = rank + 1 self._info['mutation_finite'] = True self._info['affine'] = True - self._graph.add_edges( [ (0,1,None),(1,2,(1,-3)) ] ) + self._graph.add_edges([(0, 1, None), (1, 2, (1, -3))]) elif rank == 2 and twist == 1: self._rank = rank + 1 self._info['mutation_finite'] = True self._info['affine'] = True - self._graph.add_edges( [ (0,1,None),(1,2,(3,-1)) ] ) - elif rank == 2 and (twist == [1,3]): + self._graph.add_edges([(0, 1, None), (1, 2, (3, -1))]) + elif rank == 2 and (twist == [1, 3]): self._rank = rank + 2 self._info['mutation_finite'] = True self._info['elliptic'] = True - self._digraph.add_edges( [ (0,1,None), (1,2,(3,-1)), - (3,1,(1,-3)), (2,3,2)] ) - elif rank == 2 and (twist == [3,1]): + self._digraph.add_edges([(0, 1, None), (1, 2, (3, -1)), + (3, 1, (1, -3)), (2, 3, 2)]) + elif rank == 2 and (twist == [3, 1]): self._rank = rank + 2 self._info['mutation_finite'] = True self._info['elliptic'] = True - self._digraph.add_edges( [ (0,1,None), (1,2,(1,-3)), - (3,1,(3,-1)), (2,3,2)] ) - elif rank == 2 and twist == [3,3]: + self._digraph.add_edges([(0, 1, None), (1, 2, (1, -3)), + (3, 1, (3, -1)), (2, 3, 2)]) + elif rank == 2 and twist == [3, 3]: self._rank = rank + 2 self._info['mutation_finite'] = True self._info['elliptic'] = True - self._digraph.add_edges( [ (1,0,None), (0,2,2), (3,0,(3,-1)), - (2,1,None), (2,3, (1,-3))]) - elif rank == 2 and twist == [1,1]: + self._digraph.add_edges([(1, 0, None), (0, 2, 2), (3, 0, (3, -1)), + (2, 1, None), (2, 3, (1, -3))]) + elif rank == 2 and twist == [1, 1]: self._rank = rank + 2 self._info['mutation_finite'] = True self._info['elliptic'] = True - self._digraph.add_edges( [ (1,0,None), (0,2,2), (3,0,(1,-3)), - (2,1,None), (2,3,(3,-1)) ] ) + self._digraph.add_edges([(1, 0, None), (0, 2, 2), (3, 0, (1, -3)), + (2, 1, None), (2, 3, (3, -1))]) else: _mutation_type_error(data) # type GR (mutation infinite) elif letter == 'GR': - if twist is None and isinstance(rank, list) and len(rank) == 2 and all( rank[i] in ZZ and rank[i] > 0 for i in [0,1] ) and rank[1] - 1 > rank[0] > 1: - gr_rank = (rank[0]-1,rank[1]-rank[0]-1) + if twist is None and isinstance(rank, list) and len(rank) == 2 and all(rank[i] in ZZ and rank[i] > 0 for i in [0, 1]) and rank[1] - 1 > rank[0] > 1: + gr_rank = (rank[0]-1, rank[1]-rank[0]-1) self._rank = prod(gr_rank) self._info['simply_laced'] = True self._info['skew_symmetric'] = True - a,b = gr_rank + a, b = gr_rank for i in range(a): for j in range(b): if i < a-1: if (i+j) % 2 == 0: - self._digraph.add_edge(i*b+j,(i+1)*b+j) + self._digraph.add_edge(i*b+j, (i+1)*b+j) else: - self._digraph.add_edge((i+1)*b+j,i*b+j) + self._digraph.add_edge((i+1)*b+j, i*b+j) if j < b-1: if (i+j) % 2 == 0: - self._digraph.add_edge(i*b+j+1,i*b+j) + self._digraph.add_edge(i*b+j+1, i*b+j) else: - self._digraph.add_edge(i*b+j,i*b+j+1) + self._digraph.add_edge(i*b+j, i*b+j+1) else: _mutation_type_error(data) # type R2 (rank 2 finite mutation types) elif letter == 'R2': - if twist is None and isinstance(rank, list) and len(rank) == 2 and all( rank[i] in ZZ and rank[i] > 0 for i in [0,1] ): + if twist is None and isinstance(rank, list) and len(rank) == 2 and all(rank[i] in ZZ and rank[i] > 0 for i in [0, 1]): rank = sorted(rank) - b,c = rank + b, c = rank self._rank = 2 if b == c: self._info['skew_symmetric'] = True - self._graph.add_edge(0,1,(b,-c)) + self._graph.add_edge(0, 1, (b, -c)) else: _mutation_type_error(data) # type T elif letter == 'T': - if twist is None and isinstance(rank, list) and len(rank) == 3 and all( rank[i] in ZZ and rank[i] > 0 for i in [0,1,2] ): + if twist is None and isinstance(rank, list) and len(rank) == 3 and all(rank[i] in ZZ and rank[i] > 0 for i in [0, 1, 2]): if isinstance(rank, tuple): - rank = list( rank ) + rank = list(rank) data[1] = rank - rank = sorted( rank ) - self._rank = sum( rank ) - 2 + rank = sorted(rank) + self._rank = sum(rank) - 2 self._info['simply_laced'] = True self._info['skew_symmetric'] = True - r,p,q = rank + r, p, q = rank for i in range(q-1): if i == 0: - self._graph.add_edge(0,1) - self._graph.add_edge(0,r) - self._graph.add_edge(0,r+p-1) + self._graph.add_edge(0, 1) + self._graph.add_edge(0, r) + self._graph.add_edge(0, r+p-1) else: if i < r-1: - self._graph.add_edge(i,i+1) + self._graph.add_edge(i, i+1) if i < p-1: - self._graph.add_edge(i+r-1,i+r) - self._graph.add_edge(i+r+p-2,i+r+p-1) + self._graph.add_edge(i+r-1, i+r) + self._graph.add_edge(i+r+p-2, i+r+p-1) else: _mutation_type_error(data) # type TR (mutation infinite if rank > 2) elif letter == 'TR': - # type ['TR',1] needs to be treated on itself (as there is no edge) + # type ['TR', 1] needs to be treated on itself (as there is no edge) if twist is None and rank == 1: - self._graph.add_vertex( 0 ) + self._graph.add_vertex(0) elif twist is None and rank > 1: self._rank = rank*(rank+1)//2 self._info['simply_laced'] = True @@ -1623,25 +1626,25 @@ def __init__(self, letter, rank, twist=None): level = 0 while level < rank: nr = rank*level-sum(range(level)) - for i in range(nr,nr+rank-level-1): - self._digraph.add_edge(i,i+1) - self._digraph.add_edge(i+rank-level,i) - self._digraph.add_edge(i+1,i+rank-level) + for i in range(nr, nr+rank-level-1): + self._digraph.add_edge(i, i+1) + self._digraph.add_edge(i+rank-level, i) + self._digraph.add_edge(i+1, i+rank-level) level += 1 else: _mutation_type_error(data) # type X elif letter == 'X': - if rank in [6,7] and twist is None: + if rank in [6, 7] and twist is None: self._rank = rank self._info['mutation_finite'] = True self._info['skew_symmetric'] = True - self._digraph.add_edges( [ (0,1,2),(1,2,None),(2,0,None), - (2,3,None),(3,4,2),(4,2,None), - (2,5,None) ] ) + self._digraph.add_edges([(0, 1, 2), (1, 2, None), (2, 0, None), + (2, 3, None), (3, 4, 2), (4, 2, None), + (2, 5, None)]) if rank == 7: - self._digraph.add_edges( [ (5,6,2),(6,2,None) ] ) + self._digraph.add_edges([(5, 6, 2), (6, 2, None)]) else: _mutation_type_error(data) @@ -1652,7 +1655,7 @@ def __init__(self, letter, rank, twist=None): # in the bipartite case, the digraph is constructed from the graph if not self._digraph: if self._graph.is_bipartite(): - self._digraph = _bipartite_graph_to_digraph( self._graph ) + self._digraph = _bipartite_graph_to_digraph(self._graph) else: raise ValueError('The QuiverMutationType does not have ' 'a Coxeter diagram.') @@ -1667,7 +1670,7 @@ def __init__(self, letter, rank, twist=None): else: self._description = str([letter, rank]) - def irreducible_components( self ): + def irreducible_components(self): """ Return a list of all irreducible components of ``self``. @@ -1708,7 +1711,7 @@ def class_size(self): sage: mut_type.class_size() 19 - sage: mut_type = QuiverMutationType( ['A',[10,3],1] ); mut_type + sage: mut_type = QuiverMutationType( ['A',[10,3], 1] ); mut_type ['A', [3, 10], 1] sage: mut_type.class_size() 142120 @@ -1718,7 +1721,7 @@ def class_size(self): sage: mut_type.class_size() 132 - sage: mut_type = QuiverMutationType( ['BD',6,1] ); mut_type + sage: mut_type = QuiverMutationType( ['BD',6, 1] ); mut_type ['BD', 6, 1] sage: mut_type.class_size() Warning: This method uses a formula which has not been proved correct. @@ -1726,7 +1729,7 @@ def class_size(self): Check that :trac:`14048` is fixed:: - sage: mut_type = QuiverMutationType( ['F',4,(2,1)] ) + sage: mut_type = QuiverMutationType( ['F',4,(2, 1)] ) sage: mut_type.class_size() 90 """ @@ -1739,29 +1742,29 @@ def class_size(self): # cluster-tilted algebras of type A if self.is_finite(): n = self._rank - a = binomial( 2*(n+1), n+1 ) // (n+2) + a = binomial(2*(n+1), n+1) // (n+2) if n % 2 == 1: - a += binomial( n+1, (n+1)//2 ) + a += binomial(n+1, (n+1)//2) if n % 3 == 0: - a += 2 * binomial( 2*n//3, n//3 ) + a += 2 * binomial(2*n//3, n//3) return a // (n+3) # the formula is taken from Bastian, Prellberg, Rubey, Stump elif self.is_affine(): - i,j = self._bi_rank + i, j = self._bi_rank i = ZZ(i) j = ZZ(j) n = i+j f = euler_phi if i == j: - return ( binomial( 2*i,i ) + - sum( f(k) * binomial(2*i//k,i//k)**2 - for k in [k for k in i.divisors() - if k in j.divisors()] ) // n ) // 4 + return (binomial(2 * i, i) + + sum(f(k) * binomial(2 * i // k, i // k)**2 + for k in i.divisors() + if k in j.divisors()) // n) // 4 else: - return sum( f(k) * binomial(2*i//k,i//k) * - binomial(2*j//k,j//k) - for k in [k for k in i.divisors() - if k in j.divisors()] ) // ( 2 * n ) + return sum(f(k) * binomial(2 * i // k, i // k) * + binomial(2 * j // k, j // k) + for k in i.divisors() + if k in j.divisors()) // (2 * n) # types B and C (finite and affine) elif self._letter in ['B', 'C']: @@ -1771,7 +1774,7 @@ def class_size(self): n = self._rank return binomial(2 * n, n) // (n + 1) - elif self._letter in ['BB','CC']: + elif self._letter in ['BB', 'CC']: # these two formulas are not yet proven print("Warning: This method uses a formula " "which has not been proved correct.") @@ -1795,7 +1798,7 @@ def class_size(self): return binomial(2 * n, n) # types BD and CD (affine) - elif self._letter in ['BD','CD']: + elif self._letter in ['BD', 'CD']: # this formula is not yet proven print("Warning: This method uses a formula " "which has not been proved correct.") @@ -1860,9 +1863,9 @@ def class_size(self): elif self.is_affine(): return 60 elif self.is_elliptic(): - if self._twist == [1,2]: + if self._twist == [1, 2]: return 90 - if self._twist == [1,1] or self._twist == [2,2]: + if self._twist == [1, 1] or self._twist == [2, 2]: return 35 # type G @@ -1872,9 +1875,9 @@ def class_size(self): elif self.is_affine(): return 6 elif self.is_elliptic(): - if self._twist == [1,3]: + if self._twist == [1, 3]: return 7 - if self._twist == [1,1] or self._twist == [3,3]: + if self._twist == [1, 1] or self._twist == [3, 3]: return 2 # type X @@ -1911,7 +1914,7 @@ def dual(self): """ letter = self.letter() # the self-dual cases - if letter != 'BC' and letter[0] in ['B','C']: + if letter != 'BC' and letter[0] in ['B', 'C']: if letter == 'BB': letter = 'CC' elif letter == 'CC': @@ -1924,9 +1927,9 @@ def dual(self): if self.is_affine(): rank -= 1 twist = self._twist - return QuiverMutationType(letter,rank,twist) + return QuiverMutationType(letter, rank, twist) # the cases F and G have non-trivial duality in some cases - elif letter in ['F','G']: + elif letter in ['F', 'G']: if self.is_finite(): return self elif self.is_affine(): @@ -1936,15 +1939,15 @@ def dual(self): twist = self._twist rank = self._rank - 2 if letter == 'F': - if self._twist == [2,2]: - twist == [1,1] - if self._twist == [1,1]: - twist == [2,2] + if self._twist == [2, 2]: + twist == [1, 1] + if self._twist == [1, 1]: + twist == [2, 2] if letter == 'G': - if self._twist == [3,3]: - twist = [1,1] - elif self._twist == [1,1]: - twist = [3,3] + if self._twist == [3, 3]: + twist = [1, 1] + elif self._twist == [1, 1]: + twist = [3, 3] else: rank = self._rank return QuiverMutationType(letter, rank, twist) @@ -1958,6 +1961,7 @@ class QuiverMutationType_Reducible(QuiverMutationType_abstract): called directly, but through QuiverMutationType. Inherits from QuiverMutationType_abstract. """ + def __init__(self, *args): """ Should not be called directly, but through QuiverMutationType. @@ -1973,7 +1977,7 @@ def __init__(self, *args): [ ['A', 4], ['B', 6] ] """ data = args - if len(data) < 2 or not all( isinstance(comp, QuiverMutationType_Irreducible) for comp in data ): + if len(data) < 2 or not all(isinstance(comp, QuiverMutationType_Irreducible) for comp in data): return _mutation_type_error(data) # _info is initialized @@ -2017,7 +2021,7 @@ def __init__(self, *args): self._description += comps[i]._description self._description += " ]" - def irreducible_components( self ): + def irreducible_components(self): """ Return a list of all irreducible components of ``self``. @@ -2085,7 +2089,7 @@ def class_size(self): multiplicities[i]) for i in range(len(sizes))) - def dual(self): + def dual(self) -> QuiverMutationType: """ Return the QuiverMutationType which is dual to ``self``. @@ -2097,10 +2101,10 @@ def dual(self): [ ['A', 5], ['C', 6], ['B', 5], ['D', 4] ] """ comps = self.irreducible_components() - return QuiverMutationType( [comp.dual() for comp in comps ] ) + return QuiverMutationType([comp.dual() for comp in comps]) -def _construct_classical_mutation_classes(n): +def _construct_classical_mutation_classes(n) -> dict: r""" Return a dict with keys being tuples representing regular QuiverMutationTypes of the given rank, and with values being lists @@ -2122,42 +2126,42 @@ def _construct_classical_mutation_classes(n): data = {} # finite A - data[ ('A',n) ] = ClusterQuiver(['A',n]).mutation_class(data_type='dig6') + data[('A', n)] = ClusterQuiver(['A', n]).mutation_class(data_type='dig6') # affine A for j in range(1, n//2+1): - data[ ('A',(n-j,j),1) ] = ClusterQuiver(['A',[n-j,j],1]).mutation_class(data_type='dig6') + data[('A', (n-j, j), 1)] = ClusterQuiver(['A', [n-j, j], 1]).mutation_class(data_type='dig6') # finite B if n > 1: - data[ ('B',n) ] = ClusterQuiver(['B',n]).mutation_class(data_type='dig6') + data[('B', n)] = ClusterQuiver(['B', n]).mutation_class(data_type='dig6') # affine B if n > 2: - data[ ('BB',n-1,1) ] = ClusterQuiver(['BB',n-1,1]).mutation_class(data_type='dig6') + data[('BB', n-1, 1)] = ClusterQuiver(['BB', n-1, 1]).mutation_class(data_type='dig6') # finite C if n > 2: - data[ ('C',n) ] = ClusterQuiver(['C',n]).mutation_class(data_type='dig6') + data[('C', n)] = ClusterQuiver(['C', n]).mutation_class(data_type='dig6') # affine C if n > 1: - data[ ('BC',n-1,1) ] = ClusterQuiver(['BC',n-1,1]).mutation_class(data_type='dig6') + data[('BC', n-1, 1)] = ClusterQuiver(['BC', n-1, 1]).mutation_class(data_type='dig6') # affine CC if n > 2: - data[ ('CC',n-1,1) ] = ClusterQuiver(['CC',n-1,1]).mutation_class(data_type='dig6') + data[('CC', n-1, 1)] = ClusterQuiver(['CC', n-1, 1]).mutation_class(data_type='dig6') # affine BD if n > 3: - data[ ('BD',n-1,1) ] = ClusterQuiver(['BD',n-1,1]).mutation_class(data_type='dig6') + data[('BD', n-1, 1)] = ClusterQuiver(['BD', n-1, 1]).mutation_class(data_type='dig6') # affine CD if n > 3: - data[ ('CD',n-1,1) ] = ClusterQuiver(['CD',n-1,1]).mutation_class(data_type='dig6') + data[('CD', n-1, 1)] = ClusterQuiver(['CD', n-1, 1]).mutation_class(data_type='dig6') # finite D if n > 3: - data[ ('D',n) ] = ClusterQuiver(['D',n]).mutation_class(data_type='dig6') + data[('D', n)] = ClusterQuiver(['D', n]).mutation_class(data_type='dig6') # affine D if n > 4: - data[ ('D',n-1,1) ] = ClusterQuiver(['D',n-1,1]).mutation_class(data_type='dig6') + data[('D', n-1, 1)] = ClusterQuiver(['D', n-1, 1]).mutation_class(data_type='dig6') return data -def _construct_exceptional_mutation_classes(n): +def _construct_exceptional_mutation_classes(n) -> dict: r""" Return a dict with keys being tuples representing exceptional QuiverMutationTypes of the given rank, and with values being lists @@ -2183,41 +2187,41 @@ def _construct_exceptional_mutation_classes(n): from sage.combinat.cluster_algebra_quiver.quiver import ClusterQuiver data = {} # finite E - if n in [6,7,8]: - data[ ('E',n) ] = ClusterQuiver(['E',n]).mutation_class(data_type='dig6') + if n in [6, 7, 8]: + data[('E', n)] = ClusterQuiver(['E', n]).mutation_class(data_type='dig6') # affine E - if n in [7,8,9]: - data[ ('E',n-1,1) ] = ClusterQuiver(['E',n-1,1]).mutation_class(data_type='dig6') + if n in [7, 8, 9]: + data[('E', n - 1, 1)] = ClusterQuiver(['E', n - 1, 1]).mutation_class(data_type='dig6') # elliptic E - if n in [8,9,10]: - data[ ('E',n-2,(1,1)) ] = ClusterQuiver(['E',n-2,[1,1]]).mutation_class(data_type='dig6') + if n in [8, 9, 10]: + data[('E', n - 2, (1, 1))] = ClusterQuiver(['E', n - 2, [1, 1]]).mutation_class(data_type='dig6') # finite F if n == 4: - data[ ('F',4) ] = ClusterQuiver(['F',4]).mutation_class(data_type='dig6') + data[('F', 4)] = ClusterQuiver(['F', 4]).mutation_class(data_type='dig6') # affine F if n == 5: - data[ ('F',4,1) ] = ClusterQuiver(['F',4,1]).mutation_class(data_type='dig6') - data[ ('F',4,-1) ] = ClusterQuiver(['F',4,-1]).mutation_class(data_type='dig6') + data[('F', 4, 1)] = ClusterQuiver(['F', 4, 1]).mutation_class(data_type='dig6') + data[('F', 4, -1)] = ClusterQuiver(['F', 4, -1]).mutation_class(data_type='dig6') # finite G if n == 2: - data[ ('G',2) ] = ClusterQuiver(['G',2]).mutation_class(data_type='dig6') + data[('G', 2)] = ClusterQuiver(['G', 2]).mutation_class(data_type='dig6') # affine G if n == 3: - data[ ('G',2,1) ] = ClusterQuiver(['G',2,1]).mutation_class(data_type='dig6') - data[ ('G',2,-1) ] = ClusterQuiver(['G',2,-1]).mutation_class(data_type='dig6') + data[('G', 2, 1)] = ClusterQuiver(['G', 2, 1]).mutation_class(data_type='dig6') + data[('G', 2, -1)] = ClusterQuiver(['G', 2, -1]).mutation_class(data_type='dig6') # elliptic G if n == 4: - data[ ('G',2,(1,3)) ] = ClusterQuiver(['G',2,(1,3)]).mutation_class(data_type='dig6') - data[ ('G',2,(1,1)) ] = ClusterQuiver(['G',2,(1,1)]).mutation_class(data_type='dig6') - data[ ('G',2,(3,3)) ] = ClusterQuiver(['G',2,(3,3)]).mutation_class(data_type='dig6') + data[('G', 2, (1, 3))] = ClusterQuiver(['G', 2, (1, 3)]).mutation_class(data_type='dig6') + data[('G', 2, (1, 1))] = ClusterQuiver(['G', 2, (1, 1)]).mutation_class(data_type='dig6') + data[('G', 2, (3, 3))] = ClusterQuiver(['G', 2, (3, 3)]).mutation_class(data_type='dig6') # X - if n in [6,7]: - data[ ('X',n) ] = ClusterQuiver(['X',n]).mutation_class(data_type='dig6') + if n in [6, 7]: + data[('X', n)] = ClusterQuiver(['X', n]).mutation_class(data_type='dig6') # elliptic F if n == 6: - data[ ('F',4,(1,2)) ] = ClusterQuiver(['F',4,(1,2)]).mutation_class(data_type='dig6') - data[ ('F',4,(1,1)) ] = ClusterQuiver(['F',4,(1,1)]).mutation_class(data_type='dig6') - data[ ('F',4,(2,2)) ] = ClusterQuiver(['F',4,(2,2)]).mutation_class(data_type='dig6') + data[('F', 4, (1, 2))] = ClusterQuiver(['F', 4, (1, 2)]).mutation_class(data_type='dig6') + data[('F', 4, (1, 1))] = ClusterQuiver(['F', 4, (1, 1)]).mutation_class(data_type='dig6') + data[('F', 4, (2, 2))] = ClusterQuiver(['F', 4, (2, 2)]).mutation_class(data_type='dig6') return data @@ -2268,14 +2272,14 @@ def _save_data_dig6(n, types='ClassicalExceptional', verbose=False): from sage.env import DOT_SAGE from sage.misc.misc import sage_makedirs types_path = os.path.join(DOT_SAGE, 'cluster_algebra_quiver') - types_file = os.path.join(types_path,'mutation_classes_%s.dig6' % n) + types_file = os.path.join(types_path, 'mutation_classes_%s.dig6' % n) sage_makedirs(types_path) from sage.misc.temporary_file import atomic_write with atomic_write(types_file, binary=True) as f: pickle.dump(data, f) if verbose: - keys = sorted(data.keys(),key=str) - print("\nThe following types are saved to file", types_file,"and will now be used to determine quiver mutation types:") + keys = sorted(data, key=str) + print("\nThe following types are saved to file", types_file, "and will now be used to determine quiver mutation types:") print(keys) @@ -2331,16 +2335,16 @@ def save_quiver_data(n, up_to=True, types='ClassicalExceptional', verbose=True): """ from sage.combinat.cluster_algebra_quiver.mutation_type import load_data if up_to is True: - ranks = range(1,n+1) + ranks = range(1, n + 1) elif up_to is False: ranks = [n] for i in ranks: - _save_data_dig6(i,types=types,verbose=verbose) + _save_data_dig6(i, types=types, verbose=verbose) # we finally clear the load_data load_data.clear_cache() -def _bipartite_graph_to_digraph(g): +def _bipartite_graph_to_digraph(g) -> DiGraph: """ Return a digraph obtained from a bipartite graph ``g`` by choosing one set of the bipartition to be the set of sinks and the other to be the @@ -2349,7 +2353,7 @@ def _bipartite_graph_to_digraph(g): EXAMPLES:: sage: from sage.combinat.cluster_algebra_quiver.quiver_mutation_type import _bipartite_graph_to_digraph - sage: G = Graph([(1,2)]) + sage: G = Graph([(1, 2)]) sage: _bipartite_graph_to_digraph(G) Digraph on 2 vertices """ @@ -2364,7 +2368,7 @@ def _bipartite_graph_to_digraph(g): return dg -def _is_mutation_type(data): +def _is_mutation_type(data) -> bool: """ Return ``True`` if ``data`` is a QuiverMutationType. @@ -2412,7 +2416,7 @@ def _mutation_type_error(data): raise ValueError(return_str) -def _edge_list_to_matrix(edges, nlist, mlist): +def _edge_list_to_matrix(edges, nlist, mlist) -> matrix: r""" Return the matrix obtained from the edge list of a quiver. @@ -2429,8 +2433,8 @@ def _edge_list_to_matrix(edges, nlist, mlist): EXAMPLES:: sage: from sage.combinat.cluster_algebra_quiver.quiver_mutation_type import _edge_list_to_matrix - sage: G = QuiverMutationType(['A',2])._digraph - sage: _edge_list_to_matrix(G.edges(), [0,1], []) + sage: G = QuiverMutationType(['A', 2])._digraph + sage: _edge_list_to_matrix(G.edges(), [0, 1], []) [ 0 1] [-1 0] @@ -2446,15 +2450,16 @@ def _edge_list_to_matrix(edges, nlist, mlist): [ 0 -1] """ n = len(nlist) - m = len(mlist) nmlist = nlist + mlist - M = matrix(ZZ, n + m, n, sparse=True) - for edge in edges: - if edge[2] is None: - edge = (edge[0], edge[1], (1, -1)) - elif edge[2] in ZZ: - edge = (edge[0], edge[1], (edge[2], -edge[2])) - v1, v2, (a, b) = edge + nm = len(nmlist) + M = matrix(ZZ, nm, n, sparse=True) + for v1, v2, label in edges: + if label is None: + a, b = 1, -1 + elif label in ZZ: + a, b = label, -label + else: + a, b = label if v1 in nlist: M[nmlist.index(v2), nmlist.index(v1)] = b if v2 in nlist: diff --git a/src/sage/combinat/combination.py b/src/sage/combinat/combination.py index 38152061cd0..7936bbc3516 100644 --- a/src/sage/combinat/combination.py +++ b/src/sage/combinat/combination.py @@ -159,16 +159,22 @@ class of combinations of ``mset`` of size ``k``. [[], [(0, 0)], [(0, 1)], [(0, 0), (0, 1)]] """ # Check to see if everything in mset is unique + is_unique = False if isinstance(mset, (int, Integer)): mset = list(range(mset)) + is_unique = True + elif isinstance(mset, range): + mset = list(mset) + is_unique = True else: mset = list(mset) + for i, e in enumerate(mset): + if mset.index(e) != i: + break + else: + is_unique = True - d = {} - for i in mset: - d[mset.index(i)] = 1 - - if len(d) == len(mset): + if is_unique: if k is None: return Combinations_set(mset) else: @@ -316,6 +322,17 @@ def rank(self, x): r += rank(x, n) return r + def cardinality(self): + """ + Return the size of Combinations(set). + + EXAMPLES:: + + sage: Combinations(range(16000)).cardinality() == 2^16000 + True + """ + return 2**len(self.mset) + class Combinations_msetk(Parent): def __init__(self, mset, k): @@ -511,6 +528,17 @@ def rank(self, x): x = [self.mset.index(_) for _ in x] return rank(x, len(self.mset)) + def cardinality(self): + """ + Return the size of combinations(set, k). + + EXAMPLES:: + + sage: Combinations(range(16000), 5).cardinality() + 8732673194560003200 + """ + return binomial(len(self.mset), self.k) + def rank(comb, n, check=True): """ diff --git a/src/sage/combinat/derangements.py b/src/sage/combinat/derangements.py index d9db2b087e1..e8e25e9cd79 100644 --- a/src/sage/combinat/derangements.py +++ b/src/sage/combinat/derangements.py @@ -29,7 +29,8 @@ from sage.misc.misc_c import prod from sage.misc.prandom import random, randrange from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.rings.integer import Integer from sage.combinat.combinat import CombinatorialElement from sage.combinat.permutation import Permutation, Permutations diff --git a/src/sage/combinat/descent_algebra.py b/src/sage/combinat/descent_algebra.py index bff1e214ee5..8d2678bc518 100644 --- a/src/sage/combinat/descent_algebra.py +++ b/src/sage/combinat/descent_algebra.py @@ -20,7 +20,8 @@ from sage.categories.algebras import Algebras from sage.categories.realizations import Realizations, Category_realization_of_parent from sage.categories.all import FiniteDimensionalAlgebrasWithBasis -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.arith.misc import factorial from sage.combinat.free_module import CombinatorialFreeModule from sage.combinat.permutation import Permutations diff --git a/src/sage/combinat/diagram_algebras.py b/src/sage/combinat/diagram_algebras.py index 1f7dfef039d..17a9f85bc5f 100644 --- a/src/sage/combinat/diagram_algebras.py +++ b/src/sage/combinat/diagram_algebras.py @@ -41,7 +41,8 @@ from sage.misc.lazy_attribute import lazy_attribute from sage.misc.flatten import flatten from sage.misc.misc_c import prod -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.functions.other import floor, ceil import itertools diff --git a/src/sage/combinat/dyck_word.py b/src/sage/combinat/dyck_word.py index 10f8a588a8b..4eb3cebf1b4 100644 --- a/src/sage/combinat/dyck_word.py +++ b/src/sage/combinat/dyck_word.py @@ -91,7 +91,8 @@ from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets from sage.categories.all import Posets -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.combinat.permutation import Permutation, Permutations from sage.combinat.words.word import Word from sage.combinat.alternating_sign_matrix import AlternatingSignMatrices diff --git a/src/sage/combinat/fqsym.py b/src/sage/combinat/fqsym.py index fc29f0f0a06..ba89286a1a3 100644 --- a/src/sage/combinat/fqsym.py +++ b/src/sage/combinat/fqsym.py @@ -1337,7 +1337,7 @@ def basis(self, degree=None): sage: G.basis(degree=3).list() [G[1, 2, 3], G[1, 3, 2], G[2, 1, 3], G[2, 3, 1], G[3, 1, 2], G[3, 2, 1]] """ - from sage.combinat.family import Family + from sage.sets.family import Family if degree is None: return Family(self._indices, self.monomial) else: diff --git a/src/sage/combinat/gelfand_tsetlin_patterns.py b/src/sage/combinat/gelfand_tsetlin_patterns.py index 4cd334ceaf6..1ab6ef536fa 100644 --- a/src/sage/combinat/gelfand_tsetlin_patterns.py +++ b/src/sage/combinat/gelfand_tsetlin_patterns.py @@ -150,7 +150,7 @@ def __classcall_private__(self, gt): """ return GelfandTsetlinPatterns()(gt) - def check(self) -> bool: + def check(self): """ Check that this is a valid Gelfand-Tsetlin pattern. @@ -159,8 +159,8 @@ def check(self) -> bool: sage: G = GelfandTsetlinPatterns() sage: G([[3,2,1],[2,1],[1]]).check() """ - assert all( self[i-1][j] >= self[i][j] >= self[i-1][j+1] - for i in range(1, len(self)) for j in range(len(self[i])) ) + assert all(self[i - 1][j] >= self[i][j] >= self[i - 1][j + 1] + for i in range(1, len(self)) for j in range(len(self[i]))) def _hash_(self) -> int: """ diff --git a/src/sage/combinat/integer_list_old.py b/src/sage/combinat/integer_list_old.py deleted file mode 100644 index cdd420bb79e..00000000000 --- a/src/sage/combinat/integer_list_old.py +++ /dev/null @@ -1,1214 +0,0 @@ -r""" -Tools for generating lists of integers in lexicographic order - -IMPORTANT NOTE (2009/02): -The internal functions in this file will be deprecated soon. -Please only use them through :class:`IntegerListsLex`. - -AUTHORS: - -- Mike Hansen - -- Travis Scrimshaw (2012-05-12): Fixed errors when returning ``None`` from - first. Added checks to make sure ``max_slope`` is satisfied. - -- Travis Scrimshaw (2012-10-29): Made ``IntegerListsLex`` into a parent with - the element class ``IntegerListsLexElement``. -""" -# **************************************************************************** -# Copyright (C) 2007 Mike Hansen , -# Copyright (C) 2012 Travis Scrimshaw -# -# Distributed under the terms of the GNU General Public License (GPL) -# -# This code is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# The full text of the GPL is available at: -# -# https://www.gnu.org/licenses/ -# **************************************************************************** - -from sage.arith.all import binomial -from sage.rings.integer_ring import ZZ -from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets -from sage.structure.parent import Parent -from sage.structure.list_clone import ClonableArray -from sage.misc.stopgap import stopgap - - -def first(n, min_length, max_length, floor, ceiling, min_slope, max_slope): - """ - Return the lexicographically smallest valid composition of ``n`` - satisfying the conditions. - - .. warning:: - - INTERNAL FUNCTION! DO NOT USE DIRECTLY! - - .. TODO:: - - Move this into Cython. - - Preconditions: - - - ``floor`` and ``ceiling`` need to satisfy the slope constraints, - e.g. be obtained ``fromcomp2floor`` or ``comp2ceil`` - - - ``floor`` must be below ``ceiling`` to ensure - the existence a valid composition - - TESTS:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: f = lambda l: lambda i: l[i-1] - sage: f([0,1,2,3,4,5])(1) - 0 - sage: integer_list.first(12, 4, 4, f([0,0,0,0]), f([4,4,4,4]), -1, 1) - [4, 3, 3, 2] - sage: integer_list.first(36, 9, 9, f([3,3,3,2,1,1,0,0,0]), f([7,6,5,5,5,5,5,4,4]), -1, 1) - [7, 6, 5, 5, 4, 3, 3, 2, 1] - sage: integer_list.first(25, 9, 9, f([3,3,3,2,1,1,0,0,0]), f([7,6,5,5,5,5,5,4,4]), -2, 1) - [7, 6, 5, 4, 2, 1, 0, 0, 0] - sage: integer_list.first(36, 9, 9, f([3,3,3,2,1,4,2,0,0]), f([7,6,5,5,5,5,5,4,4]), -2, 1) - [7, 6, 5, 5, 5, 4, 3, 1, 0] - - :: - - sage: I = integer_list.IntegerListsLex(6, max_slope=2, min_slope=2) - sage: list(I) - [[6], [2, 4], [0, 2, 4]] - """ - stopgap("First uses the old implementation of IntegerListsLex, which does not allow for arbitrary input;" - " non-allowed input can return wrong results," - " please see the documentation for IntegerListsLex for details.", - 17548) - # Check trivial cases, and standardize min_length to be at least 1 - if n < 0: - return None - if max_length <= 0: - if n == 0: - return [] - return None - if min_length <= 0: - if n == 0: - return [] - min_length = 1 - - # Increase min_length until n <= sum([ceiling(i) for i in range(min_length)]) - # This may run forever! - # Find the actual length the list needs to be - N = 0 - for i in range(1, min_length + 1): - ceil = ceiling(i) - if ceil < floor(i): - return None - N += ceil - while N < n: - min_length += 1 - if min_length > max_length: - return None - - ceil = ceiling(min_length) - if ceil == 0 and max_slope <= 0 or ceil < floor(min_length): - return None - - N += ceil - - # Trivial case - if min_length == 1: - if n < floor(1): - return None - return [n] - - if max_slope < min_slope: - return None - - # Compute the minimum values - # We are constrained below by the max slope - result = [floor(min_length)] - n -= floor(min_length) - for i in reversed(range(1, min_length)): - result.insert(0, max(floor(i), result[0] - max_slope)) - n -= result[0] - if n < 0: - return None - - if n == 0: # There is nothing more to do - return result - - if min_slope == float('-inf'): - for i in range(1, min_length+1): - if n <= ceiling(i) - result[i-1]: # -1 for indexing - result[i-1] += n - break - else: - n -= ceiling(i) - result[i-1] - result[i-1] = ceiling(i) - else: - low_x = 1 - low_y = result[0] - high_x = 1 - high_y = result[0] - - while n > 0: - # invariant after each iteration of the loop: - # [low_x, low_y] is the coordinate of the rightmost point of the - # current diagonal s.t. result[low_x] < low_y - low_y += 1 - while low_x < min_length and low_y + min_slope > result[low_x]: - low_x += 1 - low_y += min_slope - - high_y += 1 - while high_y > ceiling(high_x): - high_x += 1 - high_y += min_slope - - n -= low_x - high_x + 1 - - for j in range(1, high_x): - result[j-1] = ceiling(j) - for i in range(0, -n): - result[high_x+i-1] = high_y + min_slope * i - 1 - for i in range(-n, low_x-high_x+1): - result[high_x+i-1] = high_y + min_slope * i - - # Special check for equal slopes - if min_slope == max_slope and any(val + min_slope != result[i + 1] - for i, val in enumerate(result[:-1])): - return None - - return result - - -def lower_regular(comp, min_slope, max_slope): - """ - Return the uppest regular composition below ``comp`` - - TESTS:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: integer_list.lower_regular([4,2,6], -1, 1) - [3, 2, 3] - sage: integer_list.lower_regular([4,2,6], -1, infinity) - [3, 2, 6] - sage: integer_list.lower_regular([1,4,2], -1, 1) - [1, 2, 2] - sage: integer_list.lower_regular([4,2,6,3,7], -2, 1) - [4, 2, 3, 3, 4] - sage: integer_list.lower_regular([4,2,infinity,3,7], -2, 1) - [4, 2, 3, 3, 4] - sage: integer_list.lower_regular([1, infinity, 2], -1, 1) - [1, 2, 2] - sage: integer_list.lower_regular([infinity, 4, 2], -1, 1) - [4, 3, 2] - """ - new_comp = comp[:] - for i in range(1, len(new_comp)): - new_comp[i] = min(new_comp[i], new_comp[i-1] + max_slope) - - for i in reversed(range(len(new_comp)-1)): - new_comp[i] = min(new_comp[i], new_comp[i+1] - min_slope) - - return new_comp - - -def rightmost_pivot(comp, min_length, max_length, floor, ceiling, min_slope, max_slope): - """ - TESTS:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: f = lambda l: lambda i: l[i-1] - sage: integer_list.rightmost_pivot([7,6,5,5,4,3,3,2,1], 9, 9, f([3,3,3,2,1,1,0,0,0]), f([7,6,5,5,5,5,5,4,4]), -1, 0) - [7, 2] - sage: integer_list.rightmost_pivot([7,6,5,5,4,3,3,2,1], 9, 9,f([3,3,3,2,1,1,0,0,0]), f([7,6,5,5,5,5,5,4,4]), -2, 0) - [7, 1] - sage: integer_list.rightmost_pivot([7,6,5,5,4,3,3,2,1], 9, 9,f([3,3,3,2,1,1,0,0,0]), f([7,6,5,5,5,5,5,4,4]), -2, 4) - [8, 1] - sage: integer_list.rightmost_pivot([7,6,5,5,4,3,3,2,1], 9, 9,f([3,3,3,2,1,1,0,0,0]), f([7,6,5,5,5,5,5,4,4]), -2, 1) - [8, 1] - sage: integer_list.rightmost_pivot([7,6,5,5,5,5,5,4,4], 9, 9,f([3,3,3,2,1,1,0,0,0]), f([7,6,5,5,5,5,5,4,4]), -2, 1) - sage: integer_list.rightmost_pivot([3,3,3,2,1,1,0,0,0], 9, 9,f([3,3,3,2,1,1,0,0,0]), f([7,6,5,5,5,5,5,4,4]), -2, 1) - sage: g = lambda x: lambda i: x - sage: integer_list.rightmost_pivot([1],1,1,g(0),g(2),-10, 10) - sage: integer_list.rightmost_pivot([1,2],2,2,g(0),g(2),-10, 10) - sage: integer_list.rightmost_pivot([1,2],2,2,g(1),g(2), -10, 10) - sage: integer_list.rightmost_pivot([1,2],2,3,g(1),g(2), -10, 10) - [2, 1] - sage: integer_list.rightmost_pivot([2,2],2,3,g(2),g(2),-10, 10) - sage: integer_list.rightmost_pivot([2,3],2,3,g(2),g(2),-10,+10) - sage: integer_list.rightmost_pivot([3,2],2,3,g(2),g(2),-10,+10) - sage: integer_list.rightmost_pivot([3,3],2,3,g(2),g(2),-10,+10) - [1, 2] - sage: integer_list.rightmost_pivot([6],1,3,g(0),g(6),-1,0) - [1, 0] - sage: integer_list.rightmost_pivot([6],1,3,g(0),g(6),-2,0) - [1, 0] - sage: integer_list.rightmost_pivot([7,9,8,7],1,5,g(0),g(10),-1,10) - [2, 6] - sage: integer_list.rightmost_pivot([7,9,8,7],1,5,g(5),g(10),-10,10) - [3, 5] - sage: integer_list.rightmost_pivot([7,9,8,7],1,5,g(5),g(10),-1,10) - [2, 6] - sage: integer_list.rightmost_pivot([7,9,8,7],1,5,g(4),g(10),-2,10) - [3, 7] - sage: integer_list.rightmost_pivot([9,8,7],1,4,g(4),g(10),-2,0) - [1, 4] - sage: integer_list.rightmost_pivot([1,3],1,5,lambda i: i,g(10),-10,10) - sage: integer_list.rightmost_pivot([1,4],1,5,lambda i: i,g(10),-10,10) - sage: integer_list.rightmost_pivot([2,4],1,5,lambda i: i,g(10),-10,10) - [1, 1] - """ - if max_slope < min_slope: - return None - - x = len(comp) - if x == 0: - return None - - y = len(comp) + 1 - while y <= max_length: - if ceiling(y) > 0: - break - if max_slope <= 0: - y = max_length + 1 - break - y += 1 - - ceilingx_x = comp[x - 1]-1 - floorx_x = floor(x) - if x > 1: - floorx_x = max(floorx_x, comp[x - 2] + min_slope) - - F = comp[x - 1] - floorx_x - G = ceilingx_x - comp[x - 1] # this is -1 - - highX = x - lowX = x - - while not (ceilingx_x >= floorx_x and - (G >= 0 or - (y < max_length + 1 and - F - max(floor(y), floorx_x + (y - x) * min_slope) >= 0 and - G + min(ceiling(y), ceilingx_x + (y - x) * max_slope) >= 0))): - - if x == 1: - return None - - x -= 1 - - oldfloorx_x = floorx_x - ceilingx_x = comp[x-1] - 1 - floorx_x = floor(x) - if x > 1: - floorx_x = max(floorx_x, comp[x-2] + min_slope) - - min_slope_lowX = min_slope * (lowX - x) - max_slope_highX = max_slope * (highX - x) - - # Update G - if max_slope == float('+inf'): - # In this case, we have - # -- ceiling_x(i) = ceiling(i) for i > x - # --G >= 0 or G = -1 - G += ceiling(x + 1) - comp[x] - else: - G += (highX - x) * ((comp[x-1] + max_slope) - comp[x]) - 1 - temp = (ceilingx_x + max_slope_highX) - ceiling(highX) - while highX > x and temp >= 0: - G -= temp - highX -= 1 - max_slope_highX = max_slope * (highX-x) - temp = (ceilingx_x + max_slope_highX) - ceiling(highX) - - if G >= 0 and comp[x-1] > floorx_x: - # By case 1, x is at the rightmost pivot position - break - - # Update F - if y < max_length+1: - F += comp[x-1] - floorx_x - if min_slope != float('-inf'): - F += (lowX - x) * (oldfloorx_x - (floorx_x + min_slope)) - temp = floor(lowX) - (floorx_x + min_slope_lowX) - while lowX > x and temp >= 0: - F -= temp - lowX -= 1 - min_slope_lowX = min_slope * (lowX-x) - temp = floor(lowX) - (floorx_x + min_slope_lowX) - - return [x, floorx_x] - - -def next(comp, min_length, max_length, floor, ceiling, min_slope, max_slope): - """ - Return the next integer list after ``comp`` that satisfies the - constraints. - - .. WARNING:: - - INTERNAL FUNCTION! DO NOT USE DIRECTLY! - - EXAMPLES:: - - sage: from sage.combinat.integer_list_old import next - sage: IV = sage.combinat.integer_list_old.IntegerListsLex(n=2,length=3,min_slope=0) - sage: next([0,1,1], 3, 3, lambda i: 0, lambda i: 5, 0, 10) - [0, 0, 2] - """ - stopgap("Next uses the old implementation of IntegerListsLex, which does not allow for arbitrary input;" - " non-allowed input can return wrong results," - " please see the documentation for IntegerListsLex for details.", - 17548) - x = rightmost_pivot(comp, min_length, max_length, floor, ceiling, min_slope, max_slope) - if x is None: - return None - [x, low] = x - high = comp[x-1] - 1 - -# // Build wrappers around floor and ceiling to take into -# // account the new constraints on the value of compo[x]. -# // -# // Efficiency note: they are not wrapped more than once, since -# // the method Next calls first, but not the converse. - - if min_slope == float('-inf'): - new_floor = lambda i: floor(x+(i-1)) - else: - new_floor = lambda i: max(floor(x+(i-1)), low+(i-1)*min_slope) - - if max_slope == float('+inf'): - new_ceiling = lambda i: comp[x-1] - 1 if i == 1 else ceiling(x+(i-1)) - else: - new_ceiling = lambda i: min(ceiling(x+(i-1)), high+(i-1)*max_slope) - - res = [] - res += comp[:x-1] - f = first(sum(comp[x-1:]), max(min_length-x+1, 0), max_length-x+1, - new_floor, new_ceiling, min_slope, max_slope) - if f is None: # Check to make sure it is valid - return None - res += f - return res - - -def iterator(n, min_length, max_length, floor, ceiling, min_slope, max_slope): - """ - .. WARNING:: - - INTERNAL FUNCTION! DO NOT USE DIRECTLY! - - EXAMPLES:: - - sage: from sage.combinat.integer_list_old import iterator - sage: IV = sage.combinat.integer_list_old.IntegerListsLex(n=2,length=3,min_slope=0) - sage: list(iterator(2, 3, 3, lambda i: 0, lambda i: 5, 0, 10)) - [[0, 1, 1], [0, 0, 2]] - """ - stopgap("Iterator uses the old implementation of IntegerListsLex, which does not allow for arbitrary input;" - " non-allowed input can return wrong results," - " please see the documentation for IntegerListsLex for details.", - 17548) - succ = lambda x: next(x, min_length, max_length, floor, ceiling, min_slope, max_slope) - - # Handle the case where n is a list of integers - if isinstance(n, list): - for i in range(n[0], min(n[1]+1, upper_bound(min_length, max_length, floor, ceiling, min_slope, max_slope))): - for el in iterator(i, min_length, max_length, floor, ceiling, min_slope, max_slope): - yield el - else: - f = first(n, min_length, max_length, floor, ceiling, min_slope, max_slope) - while f is not None: - yield f - f = succ(f) - - -def upper_regular(comp, min_slope, max_slope): - """ - Return the uppest regular composition above ``comp``. - - TESTS:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: integer_list.upper_regular([4,2,6],-1,1) - [4, 5, 6] - sage: integer_list.upper_regular([4,2,6],-2, 1) - [4, 5, 6] - sage: integer_list.upper_regular([4,2,6,3,7],-2, 1) - [4, 5, 6, 6, 7] - sage: integer_list.upper_regular([4,2,6,1], -2, 1) - [4, 5, 6, 4] - """ - - new_comp = comp[:] - for i in range(1, len(new_comp)): - new_comp[i] = max(new_comp[i], new_comp[i-1] + min_slope) - - for i in reversed(range(len(new_comp)-1)): - new_comp[i] = max(new_comp[i], new_comp[i+1] - max_slope) - - return new_comp - - -def comp2floor(f, min_slope, max_slope): - """ - Given a composition, returns the lowest regular function N->N above - it. - - EXAMPLES:: - - sage: from sage.combinat.integer_list_old import comp2floor - sage: f = comp2floor([2, 1, 1],-1,0) - sage: [f(i) for i in range(10)] - [2, 1, 1, 1, 2, 3, 4, 5, 6, 7] - """ - if not f: - return lambda i: 0 - floor = upper_regular(f, min_slope, max_slope) - return lambda i: floor[i] if i < len(floor) else max(0, floor[-1]-(i-len(floor))*min_slope) - - -def comp2ceil(c, min_slope, max_slope): - """ - Given a composition, return the lowest regular function N->N below it. - - EXAMPLES:: - - sage: from sage.combinat.integer_list_old import comp2ceil - sage: f = comp2ceil([2, 1, 1],-1,0) - sage: [f(i) for i in range(10)] - [2, 1, 1, 1, 2, 3, 4, 5, 6, 7] - """ - if not c: - return lambda i: 0 - ceil = lower_regular(c, min_slope, max_slope) - return lambda i: ceil[i] if i < len(ceil) else max(0, ceil[-1]-(i-len(ceil))*min_slope) - - -def upper_bound(min_length, max_length, floor, ceiling, min_slope, max_slope): - """ - Compute a coarse upper bound on the size of a vector satisfying the - constraints. - - TESTS:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: f = lambda x: lambda i: x - sage: integer_list.upper_bound(0,4,f(0), f(1),-infinity,infinity) - 4 - sage: integer_list.upper_bound(0, infinity, f(0), f(1), -infinity, infinity) - inf - sage: integer_list.upper_bound(0, infinity, f(0), f(1), -infinity, -1) - 1 - sage: integer_list.upper_bound(0, infinity, f(0), f(5), -infinity, -1) - 15 - sage: integer_list.upper_bound(0, infinity, f(0), f(5), -infinity, -2) - 9 - """ - from sage.functions.all import floor as flr - if max_length < float('inf'): - return sum([ceiling(j) for j in range(max_length)]) - elif max_slope < 0 and ceiling(1) < float('inf'): - maxl = flr(-ceiling(1) / max_slope) - return ceiling(1) * (maxl + 1) + binomial(maxl + 1, 2) * max_slope - # FIXME: only checking the first 10000 values, but that should generally - # be enough - elif [ceiling(j) for j in range(10000)] == [0] * 10000: - return 0 - else: - return float('inf') - - -def is_a(comp, min_length, max_length, floor, ceiling, min_slope, max_slope): - """ - Return ``True`` if ``comp`` meets the constraints imposed by the - arguments. - - .. WARNING:: - - INTERNAL FUNCTION! DO NOT USE DIRECTLY! - - EXAMPLES:: - - sage: from sage.combinat.integer_list_old import is_a - sage: IV = sage.combinat.integer_list_old.IntegerListsLex(n=2,length=3,min_slope=0) - sage: all(is_a(iv, 3, 3, lambda i: 0, lambda i: 5, 0, 10) for iv in IV) - True - """ - if not(min_length <= len(comp) <= max_length): - return False - for i in range(len(comp)): - if not(floor(i + 1) <= comp[i] <= ceiling(i + 1)): - return False - for i in range(len(comp) - 1): - slope = comp[i + 1] - comp[i] - if not(min_slope <= slope <= max_slope): - return False - return True - - -class IntegerListsLexElement(ClonableArray): - """ - Element class for :class:`IntegerListsLex`. - """ - def check(self): - """ - Check to make sure this is a valid element in its - :class:`IntegerListsLex` parent. - - .. TODO:: Placeholder. Implement a proper check. - - EXAMPLES:: - - sage: C = IntegerListsLex(4) - sage: C([4]).check() - True - """ - return True - - -class IntegerListsLex(Parent): - r""" - A combinatorial class `C` for integer lists satisfying certain - sum, length, upper/lower bound and regularity constraints. The - purpose of this tool is mostly to provide a Constant Amortized - Time iterator through those lists, in lexicographic order. - - INPUT: - - - ``n`` -- a non negative integer - - ``min_length`` -- a non negative integer - - ``max_length`` -- an integer or `\infty` - - ``length`` -- an integer; overrides min_length and max_length if - specified - - ``min_part`` -- the minimum value of each part; defaults to ``0`` - - ``max_part`` -- the maximum value of each part; defaults to `+\infty` - - ``floor`` -- a function `f` (or list); defaults to - ``lambda i: min_part`` - - ``ceiling`` -- a function `f` (or list); defaults to - ``lambda i: max_part`` - - ``min_slope`` -- an integer or `-\infty`; defaults to `-\infty` - - ``max_slope`` -- an integer or `+\infty`; defaults to `+\infty` - - An *integer list* is a list `l` of nonnegative integers, its - *parts*. The *length* of `l` is the number of its parts; - the *sum* of `l` is the sum of its parts. - - .. NOTE:: - - Two valid integer lists are considered equivalent if they only - differ by trailing zeroes. In this case, only the list with the - least number of trailing zeroes will be produced. - - The constraints on the lists are as follow: - - - Sum: `sum(l) == n` - - - Length: ``min_length <= len(l) <= max_length`` - - - Lower and upper bounds: ``floor(i) <= l[i] <= ceiling(i)``, for - ``i`` from 0 to ``len(l)`` - - - Regularity condition: ``minSlope <= l[i+1]-l[i] <= maxSlope``, - for ``i`` from 0 to ``len(l)-1`` - - This is a generic low level tool. The interface has been designed - with efficiency in mind. It is subject to incompatible changes in - the future. More user friendly interfaces are provided by high - level tools like :class:`Partitions` or :class:`Compositions`. - - EXAMPLES: - - We create the combinatorial class of lists of length 3 and sum 2:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(2, length=3) - sage: C - Integer lists of sum 2 satisfying certain constraints - sage: C.cardinality() - 6 - sage: [p for p in C] - [[2, 0, 0], [1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1], [0, 0, 2]] - - sage: [2, 0, 0] in C - True - sage: [2, 0, 1] in C - False - sage: "a" in C - False - sage: ["a"] in C - False - - sage: C.first() - [2, 0, 0] - - One can specify lower and upper bound on each part:: - - sage: list(integer_list.IntegerListsLex(5, length = 3, floor = [1,2,0], ceiling = [3,2,3])) - [[3, 2, 0], [2, 2, 1], [1, 2, 2]] - - Using the slope condition, one can generate integer partitions - (but see :mod:`sage.combinat.partition.Partitions`):: - - sage: list(integer_list.IntegerListsLex(4, max_slope=0)) - [[4], [3, 1], [2, 2], [2, 1, 1], [1, 1, 1, 1]] - - This is the list of all partitions of `7` with parts at least `2`:: - - sage: list(integer_list.IntegerListsLex(7, max_slope = 0, min_part = 2)) - [[7], [5, 2], [4, 3], [3, 2, 2]] - - This is the list of all partitions of `5` and length at most 3 - which are bounded below by [2,1,1]:: - - sage: list(integer_list.IntegerListsLex(5, max_slope = 0, max_length = 3, floor = [2,1,1])) - [[5], [4, 1], [3, 2], [3, 1, 1], [2, 2, 1]] - - Note that ``[5]`` is considered valid, because the lower bound - constraint only apply to existing positions in the list. To - obtain instead the partitions containing ``[2,1,1]``, one need to - use ``min_length``:: - - sage: list(integer_list.IntegerListsLex(5, max_slope = 0, min_length = 3, max_length = 3, floor = [2,1,1])) - [[3, 1, 1], [2, 2, 1]] - - This is the list of all partitions of `5` which are contained in - ``[3,2,2]``:: - - sage: list(integer_list.IntegerListsLex(5, max_slope = 0, max_length = 3, ceiling = [3,2,2])) - [[3, 2], [3, 1, 1], [2, 2, 1]] - - This is the list of all compositions of `4` (but see Compositions):: - - sage: list(integer_list.IntegerListsLex(4, min_part = 1)) - [[4], [3, 1], [2, 2], [2, 1, 1], [1, 3], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]] - - This is the list of all integer vectors of sum `4` and length `3`:: - - sage: list(integer_list.IntegerListsLex(4, length = 3)) - [[4, 0, 0], [3, 1, 0], [3, 0, 1], [2, 2, 0], [2, 1, 1], - [2, 0, 2], [1, 3, 0], [1, 2, 1], [1, 1, 2], [1, 0, 3], - [0, 4, 0], [0, 3, 1], [0, 2, 2], [0, 1, 3], [0, 0, 4]] - - There are all the lists of sum 4 and length 4 such that l[i] <= i:: - - sage: list(integer_list.IntegerListsLex(4, length=4, ceiling=lambda i: i)) - [[0, 1, 2, 1], [0, 1, 1, 2], [0, 1, 0, 3], [0, 0, 2, 2], [0, 0, 1, 3]] - - This is the list of all monomials of degree `4` which divide the - monomial `x^3y^1z^2` (a monomial being identified with its - exponent vector):: - - sage: R. = QQ[] - sage: m = [3,1,2] - sage: def term(exponents): - ....: return x^exponents[0] * y^exponents[1] * z^exponents[2] - sage: list( integer_list.IntegerListsLex(4, length = len(m), ceiling = m, element_constructor = term) ) - [x^3*y, x^3*z, x^2*y*z, x^2*z^2, x*y*z^2] - - Note the use of the element_constructor feature. - - In general, the complexity of the iteration algorithm is constant - time amortized for each integer list produced. There is one - degenerate case though where the algorithm may run forever without - producing anything. If max_length is `+\infty` and max_slope `>0`, - testing whether there exists a valid integer list of sum `n` may - be only semi-decidable. In the following example, the algorithm - will enter an infinite loop, because it needs to decide whether - `ceiling(i)` is nonzero for some `i`:: - - sage: list( integer_list.IntegerListsLex(1, ceiling = lambda i: 0) ) # todo: not implemented - - .. NOTE:: - - Caveat: counting is done by brute force generation. In some - special cases, it would be possible to do better by counting - techniques for integral point in polytopes. - - .. NOTE:: - - Caveat: with the current implementation, the constraints should - satisfy the following conditions: - - - The upper and lower bounds themselves should satisfy the - slope constraints. - - - The maximal and minimal part values should not be equal. - - Those conditions are not always checked by the algorithm, and the - result may be completely incorrect if they are not satisfied: - - In the following example, the floor conditions do not satisfy the - slope conditions since the floor for the third part is also 3:: - - sage: I = integer_list.IntegerListsLex(16, min_length=2, min_part=3, max_slope=-1, floor=[5,3]) - Traceback (most recent call last): - ... - ValueError: floor does not satisfy the max slope condition - - Compare this with the following input, which is equivalent - but it bypasses the checks because the floor is a function:: - - sage: f = lambda x: 5 if x == 0 else 3 - sage: I = integer_list.IntegerListsLex(16, min_length=2, max_slope=-1, floor=f) - sage: list(I) - [[13, 3], [12, 4], [11, 5], [10, 6]] - - With some work, this could be fixed without affecting the overall - complexity and efficiency. Also, the generation algorithm could be - extended to deal with non-constant slope constraints and with - negative parts, as well as to accept a range parameter instead of - a single integer for the sum `n` of the lists (the later was - readily implemented in MuPAD-Combinat). Encouragements, - suggestions, and help are welcome. - - .. TODO:: - - Integrate all remaining tests from - http://mupad-combinat.svn.sourceforge.net/viewvc/mupad-combinat/trunk/MuPAD-Combinat/lib/COMBINAT/TEST/MachineIntegerListsLex.tst - - TESTS:: - - sage: g = lambda x: lambda i: x - sage: list(integer_list.IntegerListsLex(0, floor = g(1), min_slope = 0)) - [[]] - sage: list(integer_list.IntegerListsLex(0, floor = g(1), min_slope = 0, max_slope = 0)) - [[]] - sage: list(integer_list.IntegerListsLex(0, max_length=0, floor = g(1), min_slope = 0, max_slope = 0)) - [[]] - sage: list(integer_list.IntegerListsLex(0, max_length=0, floor = g(0), min_slope = 0, max_slope = 0)) - [[]] - sage: list(integer_list.IntegerListsLex(0, min_part = 1, min_slope = 0)) - [[]] - sage: list(integer_list.IntegerListsLex(1, min_part = 1, min_slope = 0)) - [[1]] - sage: list(integer_list.IntegerListsLex(0, min_length = 1, min_part = 1, min_slope = 0)) - [] - sage: list(integer_list.IntegerListsLex(0, min_length = 1, min_slope = 0)) - [[0]] - sage: list(integer_list.IntegerListsLex(3, max_length=2, )) - [[3], [2, 1], [1, 2], [0, 3]] - sage: partitions = {"min_part": 1, "max_slope": 0} - sage: partitions_min_2 = {"floor": g(2), "max_slope": 0} - sage: compositions = {"min_part": 1} - sage: integer_vectors = lambda l: {"length": l} - sage: lower_monomials = lambda c: {"length": c, "floor": lambda i: c[i]} - sage: upper_monomials = lambda c: {"length": c, "ceiling": lambda i: c[i]} - sage: constraints = { "min_part":1, "min_slope": -1, "max_slope": 0} - sage: list(integer_list.IntegerListsLex(6, **partitions)) - [[6], - [5, 1], - [4, 2], - [4, 1, 1], - [3, 3], - [3, 2, 1], - [3, 1, 1, 1], - [2, 2, 2], - [2, 2, 1, 1], - [2, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1]] - sage: list(integer_list.IntegerListsLex(6, **constraints)) - [[6], - [3, 3], - [3, 2, 1], - [2, 2, 2], - [2, 2, 1, 1], - [2, 1, 1, 1, 1], - [1, 1, 1, 1, 1, 1]] - sage: list(integer_list.IntegerListsLex(1, **partitions_min_2)) - [] - sage: list(integer_list.IntegerListsLex(2, **partitions_min_2)) - [[2]] - sage: list(integer_list.IntegerListsLex(3, **partitions_min_2)) - [[3]] - sage: list(integer_list.IntegerListsLex(4, **partitions_min_2)) - [[4], [2, 2]] - sage: list(integer_list.IntegerListsLex(5, **partitions_min_2)) - [[5], [3, 2]] - sage: list(integer_list.IntegerListsLex(6, **partitions_min_2)) - [[6], [4, 2], [3, 3], [2, 2, 2]] - sage: list(integer_list.IntegerListsLex(7, **partitions_min_2)) - [[7], [5, 2], [4, 3], [3, 2, 2]] - sage: list(integer_list.IntegerListsLex(9, **partitions_min_2)) - [[9], [7, 2], [6, 3], [5, 4], [5, 2, 2], [4, 3, 2], [3, 3, 3], [3, 2, 2, 2]] - sage: list(integer_list.IntegerListsLex(10, **partitions_min_2)) - [[10], - [8, 2], - [7, 3], - [6, 4], - [6, 2, 2], - [5, 5], - [5, 3, 2], - [4, 4, 2], - [4, 3, 3], - [4, 2, 2, 2], - [3, 3, 2, 2], - [2, 2, 2, 2, 2]] - sage: list(integer_list.IntegerListsLex(4, **compositions)) - [[4], [3, 1], [2, 2], [2, 1, 1], [1, 3], [1, 2, 1], [1, 1, 2], [1, 1, 1, 1]] - sage: list(integer_list.IntegerListsLex(6, min_length=1, floor=[7])) - [] - - Noted on :trac:`17898`:: - - sage: list(integer_list.IntegerListsLex(4, min_part=1, length=3, min_slope=1)) - [] - sage: integer_list.IntegerListsLex(6, ceiling=[4,2], floor=[3,3]).list() - [] - sage: integer_list.IntegerListsLex(6, min_part=1, max_part=3, max_slope=-4).list() - [] - """ - def __init__(self, - n, - length = None, min_length=0, max_length=float('+inf'), - floor=None, ceiling = None, - min_part = 0, max_part = float('+inf'), - min_slope=float('-inf'), max_slope=float('+inf'), - name = None, - element_constructor = None, - element_class = None, - global_options = None): - """ - Initialize ``self``. - - TESTS:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(2, length=3) - sage: C == loads(dumps(C)) - True - sage: C == loads(dumps(C)) # this did fail at some point, really! - True - sage: C is loads(dumps(C)) # todo: not implemented - True - sage: C.cardinality().parent() is ZZ - True - sage: TestSuite(C).run() - """ - stopgap("The old implementation of IntegerListsLex does not allow for arbitrary input;" - " non-allowed input can return wrong results," - " please see the documentation for IntegerListsLex for details.", - 17548) - # Convert to float infinity - from sage.rings.infinity import infinity - if max_slope == infinity: - max_slope = float('+inf') - if min_slope == -infinity: - min_slope = float('-inf') - if max_length == infinity: - max_length = float('inf') - if max_part == infinity: - max_part = float('+inf') - - if floor is None: - self.floor_list = [] - else: - try: - # Is ``floor`` an iterable? - # Not ``floor[:]`` because we want ``self.floor_list`` - # mutable, and applying [:] to a tuple gives a tuple. - self.floor_list = list(floor) - # Make sure the floor list will make the list satisfy the constraints - if min_slope != float('-inf'): - for i in range(1, len(self.floor_list)): - self.floor_list[i] = max(self.floor_list[i], self.floor_list[i-1] + min_slope) - - # Some input checking - for i in range(1, len(self.floor_list)): - if self.floor_list[i] - self.floor_list[i-1] > max_slope: - raise ValueError("floor does not satisfy the max slope condition") - if self.floor_list and min_part - self.floor_list[-1] > max_slope: - raise ValueError("floor does not satisfy the max slope condition") - except TypeError: - self.floor = floor - if ceiling is None: - self.ceiling_list = [] - else: - try: - # Is ``ceiling`` an iterable? - self.ceiling_list = list(ceiling) - # Make sure the ceiling list will make the list satisfy the constraints - if max_slope != float('+inf'): - for i in range(1, len(self.ceiling_list)): - self.ceiling_list[i] = min(self.ceiling_list[i], self.ceiling_list[i-1] + max_slope) - - # Some input checking - for i in range(1, len(self.ceiling_list)): - if self.ceiling_list[i] - self.ceiling_list[i-1] < min_slope: - raise ValueError("ceiling does not satisfy the min slope condition") - if self.ceiling_list and max_part - self.ceiling_list[-1] < min_slope: - raise ValueError("ceiling does not satisfy the min slope condition") - except TypeError: - # ``ceiling`` is not an iterable. - self.ceiling = ceiling - if name is not None: - self.rename(name) - if n in ZZ: - self.n = n - self.n_range = [n] - else: - self.n_range = n - if length is not None: - min_length = length - max_length = length - self.min_length = min_length - self.max_length = max_length - self.min_part = min_part - self.max_part = max_part - # FIXME: the internal functions currently assume that floor and ceiling start at 1 - # this is a workaround - self.max_slope = max_slope - self.min_slope = min_slope - if element_constructor is not None: - self._element_constructor_ = element_constructor - if element_class is not None: - self.Element = element_class - if global_options is not None: - self.global_options = global_options - Parent.__init__(self, category=FiniteEnumeratedSets()) - - Element = IntegerListsLexElement - - def _element_constructor_(self, lst): - """ - Construct an element with ``self`` as parent. - - EXAMPLES:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(4) - sage: C([4]) - [4] - """ - return self.element_class(self, lst) - - def __eq__(self, x): - """ - Compare two different :class:`IntegerListsLex`. - - For now, the comparison is done just on their repr's which is - not robust! - - EXAMPLES:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(2, length=3) - sage: D = integer_list.IntegerListsLex(4, length=3) - sage: repr(C) == repr(D) - False - sage: C == D - False - """ - return repr(self) == repr(x) - - def __ne__(self, other): - """ - Compare two different :class:`IntegerListsLex`. - - For now, the comparison is done just on their repr's which is - not robust! - - EXAMPLES:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(2, length=3) - sage: D = integer_list.IntegerListsLex(4, length=3) - sage: C != D - True - """ - return not self.__eq__(other) - - def __hash__(self): - """ - Compute a hash for ``self``. - - EXAMPLES:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(2, length=3) - sage: h = hash(C) - """ - return hash(repr(self)) ^ 53397379531 - - def _repr_(self): - """ - Return the name of this combinatorial class. - - EXAMPLES:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(2, length=3) - sage: C # indirect doctest - Integer lists of sum 2 satisfying certain constraints - - sage: C = integer_list.IntegerListsLex([1,2,4], length=3) - sage: C # indirect doctest - Integer lists of sum in [1, 2, 4] satisfying certain constraints - - sage: C = integer_list.IntegerListsLex([1,2,4], length=3, name="A given name") - sage: C - A given name - """ - if hasattr(self, "n"): - return "Integer lists of sum %s satisfying certain constraints" % self.n - - return "Integer lists of sum in %s satisfying certain constraints" % self.n_range - - def floor(self, i): - """ - Return the minimum part that can appear at the `i^{th}` position of - any list produced. - - EXAMPLES:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(4, length=2, min_part=1) - sage: C.floor(0) - 1 - sage: C = integer_list.IntegerListsLex(4, length=2, floor=[1,2]) - sage: C.floor(0) - 1 - sage: C.floor(1) - 2 - """ - if i < len(self.floor_list): - return max(self.min_part, self.floor_list[i]) - if self.min_slope != float('-inf') and self.min_slope > 0: - return self.min_part + (i - len(self.floor_list)) * self.min_slope - return self.min_part - - def ceiling(self, i): - """ - Return the maximum part that can appear in the `i^{th}` - position in any list produced. - - EXAMPLES:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(4, length=2, max_part=3) - sage: C.ceiling(0) - 3 - sage: C = integer_list.IntegerListsLex(4, length=2, ceiling=[3,2]) - sage: C.ceiling(0) - 3 - sage: C.ceiling(1) - 2 - """ - if i < len(self.ceiling_list): - return min(self.max_part, self.ceiling_list[i]) - if self.max_slope != float('inf') and self.max_slope < 0: - return self.max_part + (i - len(self.ceiling_list)) * self.max_slope - return self.max_part - - # Temporary adapter to use the preexisting list/iterator/is_a function above. - # FIXME: fix their specs so that floor and ceiling start from 0 instead of 1... - # FIXME: integrate them as methods of this class - def build_args(self): - """ - Return a list of arguments that can be passed into the pre-existing - ``first``, ``next``, ``is_a``, ... functions in this module. - - ``n`` is currently not included in this list. - - EXAMPLES:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(2, length=3) - sage: C.build_args() - [3, - 3, - at 0x...>, - at 0x...>, - -inf, - inf] - """ - return [self.min_length, self.max_length, - lambda i: self.floor(i - 1), lambda i: self.ceiling(i - 1), - self.min_slope, self.max_slope] - - def first(self): - """ - Return the lexicographically maximal element in ``self``. - - EXAMPLES:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(2, length=3) - sage: C.first() - [2, 0, 0] - """ - # Make sure we have a valid return - f = first(self.n_range[0], *(self.build_args())) - if f is None: - return None - return self._element_constructor_(f) - - def __iter__(self): - """ - Return an iterator for the elements of ``self``. - - EXAMPLES:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(2, length=3) - sage: list(C) #indirect doctest - [[2, 0, 0], [1, 1, 0], [1, 0, 1], [0, 2, 0], [0, 1, 1], [0, 0, 2]] - """ - args = self.build_args() - for n in self.n_range: - l = first(n, *args) - while l is not None: - yield self._element_constructor_(l) - l = next(l, *args) - - def count(self): - """ - Default brute force implementation of count by iteration - through all the objects. - - Note that this skips the call to ``_element_constructor_``, - unlike the default implementation. - - .. TODO:: - - Do the iteration in place to save on copying time - - EXAMPLES:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(2, length=3) - sage: C.cardinality() == C.count() - True - """ - args = self.build_args() - c = ZZ(0) - for n in self.n_range: - l = first(n, *args) - while l is not None: - c += 1 - l = next(l, *args) - return c - - def __contains__(self, v): - """ - Return ``True`` if and only if ``v`` is in ``self``. - - EXAMPLES:: - - sage: import sage.combinat.integer_list_old as integer_list - sage: C = integer_list.IntegerListsLex(2, length=3) - sage: [2, 0, 0] in C - True - sage: [2, 0] in C - False - sage: [3, 0, 0] in C - False - sage: all(v in C for v in C) - True - """ - if isinstance(v, (self.element_class, list)): - return is_a(v, *(self.build_args())) and sum(v) in self.n_range - return False diff --git a/src/sage/combinat/lr_tableau.py b/src/sage/combinat/lr_tableau.py index 6d14d998066..a300846d8de 100644 --- a/src/sage/combinat/lr_tableau.py +++ b/src/sage/combinat/lr_tableau.py @@ -116,12 +116,12 @@ def check(self): Traceback (most recent call last): ... ValueError: [[1, 1, 2], [3, 3], [4]] is not an element of - Littlewood-Richardson Tableaux of shape [3, 2, 1] and weight ([2, 1], [2, 1]). + Littlewood-Richardson Tableaux of shape [3, 2, 1] and weight ([2, 1], [2, 1]) sage: LR([[1, 1, 2, 3], [3], [4]]) Traceback (most recent call last): ... ValueError: [[1, 1, 2, 3], [3], [4]] is not an element of - Littlewood-Richardson Tableaux of shape [3, 2, 1] and weight ([2, 1], [2, 1]). + Littlewood-Richardson Tableaux of shape [3, 2, 1] and weight ([2, 1], [2, 1]) sage: LR([[1, 1, 3], [3, 3], [4]]) Traceback (most recent call last): ... @@ -304,3 +304,4 @@ def _tableau_join(t1, t2, shift=0): """ return [[e1 for e1 in row1] + [e2+shift for e2 in row2 if e2 is not None] for (row1, row2) in zip_longest(t1, t2, fillvalue=[])] + diff --git a/src/sage/combinat/ncsf_qsym/ncsf.py b/src/sage/combinat/ncsf_qsym/ncsf.py index f145ecde76d..a746239b155 100644 --- a/src/sage/combinat/ncsf_qsym/ncsf.py +++ b/src/sage/combinat/ncsf_qsym/ncsf.py @@ -3795,8 +3795,6 @@ def internal_product_on_basis_by_bracketing(self, I, J): True sage: psi_int_test(4) # long time True - sage: psi_int_test(5) # long time - True """ # The algorithm used here is described in # :meth:`generic_basis_code.GradedModulesWithInternalProduct.ElementMethods.internal_product`. diff --git a/src/sage/combinat/ncsf_qsym/qsym.py b/src/sage/combinat/ncsf_qsym/qsym.py index 3a46c666078..747dd7a9894 100644 --- a/src/sage/combinat/ncsf_qsym/qsym.py +++ b/src/sage/combinat/ncsf_qsym/qsym.py @@ -1908,7 +1908,8 @@ def lambda_of_monomial(self, I, n): # The following algorithm is a rewriting of the formula in the docstring. # We are working over QQ because there are denominators which don't # immediately cancel. - from sage.rings.all import ZZ, QQ + from sage.rings.integer_ring import ZZ + from sage.rings.rational_field import QQ QQM = QuasiSymmetricFunctions(QQ).M() QQ_result = QQM.zero() for lam in Partitions(n): diff --git a/src/sage/combinat/parking_functions.py b/src/sage/combinat/parking_functions.py index d1a551ffc40..3a859dbaf6b 100644 --- a/src/sage/combinat/parking_functions.py +++ b/src/sage/combinat/parking_functions.py @@ -62,7 +62,8 @@ # the License, or (at your option) any later version. # https://www.gnu.org/licenses/ # **************************************************************************** -from typing import NewType, Iterator, Tuple +from __future__ import annotations +from typing import Iterator from sage.rings.integer import Integer from sage.rings.rational_field import QQ @@ -81,9 +82,6 @@ from sage.structure.unique_representation import UniqueRepresentation -PF = NewType('PF', 'ParkingFunction') - - def is_a(x, n=None) -> bool: r""" Check whether a list is a parking function. @@ -108,6 +106,7 @@ def is_a(x, n=None) -> bool: A = sorted(x) return check_NDPF(A, n) + class ParkingFunction(ClonableArray, metaclass=InheritComparisonClasscallMetaclass): r""" A Parking Function. @@ -308,8 +307,9 @@ def diagonal_reading_word(self) -> Permutation: L = self.to_labelling_permutation() D = self.to_area_sequence() m = max(D) - return Permutation([L[-j - 1] for i in range(m + 1) - for j in range(len(L)) if D[-j - 1] == m - i]) + data = [L[-j - 1] for i in range(m + 1) + for j in range(len(L)) if D[-j - 1] == m - i] + return Permutation(data) # type: ignore diagonal_word = diagonal_reading_word @@ -385,7 +385,8 @@ def cars_permutation(self) -> Permutation: while self[i] + j in out: j += 1 out[self[i] + j] = i - return Permutation([out[i + 1] + 1 for i in range(len(self))]) + data = [out[i + 1] + 1 for i in range(len(self))] + return Permutation(data) # type: ignore def jump_list(self) -> list: # cars displacements r""" @@ -893,7 +894,7 @@ def to_dyck_word(self) -> DyckWord: sage: ParkingFunction([2,1,4,1]).to_dyck_word() [1, 1, 0, 1, 0, 0, 1, 0] """ - return DyckWord(area_sequence=self.to_area_sequence()) + return DyckWord(area_sequence=self.to_area_sequence()) # type: ignore def to_labelled_dyck_word(self): r""" @@ -930,7 +931,7 @@ def to_labelled_dyck_word(self): out.insert(i, 0) return out - def to_labelling_dyck_word_pair(self) -> Tuple[Permutation, DyckWord]: + def to_labelling_dyck_word_pair(self) -> tuple[Permutation, DyckWord]: r""" Return the pair ``(L, D)`` where ``L`` is a labelling and ``D`` is the Dyck word of the parking function. @@ -988,7 +989,7 @@ def to_NonDecreasingParkingFunction(self) -> PF: sage: ParkingFunction([4,1,2,1]).to_NonDecreasingParkingFunction() [1, 1, 2, 4] """ - return ParkingFunction(sorted(self)) + return ParkingFunction(sorted(self)) # type: ignore def characteristic_quasisymmetric_function(self, q=None, R=QQ['q', 't'].fraction_field()): @@ -1138,6 +1139,9 @@ def pretty_print(self, underpath=True): else: dw.pretty_print(labelling=L, underpath=False) + +PF = ParkingFunction + # ***************************************************************************** # CONSTRUCTIONS # ***************************************************************************** @@ -1218,9 +1222,10 @@ def from_labelled_dyck_word(LDW) -> PF: [2, 1, 4, 1] """ L = [ell for ell in LDW if ell != 0] - D = DyckWord([Integer(not x.is_zero()) for x in LDW]) + D = DyckWord([Integer(not x.is_zero()) for x in LDW]) # type: ignore return from_labelling_and_area_sequence(L, D.to_area_sequence()) + class ParkingFunctions(UniqueRepresentation, Parent): r""" Return the combinatorial class of Parking Functions. @@ -1319,6 +1324,7 @@ def __classcall_private__(cls, n=None): raise ValueError("%s is not a non-negative integer" % n) return ParkingFunctions_n(n) + class ParkingFunctions_all(ParkingFunctions): def __init__(self): """ @@ -1606,4 +1612,3 @@ def random_element(self) -> PF: position += Zm.one() free.remove(position) return self.element_class(self, [(i - free[0]).lift() for i in fun]) - diff --git a/src/sage/combinat/partition_algebra.py b/src/sage/combinat/partition_algebra.py index 9a6869b0de2..a820494f388 100644 --- a/src/sage/combinat/partition_algebra.py +++ b/src/sage/combinat/partition_algebra.py @@ -23,7 +23,8 @@ from sage.graphs.graph import Graph from sage.arith.all import factorial, binomial from .permutation import Permutations -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from .subset import Subsets from sage.functions.all import ceil diff --git a/src/sage/combinat/path_tableaux/frieze.py b/src/sage/combinat/path_tableaux/frieze.py index e68a0747b9d..da1d4205b00 100644 --- a/src/sage/combinat/path_tableaux/frieze.py +++ b/src/sage/combinat/path_tableaux/frieze.py @@ -25,7 +25,8 @@ from sage.categories.sets_cat import Sets from sage.combinat.path_tableaux.path_tableau import PathTableau, PathTableaux, CylindricalDiagram from sage.categories.fields import Fields -from sage.rings.all import QQ, ZZ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ class FriezePattern(PathTableau, metaclass=InheritComparisonClasscallMetaclass): diff --git a/src/sage/combinat/plane_partition.py b/src/sage/combinat/plane_partition.py index 52d7897b498..857924a64a5 100644 --- a/src/sage/combinat/plane_partition.py +++ b/src/sage/combinat/plane_partition.py @@ -22,7 +22,8 @@ # # https://www.gnu.org/licenses/ # **************************************************************************** -from typing import NewType, Iterator, Tuple +from __future__ import annotations +from typing import Iterator from sage.structure.list_clone import ClonableArray from sage.misc.inherit_comparison import InheritComparisonClasscallMetaclass @@ -36,9 +37,6 @@ from sage.plot.plot3d.platonic import cube -PP = NewType('PP', 'PlanePartition') - - class PlanePartition(ClonableArray, metaclass=InheritComparisonClasscallMetaclass): r""" @@ -141,7 +139,7 @@ def to_tableau(self) -> Tableau: sage: PP.to_tableau() [[4, 3, 3, 1], [2, 1, 1], [1, 1]] """ - return Tableau(self) + return Tableau(self) # type: ignore def z_tableau(self): r""" @@ -768,6 +766,9 @@ def is_TSSCPP(self) -> bool: return self.is_TSPP() and self.is_SCPP() +PP = PlanePartition + + class PlanePartitions(UniqueRepresentation, Parent): r""" All plane partitions inside a rectangular box of given side lengths. @@ -832,7 +833,7 @@ def _repr_(self) -> str: return "Plane partitions inside a {} x {} x {} box".format( self._box[0], self._box[1], self._box[2]) - def __iter__(self) -> Iterator: + def __iter__(self) -> Iterator[PP]: """ Iterate over ``self``. @@ -848,7 +849,7 @@ def __iter__(self) -> Iterator: C = self._box[2] from sage.combinat.tableau import SemistandardTableaux for T in SemistandardTableaux([B for i in range(A)], max_entry=C + A): - PP = [[0 for i in range(B)] for j in range(A)] + PP = [[0 for _ in range(B)] for _ in range(A)] for r in range(A): for c in range(B): PP[A - 1 - r][B - 1 - c] = T[r][c] - r - 1 @@ -880,7 +881,7 @@ def cardinality(self) -> Integer: for j in range(1, B + 1) for k in range(1, C + 1))) - def box(self) -> Tuple: + def box(self) -> tuple: """ Return the sizes of the box of the plane partitions of ``self`` are contained in. diff --git a/src/sage/combinat/posets/hasse_diagram.py b/src/sage/combinat/posets/hasse_diagram.py index 17c632e9b02..9d0a62a1f5a 100644 --- a/src/sage/combinat/posets/hasse_diagram.py +++ b/src/sage/combinat/posets/hasse_diagram.py @@ -2353,6 +2353,64 @@ def chains(self, element_class=list, exclude=None, conversion=None): """ return IncreasingChains(self._leq_storage, element_class, exclude, conversion) + def is_linear_interval(self, t_min, t_max) -> bool: + """ + Return whether the interval ``[t_min, t_max]`` is linear. + + This means that this interval is a total order. + + EXAMPLES:: + + sage: P = posets.PentagonPoset() + sage: H = P._hasse_diagram + sage: H.is_linear_interval(0, 4) + False + sage: H.is_linear_interval(0, 3) + True + sage: H.is_linear_interval(1, 3) + False + sage: H.is_linear_interval(1, 1) + True + + TESTS:: + + sage: P = posets.TamariLattice(3) + sage: H = P._hasse_diagram + sage: D = H._leq_storage + sage: a, b = H.bottom(), H.top() + sage: H.is_linear_interval(a, b) + False + sage: H.is_linear_interval(a, a) + True + """ + if '_leq_storage' in self.__dict__: + if not self.is_lequal(t_min, t_max): # very quick check + return False + t = t_max + while t != t_min: + found = False + for u in self.neighbor_in_iterator(t): + if self.is_lequal(t_min, u): + if not found: + found = True + t = u + else: + return False + return True + + # fall back to default implementation + it = self.all_paths_iterator([t_min], [t_max], + simple=True, trivial=True) + try: + next(it) + except StopIteration: # not comparable + return False + try: + next(it) + except StopIteration: # one path + return True + return False + def diamonds(self): r""" Return the list of diamonds of ``self``. @@ -3281,7 +3339,7 @@ def principal_congruences_poset(self): D[ab] = cong P[ab] = cong_ - # Todo: Make a function that creates the poset from a set + # TODO: Make a function that creates the poset from a set # by comparison function with minimal number of comparisons. T = SetPartitions(n) diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index 3c5b56dedf2..d0795a11556 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -127,7 +127,7 @@ :meth:`~FinitePoset.canonical_label` | Return copy of the poset canonically (re)labelled to integers. :meth:`~FinitePoset.slant_sum` | Return the slant sum poset of two posets. -**Chains & antichains** +**Chains, antichains & linear intervals** .. csv-table:: :class: contentstable @@ -136,6 +136,7 @@ :meth:`~FinitePoset.is_chain_of_poset` | Return ``True`` if elements in the given list are comparable. :meth:`~FinitePoset.is_antichain_of_poset` | Return ``True`` if elements in the given list are incomparable. + :meth:`~FinitePoset.is_linear_interval` | Return whether the given interval is a total order. :meth:`~FinitePoset.chains` | Return the chains of the poset. :meth:`~FinitePoset.antichains` | Return the antichains of the poset. :meth:`~FinitePoset.maximal_chains` | Return the maximal chains of the poset. @@ -145,6 +146,7 @@ :meth:`~FinitePoset.antichains_iterator` | Return an iterator over the antichains of the poset. :meth:`~FinitePoset.random_maximal_chain` | Return a random maximal chain. :meth:`~FinitePoset.random_maximal_antichain` | Return a random maximal antichain. + :meth:`~FinitePoset.linear_intervals_count` | Return the enumeration of linear intervals in the poset. **Drawing** @@ -281,8 +283,9 @@ # (at your option) any later version. # https://www.gnu.org/licenses/ # **************************************************************************** - +from __future__ import annotations from copy import copy, deepcopy + from sage.misc.cachefunc import cached_method from sage.misc.lazy_attribute import lazy_attribute from sage.misc.misc_c import prod @@ -2649,6 +2652,76 @@ def relations_number(self): # Maybe this should also be deprecated. intervals_number = relations_number + def linear_intervals_count(self) -> list[int]: + """ + Return the enumeration of linear intervals w.r.t. their cardinality. + + An interval is linear if it is a total order. + + OUTPUT: list of integers + + .. SEEALSO:: :meth:`is_linear_interval` + + EXAMPLES:: + + sage: P = posets.PentagonPoset() + sage: P.linear_intervals_count() + [5, 5, 2] + sage: P = posets.TamariLattice(4) + sage: P.linear_intervals_count() + [14, 21, 12, 2] + + TESTS:: + + sage: P = Poset() + sage: P.linear_intervals_count() + [] + """ + if not self.cardinality(): + return [] + H = self._hasse_diagram + stock = [(x, x, x) for x in H] + poly = [len(stock)] + exposant = 0 + while True: + exposant += 1 + next_stock = [] + short_stock = [(ch[0], ch[2]) for ch in stock] + for xmin, cov_xmin, xmax in stock: + for y in H.neighbor_out_iterator(xmax): + if exposant == 1: + next_stock.append((xmin, y, y)) + else: + if (cov_xmin, y) in short_stock: + if H.is_linear_interval(xmin, y): + next_stock.append((xmin, cov_xmin, y)) + if next_stock: + poly.append(len(next_stock)) + stock = next_stock + else: + break + return poly + + def is_linear_interval(self, x, y) -> bool: + """ + Return whether the interval ``[x, y]`` is linear. + + This means that this interval is a total order. + + EXAMPLES:: + + sage: P = posets.PentagonPoset() + sage: P.is_linear_interval(0, 4) + False + sage: P.is_linear_interval(0, 3) + True + sage: P.is_linear_interval(1, 3) + False + """ + a = self._element_to_vertex(x) + b = self._element_to_vertex(y) + return self._hasse_diagram.is_linear_interval(a, b) + def is_incomparable_chain_free(self, m, n=None) -> bool: r""" Return ``True`` if the poset is `(m+n)`-free, and ``False`` otherwise. @@ -6885,8 +6958,10 @@ def maximal_chains(self, partial=None): INPUT: - - ``partial`` -- list (optional); if present, find all maximal - chains starting with the elements in partial + - ``partial`` -- list (optional); if given, the list + ``partial`` is assumed to be the start of a maximal chain, + and the function will find all maximal chains starting with + the elements in ``partial`` This is used in constructing the order complex for the poset. @@ -6913,8 +6988,10 @@ def maximal_chains_iterator(self, partial=None): INPUT: - - ``partial`` -- list (optional); if present, yield all maximal - chains starting with the elements in partial + - ``partial`` -- list (optional); if given, the list + ``partial`` is assumed to be the start of a maximal chain, + and the function will yield all maximal chains starting with + the elements in ``partial`` EXAMPLES:: @@ -6923,6 +7000,13 @@ def maximal_chains_iterator(self, partial=None): sage: next(it) [0, 1, 3, 7] + TESTS:: + + sage: P = posets.BooleanLattice(3) + sage: it = P.maximal_chains_iterator([0, 4]) + sage: next(it) + [0, 4, 5, 7] + .. SEEALSO:: :meth:`antichains_iterator` diff --git a/src/sage/combinat/ribbon_tableau.py b/src/sage/combinat/ribbon_tableau.py index f164a886729..b6cf87a57b5 100644 --- a/src/sage/combinat/ribbon_tableau.py +++ b/src/sage/combinat/ribbon_tableau.py @@ -21,7 +21,8 @@ from sage.structure.unique_representation import UniqueRepresentation from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets from sage.categories.sets_cat import Sets -from sage.rings.all import QQ, ZZ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.rings.integer import Integer from sage.combinat.combinat import CombinatorialElement from sage.combinat.skew_partition import SkewPartition, SkewPartitions diff --git a/src/sage/combinat/root_system/ambient_space.py b/src/sage/combinat/root_system/ambient_space.py index e1d4adea0ea..c55646e94ce 100644 --- a/src/sage/combinat/root_system/ambient_space.py +++ b/src/sage/combinat/root_system/ambient_space.py @@ -11,7 +11,8 @@ from sage.misc.cachefunc import cached_method from sage.combinat.free_module import CombinatorialFreeModule from .weight_lattice_realizations import WeightLatticeRealizations -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.categories.homset import End diff --git a/src/sage/combinat/root_system/associahedron.py b/src/sage/combinat/root_system/associahedron.py index 498e37aa782..30092073473 100644 --- a/src/sage/combinat/root_system/associahedron.py +++ b/src/sage/combinat/root_system/associahedron.py @@ -27,7 +27,8 @@ from sage.geometry.polyhedron.parent import Polyhedra, Polyhedra_base, Polyhedra_QQ_ppl, Polyhedra_QQ_normaliz, Polyhedra_QQ_cdd, Polyhedra_polymake, Polyhedra_field from sage.combinat.root_system.cartan_type import CartanType from sage.modules.free_module_element import vector -from sage.rings.all import QQ, ZZ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ ancestors_of_associahedron = set([Polyhedron_QQ_ppl, Polyhedron_QQ_normaliz, Polyhedron_QQ_cdd, Polyhedron_field, Polyhedron_polymake]) diff --git a/src/sage/combinat/root_system/plot.py b/src/sage/combinat/root_system/plot.py index 5e8ee505465..36da0e98384 100644 --- a/src/sage/combinat/root_system/plot.py +++ b/src/sage/combinat/root_system/plot.py @@ -809,7 +809,8 @@ from sage.misc.lazy_import import lazy_import from sage.structure.element import parent from sage.modules.free_module_element import vector -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.combinat.root_system.cartan_type import CartanType lazy_import("sage.combinat.root_system.root_lattice_realizations", "RootLatticeRealizations") diff --git a/src/sage/combinat/root_system/reflection_group_complex.py b/src/sage/combinat/root_system/reflection_group_complex.py index 5f769683634..f66ff07ab5c 100644 --- a/src/sage/combinat/root_system/reflection_group_complex.py +++ b/src/sage/combinat/root_system/reflection_group_complex.py @@ -205,7 +205,8 @@ from sage.sets.family import Family from sage.structure.unique_representation import UniqueRepresentation from sage.groups.perm_gps.permgroup import PermutationGroup_generic -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.matrix.all import Matrix, identity_matrix from sage.structure.element import is_Matrix from sage.interfaces.gap3 import gap3 diff --git a/src/sage/combinat/root_system/reflection_group_element.pyx b/src/sage/combinat/root_system/reflection_group_element.pyx index 157c74e18dd..bd96e4297c3 100644 --- a/src/sage/combinat/root_system/reflection_group_element.pyx +++ b/src/sage/combinat/root_system/reflection_group_element.pyx @@ -27,7 +27,8 @@ from sage.misc.lazy_attribute import lazy_attribute from sage.misc.misc_c import prod from sage.arith.functions import lcm from sage.combinat.root_system.cartan_type import CartanType, CartanType_abstract -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.interfaces.gap3 import gap3 from sage.combinat.root_system.cartan_matrix import CartanMatrix from sage.misc.sage_eval import sage_eval diff --git a/src/sage/combinat/root_system/root_lattice_realizations.py b/src/sage/combinat/root_system/root_lattice_realizations.py index 1eaf908e63c..95301036614 100644 --- a/src/sage/combinat/root_system/root_lattice_realizations.py +++ b/src/sage/combinat/root_system/root_lattice_realizations.py @@ -22,7 +22,8 @@ from sage.categories.modules_with_basis import ModulesWithBasis from sage.structure.element import Element from sage.sets.family import Family -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.matrix.constructor import matrix from sage.modules.free_module_element import vector from sage.sets.recursively_enumerated_set import RecursivelyEnumeratedSet diff --git a/src/sage/combinat/root_system/root_system.py b/src/sage/combinat/root_system/root_system.py index 628afb34833..9285d9b958b 100644 --- a/src/sage/combinat/root_system/root_system.py +++ b/src/sage/combinat/root_system/root_system.py @@ -18,7 +18,8 @@ from sage.structure.sage_object import SageObject from sage.structure.unique_representation import UniqueRepresentation from .cartan_type import CartanType -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.misc.all import cached_method from .root_space import RootSpace from .weight_space import WeightSpace diff --git a/src/sage/combinat/root_system/type_E.py b/src/sage/combinat/root_system/type_E.py index 5c49a148806..4d60f4b6038 100644 --- a/src/sage/combinat/root_system/type_E.py +++ b/src/sage/combinat/root_system/type_E.py @@ -13,7 +13,7 @@ from . import ambient_space from sage.rings.integer_ring import ZZ -from sage.combinat.family import Family +from sage.sets.family import Family class AmbientSpace(ambient_space.AmbientSpace): """ diff --git a/src/sage/combinat/root_system/type_F.py b/src/sage/combinat/root_system/type_F.py index 744ef0547bb..8d63ec1bf19 100644 --- a/src/sage/combinat/root_system/type_F.py +++ b/src/sage/combinat/root_system/type_F.py @@ -13,7 +13,7 @@ from . import ambient_space from sage.rings.integer_ring import ZZ -from sage.combinat.family import Family +from sage.sets.family import Family # TODO: double check that this can't be defined over ZZ diff --git a/src/sage/combinat/root_system/weight_lattice_realizations.py b/src/sage/combinat/root_system/weight_lattice_realizations.py index 3ad10279619..bc9baf632b4 100644 --- a/src/sage/combinat/root_system/weight_lattice_realizations.py +++ b/src/sage/combinat/root_system/weight_lattice_realizations.py @@ -23,7 +23,7 @@ from sage.misc.lazy_attribute import lazy_attribute from sage.misc.misc_c import prod from sage.categories.category_types import Category_over_base_ring -from sage.combinat.family import Family +from sage.sets.family import Family from .root_lattice_realizations import RootLatticeRealizations diff --git a/src/sage/combinat/root_system/weyl_group.py b/src/sage/combinat/root_system/weyl_group.py index e546d399274..f5b693f1313 100644 --- a/src/sage/combinat/root_system/weyl_group.py +++ b/src/sage/combinat/root_system/weyl_group.py @@ -40,7 +40,8 @@ from sage.groups.matrix_gps.finitely_generated import FinitelyGeneratedMatrixGroup_gap from sage.groups.matrix_gps.group_element import MatrixGroupElement_gap from sage.groups.perm_gps.permgroup import PermutationGroup_generic -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.interfaces.gap import gap from sage.misc.cachefunc import cached_method from sage.combinat.root_system.cartan_type import CartanType diff --git a/src/sage/combinat/skew_partition.py b/src/sage/combinat/skew_partition.py index 9be0a9b6237..585e1802c74 100644 --- a/src/sage/combinat/skew_partition.py +++ b/src/sage/combinat/skew_partition.py @@ -148,7 +148,8 @@ from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.sets.set import Set from sage.graphs.digraph import DiGraph from sage.matrix.matrix_space import MatrixSpace diff --git a/src/sage/combinat/skew_tableau.py b/src/sage/combinat/skew_tableau.py index c04128ce691..676aff61440 100644 --- a/src/sage/combinat/skew_tableau.py +++ b/src/sage/combinat/skew_tableau.py @@ -437,7 +437,8 @@ def size(self): sage: SkewTableau([[None, 2], [1, 3]]).size() 3 """ - return sum(len([x for x in row if x is not None]) for row in self) + one = ZZ.one() + return sum(one for row in self for x in row if x is not None) def conjugate(self): """ @@ -539,10 +540,8 @@ def to_permutation(self): [] """ from sage.combinat.permutation import Permutation - word = [] - for row in reversed(self): - word += [i for i in row if i is not None] - return Permutation(word) + perm = [i for row in reversed(self) for i in row if i is not None] + return Permutation(perm) def weight(self): r""" @@ -591,7 +590,7 @@ def weight(self): sage: all(by_word(t) == SkewTableau(t).weight() for t in SST) True """ - if len(self) == 0 or all(c is None for row in self for c in row): + if (not self) or all(c is None for row in self for c in row): return [] m = max(c for row in self for c in row if c is not None) if m is None: @@ -623,10 +622,7 @@ def is_standard(self): """ # Check to make sure that it is filled with 1...size w = [i for row in self for i in row if i is not None] - if sorted(w) != list(range(1, len(w) + 1)): - return False - else: - return self.is_semistandard() + return sorted(w) == list(range(1, len(w) + 1)) and self.is_semistandard() def is_semistandard(self): """ @@ -683,9 +679,8 @@ def to_tableau(self): if self.inner_size() != 0: raise ValueError("the inner size of the skew tableau must be 0") - else: - from sage.combinat.tableau import Tableau - return Tableau(self[:]) + from sage.combinat.tableau import Tableau + return Tableau(self[:]) def restrict(self, n): """ @@ -708,9 +703,8 @@ def restrict(self, n): sage: SkewTableau([[None,1],[1],[2]]).restrict(1) [[None, 1], [1]] """ - t = self[:] - return SkewTableau([z for z in [[y for y in x if y is None or y <= n] - for x in t] if z]) + data = ([y for y in x if y is None or y <= n] for x in self) + return SkewTableau([z for z in data if z]) def restriction_outer_shape(self, n): """ @@ -743,9 +737,10 @@ def restriction_outer_shape(self, n): sage: T.restriction_outer_shape(19) [4, 3, 1] """ - from sage.combinat.partition import Partition - res = [len([y for y in row if y is None or y <= n]) for row in self] - return Partition(res) + from sage.combinat.partition import _Partitions + one = ZZ.one() + res = [sum(one for y in row if y is None or y <= n) for row in self] + return _Partitions(res) def restriction_shape(self, n): """ @@ -821,7 +816,7 @@ def to_chain(self, max_entry=None): [[1]] """ if max_entry is None: - if len(self) == 0 or all(c is None for row in self for c in row): + if (not self) or all(c is None for row in self for c in row): max_entry = 0 else: max_entry = max(c for row in self for c in row if c is not None) @@ -1214,38 +1209,49 @@ def bender_knuth_involution(self, k, rows=None, check=True): EXAMPLES:: - sage: t = SkewTableau([[None,None,None,4,4,5,6,7],[None,2,4,6,7,7,7],[None,4,5,8,8,9],[None,6,7,10],[None,8,8,11],[None],[4]]) + sage: t = SkewTableau([[None,None,None,4,4,5,6,7],[None,2,4,6,7,7,7], + ....: [None,4,5,8,8,9],[None,6,7,10],[None,8,8,11],[None],[4]]) sage: t - [[None, None, None, 4, 4, 5, 6, 7], [None, 2, 4, 6, 7, 7, 7], [None, 4, 5, 8, 8, 9], [None, 6, 7, 10], [None, 8, 8, 11], [None], [4]] + [[None, None, None, 4, 4, 5, 6, 7], [None, 2, 4, 6, 7, 7, 7], + [None, 4, 5, 8, 8, 9], [None, 6, 7, 10], [None, 8, 8, 11], [None], [4]] sage: t.bender_knuth_involution(1) - [[None, None, None, 4, 4, 5, 6, 7], [None, 1, 4, 6, 7, 7, 7], [None, 4, 5, 8, 8, 9], [None, 6, 7, 10], [None, 8, 8, 11], [None], [4]] + [[None, None, None, 4, 4, 5, 6, 7], [None, 1, 4, 6, 7, 7, 7], + [None, 4, 5, 8, 8, 9], [None, 6, 7, 10], [None, 8, 8, 11], [None], [4]] sage: t.bender_knuth_involution(4) - [[None, None, None, 4, 5, 5, 6, 7], [None, 2, 4, 6, 7, 7, 7], [None, 5, 5, 8, 8, 9], [None, 6, 7, 10], [None, 8, 8, 11], [None], [5]] + [[None, None, None, 4, 5, 5, 6, 7], [None, 2, 4, 6, 7, 7, 7], + [None, 5, 5, 8, 8, 9], [None, 6, 7, 10], [None, 8, 8, 11], [None], [5]] sage: t.bender_knuth_involution(5) - [[None, None, None, 4, 4, 5, 6, 7], [None, 2, 4, 5, 7, 7, 7], [None, 4, 6, 8, 8, 9], [None, 5, 7, 10], [None, 8, 8, 11], [None], [4]] + [[None, None, None, 4, 4, 5, 6, 7], [None, 2, 4, 5, 7, 7, 7], + [None, 4, 6, 8, 8, 9], [None, 5, 7, 10], [None, 8, 8, 11], [None], [4]] sage: t.bender_knuth_involution(6) - [[None, None, None, 4, 4, 5, 6, 6], [None, 2, 4, 6, 6, 7, 7], [None, 4, 5, 8, 8, 9], [None, 6, 7, 10], [None, 8, 8, 11], [None], [4]] + [[None, None, None, 4, 4, 5, 6, 6], [None, 2, 4, 6, 6, 7, 7], + [None, 4, 5, 8, 8, 9], [None, 6, 7, 10], [None, 8, 8, 11], [None], [4]] sage: t.bender_knuth_involution(666) == t True sage: t.bender_knuth_involution(4, 2) == t True sage: t.bender_knuth_involution(4, 3) - [[None, None, None, 4, 4, 5, 6, 7], [None, 2, 4, 6, 7, 7, 7], [None, 5, 5, 8, 8, 9], [None, 6, 7, 10], [None, 8, 8, 11], [None], [4]] + [[None, None, None, 4, 4, 5, 6, 7], [None, 2, 4, 6, 7, 7, 7], + [None, 5, 5, 8, 8, 9], [None, 6, 7, 10], [None, 8, 8, 11], [None], [4]] The Bender--Knuth involution is an involution:: sage: t = SkewTableau([[None,3,4,4],[None,6,10],[7,7,11],[18]]) - sage: all(t.bender_knuth_involution(k).bender_knuth_involution(k) == t for k in range(1,4)) + sage: all(t.bender_knuth_involution(k).bender_knuth_involution(k) + ....: == t for k in range(1,4)) True The same for the single switches:: - sage: all(t.bender_knuth_involution(k, j).bender_knuth_involution(k, j) == t for k in range(1,5) for j in range(1, 5)) + sage: all(t.bender_knuth_involution(k, j).bender_knuth_involution(k, j) + ....: == t for k in range(1,5) for j in range(1, 5)) True Locality of the Bender--Knuth involutions:: - sage: all(t.bender_knuth_involution(k).bender_knuth_involution(l) == t.bender_knuth_involution(l).bender_knuth_involution(k) for k in range(1,5) for l in range(1,5) if abs(k - l) > 1) + sage: all(t.bender_knuth_involution(k).bender_knuth_involution(l) + ....: == t.bender_knuth_involution(l).bender_knuth_involution(k) + ....: for k in range(1,5) for l in range(1,5) if abs(k - l) > 1) True TESTS:: @@ -1494,7 +1500,7 @@ def cells_by_content(self, c): sage: s.cells_by_content(-2) [(2, 0)] """ - if len(self) == 0: + if not self: return [] if c >= 0: @@ -1704,8 +1710,10 @@ def __contains__(self, x): def from_expr(self, expr): """ - Return a :class:`SkewTableau` from a MuPAD-Combinat expr for a skew - tableau. The first list in ``expr`` is the inner shape of the skew + Return a :class:`SkewTableau` from a MuPAD-Combinat expr for + a skew tableau. + + The first list in ``expr`` is the inner shape of the skew tableau. The second list are the entries in the rows of the skew tableau from bottom to top. @@ -1735,7 +1743,7 @@ def from_chain(self, chain): [[None, 1, 2], [None, 3, 4], [5]] """ shape = chain[-1] - T = [[None for _ in range(r)] for r in shape] + T = [[None]*r for r in shape] for i in range(1, len(chain)): la = chain[i] mu = chain[i - 1] @@ -1760,11 +1768,16 @@ def from_shape_and_word(self, shape, word): sage: SkewTableaux().from_shape_and_word(shape, word) [[None, 1, 3], [None, 2], [4]] """ - st = [[None] * row_length for row_length in shape[0]] + outer, inner = shape + st = [[None] * row_length for row_length in outer] w_count = 0 - for i in reversed(range(len(shape[0]))): - for j in range(shape[0][i]): - if i >= len(shape[1]) or j >= shape[1][i]: + for i in reversed(range(len(inner), len(outer))): + for j in range(outer[i]): + st[i][j] = word[w_count] + w_count += 1 + for i in reversed(range(len(inner))): + for j in range(outer[i]): + if j >= inner[i]: st[i][j] = word[w_count] w_count += 1 return self.element_class(self, st) diff --git a/src/sage/combinat/tableau.py b/src/sage/combinat/tableau.py index 3cb05d80804..6301ffd4a35 100644 --- a/src/sage/combinat/tableau.py +++ b/src/sage/combinat/tableau.py @@ -175,11 +175,11 @@ class Tableau(ClonableList, metaclass=InheritComparisonClasscallMetaclass): sage: Tableau([[1],[2,3]]) Traceback (most recent call last): ... - ValueError: A tableau must be a list of iterables of weakly decreasing length. + ValueError: a tableau must be a list of iterables of weakly decreasing length sage: Tableau([1,2,3]) Traceback (most recent call last): ... - ValueError: A tableau must be a list of iterables. + ValueError: a tableau must be a list of iterables """ @staticmethod @@ -208,7 +208,7 @@ def __classcall_private__(cls, t): try: t = [tuple(_) for _ in t] except TypeError: - raise ValueError("A tableau must be a list of iterables.") + raise ValueError("a tableau must be a list of iterables") return Tableaux_all().element_class(Tableaux_all(), t) @@ -330,16 +330,16 @@ def check(self): sage: t = Tableau([[None, None, 1], [2, 4], [3, 4, 5]]) # indirect doctest Traceback (most recent call last): ... - ValueError: A tableau must be a list of iterables of weakly decreasing length. + ValueError: a tableau must be a list of iterables of weakly decreasing length """ # Check that it has partition shape. That's all we require from a # general tableau. - lens = [len(_) for _ in self] + lens = [len(row) for row in self] for (a, b) in zip(lens, lens[1:]): if a < b: - raise ValueError("A tableau must be a list of iterables of weakly decreasing length.") + raise ValueError("a tableau must be a list of iterables of weakly decreasing length") if lens and lens[-1] == 0: - raise ValueError("A tableau must not have empty rows.") + raise ValueError("a tableau must not have empty rows") def _repr_(self): """ @@ -4884,7 +4884,8 @@ def from_chain(chain): for j in range(len(chain[i - 1])): for k in range(chain[i - 1][j]): res[j][k] = i -1 - return Tableau(res) + T = Tableaux_all() + return T.element_class(T, res) def from_shape_and_word(shape, w, convention="French"): @@ -4919,7 +4920,7 @@ def from_shape_and_word(shape, w, convention="French"): sage: from_shape_and_word(shape, word) [[1, 3], [2], [4]] sage: word = Word(flatten(t)) - sage: from_shape_and_word(shape, word, convention = "English") + sage: from_shape_and_word(shape, word, convention="English") [[1, 3], [2], [4]] """ res = [] @@ -4927,11 +4928,12 @@ def from_shape_and_word(shape, w, convention="French"): if convention == "French": shape = reversed(shape) for l in shape: - res.append( list(w[j:j+l]) ) + res.append( tuple(w[j:j+l]) ) j += l if convention == "French": res.reverse() - return Tableau(res) + T = Tableaux_all() + return T.element_class(T, res) class IncreasingTableau(Tableau): @@ -5324,7 +5326,7 @@ class Tableaux(UniqueRepresentation, Parent): sage: Tableaux(3)([[1, 1]]) Traceback (most recent call last): ... - ValueError: [[1, 1]] is not an element of Tableaux of size 3. + ValueError: [[1, 1]] is not an element of Tableaux of size 3 sage: t0 = Tableau([[1]]) sage: t1 = Tableaux()([[1]]) @@ -5498,10 +5500,10 @@ def _element_constructor_(self, t): sage: T([[1,2]]) Traceback (most recent call last): ... - ValueError: [[1, 2]] is not an element of Tableaux of size 3. + ValueError: [[1, 2]] is not an element of Tableaux of size 3 """ if t not in self: - raise ValueError("%s is not an element of %s." % (t, self)) + raise ValueError("%s is not an element of %s" % (t, self)) return self.element_class(self, t) @@ -5541,7 +5543,7 @@ def __contains__(self, x): except TypeError: return False # any list of lists of partition shape is a tableau - return [len(_) for _ in x] in _Partitions + return [len(row) for row in x] in _Partitions else: return False diff --git a/src/sage/combinat/tableau_tuple.py b/src/sage/combinat/tableau_tuple.py index 9e8e689ac0f..ac3f23b1375 100644 --- a/src/sage/combinat/tableau_tuple.py +++ b/src/sage/combinat/tableau_tuple.py @@ -346,7 +346,7 @@ class TableauTuple(CombinatorialElement): sage: TableauTuple([[1],[2,3]]) Traceback (most recent call last): ... - ValueError: A tableau must be a list of iterables. + ValueError: a tableau must be a list of iterables sage: TestSuite( TableauTuple([ [[1,2],[3,4]], [[1,2],[3,4]] ]) ).run() sage: TestSuite( TableauTuple([ [[1,2],[3,4]], [], [[1,2],[3,4]] ]) ).run() diff --git a/src/sage/cpython/cython_metaclass.pyx b/src/sage/cpython/cython_metaclass.pyx index e3a00bdecb5..a5197e6734d 100644 --- a/src/sage/cpython/cython_metaclass.pyx +++ b/src/sage/cpython/cython_metaclass.pyx @@ -30,9 +30,6 @@ metaclass: from foo import MyMetaclass return MyMetaclass -The above ``__getmetaclass__`` method is analogous to -``__metaclass__ = MyMetaclass`` in Python 2. - .. WARNING:: ``__getmetaclass__`` must be defined as an ordinary method taking a diff --git a/src/sage/crypto/util.py b/src/sage/crypto/util.py index 44b7185f43e..de5872919d7 100644 --- a/src/sage/crypto/util.py +++ b/src/sage/crypto/util.py @@ -334,6 +334,8 @@ def carmichael_lambda(n): ....: L = coprime(n) ....: return list(map(power_mod, L, [k]*len(L), [n]*len(L))) sage: def my_carmichael(n): + ....: if n == 1: + ....: return 1 ....: for k in range(1, n): ....: L = znpower(n, k) ....: ones = [1] * len(L) diff --git a/src/sage/doctest/control.py b/src/sage/doctest/control.py index 8ba552e6806..858d8cb5679 100644 --- a/src/sage/doctest/control.py +++ b/src/sage/doctest/control.py @@ -28,6 +28,7 @@ import re import types import sage.misc.flatten +import sage.misc.randstate as randstate from sage.structure.sage_object import SageObject from sage.env import DOT_SAGE, SAGE_LIB, SAGE_SRC, SAGE_VENV, SAGE_EXTCODE from sage.misc.temporary_file import tmp_dir @@ -41,7 +42,7 @@ from .parsing import parse_optional_tags nodoctest_regex = re.compile(r'\s*(#+|%+|r"+|"+|\.\.)\s*nodoctest') -optionaltag_regex = re.compile(r'^\w+$') +optionaltag_regex = re.compile(r'^(\w|[.])+$') optionalfiledirective_regex = re.compile(r'\s*(#+|%+|r"+|"+|\.\.)\s*sage\.doctest: (.*)') # Optional tags which are always automatically added @@ -407,6 +408,9 @@ def __init__(self, options, args): from sage.features import package_systems options.optional.update(system.name for system in package_systems()) + from sage.features.sagemath import sage_features + options.optional.update(feature.name for feature in sage_features()) + # Check that all tags are valid for o in options.optional: if not optionaltag_regex.search(o): @@ -458,7 +462,8 @@ def __init__(self, options, args): self._init_warn_long() if self.options.random_seed is None: - self.options.random_seed = 0 + randstate.set_random_seed() + self.options.random_seed = randstate.initial_seed() def __del__(self): if getattr(self, 'logfile', None) is not None: diff --git a/src/sage/doctest/forker.py b/src/sage/doctest/forker.py index 0151041d08f..3307d50939e 100644 --- a/src/sage/doctest/forker.py +++ b/src/sage/doctest/forker.py @@ -2496,6 +2496,11 @@ def _run(self, runner, options, results): from importlib import import_module sage_all = import_module(options.environment) dict_all = sage_all.__dict__ + # When using global environments other than sage.all, + # make sure startup is finished so we don't get "Resolving lazy import" + # warnings. + from sage.misc.lazy_import import ensure_startup_finished + ensure_startup_finished() # Remove '__package__' item from the globals since it is not # always in the globals in an actual Sage session. dict_all.pop('__package__', None) diff --git a/src/sage/doctest/parsing.py b/src/sage/doctest/parsing.py index 0be358f35be..d61ed098a68 100644 --- a/src/sage/doctest/parsing.py +++ b/src/sage/doctest/parsing.py @@ -34,7 +34,7 @@ from .external import available_software float_regex = re.compile(r'\s*([+-]?\s*((\d*\.?\d+)|(\d+\.?))([eE][+-]?\d+)?)') -optional_regex = re.compile(r'(arb216|arb218|py2|py3|long time|not implemented|not tested|known bug)|([^ a-z]\s*optional\s*[:-]*((\s|\w)*))') +optional_regex = re.compile(r'(arb216|arb218|py2|py3|long time|not implemented|not tested|known bug)|([^ a-z]\s*optional\s*[:-]*((\s|\w|[.])*))') # Version 4.65 of glpk prints the warning "Long-step dual simplex will # be used" frequently. When Sage uses a system installation of glpk # which has not been patched, we need to ignore that message. @@ -83,9 +83,17 @@ def RIFtol(*args): """ global _RIFtol if _RIFtol is None: - # We need to import from sage.all to avoid circular imports. - from sage.all import RealIntervalField - _RIFtol = RealIntervalField(1044) + try: + # We need to import from sage.all to avoid circular imports. + from sage.all import RealIntervalField + except ImportError: + from warnings import warn + warn("RealIntervalField not available, ignoring all tolerance specifications in doctests") + def fake_RIFtol(*args): + return 0 + _RIFtol = fake_RIFtol + else: + _RIFtol = RealIntervalField(1044) return _RIFtol(*args) # This is the correct pattern to match ISO/IEC 6429 ANSI escape sequences: @@ -316,6 +324,8 @@ def parse_optional_tags(string): {''} sage: sorted(list(parse_optional_tags("sage: #optional -- foo bar, baz"))) ['bar', 'foo'] + sage: parse_optional_tags("sage: #optional -- foo.bar, baz") + {'foo.bar'} sage: sorted(list(parse_optional_tags(" sage: factor(10^(10^10) + 1) # LoNg TiME, NoT TeSTED; OptioNAL -- P4cka9e"))) ['long time', 'not tested', 'p4cka9e'] sage: parse_optional_tags(" sage: raise RuntimeError # known bug") diff --git a/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py b/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py index d46c8601b25..e5ef59acf59 100644 --- a/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +++ b/src/sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py @@ -8,6 +8,8 @@ Xander Faber, Michelle Manes, and Bianca Viray [FMV]_. - Joao de Faria, Ben Hutz, Bianca Thompson (11-2013): adaptation for inclusion in Sage + +- Alexander Galarraga (7-2021): Added helper functions for conjugating set """ #***************************************************************************** @@ -19,10 +21,10 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from copy import copy +from copy import copy, deepcopy from sage.combinat.subset import Subsets from sage.functions.all import sqrt -from itertools import permutations, combinations +from itertools import permutations, combinations, product from sage.matrix.constructor import matrix from sage.structure.element import is_Matrix from sage.misc.misc_c import prod @@ -34,6 +36,10 @@ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.rational_field import QQ from sage.sets.primes import Primes +from sage.sets.set import Set +from sage.combinat.permutation import Arrangements +from sage.parallel.use_fork import p_iter_fork +from sage.functions.other import floor def automorphism_group_QQ_fixedpoints(rational_function, return_functions=False, iso_type=False): r""" @@ -1783,3 +1789,606 @@ def which_group(list_of_elements): return ['S_4'] else: return ['A_5'] + +def conjugating_set_initializer(f, g): + """ + Return a conjugation invariant set together with information + to reduce the combinatorics of checking all possible conjugations. + + This function constructs the invariant pair (``source``, ``possible_targets``) + necessary for the conjugating set algorithm described in [FMV2014]_. + Let `f` and `g` be dynamical systems on `\mathbb{P}^n`. + An invariant pair is a pair of two sets `U`, `V` such that + `|U| = |V|` and for all `\phi \in PGL` such that `f^\phi = g`, + `\phi(u) \in V` for all `u \in U`. Invariant pairs can be used + to determine all conjugations from `f` to `g`. For details + in the `\mathbb{P}^1` case, see [FMV2014]_. + + Additionally, this function keeps track of multipliers to reduce the combinatorics. + This information is then passed to ``conjugating_set_helper`` or + ``is_conjugate_helper``, which check all possible conjugations determined + by the invariant pair. + + Do not call this function directly, instead use ``f.conjugating_set(g)``. + + INPUT: + + - ``f`` -- a rational function of degree at least 2, and the same + degree as ``g`` + + - ``g`` -- a nonconstant rational function of the same + degree as ``f`` + + OUTPUT: + + A tuple of the form (``source``, ``possible_targets``). + + - ``source`` -- a conjugation invariant set of `n+2` points of the domain of `f`, + of which no `n+1` are linearly dependent. Used to specify a possible conjugation + from `f` to `g`. + + - ``possible_targets`` -- a list of tuples of the form (``points``, ``repeated``). ``points`` + is a list of ``points`` which are possible targets for point(s) in ``source``. ``repeated`` + specifies how many points in ``source`` have points in ``points`` as their possible target. + + EXAMPLES: + + We check that ``source`` has no `n+1` linearly dependent points, and that + ``possible_targets`` tracks multiplier information:: + + sage: P. = ProjectiveSpace(QQ, 2) + sage: f = DynamicalSystem([(8*x^7 - 35*x^4*y^3 - 35*x^4*z^3 - 7*x*y^6 - 140*x*y^3*z^3 \ + - 7*x*z^6), (-7*x^6*y - 35*x^3*y^4 - 140*x^3*y*z^3 + 8*y^7 - 35*y^4*z^3 \ + - 7*y*z^6), -7*x^6*z - 140*x^3*y^3*z - 35*x^3*z^4 - 7*y^6*z - 35*y^3*z^4 + 8*z^7]) + sage: from sage.dynamics.arithmetic_dynamics.endPN_automorphism_group import conjugating_set_initializer + sage: source, possible_targets = conjugating_set_initializer(f, f) + sage: P.is_linearly_independent(source, 3) + True + sage: f.multiplier(possible_targets[0][0][0], 1) == f.multiplier(source[0], 1) + True + """ + n = f.domain().dimension_relative() + + L = Set(f.periodic_points(1)) + K = Set(g.periodic_points(1)) + P = f.codomain().ambient_space() + if len(L) != len(K): # checks maps have the same number of fixed points + return [] + + # we store fixed points an multipliers in dictionaries + # to avoid recalculating them + mult_to_point_L = {} + mult_to_point_K = {} + point_to_mult_L = {} + point_to_mult_K = {} + + # as we will calculate preimages, we differentiate points by their 'level' + # which is how many preimages of a fixed point they are, i.e. a fixed point + # has level 0, a preimage of a fixed point level 1, etc. + level = 0 + + # initializing the dictionaries + for i in range(len(L)): + mult_L = f.multiplier(L[i], 1).charpoly() + mult_K = g.multiplier(K[i], 1).charpoly() + tup_L = (mult_L, level) + tup_K = (mult_K, level) + if tup_L not in mult_to_point_L: + mult_to_point_L[tup_L] = [L[i]] + else: + mult_to_point_L[tup_L] += [L[i]] + if tup_K not in mult_to_point_K: + mult_to_point_K[tup_K] = [K[i]] + else: + mult_to_point_K[tup_K] += [K[i]] + point_to_mult_L[L[i]] = (mult_L, level) + point_to_mult_K[K[i]] = (mult_K, level) + + # we keep a dictionary which tracks how often a (multiplier, level) pair + # is repeated. As points can only be sent to points with the same (multiplier, level) + # pair, the less times a (multiplier, level) pair are repeated the better the + # combinatorics + repeated_mult_L = {} + for mult_L in mult_to_point_L: + repeated = len(mult_to_point_L[mult_L]) + if mult_L not in mult_to_point_K: + return [] + elif len(mult_to_point_K[mult_L]) != repeated: + return [] + if repeated not in repeated_mult_L: + repeated_mult_L[repeated] = [mult_to_point_L[mult_L]] + else: + repeated_mult_L[repeated] += [mult_to_point_L[mult_L]] + r = f.domain().base_ring() + more = True + + # the n+2 points to be used to specificy PGL conjugations + source = [] + + # a list of tuples of the form ((multiplier, level), repeat) where the + # (multiplier, level) pair specifies the possible targets of a point in source and repeat + # specifies how many points in source have that (multiplier, level) pair + corresponding = [] + + # we now greedily look for a set of n+2 points, of which no n+1 are linearly dependent, + # and we make sure to add the points with the best combinatorics first. + # this check sometimes fails, i.e. sometimes there is a subset with the + # desired property which is not found. however, this check is very fast and if it + # does find a subset, then the subset will most likely minimize the combinatorics + # of checking conjugations + tup = greedy_independence_check(P, repeated_mult_L, point_to_mult_L) + if not tup is None: + more = False + source, corresponding = tup + + else: + # loop_repeated_mult stores the points to find preimages of + loop_repeated_mult = deepcopy(repeated_mult_L) + # next_repeated_mult stores the points to find preimages of on the next loop + next_repeated_mult = {} + found_no_more = True + + # if we don't find enough points, we go to preimages + while more: + level += 1 + # we calculate preimages, starting with preimages with the best + # expected combinatorics + for r in sorted(loop_repeated_mult.keys()): + for point_lst_L in loop_repeated_mult[r]: + old_tup_L = point_to_mult_L[point_lst_L[0]] + point_lst_K = mult_to_point_K[old_tup_L] + mult_L = old_tup_L[0] + Tl = [] + Tk = [] + # first we calculate preimages + for pnt in point_lst_L: + for preimage in f.rational_preimages(pnt): + if preimage != pnt: + Tl.append(preimage) + for pnt in point_lst_K: + for preimage in g.rational_preimages(pnt): + if preimage != pnt: + Tk.append(preimage) + if len(Tl) != len(Tk): + return [] + if len(Tl) != 0: + found_no_more = False + new_tup_L = (mult_L, level) + new_tup_K = (mult_L, level) + # we update dictionaries with the new preimages + mult_to_point_L[new_tup_L] = Tl + mult_to_point_K[new_tup_K] = Tk + for i in range(len(Tl)): + point_to_mult_L[Tl[i]] = new_tup_L + point_to_mult_K[Tk[i]] = new_tup_K + repeated = len(Tl) + if repeated not in repeated_mult_L: + repeated_mult_L[repeated] = [Tl] + else: + repeated_mult_L[repeated] += [Tl] + if repeated not in next_repeated_mult: + next_repeated_mult[repeated] = [Tl] + else: + next_repeated_mult[repeated] += [Tl] + # we again do a greedy check for a subset of n+2 points, of which no n+1 + # are linearly dependent + tup = greedy_independence_check(P, repeated_mult_L, point_to_mult_L) + if not tup is None: + more = False + source, corresponding = tup + if not more: + break + if not more: + break + + # if no more preimages can be found, we must check all subsets + # of size n+2 to see if there is a subset in which no n+1 points + # are linearly dependent + if found_no_more: + # we construct a list of all the possible sources points + all_points = [] + # we order the list by how many repeated multipliers each point has + # in an attempt to reduce the combinatorics of checking conjugations + for r in sorted(repeated_mult_L.keys()): + for point_lst in repeated_mult_L[r]: + all_points += point_lst + # this loop is quite long, so we break after finding the first subset + # with the desired property. There is, however, no guarentee that the + # subset we found minimizes the combinatorics when checking conjugations + for subset in Subsets(range(len(all_points)), n+2): + source = [] + for i in subset: + source.append(all_points[i]) + if P.is_linearly_independent(source, n+1): + more = False + corresponding = [] + mult_only = [] + for i in subset: + mult = point_to_mult_L[all_points[i]] + if mult in mult_only: + corresponding[mult_only.index(mult)][1] += 1 + else: + corresponding.append([mult, 1]) + mult_only.append(mult) + break + # if we iterated over all subsets of size n+2, and did not find one + # in which all subsets of size n+1 are linearly independent, + # then we fail as we cannot specify conjugations + if more: + raise ValueError('no more rational preimages. try extending the base field and trying again.') + + # if we need to add more preimages, we update loop dictionaries + if more: + loop_repeated_mult = deepcopy(next_repeated_mult) + next_repeated_mult = {} + found_no_more = True + + # we build a list of iterators in order to loop over the product of those iterators + possible_targets = [] + for tup in corresponding: + possible_targets.append([mult_to_point_K[tup[0]], tup[1]]) + return source, possible_targets + +def greedy_independence_check(P, repeated_mult, point_to_mult): + r""" + Return an invariant pair together with information + to reduce the combinatorics of checking all possible conjugations. + + Let `f` and `g` be dynamical systems on `\mathbb{P}^n`. + An invariant pair is a pair of two sets `U`, `V` such that + `|U| = |V|` and for all `\phi \in PGL` such that `f^\phi = g`, + `\phi(u) \in V` for all `u \in U`. Invariant pairs can be used + to determine all conjugations from `f` to `g`. For details + in the `\mathbb{P}^1` case, see [FMV2014]_. + + This function may sometimes fail to find the invariant pair + set even though one exists. It is useful, however, as it is fast + and returns a set which usually minimizes the combinatorics of + checking all conjugations. + + INPUT: + + - ``P`` -- a projective space + + - ``repeated_mult`` -- a dictionary of integers to lists of points of + the projective space ``P``. The list of points should be conjugation + invariant. The keys are considered as weights, and this function attempts + to minimize the total weight + + - ``point_to_mult`` -- a dictionary of points of ``P`` to tuples of the form + (multiplier, level), where multiplier is the characteristic polynomial + of the multiplier of the point, and level is the number of preimages + taken to find the point + + OUTPUT: + + If no set of `n+2` points of which all subsets of size `n+1` are linearly + independent can be found, then ``None`` is returned. + + Otherwise, a tuple of the form (``source``, ``corresponding``) is returned. + + - ``source`` -- the set `U` of the conjugation invariant pair. A set of `n+2` points + of the domain of `f`, of which no `n+1` are linearly dependent. + + - ``corresponding`` -- a list of tuples of the form ((multiplier, level), repeat) where the + (multiplier, level) pair is the multiplier of a point in ``source`` and repeat + specifies how many points in source have that (multiplier, level) pair. This + information specifies the set `V` of the invariant pair. + + EXAMPLES:: + + sage: from sage.dynamics.arithmetic_dynamics.endPN_automorphism_group import greedy_independence_check + sage: P. = ProjectiveSpace(QQ, 1) + sage: repeated_mult = {2: [[P((0, 1)), P((1, 0))]], 1: [[P((1, 1))]]} + sage: point_to_mult = {P((0, 1)): (x, 0), P((1, 0)): (x, 0), P((1, 1)): (x - 2, 0)} + sage: greedy_independence_check(P, repeated_mult, point_to_mult) + ([(1 : 1), (0 : 1), (1 : 0)], [[(x - 2, 0), 1], [(x, 0), 2]]) + """ + n = P.dimension_relative() + source = [] + corresponding = [] + for r in sorted(repeated_mult.keys()): + for point_lst in repeated_mult[r]: + for point in point_lst: + if len(source) == n+1: + independent = P.is_linearly_independent(source + [point], n+1) + else: + independent = P.is_linearly_independent(source + [point]) + if independent: + source.append(point) + mult = point_to_mult[point] + # if another point with this multiplier and level pair is in S + # then the multiplier level pair will be the last element of corresponding + if len(corresponding) != 0: + if corresponding[-1][0] == mult: + corresponding[-1][1] += 1 + else: + corresponding.append([mult, 1]) + else: + corresponding.append([mult, 1]) + if len(source) == n+2: + return source, corresponding + +def conjugating_set_helper(f, g, num_cpus, source, possible_targets): + r""" + Return the set of elements in PGL over the base ring + that conjugates ``f`` to ``g``. + + This function takes as input the invariant pair + and multiplier data from ``conjugating_set_initializer``. + + Do not call this function directly, instead use ``f.conjugate_set(g)``. + + INPUT: + + - ``f`` -- a rational function of degree at least 2, and the same + degree as ``g`` + + - ``g`` -- a rational function of the same degree as ``f`` + + - ``num_cpus`` -- the number of threads to run in parallel + + - ``source`` -- a list of `n+2` conjugation invariant points, of which + no `n+1` are linearly dependent. + + - ``possible_targets`` -- a list of tuples of the form (``points``, ``repeated``). ``points`` + is a list of ``points`` which are possible targets for point(s) in ``source``. ``repeated`` + specifies how many points in ``source`` have points in ``points`` as their possible target. + + OUTPUT: a list of elements of PGL which conjugate ``f`` to ``g``. + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem([x^2, y^2]) + sage: source = [P((1, 1)), P((0, 1)), P((1, 0))] + sage: possible_targets = [[[P((1, 1))], 1], [[P((0, 1)), P((1, 0))], 2]] + sage: from sage.dynamics.arithmetic_dynamics.endPN_automorphism_group import conjugating_set_helper + sage: sorted(conjugating_set_helper(f, f, 2, source, possible_targets)) + [ + [0 1] [1 0] + [1 0], [0 1] + ] + """ + Conj = [] + P = f.domain().ambient_space() + n = f.domain().dimension_relative() + + subset_iterators = [] + + for lst in possible_targets: + subset_iterators.append(Subsets(range(len(lst[0])), lst[1])) + + # helper function for parallelization + # given a list of tuples which specify indicies of possible target points + # in possible_targets, check all arragements of those possible target points + # and if any of them define a conjugation which sends f to g, return + # those conjugations as a list + def find_conjugations_subset(tuples): + conj = [] + for tup in tuples: + target_set = [] + for i in range(len(tup)): + for j in tup[i]: + target_set.append(possible_targets[i][0][j]) + + # if there is a subset of n+1 points which is linearly dependent, + # we don't need to check any of these arrangements + if P.is_linearly_independent(target_set, n+1): + subset_arrangements = [] + for subset in tup: + subset_arrangements.append(Arrangements(subset, len(subset))) + for tup in product(*subset_arrangements): + current_target = [] + for i in range(len(tup)): + for j in tup[i]: + current_target.append(possible_targets[i][0][j]) + phi = P.point_transformation_matrix(current_target, source) + if f.conjugate(phi) == g: + conj.append(phi) + return conj + + # helper function for parallelization + # given a list of tuples which specify indicies of possible target points + # in possible_targets, check all possible target points + # and if any of them define a conjugation which sends f to g, return + # those conjugations as a list + def find_conjugations_arrangement(tuples): + conj = [] + for tup in tuples: + current_target = [] + for i in range(len(tup)): + for j in tup[i]: + current_target.append(possible_targets[i][0][j]) + phi = P.point_transformation_matrix(current_target, source) + if f.conjugate(phi) == g: + conj.append(phi) + return conj + + if num_cpus > 1: + all_subsets = list(product(*subset_iterators)) + parallel_data = [] + + # if there are enough subsets, we can divide up the work based on subsets + # and check linear independence in parallel + if len(all_subsets) > num_cpus: + for i in range(num_cpus): + start = floor(len(all_subsets)*i/num_cpus) + end = floor(len(all_subsets)*(i+1)/num_cpus) + tuples = all_subsets[start:end] + parallel_data.append(([tuples], {})) + + X = p_iter_fork(num_cpus) + for ret in X(find_conjugations_subset, parallel_data): + if ret[1]: + Conj += ret[1] + # otherwise, we need to first check linear independence of the subsets + # and then build a big list of all the arrangemenets to split among + # the threads + else: + good_targets = [] + for tup in product(*subset_iterators): + target_set = [] + for i in range(len(tup)): + for j in tup[i]: + target_set.append(possible_targets[i][0][j]) + if P.is_linearly_independent(target_set, n+1): + good_targets.append(tup) + all_arrangements = [] + for tup in good_targets: + subset_arrangements = [] + for subset in tup: + subset_arrangements.append(Arrangements(subset, len(subset))) + all_arrangements += list(product(*subset_arrangements)) + parallel_data = [] + for i in range(num_cpus): + start = floor(len(all_arrangements)*i/num_cpus) + end = floor(len(all_arrangements)*(i+1)/num_cpus) + tuples = all_arrangements[start:end] + parallel_data.append(([tuples], {})) + X = p_iter_fork(num_cpus) + for ret in X(find_conjugations_arrangement, parallel_data): + if ret[1]: + Conj += ret[1] + else: + Conj = find_conjugations_subset(product(*subset_iterators)) + return Conj + +def is_conjugate_helper(f, g, num_cpus, source, possible_targets): + r""" + Return if ``f`` is conjugate to ``g``. + + This function takes as input the invariant pair + and multiplier data from ``conjugating_set_initializer``. + + Do not call this function directly, instead use ``f.is_conjugate(g)``. + + INPUT: + + - ``f`` -- a rational function of degree at least 2, and the same + degree as ``g`` + + - ``g`` -- a rational function of the same degree as ``f`` + + - ``num_cpus`` -- the number of threads to run in parallel + + - ``source`` -- a list of `n+2` conjugation invariant points, of which + no `n+1` are linearly dependent. + + - ``possible_targets`` -- a list of tuples of the form (``points``, ``repeated``). ``points`` + is a list of ``points`` which are possible targets for point(s) in ``source``. ``repeated`` + specifies how many points in ``source`` have points in ``points`` as their possible target. + + OUTPUT: ``True`` if ``f`` is conjugate to ``g``, ``False`` otherwise. + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem([x^2, y^2]) + sage: source = [P((1, 1)), P((0, 1)), P((1, 0))] + sage: possible_targets = [[[P((1, 1))], 1], [[P((0, 1)), P((1, 0))], 2]] + sage: from sage.dynamics.arithmetic_dynamics.endPN_automorphism_group import is_conjugate_helper + sage: is_conjugate_helper(f, f, 2, source, possible_targets) + True + """ + is_conj = False + P = f.domain().ambient_space() + n = f.domain().dimension_relative() + + subset_iterators = [] + + for lst in possible_targets: + subset_iterators.append(Subsets(range(len(lst[0])), lst[1])) + + # helper function for parallelization + # given a list of tuples which specify indicies of possible target points + # in possible_targets, check all arragements of those possible target points + # and if any of them define a conjugation which sends f to g, return True + def find_conjugations_subset(tuples): + for tup in tuples: + target_set = [] + for i in range(len(tup)): + for j in tup[i]: + target_set.append(possible_targets[i][0][j]) + + # if there is a subset of n+1 points which is linearly dependent, + # we don't need to check any of these arrangements + if P.is_linearly_independent(target_set, n+1): + subset_arrangements = [] + for subset in tup: + subset_arrangements.append(Arrangements(subset, len(subset))) + for tup in product(*subset_arrangements): + current_target = [] + for i in range(len(tup)): + for j in tup[i]: + current_target.append(possible_targets[i][0][j]) + phi = P.point_transformation_matrix(current_target, source) + if f.conjugate(phi) == g: + return True + return False + + # helper function for parallelization + # given a list of tuples which specify indicies of possible target points + # in possible_targets, check all possible target points + # and if any of them define a conjugation which sends f to g, return True + def find_conjugations_arrangement(tuples): + for tup in tuples: + current_target = [] + for i in range(len(tup)): + for j in tup[i]: + current_target.append(possible_targets[i][0][j]) + phi = P.point_transformation_matrix(current_target, source) + if f.conjugate(phi) == g: + return True + return False + + if num_cpus > 1: + all_subsets = list(product(*subset_iterators)) + parallel_data = [] + + # if there are enough subsets, we can divide up the work based on subsets + # and check linear independence in parallel + if len(all_subsets) > num_cpus: + for i in range(num_cpus): + start = floor(len(all_subsets)*i/num_cpus) + end = floor(len(all_subsets)*(i+1)/num_cpus) + tuples = all_subsets[start:end] + parallel_data.append(([tuples], {})) + + X = p_iter_fork(num_cpus) + for ret in X(find_conjugations_subset, parallel_data): + if ret[1]: + is_conj = True + break + # otherwise, we need to first check linear independence of the subsets + # and then build a big list of all the arrangemenets to split among + # the threads + else: + good_targets = [] + for tup in product(*subset_iterators): + target_set = [] + for i in range(len(tup)): + for j in tup[i]: + target_set.append(possible_targets[i][0][j]) + if P.is_linearly_independent(target_set, n+1): + good_targets.append(tup) + all_arrangements = [] + for tup in good_targets: + subset_arrangements = [] + for subset in tup: + subset_arrangements.append(Arrangements(subset, len(subset))) + all_arrangements += list(product(*subset_arrangements)) + parallel_data = [] + for i in range(num_cpus): + start = floor(len(all_arrangements)*i/num_cpus) + end = floor(len(all_arrangements)*(i+1)/num_cpus) + tuples = all_arrangements[start:end] + parallel_data.append(([tuples], {})) + X = p_iter_fork(num_cpus) + for ret in X(find_conjugations_arrangement, parallel_data): + if ret[1]: + is_conj = True + break + else: + is_conj = find_conjugations_subset(product(*subset_iterators)) + return is_conj diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py index 164c4c35f47..27f9c39b583 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds.py @@ -53,6 +53,7 @@ class initialization directly. # **************************************************************************** from sage.arith.misc import is_prime +from sage.calculus.functions import jacobian from sage.categories.fields import Fields from sage.categories.function_fields import FunctionFields from sage.categories.number_fields import NumberFields @@ -80,7 +81,6 @@ class initialization directly. from sage.rings.polynomial.flatten import FlatteningMorphism, UnflatteningMorphism from sage.rings.morphism import RingHomomorphism_im_gens from sage.rings.number_field.number_field_ideal import NumberFieldFractionalIdeal -from sage.rings.number_field.number_field import is_NumberField from sage.rings.padics.all import Qp from sage.rings.polynomial.multi_polynomial_ring_base import is_MPolynomialRing from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing @@ -88,8 +88,8 @@ class initialization directly. from sage.rings.qqbar import QQbar, number_field_elements_from_algebraics from sage.rings.quotient_ring import QuotientRing_generic from sage.rings.rational_field import QQ -from sage.rings.real_double import RDF -from sage.rings.real_mpfr import (RealField, is_RealField) +import sage.rings.abc +from sage.rings.real_mpfr import RealField from sage.schemes.generic.morphism import SchemeMorphism_polynomial from sage.schemes.projective.projective_subscheme import AlgebraicScheme_subscheme_projective from sage.schemes.projective.projective_morphism import ( @@ -105,11 +105,15 @@ class initialization directly. from sage.parallel.ncpus import ncpus from sage.parallel.use_fork import p_iter_fork from sage.dynamics.arithmetic_dynamics.projective_ds_helper import (_fast_possible_periods,_all_periodic_points) -from sage.sets.set import Set -from sage.combinat.permutation import Arrangements -from sage.combinat.subset import Subsets from sage.symbolic.ring import SR from itertools import count, product +from .endPN_automorphism_group import ( + automorphism_group_QQ_CRT, + automorphism_group_QQ_fixedpoints, + conjugating_set_helper, + conjugating_set_initializer, + is_conjugate_helper) +from .endPN_automorphism_group import automorphism_group_FF class DynamicalSystem_projective(SchemeMorphism_polynomial_projective_space, @@ -2062,10 +2066,10 @@ def canonical_height(self, P, **kwds): # Archimedean local heights # :: WARNING: If places is fed the default Sage precision of 53 bits, - # it uses Real or Complex Double Field in place of RealField(prec) or ComplexField(prec) - # the function is_RealField does not identify RDF as real, so we test for that ourselves. + # it uses Real or Complex Double Field in place of RealField(prec) or ComplexField(prec). + # RDF is an instance of a separate class. for v in emb: - if is_RealField(v.codomain()) or v.codomain() is RDF: + if isinstance(v.codomain(), (sage.rings.abc.RealField, sage.rings.abc.RealDoubleField)): dv = R.one() else: dv = R(2) @@ -3242,7 +3246,13 @@ def automorphism_group(self, **kwds): INPUT: - keywords: + The following keywords are used in most cases: + + - ``num_cpus`` -- (default: 2) the number of threads to use. Setting to a + larger number can greatly speed up this function. + + The following keywords are used only when the dimension of the domain is 1 and + the base ring is the rationals, but ignored in all other cases: - ``starting_prime`` -- (default: 5) the first prime to use for CRT @@ -3273,14 +3283,14 @@ def automorphism_group(self, **kwds): EXAMPLES:: - sage: R. = ProjectiveSpace(QQ,1) + sage: R. = ProjectiveSpace(QQ, 1) sage: f = DynamicalSystem_projective([x^2-y^2, x*y]) sage: f.automorphism_group(return_functions=True) [x, -x] :: - sage: R. = ProjectiveSpace(QQ,1) + sage: R. = ProjectiveSpace(QQ, 1) sage: f = DynamicalSystem_projective([x^2 + 5*x*y + 5*y^2, 5*x^2 + 5*x*y + y^2]) sage: f.automorphism_group() [ @@ -3290,14 +3300,21 @@ def automorphism_group(self, **kwds): :: - sage: R. = ProjectiveSpace(QQ,1) + sage: P. = ProjectiveSpace(QQ, 2) + sage: f = DynamicalSystem([x^3, y^3, z^3]) + sage: len(f.automorphism_group()) + 24 + + :: + + sage: R. = ProjectiveSpace(QQ, 1) sage: f = DynamicalSystem_projective([x^2-2*x*y-2*y^2, -2*x^2-2*x*y+y^2]) sage: f.automorphism_group(return_functions=True) [x, 1/x, -x - 1, -x/(x + 1), (-x - 1)/x, -1/(x + 1)] :: - sage: R. = ProjectiveSpace(QQ,1) + sage: R. = ProjectiveSpace(QQ, 1) sage: f = DynamicalSystem_projective([3*x^2*y - y^3, x^3 - 3*x*y^2]) sage: lst, label = f.automorphism_group(algorithm='CRT', return_functions=True, iso_type=True) sage: sorted(lst), label @@ -3306,7 +3323,7 @@ def automorphism_group(self, **kwds): :: - sage: A. = AffineSpace(QQ,1) + sage: A. = AffineSpace(QQ, 1) sage: f = DynamicalSystem_affine([1/z^3]) sage: F = f.homogenize(1) sage: F.automorphism_group() @@ -3317,9 +3334,9 @@ def automorphism_group(self, **kwds): :: - sage: P. = ProjectiveSpace(QQ,2) + sage: P. = ProjectiveSpace(QQ, 2) sage: f = DynamicalSystem_projective([x**2 + x*z, y**2, z**2]) - sage: f.automorphism_group() # long time + sage: f.automorphism_group() [ [1 0 0] [0 1 0] @@ -3341,10 +3358,11 @@ def automorphism_group(self, **kwds): p = kwds.get('starting_prime', 5) return_functions = kwds.get('return_functions', False) iso_type = kwds.get('iso_type', False) + num_cpus = kwds.get('num_cpus', 2) if self.domain().dimension_relative() != 1: - return self.conjugating_set(self) - if self.base_ring() != QQ and self.base_ring != ZZ: - return self.conjugating_set(self) + return self.conjugating_set(self, num_cpus) + if self.base_ring() != QQ and self.base_ring() != ZZ: + return self.conjugating_set(self, num_cpus) self.normalize_coordinates() if (self.degree() == 1) or (self.degree() == 0): raise NotImplementedError("Rational function of degree 1 not implemented.") @@ -3354,7 +3372,6 @@ def automorphism_group(self, **kwds): F = (f[0].numerator().univariate_polynomial(R))/f[0].denominator().univariate_polynomial(R) else: F = f[0].univariate_polynomial(R) - from .endPN_automorphism_group import automorphism_group_QQ_CRT, automorphism_group_QQ_fixedpoints if alg is None: if self.degree() <= 12: return automorphism_group_QQ_fixedpoints(F, return_functions, iso_type) @@ -4263,6 +4280,7 @@ def preperiodic_points(self, m, n, **kwds): Z(list(Q)) except TypeError: good_points.append(Q) + good_points.sort() return good_points else: raise NotImplementedError("ring must a number field or finite field") @@ -4607,6 +4625,7 @@ def periodic_points(self, n, minimal=True, formal=False, R=None, algorithm='vari Z(list(Q)) except TypeError: good_points.append(Q) + good_points.sort() return good_points else: raise NotImplementedError("ring must be a number field or finite field") @@ -4825,39 +4844,82 @@ def multiplier_spectra(self, n, formal=False, type='point', use_algebraic_closur return multipliers - def sigma_invariants(self, n, formal=False, embedding=None, type='point'): + def sigma_invariants(self, n, formal=False, embedding=None, type='point', + return_polynomial=False, chow=False, deform=False, check=True): r""" - Computes the values of the elementary symmetric polynomials of - the ``n`` multiplier spectra of this dynamical system. + Computes the values of the elementary symmetric polynomials evaluated + on the ``n`` multiplier spectra of this dynamical system. + + The sigma invariants are the symetric polynomials evaluated on the + characteristic polynomial of the multipliers. See [Hutz2019]_ for + the full definition. Spepcifically, this function returns either + the following polynomial or its coefficients (with signs + appropriately adjusted): + + .. MATH:: - Can specify to instead compute the values corresponding to the - elementary symmetric polynomials of the formal ``n`` multiplier - spectra. The map must be defined over projective space of dimension - `1`. The base ring should be a number field, number field order, or + \prod_{P \text{ period n}} ( w - c(P,t)), + + where `c(P,t)` is the charateristic polynomial (variable `t`) of the + multiplier at `P`. Note that in dimension 1, only the coefficients + of the constant term is returned. + + The invariants can be computed for points of period ``n`` or + points of formal period ``n``. The base + ring should be a number field, number field order, or a finite field or a polynomial ring or function field over a number field, number field order, or finite field. The parameter ``type`` determines if the sigma are computed from the multipliers calculated at one per cycle (with multiplicity) - or one per point (with multiplicity). Note that in the ``cycle`` - case, a map with a cycle which collapses into multiple smaller - cycles, this is still considered one cycle. In other words, if a - 4-cycle collapses into a 2-cycle with multiplicity 2, there is only - one multiplier used for the doubled 2-cycle when computing ``n=4``. + or one per point (with multiplicity). Only implemented + for dimension 1. Note that in the ``cycle`` case, a map with a cycle + which collapses into multiple smaller cycles, this is still + considered one cycle. In other words, if a 4-cycle collapses into + a 2-cycle with multiplicity 2, there is only one multiplier used + for the doubled 2-cycle when computing ``n=4``. ALGORITHM: - We use the Poisson product of the resultant of two polynomials: + In dimension 1, we use the Poisson product of the resultant of + two polynomials: .. MATH:: res(f,g) = \prod_{f(a)=0} g(a). - Letting `f` be the polynomial defining the periodic or formal - periodic points and `g` the polynomial `w - f'` for an auxilarly - variable `w`. Note that if `f` is a rational function, we clear + In higher dimensions, we use elimination theory (Groebner bases) + to compute the equivalent of the Poisson product. Letting `f` be + the polynomial defining the periodic or formal + periodic points and `g` the polynomial `w - F` for an auxilarly + variable `w` and `F` the characteristic polynomial of the Jacobian matrix + of `f`. Note that if `f` is a rational function, we clear denominators for `g`. + To calculate the full polynomial defining the sigma invariants, + we follow the algorithm outlined in section 4 of [Hutz2019]_. There + are 4 cases: + + - multipliers and ``n`` periodic points all distinct -- in this case, + we can use Proposition 4.1 of [Hutz2019]_ to compute the sigma invariants. + + - ``n`` periodic points are all distinct, multipliers are repeated -- here we + can use Proposition 4.2 of [Hutz2019]_ to compute the sigma invariants. + This corresponds to ``chow=True``. + + - ``n`` periodic points are repeated, multipliers are all distinct -- to deal + with this case, we deform the map by a formal parameter `k`. The deformation + seperates the ``n`` periodic points, making them distinct, and we can recover + the ``n`` periodic points of the original map by specializing `k` to 0. + This corresponds to ``deform=True``. + + - ``n`` periodic points are repeated, multipliers are repeated -- here we + can use both cases 2 and 3 together. This corresponds to ``deform=True`` + and ``chow=True``. + + As we do not want to check which case we are in beforehand, we throw a + ValueError if the computed polynomial does not have the correct degree. + INPUT: - ``n`` -- a positive integer, the period @@ -4873,20 +4935,105 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point'): - ``type`` -- (default: ``'point'``) string; either ``'point'`` or ``'cycle'`` depending on whether you compute with one - multiplier per point or one per cycle + multiplier per point or one per cycle. Not implemented for + dimension greater than 1. + + - ``return polynomial`` -- (default: ``False``) boolean; + ``True`` specifies returning the polynomial which generates + the sigma invariants, see [Hutz2019]_ for the full definition. + The polynomial is always a multivariate polynomial with variables + ``w`` and ``t``. + + - ``chow`` -- (default: ``False``) boolean; ``True`` specifies + using the Chow algorithm from [Hutz2019]_ to compute the sigma + invariants. While slower, the Chow algorithm does not lose + information about multiplicities of the multipliers. In order + to accurately compute the sigma polynomial when there is a + repeated multiplier, ``chow`` must be ``True``. + + - ``deform`` -- (default: ``False``) boolean; ``True`` specifies + first deforming the map so that all periodic points are distinct + and then calculating the sigma invariants. In order to accurately + calculate the sigma polynomial when there is a periodic point with + multiplicity, ``deform`` must be ``True``. + + - ``check`` -- (default: ``True``) boolean; when ``True`` the degree of + the sigma polynomial is checked against the expected degree. This is + done as the sigma polynomial may drop degree if multiplicites of periodic + points or multipliers are not correctly accounted for using ``chow`` or + ``deform``. + + .. WARNING:: - OUTPUT: a list of elements in the base ring + Setting ``check`` to ``False`` can lead to mathematically incorrect + answers. + + OUTPUT: a list of elements in the base ring, unless ``return_polynomial`` + is ``True``, in which case a polynomial in ``w`` and ``t`` is returned. + The variable ``t`` is the variable of the characteristic + polynomials of the multipliers. + + If this map is defined over `\mathbb{P}^N`, where `N > 1`, then + the list is the coefficients of `w` and `t`, in lexographical order with `w > t`. EXAMPLES:: - sage: P. = ProjectiveSpace(QQ,1) - sage: f = DynamicalSystem_projective([512*x^5 - 378128*x^4*y + 76594292*x^3*y^2 - 4570550136*x^2*y^3 - 2630045017*x*y^4\ - + 28193217129*y^5, 512*y^5]) + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem_projective([x^2 + x*y + y^2, y^2 + x*y]) sage: f.sigma_invariants(1) - [19575526074450617/1048576, -9078122048145044298567432325/2147483648, - -2622661114909099878224381377917540931367/1099511627776, - -2622661107937102104196133701280271632423/549755813888, - 338523204830161116503153209450763500631714178825448006778305/72057594037927936, 0] + [3, 3, 1] + + If ``return_polynomial`` is ``True``, then following [Hutz2019]_ + we return a two variable polynomial in `w` and `t`:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem_projective([x^2 + 2*y^2, y^2]) + sage: poly = f.sigma_invariants(1, return_polynomial=True); poly + w^3 - 3*w^2*t + 2*w^2 + 3*w*t^2 - 4*w*t + 8*w - t^3 + 2*t^2 - 8*t + + From the full polynomial, we can easily recover the one variable polynomial whose coefficients + are symmetric functions in the multipliers, up to sign:: + + sage: w, t = poly.variables() + sage: poly.specialization({w:0}).monic() + t^3 - 2*t^2 + 8*t + sage: f.sigma_invariants(1) + [2, 8, 0] + + For dynamical systems on `\mathbb{P}^N`, where `N > 1`, the full polynomial + is needed to distinguish the conjugacy class. We can, however, still return + a list in this case:: + + sage: P. = ProjectiveSpace(QQ, 2) + sage: f = DynamicalSystem_projective([x^2, z^2, y^2]) + sage: f.sigma_invariants(1, chow=True) + [1, 7, -6, -12, 21, -36, -60, 72, 48, 35, -90, -120, 352, 96, -288, -64, 35, -120, -120, 688, -96, + -1056, 320, 384, 0, 21, -90, -60, 672, -384, -1440, 1344, 768, -768, 0, 0, 7, -36, -12, 328, -336, + -864, 1472, 384, -1536, 512, 0, 0, 0, 1, -6, 0, 64, -96, -192, 512, 0, -768, 512, 0, 0, 0, 0, 0] + + When calculating the sigma invariants for `\mathbb{P}^N`, with `N > 1`, + the default algorithm loses information about multiplicities. Note that + the following call to sigma invariants returns a degree 6 polynomial in `w`:: + + sage: P. = ProjectiveSpace(QQ, 2) + sage: f = DynamicalSystem_projective([x^2, y^2, z^2]) + sage: f.sigma_invariants(1, return_polynomial=True, check=False) + w^6 - 6*w^5*t^2 + 8*w^5*t - 4*w^5 + 15*w^4*t^4 - 40*w^4*t^3 + 40*w^4*t^2 - + 16*w^4*t - 20*w^3*t^6 + 80*w^3*t^5 - 120*w^3*t^4 + 80*w^3*t^3 - 16*w^3*t^2 + + 15*w^2*t^8 - 80*w^2*t^7 + 160*w^2*t^6 - 144*w^2*t^5 + 48*w^2*t^4 - 6*w*t^10 + + 40*w*t^9 - 100*w*t^8 + 112*w*t^7 - 48*w*t^6 + t^12 - 8*t^11 + 24*t^10 - + 32*t^9 + 16*t^8 + + Setting ``chow`` to ``True``, while much slower, accounts correctly for multiplicities. + Note that the following returns a degree 7 polynomial in `w`:: + + sage: f.sigma_invariants(1, return_polynomial=True, chow=True) + w^7 - 7*w^6*t^2 + 10*w^6*t - 4*w^6 + 21*w^5*t^4 - 60*w^5*t^3 + 60*w^5*t^2 - + 24*w^5*t - 35*w^4*t^6 + 150*w^4*t^5 - 240*w^4*t^4 + 176*w^4*t^3 - 48*w^4*t^2 + + 35*w^3*t^8 - 200*w^3*t^7 + 440*w^3*t^6 - 464*w^3*t^5 + 224*w^3*t^4 - + 32*w^3*t^3 - 21*w^2*t^10 + 150*w^2*t^9 - 420*w^2*t^8 + 576*w^2*t^7 - + 384*w^2*t^6 + 96*w^2*t^5 + 7*w*t^12 - 60*w*t^11 + 204*w*t^10 - 344*w*t^9 + + 288*w*t^8 - 96*w*t^7 - t^14 + 10*t^13 - 40*t^12 + 80*t^11 - 80*t^10 + 32*t^9 :: @@ -4913,15 +5060,6 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point'): sage: f.sigma_invariants(2, type='point', formal=True) [0, 0] - :: - - sage: P. = ProjectiveSpace(QQ, 2) - sage: f = DynamicalSystem_projective([x^2, y^2, z^2]) - sage: f.sigma_invariants(1) - Traceback (most recent call last): - ... - NotImplementedError: only implemented for dimension 1 - :: sage: K. = QuadraticField(3) @@ -4934,10 +5072,23 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point'): :: - sage: P. = ProjectiveSpace(QQ,1) - sage: f = DynamicalSystem_projective([x^2 + x*y + y^2, y^2 + x*y]) + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem_projective([512*x^5 - 378128*x^4*y + 76594292*x^3*y^2 - 4570550136*x^2*y^3 - 2630045017*x*y^4\ + + 28193217129*y^5, 512*y^5]) sage: f.sigma_invariants(1) - [3, 3, 1] + [19575526074450617/1048576, -9078122048145044298567432325/2147483648, + -2622661114909099878224381377917540931367/1099511627776, + -2622661107937102104196133701280271632423/549755813888, + 338523204830161116503153209450763500631714178825448006778305/72057594037927936, 0] + + :: + + sage: P. = ProjectiveSpace(GF(5), 2) + sage: f = DynamicalSystem([x^2, y^2, z^2]) + sage: f.sigma_invariants(1, chow=True, return_polynomial=True) + w^7 - 2*w^6*t^2 + w^6 + w^5*t^4 + w^5*t + w^4*t^3 + 2*w^4*t^2 + w^3*t^5 - + w^3*t^4 - 2*w^3*t^3 - w^2*t^10 + w^2*t^7 + w^2*t^6 + w^2*t^5 + 2*w*t^12 - + w*t^10 + w*t^9 - 2*w*t^8 - w*t^7 - t^14 + 2*t^9 :: @@ -4951,6 +5102,31 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point'): sage: f.sigma_invariants(2, formal=True, type='cycle') [4*c + 4] + :: + + sage: R. = QQ[] + sage: P. = ProjectiveSpace(R, 1) + sage: f = DynamicalSystem([x^2 + c*y^2, y^2]) + sage: f.sigma_invariants(1, return_polynomial=True) + w^3 + (-3)*w^2*t + 2*w^2 + 3*w*t^2 + (-4)*w*t + 4*c*w - t^3 + 2*t^2 + (-4*c)*t + sage: f.sigma_invariants(2, chow=True, formal=True, return_polynomial=True) + w^2 + (-2)*w*t + (8*c + 8)*w + t^2 + (-8*c - 8)*t + 16*c^2 + 32*c + 16 + + :: + + sage: R. = QQ[] + sage: P. = ProjectiveSpace(R, 2) + sage: f = DynamicalSystem([x^2 + c*z^2, y^2 + d*z^2, z^2]) + sage: len(dict(f.sigma_invariants(1, return_polynomial=True))) + 51 + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem([x^2 + 3*y^2, x*y]) + sage: f.sigma_invariants(1, deform = True, return_polynomial=True) + w^3 - 3*w^2*t + 3*w^2 + 3*w*t^2 - 6*w*t + 3*w - t^3 + 3*t^2 - 3*t + 1 + doubled fixed point:: sage: P. = ProjectiveSpace(QQ, 1) @@ -4972,6 +5148,35 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point'): sage: f = DynamicalSystem_projective([x^2 + (t/(t^2+1))*y^2, y^2], P) sage: f.sigma_invariants(1) [2, 4*t/(t^2 + 1), 0] + + :: + + sage: R. = QQ[] + sage: N. = NumberField(w^2 + 1) + sage: P. = ProjectiveSpace(N, 2) + sage: f = DynamicalSystem_projective([x^2, y^2, z^2]) + sage: f.sigma_invariants(1, chow=True) == f.change_ring(QQ).sigma_invariants(1, chow=True) + True + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem([x^2 + 3*y^2, x*y]) + sage: f.sigma_invariants(1, formal=True, return_polynomial=True) + Traceback (most recent call last): + .. + ValueError: sigma polynomial dropped degree, as multiplicities were not accounted + for correctly. try setting chow=True and/or deform=True + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem([x^2 + 3*y^2, x*y]) + sage: f.sigma_invariants(1, return_polynomial=True) + Traceback (most recent call last): + .. + ValueError: sigma polynomial dropped degree, as multiplicities were not accounted + for correctly. try setting chow=True and/or deform=True """ n = ZZ(n) if n < 1: @@ -4979,8 +5184,6 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point'): dom = self.domain() if not is_ProjectiveSpace(dom): raise NotImplementedError("not implemented for subschemes") - if dom.dimension_relative() > 1: - raise NotImplementedError("only implemented for dimension 1") if not embedding is None: from sage.misc.superseded import deprecation deprecation(23333, "embedding keyword no longer used") @@ -4988,6 +5191,140 @@ def sigma_invariants(self, n, formal=False, embedding=None, type='point'): raise TypeError("must have degree at least 2") if not type in ['point', 'cycle']: raise ValueError("type must be either point or cycle") + if dom.dimension_relative() > 1 or return_polynomial: + if type == 'cycle': + raise NotImplementedError('cycle not implemented for dimension greater than 1') + base_ring = self.base_ring() + d = self.degree() + N = dom.dimension_relative() + f = copy(self) + Fn = f.nth_iterate_map(n) + CR = f.codomain().ambient_space().coordinate_ring() + if deform: + # we need a model with all affine periodic points + new_f = f.affine_preperiodic_model(0, n) + new_f.normalize_coordinates() + # we now deform by a parameter t + T = base_ring['k'] + k = T.gens()[0] + Pt = ProjectiveSpace(N, R=T, names = [str(i) for i in CR.gens()]) + deformed_polys = [poly + k*Pt.gens()[-1]**d for poly in new_f.defining_polynomials()[:-1]] + deformed_polys += [new_f.defining_polynomials()[-1]] + f_deformed = DynamicalSystem(deformed_polys) + sigma_poly = f_deformed.sigma_invariants(n, chow=chow, deform=False, return_polynomial=True, check=False) + sigma_polynomial = sigma_poly.specialization({k:0}) + # we fix the ordering of the parent polynomial ring + new_parent = sigma_polynomial.parent().change_ring(order='lex') + sigma_polynomial = new_parent(sigma_polynomial) + sigma_polynomial *= sigma_polynomial.coefficients()[0].inverse_of_unit() + else: + if not base_ring.is_field(): + F = FractionField(base_ring) + f.normalize_coordinates() + X = f.periodic_points(n, minimal=False, formal=formal, return_scheme=True) + X = X.change_ring(F) + else: + F = base_ring + if is_FractionField(base_ring): + if is_MPolynomialRing(base_ring.ring()) or is_PolynomialRing(base_ring.ring()): + f.normalize_coordinates() + f_ring = f.change_ring(base_ring.ring()) + X = f_ring.periodic_points(n, minimal=False, formal=formal, return_scheme=True) + X = X.change_ring(F) + else: + X = f.periodic_points(n, minimal=False, formal=formal, return_scheme=True) + newR = PolynomialRing(F, 'w, t', 2, order='lex') + if not base_ring.is_field(): + ringR = PolynomialRing(base_ring, 'w, t', 2, order='lex') + if chow: + # create full polynomial ring + R = PolynomialRing(F, 'v', 2*N+3, order='lex') + var = list(R.gens()) + # create polynomial ring for result + R2 = PolynomialRing(F, var[:N] + var[-2:]) + psi = R2.hom(N*[0]+list(newR.gens()), newR) + # create substition to set extra variables to 0 + R_zero = {R.gen(N):1} + for j in range(N+1, 2*N+1): + R_zero[R.gen(j)] = 0 + t = var.pop() + w = var.pop() + var = var[:N] + else: + R = PolynomialRing(F, 'v', N+2, order='lex') + psi = R.hom(N*[0] + list(newR.gens()), newR) + var = list(R.gens()) + t = var.pop() + w = var.pop() + sigma_polynomial = 1 + # go through each affine patch to avoid repeating periodic points + # setting the visited coordiantes to 0 as we go + for j in range(N,-1,-1): + Xa = X.affine_patch(j) + fa = Fn.dehomogenize(j) + Pa = fa.domain() + Ra = Pa.coordinate_ring() + # create the images for the Hom to the ring we will do the elimination over + # with done affine patch coordinates as 0 + if chow: + im = [R.gen(i) for i in range(j)] + (N-j)*[0] + [R.gen(i) for i in range(N, R.ngens())] + else: + im = list(R.gens())[:j] + (N-j)*[0] + [R.gen(i) for i in range(N, R.ngens())] + phi = Ra.hom(R.gens()[0:len(Ra.gens())]) + # create polymomial that evaluates to the characteristic polynomial + M = t*matrix.identity(R, N) + g = (M-jacobian([phi(F.numerator())/phi(F.denominator()) for F in fa], var)).det() + # create the terms of the sigma invariants prod(w-lambda) + g_prime = w*R(g.denominator())(im)-R(g.numerator())(im) + # move the defining polynomials to the polynomial ring + L = [phi(h)(im) for h in Xa.defining_polynomials()] + # add the appropriate final polynomial to compute the sigma invariant polynomial + # via a Poisson product in elimination + if chow: + L += [g_prime + sum(R.gen(j-1)*R.gen(N+j)*(R(g.denominator())(im)) for j in range(1,N+1))] + else: + L += [g_prime] + I = R.ideal(L) + # since R is lex ordering, this is an elimination step + G = I.groebner_basis() + # the polynomial we need is the one just in w and t + if chow: + poly = psi(G[-1].specialization(R_zero)) + if len(list(poly)) > 0: + poly *= poly.coefficients()[0].inverse_of_unit() + else: + poly = psi(G[-1]) + if not base_ring.is_field(): + denom = lcm([coeff[0].denominator() for coeff in poly]) + poly *= denom + sigma_polynomial *= poly + if not base_ring.is_field(): + sigma_polynomial = ringR(sigma_polynomial) + if check: + degree_w = sigma_polynomial.degrees()[0] + if formal: + expected_degree = 0 + for D in n.divisors(): + u = moebius(n/D) + inner_sum = sum(d**(D*j) for j in range(N+1)) + expected_degree += u*inner_sum + else: + expected_degree = sum(d**(n*i) for i in range(N+1)) + if degree_w != expected_degree: + raise ValueError('sigma polynomial dropped degree, as multiplicities were not accounted for correctly.'+ + ' try setting chow=True and/or deform=True') + if return_polynomial: + return sigma_polynomial + # if we are returing a numerical list, read off the coefficients + # in order of degree adjusting sign appropriately + sigmas = [] + sigma_dictionary = dict([list(reversed(i)) for i in list(sigma_polynomial)]) + degree_w = sigma_polynomial.degrees()[0] + w, t = sigma_polynomial.variables() + for i in range(degree_w + 1): + for j in range(2*i, -1, -1): + sigmas.append((-1)**(i+j)*sigma_dictionary.pop(w**(degree_w - i)*t**(j), 0)) + return sigmas base_ring = dom.base_ring() if is_FractionField(base_ring): @@ -5501,6 +5838,88 @@ def _is_preperiodic(self, P, err=0.1, return_period=False): else: return False + def postcritical_set(self, check=True): + r""" + Return the postcritical set of this dynamical system. + + Raises an error if this dynamical system is not postcritically finite. + + The postcritical set is union of points which are in the forward orbits + of the critical points. In other words, the set of points `Q` such that + `f^n(P) = Q` for some positive integer `n` and critical point `P`, where + `f` is this map. + + Note that the orbit of all critical points is found, even if the + critical points are defined in an extension of the base ring of + this dynamical system. We extend to the field defined by + ``f.field_of_definition_critical()``, where ``f`` is this map. + + INPUT: + + - ``check`` -- (default: ``True``) boolean; whether to check + if this dynamical system is postcritically finite or not. + + OUTPUT: The set of postcritical points. + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem([x^3 - 3/2* x*y^2, y^3]) + sage: f.postcritical_set() + [(1/2*a : 1), (-1/2*a : 1), (1 : 0)] + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem([3*x^3 - 9/2* x^2*y+y^3, y^3]) + sage: f.postcritical_set(check=False) + [(1 : 1), (-1/2 : 1), (1 : 0)] + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem([-4*y^2, 9*x^2 - 12*x*y]) + sage: f.postcritical_set() + [(1 : 1), (4/3 : 1), (1 : 0), (0 : 1)] + + :: + + sage: K. = QuadraticField(2) + sage: P. = ProjectiveSpace(K,1) + sage: f = DynamicalSystem([x^2 + (-2)*y^2, y^2]) + sage: m = matrix(K, 2, 2, [v, 1, 0, 1]) + sage: g = f.conjugate(m) + sage: g.postcritical_set() + [(-3/2*a : 1), (1/2*a : 1), (1 : 0)] + + :: + + sage: F. = FiniteField(9) + sage: P. = ProjectiveSpace(F, 1) + sage: f = DynamicalSystem([x^2 + (-2)*y^2, y^2]) + sage: m = matrix(F, 2, 2, [z, 1, 0, 1]) + sage: g = f.conjugate(m) + sage: g.postcritical_set() + [(1 : 0), (0 : 1), (a + 2 : 1)] + """ + if not is_ProjectiveSpace(self.domain()): + raise ValueError('must be a dynamical system on projective space') + if self.domain().dimension_relative() != 1: + raise ValueError('must be defined on projective space of dimension 1') + if check: + if not self.is_postcritically_finite(): + raise ValueError('map must be postcritically finite') + new_base_ring = self.field_of_definition_critical(return_embedding=True)[1] + f = self.change_ring(new_base_ring) + critical_points = f.critical_points() + post_critical_list = [] + for point in critical_points: + next_point = f(point) + while not(next_point in post_critical_list): + post_critical_list.append(next_point) + next_point = f(next_point) + return post_critical_list + class DynamicalSystem_projective_field(DynamicalSystem_projective, SchemeMorphism_polynomial_projective_space_field): @@ -6541,7 +6960,7 @@ def connected_rational_component(self, P, n=0): return points[0] - def conjugating_set(self, other, R=None): + def conjugating_set(self, other, R=None, num_cpus=2): r""" Return the set of elements in PGL over the base ring that conjugates one dynamical system to the other. @@ -6553,8 +6972,10 @@ def conjugating_set(self, other, R=None): The optional argument `R` specifies the field of definition of the PGL elements. The set is determined by taking the fixed points of one map and mapping - them to all unique permutations of the fixed points of - the other map. If there are not enough fixed points the + them to permutations of the fixed points of the other map. + As conjugacy preserves the multipliers as a set, fixed points + are only maped to fixed points with the same multiplier. + If there are not enough fixed points the function compares the mapping between rational preimages of fixed points and the rational preimages of the preimages of fixed points until there are enough points; such that there @@ -6568,9 +6989,10 @@ def conjugating_set(self, other, R=None): ALGORITHM: Implementing invariant set algorithm from the paper [FMV2014]_. - Given that the set of `n` th preimages of fixed points is - invariant under conjugation find all elements of PGL that - take one set to another. + Uses the set of `n` th preimages of fixed points, as this set is + invariant under conjugation to find all elements of PGL that + take one set to another. Additionally, keeps track of multiplier + information to reduce the necessary combinatorics. INPUT: @@ -6579,6 +7001,9 @@ def conjugating_set(self, other, R=None): - ``R`` -- a field or embedding + - ``num_cpus`` -- (default: 2) the number of threads to run in parallel. + Increasing ``num_cpus`` can potentially greatly speed up this function. + OUTPUT: Set of conjugating `n+1` by `n+1` matrices. @@ -6588,11 +7013,13 @@ def conjugating_set(self, other, R=None): - Original algorithm written by Xander Faber, Michelle Manes, Bianca Viray [FMV2014]_. - - Implemented by Rebecca Lauren Miller, as part of GSOC 2016. + - Implemented by Rebecca Lauren Miller as part of GSOC 2016. + + - Algorithmic improvement by Alexander Galarraga as part of GSOC 2021. EXAMPLES:: - sage: P. = ProjectiveSpace(QQ,1) + sage: P. = ProjectiveSpace(QQ, 1) sage: f = DynamicalSystem_projective([x^2 - 2*y^2, y^2]) sage: m = matrix(QQbar, 2, 2, [-1, 3, 2, 1]) sage: g = f.conjugate(m) @@ -6602,14 +7029,21 @@ def conjugating_set(self, other, R=None): [ 2 1] ] + Increasing ``num_cpus`` can speed up computation:: + + sage: P. = ProjectiveSpace(QQ, 3) + sage: f = DynamicalSystem_projective([x^2, y^2, z^2, w^2]) + sage: len(f.conjugating_set(f, num_cpus=3)) + 24 + :: sage: K. = QuadraticField(-1) - sage: P. = ProjectiveSpace(K,1) + sage: P. = ProjectiveSpace(K, 1) sage: f = DynamicalSystem_projective([x^2 + y^2, x*y]) sage: m = matrix(K, 2, 2, [1, 1, 2, 1]) sage: g = f.conjugate(m) - sage: sorted(f.conjugating_set(g)) # long time + sage: sorted(f.conjugating_set(g)) [ [-1 -1] [1 1] [ 2 1], [2 1] @@ -6618,9 +7052,9 @@ def conjugating_set(self, other, R=None): :: sage: K. = QuadraticField(-1) - sage: P. = ProjectiveSpace(K,1) + sage: P. = ProjectiveSpace(K, 1) sage: D8 = DynamicalSystem_projective([y^3, x^3]) - sage: sorted(D8.conjugating_set(D8)) # long time + sage: sorted(D8.conjugating_set(D8)) [ [-1 0] [-i 0] [ 0 -1] [ 0 -i] [0 i] [0 1] [i 0] [1 0] [ 0 1], [ 0 1], [ 1 0], [ 1 0], [1 0], [1 0], [0 1], [0 1] @@ -6628,16 +7062,16 @@ def conjugating_set(self, other, R=None): :: - sage: P. = ProjectiveSpace(QQ,1) + sage: P. = ProjectiveSpace(QQ, 1) sage: D8 = DynamicalSystem_projective([y^2, x^2]) sage: D8.conjugating_set(D8) Traceback (most recent call last): ... - ValueError: not enough rational preimages + ValueError: no more rational preimages. try extending the base field and trying again. :: - sage: P. = ProjectiveSpace(GF(7),1) + sage: P. = ProjectiveSpace(GF(7), 1) sage: D6 = DynamicalSystem_projective([y^2, x^2]) sage: D6.conjugating_set(D6) [ @@ -6647,9 +7081,9 @@ def conjugating_set(self, other, R=None): :: - sage: P. = ProjectiveSpace(QQ,2) + sage: P. = ProjectiveSpace(QQ, 2) sage: f = DynamicalSystem_projective([x^2 + x*z, y^2, z^2]) - sage: f.conjugating_set(f) # long time + sage: f.conjugating_set(f) [ [1 0 0] [0 1 0] @@ -6677,7 +7111,7 @@ def conjugating_set(self, other, R=None): note that only one possible conjugation is returned:: - sage: P. = ProjectiveSpace(GF(11),2) + sage: P. = ProjectiveSpace(GF(11), 2) sage: f = DynamicalSystem_projective([2*x + 12*y, 11*y+2*z, x+z]) sage: m1 = matrix(GF(11), 3, 3, [1,4,1,0,2,1,1,1,1]) sage: g = f.conjugate(m1) @@ -6704,7 +7138,7 @@ def conjugating_set(self, other, R=None): Make sure the caching problem is fixed, see #28070 :: sage: K. = QuadraticField(-1) - sage: P. = ProjectiveSpace(QQ,1) + sage: P. = ProjectiveSpace(QQ, 1) sage: f = DynamicalSystem_projective([x^2 - 2*y^2, y^2]) sage: m = matrix(QQ, 2, 2, [-1, 3, 2, 1]) sage: g = f.conjugate(m) @@ -6778,65 +7212,23 @@ def conjugating_set(self, other, R=None): if f.conjugate(m_emb) == g: return [m_emb] else: #finite field case - #always comes from prime field so an coerce + #always comes from prime field so can coerce m = matrix(base, M, M, [base(u.as_finite_field_element()[1]) for t in list(m) for u in t]) return [m] #not similar return [] - # sigma invariants are invariant under conjugacy but are only implemented in dim 1 + # sigma invariants are invariant under conjugacy but are only fast in dim 1 n = f.domain().dimension_relative() if (n == 1) and (R in NumberFields() or R in FiniteFields())\ and (f.sigma_invariants(1) != g.sigma_invariants(1)): return [] - L = Set(f.periodic_points(1)) - K = Set(g.periodic_points(1)) - if len(L) != len(K): # checks maps have the same number of fixed points + tup = conjugating_set_initializer(f, g) + if tup == []: return [] - d = len(L) - r = f.domain().base_ring() - more = True - if d >= n+2: # need at least n+2 points - for i in Subsets(range(len(L)), n+2): - # make sure all n+1 subsets are linearly independent - TL = [L[il] for il in i] - Ml = matrix(r, [list(s) for s in TL]) - if not any(j == 0 for j in Ml.minors(n + 1)): - Tf = list(TL) - more = False - break - while more: - # finds preimages of fixed points - Tl = [Q for i in L for Q in f.rational_preimages(i)] - Tk = [Q for i in K for Q in g.rational_preimages(i)] - if len(Tl) != len(Tk): - return [] - L = L.union(Set(Tl)) - K = K.union(Set(Tk)) - if d == len(L): # if no new preimages then not enough points - raise ValueError("not enough rational preimages") - d = len(L) - if d >= n + 2: # makes sure all n+1 subsets are linearly independent - for i in Subsets(range(len(L)), n+2): - TL = [L[il] for il in i] - Ml = matrix(r, [list(s) for s in TL]) - if not any(j == 0 for j in Ml.minors(n + 1)): - more = False - Tf = list(TL) - break - Conj = [] - for i in Arrangements(range(len(K)),(n+2)): - TK = [K[ik] for ik in i] - # try all possible conjugations between invariant sets - try: # need all n+1 subsets linearly independent - s = f.domain().point_transformation_matrix(TK,Tf) - # finds elements of PGL that maps one map to another - if self.conjugate(s) == other: - Conj.append(s) - except (ValueError): - pass - return Conj + source, possible_targets = tup + return conjugating_set_helper(f, g, num_cpus, source, possible_targets) - def is_conjugate(self, other, R=None): + def is_conjugate(self, other, R=None, num_cpus=2): r""" Return whether two dynamical systems are conjugate over their base ring (by default) or over the ring `R` entered as an @@ -6845,8 +7237,10 @@ def is_conjugate(self, other, R=None): ALGORITHM: Implementing invariant set algorithm from the paper [FMV2014]_. - Given that the set of `n` th preimages is invariant under - conjugation this function finds whether two maps are conjugate. + Uses the set of `n` th preimages of fixed points, as this set is + invariant under conjugation to find all elements of PGL that + take one set to another. Additionally, keeps track of multiplier + information to reduce the necessary combinatorics. INPUT: @@ -6855,6 +7249,9 @@ def is_conjugate(self, other, R=None): - ``R`` -- a field or embedding + - ``num_cpus`` -- (default: 2) the number of threads to run in parallel. + Increasing ``num_cpus`` can potentially greatly speed up this function. + OUTPUT: boolean AUTHORS: @@ -6864,28 +7261,37 @@ def is_conjugate(self, other, R=None): - Implemented by Rebecca Lauren Miller as part of GSOC 2016. + - Algorithmic improvement by Alexander Galarraga as part of GSOC 2021. + EXAMPLES:: sage: K. = CyclotomicField(3) - sage: P. = ProjectiveSpace(K,1) + sage: P. = ProjectiveSpace(K, 1) sage: D8 = DynamicalSystem_projective([y^2, x^2]) sage: D8.is_conjugate(D8) True + We can speed up computation by increasing ``num_cpus``:: + + sage: P. = ProjectiveSpace(QQ,3) + sage: f = DynamicalSystem_projective([x^2, y^2, z^2, w^2]) + sage: f.is_conjugate(f, num_cpus=2) + True + :: sage: set_verbose(None) - sage: P. = ProjectiveSpace(QQbar,1) - sage: f = DynamicalSystem_projective([x^2 + x*y,y^2]) + sage: P. = ProjectiveSpace(QQbar, 1) + sage: f = DynamicalSystem_projective([x^2 + x*y, y^2]) sage: m = matrix(QQbar, 2, 2, [1, 1, 2, 1]) sage: g = f.conjugate(m) - sage: f.is_conjugate(g) # long time + sage: f.is_conjugate(g) True :: - sage: P. = ProjectiveSpace(GF(5),1) - sage: f = DynamicalSystem_projective([x^3 + x*y^2,y^3]) + sage: P. = ProjectiveSpace(GF(5), 1) + sage: f = DynamicalSystem_projective([x^3 + x*y^2, y^3]) sage: m = matrix(GF(5), 2, 2, [1, 3, 2, 9]) sage: g = f.conjugate(m) sage: f.is_conjugate(g) @@ -6893,15 +7299,15 @@ def is_conjugate(self, other, R=None): :: - sage: P. = ProjectiveSpace(QQ,1) - sage: f = DynamicalSystem_projective([x^2 + x*y,y^2]) + sage: P. = ProjectiveSpace(QQ, 1) + sage: f = DynamicalSystem_projective([x^2 + x*y, y^2]) sage: g = DynamicalSystem_projective([x^3 + x^2*y, y^3]) sage: f.is_conjugate(g) False :: - sage: P. = ProjectiveSpace(QQ,1) + sage: P. = ProjectiveSpace(QQ, 1) sage: f = DynamicalSystem_projective([x^2 + x*y, y^2]) sage: g = DynamicalSystem_projective([x^2 - 2*y^2, y^2]) sage: f.is_conjugate(g) @@ -6920,7 +7326,7 @@ def is_conjugate(self, other, R=None): sage: P. = ProjectiveSpace(QQ, 1) sage: f = DynamicalSystem_projective([-3*y^2, 3*x^2]) sage: g = DynamicalSystem_projective([-x^2 - 2*x*y, 2*x*y + y^2]) - sage: f.is_conjugate(g), f.is_conjugate(g, R=QQbar) # long time + sage: f.is_conjugate(g), f.is_conjugate(g, R=QQbar) (False, True) :: @@ -6943,11 +7349,11 @@ def is_conjugate(self, other, R=None): :: - sage: P. = ProjectiveSpace(QQ,2) + sage: P. = ProjectiveSpace(QQ, 2) sage: f = DynamicalSystem_projective([2*x^2 + 12*y*x, 11*y*x+2*y^2, x^2+z^2]) sage: m1 = matrix(QQ, 3, 3, [1,4,1,0,2,1,1,1,1]) sage: g = f.conjugate(m1) - sage: f.is_conjugate(g) # long time + sage: f.is_conjugate(g) True TESTS: @@ -7001,57 +7407,16 @@ def is_conjugate(self, other, R=None): # so we can scale to have the determinants equal m1 = (1/det_root)*m1 return m1.is_similar(m2) - # sigma invariants are invariant under conjugacy but are only implemented in dim 1 + # sigma invariants are invariant under conjugacy but are only fast in dim 1 n = f.domain().dimension_relative() if (n==1) and (R in NumberFields() or R in FiniteFields())\ and (f.sigma_invariants(1) != g.sigma_invariants(1)): return False - L = Set(f.periodic_points(1)) - K = Set(g.periodic_points(1)) - if len(L) != len(K): # checks maps have the same number of fixed points + tup = conjugating_set_initializer(f, g) + if tup == []: return False - d = len(L) - r = f.domain().base_ring() - more = True - if d >= n+2: # need at least n+2 points - for i in Subsets(range(len(L)), n+2): - # make sure all n+1 subsets are linearly independent - TL = [L[il] for il in i] - Ml = matrix(r, [list(s) for s in TL]) - if not any(j == 0 for j in Ml.minors(n + 1)): - Tf = list(TL) - more = False - break - while more: - # finds preimages of fixed points - Tl = [Q for i in L for Q in f.rational_preimages(i)] - Tk = [Q for i in K for Q in g.rational_preimages(i)] - if len(Tl) != len(Tk): - return False - L = L.union(Set(Tl)) - K = K.union(Set(Tk)) - if d == len(L):# if no new preimages then not enough points - raise ValueError("not enough rational preimages") - d = len(L) - if d >= n + 2: # makes sure all n+1 subsets are linearly independent - for i in Subsets(range(len(L)), n+2): - TL = [L[il] for il in i] - Ml = matrix(r, [list(s) for s in TL]) - if not any(j == 0 for j in Ml.minors(n + 1)): - more = False - Tf = list(TL) - break - for i in Arrangements(range(len(K)),(n+2)): - TK = [K[ik] for ik in i] - # try all possible conjugations between invariant sets - try: # need all n+1 subsets linearly independent - s = f.domain().point_transformation_matrix(TK,Tf) - # finds elements of PGL that maps one map to another - if self.conjugate(s) == other: - return True - except (ValueError): - pass - return False + source, possible_targets = tup + return is_conjugate_helper(f, g, num_cpus, source, possible_targets) def is_polynomial(self): r""" @@ -7979,17 +8344,28 @@ def possible_periods(self, return_points=False): """ return _fast_possible_periods(self, return_points) - def automorphism_group(self, absolute=False, iso_type=False, return_functions=False): + def automorphism_group(self, **kwds): r""" Return the subgroup of `PGL2` that is the automorphism group of this dynamical system. - Only for dimension 1. The automorphism group is the set of `PGL2` - elements that fixed the map under conjugation. See [FMV2014]_ - for the algorithm. + The automorphism group is the set of `PGL2` elements that fixed the map under conjugation. + + For dimension 1, see [FMV2014]_ for the algorithm. + + For dimension greater than 1, we compute the conjugating set of this + dynamical system with itself. INPUT: + The following keywords are used when the dimension of the domain + is greater than 1: + + - ``num_cpus`` -- (default: 2) the number of threads to use. Setting to a + larger number can greatly speed up this function. + + The following keywords are used when the dimension of the domain is 1: + - ``absolute``-- (default: ``False``) boolean; if ``True``, then return the absolute automorphism group and a field of definition @@ -8068,9 +8444,20 @@ def automorphism_group(self, absolute=False, iso_type=False, return_functions=Fa [1 0] [0 1] ]] + + :: + + sage: R. = ProjectiveSpace(GF(5), 2) + sage: f = DynamicalSystem_projective([x^3 + x*z^2, y^3 + y*z^2, z^3]) + sage: all([f.conjugate(m) == f for m in f.automorphism_group()]) + True """ + absolute = kwds.get('absolute', False) + iso_type = kwds.get('iso_type', False) + return_functions = kwds.get('return_functions', False) + num_cpus = kwds.get('num_cpus', 2) if self.domain().dimension_relative() != 1: - raise NotImplementedError("must be dimension 1") + return self.conjugating_set(self, num_cpus) else: f = self.dehomogenize(1) z = f[0].parent().gen() @@ -8081,7 +8468,6 @@ def automorphism_group(self, absolute=False, iso_type=False, return_functions=Fa F = f[0].numerator().polynomial(z) / f[0].denominator().polynomial(z) else: F = f[0].numerator().polynomial(z) - from .endPN_automorphism_group import automorphism_group_FF return automorphism_group_FF(F, absolute, iso_type, return_functions) def all_periodic_points(self, **kwds): diff --git a/src/sage/ext/fast_callable.pyx b/src/sage/ext/fast_callable.pyx index d16ea7b5ed0..d54d501226c 100644 --- a/src/sage/ext/fast_callable.pyx +++ b/src/sage/ext/fast_callable.pyx @@ -308,6 +308,7 @@ from sage.rings.all import RDF, CDF from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ from sage.structure.element cimport parent +from sage.structure.element cimport Expression as Expression_abc def fast_callable(x, domain=None, vars=None, @@ -428,7 +429,6 @@ def fast_callable(x, domain=None, vars=None, vars = et._etb._vars else: from sage.symbolic.callable import is_CallableSymbolicExpression - from sage.symbolic.expression import is_Expression if not vars: # fast_float passes empty list/tuple @@ -439,7 +439,7 @@ def fast_callable(x, domain=None, vars=None, vars = x.arguments() if expect_one_var and len(vars) != 1: raise ValueError(f"passed expect_one_var=True, but the callable expression takes {len(vars)} arguments") - elif is_Expression(x): + elif isinstance(x, Expression_abc): from sage.symbolic.ring import is_SymbolicVariable if vars is None: vars = x.variables() @@ -999,8 +999,7 @@ cdef class Expression: return ExpressionIPow(es._etb, s, o) else: # I really don't like this, but I can't think of a better way - from sage.symbolic.expression import is_Expression - if is_Expression(o) and o in ZZ: + if isinstance(o, Expression_abc) and o in ZZ: es = s return ExpressionIPow(es._etb, s, ZZ(o)) else: diff --git a/src/sage/ext/memory.pyx b/src/sage/ext/memory.pyx index ab29f81c0c3..1de6dedab82 100644 --- a/src/sage/ext/memory.pyx +++ b/src/sage/ext/memory.pyx @@ -6,13 +6,7 @@ TESTS: Check that a ``MemoryError`` is raised if we try to allocate a ridiculously large integer, see :trac:`15363`:: - sage: 2^(2^63-2) # optional - mpir - Traceback (most recent call last): - ... - OverflowError: exponent must be at most 2147483647 # 32-bit - MemoryError: failed to allocate 1152921504606847008 bytes # 64-bit - - sage: 2^(2^63-3) # optional - gmp + sage: 2^(2^63-3) Traceback (most recent call last): ... OverflowError: exponent must be at most 2147483647 # 32-bit diff --git a/src/sage/features/bliss.py b/src/sage/features/bliss.py index bda43f4a5f8..d870ade5973 100644 --- a/src/sage/features/bliss.py +++ b/src/sage/features/bliss.py @@ -3,6 +3,7 @@ Checks for bliss """ from . import CythonFeature, PythonModule +from .join_feature import JoinFeature TEST_CODE = """ @@ -45,10 +46,10 @@ def __init__(self): url="http://www.tcs.hut.fi/Software/bliss/") -class Bliss(PythonModule): +class Bliss(JoinFeature): r""" A :class:`Feature` which describes whether the :mod:`sage.graphs.bliss` - module has been enabled for this build of Sage and is functional. + module is available in this installation of Sage. EXAMPLES:: @@ -61,7 +62,10 @@ def __init__(self): sage: from sage.features.bliss import Bliss sage: Bliss() - Feature('sage.graphs.bliss') + Feature('bliss') """ - PythonModule.__init__(self, "sage.graphs.bliss", spkg="bliss", - url="http://www.tcs.hut.fi/Software/bliss/") + # Currently part of sagemath_standard, conditionally built. + # Will be changed to spkg='sagemath_bliss' later + JoinFeature.__init__(self, "bliss", + [PythonModule("sage.graphs.bliss", spkg="bliss", + url="http://www.tcs.hut.fi/Software/bliss/")]) diff --git a/src/sage/features/mcqd.py b/src/sage/features/mcqd.py new file mode 100644 index 00000000000..6539af1d6d5 --- /dev/null +++ b/src/sage/features/mcqd.py @@ -0,0 +1,11 @@ +from . import PythonModule +from .join_feature import JoinFeature + + +class Mcqd(JoinFeature): + + def __init__(self): + # Currently part of sagemath_standard, conditionally built. + # Will be changed to spkg='sagemath_mcqd' later + JoinFeature.__init__(self, 'mcqd', + [PythonModule('sage.graphs.mcqd', spkg='mcqd')]) diff --git a/src/sage/features/meataxe.py b/src/sage/features/meataxe.py new file mode 100644 index 00000000000..a8b65d166dc --- /dev/null +++ b/src/sage/features/meataxe.py @@ -0,0 +1,11 @@ +from . import PythonModule +from .join_feature import JoinFeature + + +class Meataxe(JoinFeature): + + def __init__(self): + # Currently part of sagemath_standard, conditionally built. + # Will be changed to spkg='sagemath_meataxe' later + JoinFeature.__init__(self, 'meataxe', + [PythonModule('sage.matrix.matrix_gfpn_dense', spkg='meataxe')]) diff --git a/src/sage/features/sagemath.py b/src/sage/features/sagemath.py new file mode 100644 index 00000000000..2af7def3668 --- /dev/null +++ b/src/sage/features/sagemath.py @@ -0,0 +1,84 @@ +r""" +Check for SageMath Python modules +""" +from . import PythonModule +from .join_feature import JoinFeature + + +class sage__combinat(JoinFeature): + + def __init__(self): + # sage.combinat will be a namespace package. + # Testing whether sage.combinat itself can be imported is meaningless. + # Hence, we test a Python module within the package. + JoinFeature.__init__(self, 'sage.combinat', + [PythonModule('sage.combinat.combinations')]) + + +class sage__graphs(JoinFeature): + + def __init__(self): + JoinFeature.__init__(self, 'sage.graphs', + [PythonModule('sage.graphs.graph')]) + + +class sage__plot(JoinFeature): + + def __init__(self): + JoinFeature.__init__(self, 'sage.plot', + [PythonModule('sage.plot.plot')]) + + +class sage__rings__number_field(JoinFeature): + + def __init__(self): + JoinFeature.__init__(self, 'sage.rings.number_field', + [PythonModule('sage.rings.number_field.number_field_element')]) + + +class sage__rings__real_double(PythonModule): + + def __init__(self): + PythonModule.__init__(self, 'sage.rings.real_double') + + +class sage__symbolic(JoinFeature): + + def __init__(self): + JoinFeature.__init__(self, 'sage.symbolic', + [PythonModule('sage.symbolic.expression')], + spkg="sagemath_symbolics") + + +def sage_features(): + """ + Return features corresponding to parts of the Sage library. + + These tags are named after Python packages/modules (e.g., :mod:`~sage.symbolic`), + not distribution packages (``sagemath-symbolics``). + + This design is motivated by a separation of concerns: The author of a module that depends + on some functionality provided by a Python module usually already knows the + name of the Python module, so we do not want to force the author to also + know about the distribution package that provides the Python module. + + Instead, we associate distribution packages to Python modules in + :mod:`sage.features.sagemath` via the ``spkg`` parameter of :class:`Feature`. + + EXAMPLES:: + + sage: from sage.features.sagemath import sage_features + sage: list(sage_features()) # random + [Feature('sage.graphs'), + Feature('sage.plot'), + Feature('sage.rings.number_field'), + Feature('sage.rings.real_double')] + """ + for feature in [sage__combinat(), + sage__graphs(), + sage__plot(), + sage__rings__number_field(), + sage__rings__real_double(), + sage__symbolic()]: + if feature.is_present(): + yield feature diff --git a/src/sage/features/tdlib.py b/src/sage/features/tdlib.py new file mode 100644 index 00000000000..e01e1bdfdf6 --- /dev/null +++ b/src/sage/features/tdlib.py @@ -0,0 +1,11 @@ +from . import PythonModule +from .join_feature import JoinFeature + + +class Tdlib(JoinFeature): + + def __init__(self): + # Currently part of sagemath_standard, conditionally built. + # Will be changed to spkg='sagemath_tdlib' later + JoinFeature.__init__(self, 'tdlib', + [PythonModule('sage.graphs.graph_decompositions.tdlib', spkg='tdlib')]) diff --git a/src/sage/functions/bessel.py b/src/sage/functions/bessel.py index 3adee3b0c94..3ba9ece2359 100644 --- a/src/sage/functions/bessel.py +++ b/src/sage/functions/bessel.py @@ -332,7 +332,8 @@ def __init__(self): besselj(x, x) """ BuiltinFunction.__init__(self, 'bessel_J', nargs=2, - conversions=dict(mathematica='BesselJ', + conversions=dict(maple='BesselJ', + mathematica='BesselJ', maxima='bessel_j', sympy='besselj', fricas='besselJ', @@ -361,15 +362,15 @@ def _eval_(self, n, x): from sage.rings.infinity import unsigned_infinity if not isinstance(x, Expression) and x == 0: if n == 0: - return ZZ(1) + return ZZ.one() elif n.real() > 0 or n in ZZ: - return ZZ(0) + return ZZ.zero() elif n.real() < 0: return unsigned_infinity - if n == QQ(1)/2: - return sqrt(2/pi/x) * sin(x) - elif n == QQ(-1)/2: - return sqrt(2/pi/x) * cos(x) + if n == QQ((1, 2)): + return sqrt(2 / pi / x) * sin(x) + elif n == QQ((-1, 2)): + return sqrt(2 / pi / x) * cos(x) def _evalf_(self, n, x, parent=None, algorithm=None): """ @@ -437,6 +438,7 @@ def _print_latex_(self, n, z): """ return r"J_{%s}(%s)" % (latex(n), latex(z)) + bessel_J = Function_Bessel_J() @@ -549,7 +551,8 @@ def __init__(self): bessely(x, x) """ BuiltinFunction.__init__(self, 'bessel_Y', nargs=2, - conversions=dict(mathematica='BesselY', + conversions=dict(maple='BesselY', + mathematica='BesselY', maxima='bessel_y', sympy='bessely', fricas='besselY', @@ -579,10 +582,10 @@ def _eval_(self, n, x): return -infinity elif n.real() > 0 or n.real() < 0: return unsigned_infinity - if n == QQ(1)/2: - return -sqrt(2/pi/x) * cos(x) - elif n == QQ(-1)/2: - return sqrt(2/pi/x) * sin(x) + if n == QQ((1, 2)): + return -sqrt(2 / pi / x) * cos(x) + elif n == QQ((-1, 2)): + return sqrt(2 / pi / x) * sin(x) def _evalf_(self, n, x, parent=None, algorithm=None): """ @@ -649,6 +652,7 @@ def _print_latex_(self, n, z): """ return r"Y_{%s}(%s)" % (latex(n), latex(z)) + bessel_Y = Function_Bessel_Y() @@ -755,7 +759,8 @@ def __init__(self): besseli(x, x) """ BuiltinFunction.__init__(self, 'bessel_I', nargs=2, - conversions=dict(mathematica='BesselI', + conversions=dict(maple='BesselI', + mathematica='BesselI', maxima='bessel_i', sympy='besseli', fricas='besselI')) @@ -783,17 +788,16 @@ def _eval_(self, n, x): from sage.rings.infinity import unsigned_infinity if not isinstance(x, Expression) and x == 0: if n == 0: - return ZZ(1) + return ZZ.one() elif n.real() > 0 or n in ZZ: - return ZZ(0) + return ZZ.zero() elif n.real() < 0: return unsigned_infinity - if n == QQ(1)/2: + if n == QQ((1, 2)): return sqrt(2 / (pi * x)) * sinh(x) - elif n == -QQ(1)/2: + elif n == QQ((-1, 2)): return sqrt(2 / (pi * x)) * cosh(x) - def _evalf_(self, n, x, parent=None, algorithm=None): """ EXAMPLES:: @@ -838,6 +842,7 @@ def _print_latex_(self, n, z): """ return r"I_{%s}(%s)" % (latex(n), latex(z)) + bessel_I = Function_Bessel_I() @@ -955,7 +960,8 @@ def __init__(self): besselk(x, x) """ BuiltinFunction.__init__(self, 'bessel_K', nargs=2, - conversions=dict(mathematica='BesselK', + conversions=dict(maple='BesselK', + mathematica='BesselK', maxima='bessel_k', sympy='besselk', fricas='besselK')) @@ -983,10 +989,9 @@ def _eval_(self, n, x): return infinity elif n.real() > 0 or n.real() < 0: return unsigned_infinity - if n == QQ(1)/2 or n == -QQ(1)/2 and x > 0: + if n == QQ((1, 2)) or n == QQ((-1, 2)) and x > 0: return sqrt(pi / 2) * exp(-x) * x ** (-Integer(1) / Integer(2)) - def _evalf_(self, n, x, parent=None, algorithm=None): """ EXAMPLES:: @@ -1032,6 +1037,7 @@ def _print_latex_(self, n, z): """ return r"K_{%s}(%s)" % (latex(n), latex(z)) + bessel_K = Function_Bessel_K() @@ -1246,7 +1252,8 @@ def __init__(self): conversions=dict(maple='StruveH', mathematica='StruveH', maxima='struve_h', - fricas='struveH')) + fricas='struveH', + sympy='struveh')) def _eval_(self, a, z): """ @@ -1267,21 +1274,19 @@ def _eval_(self, a, z): sage: struve_H(-3/2,x) -bessel_J(3/2, x) """ - from sage.symbolic.ring import SR if z.is_zero() \ and (SR(a).is_numeric() or SR(a).is_constant()) \ and a.real() >= -1: - return ZZ(0) - if a == -Integer(1)/2: + return ZZ.zero() + if a == QQ((-1, 2)): from sage.functions.trig import sin - return sqrt(2/(pi*z)) * sin(z) - if a == Integer(1)/2: + return sqrt(2 / (pi * z)) * sin(z) + if a == QQ((1, 2)): from sage.functions.trig import cos - return sqrt(2/(pi*z)) * (1-cos(z)) - if a < 0 and not SR(a).is_integer() and SR(2*a).is_integer(): - from sage.rings.rational_field import QQ - n = (a*(-2) - 1)/2 - return Integer(-1)**n * bessel_J(n+QQ(1)/2, z) + return sqrt(2 / (pi * z)) * (1 - cos(z)) + if a < 0 and not SR(a).is_integer() and SR(2 * a).is_integer(): + n = (a * (-2) - 1) / 2 + return Integer(-1)**n * bessel_J(n + QQ((1, 2)), z) def _evalf_(self, a, z, parent=None, algorithm=None): """ @@ -1307,7 +1312,7 @@ def _derivative_(self, a, z, diff_param=None): from .gamma import gamma from .other import sqrt - return (z**a/(sqrt(pi)*2**a*gamma(a+Integer(3)/Integer(2)))-struve_H(a+1,z)+struve_H(a-1,z))/2 + return (z**a / (sqrt(pi) * 2**a * gamma(a + Integer(3) / Integer(2))) - struve_H(a + 1, z) + struve_H(a - 1, z)) / 2 def _print_latex_(self, a, z): """ @@ -1318,8 +1323,10 @@ def _print_latex_(self, a, z): """ return r"H_{{%s}}({%s})" % (a, z) + struve_H = Function_Struve_H() + class Function_Struve_L(BuiltinFunction): r""" The modified Struve functions. @@ -1361,7 +1368,8 @@ def __init__(self): conversions=dict(maple='StruveL', mathematica='StruveL', maxima='struve_l', - fricas='struveL')) + fricas='struveL', + sympy='struvel')) def _eval_(self, a, z): """ @@ -1382,21 +1390,19 @@ def _eval_(self, a, z): sage: struve_L(-3/2,x) -bessel_I(3/2, x) """ - from sage.symbolic.ring import SR if z.is_zero() \ and (SR(a).is_numeric() or SR(a).is_constant()) \ and a.real() >= -1: - return ZZ(0) - if a == -Integer(1)/2: + return ZZ.zero() + if a == -Integer(1) / 2: from sage.functions.hyperbolic import sinh - return sqrt(2/(pi*z)) * sinh(z) - if a == Integer(1)/2: + return sqrt(2 / (pi * z)) * sinh(z) + if a == Integer(1) / 2: from sage.functions.hyperbolic import cosh - return sqrt(2/(pi*z)) * (cosh(z)-1) - if a < 0 and not SR(a).is_integer() and SR(2*a).is_integer(): - from sage.rings.rational_field import QQ - n = (a*(-2) - 1)/2 - return Integer(-1)**n * bessel_I(n+QQ(1)/2, z) + return sqrt(2 / (pi * z)) * (cosh(z) - 1) + if a < 0 and not SR(a).is_integer() and SR(2 * a).is_integer(): + n = (a * (-2) - 1) / 2 + return Integer(-1)**n * bessel_I(n + QQ((1, 2)), z) def _evalf_(self, a, z, parent=None, algorithm=None): """ @@ -1422,7 +1428,7 @@ def _derivative_(self, a, z, diff_param=None): from .gamma import gamma from .other import sqrt - return (z**a/(sqrt(pi)*2**a*gamma(a+Integer(3)/Integer(2)))-struve_L(a+1,z)+struve_L(a-1,z))/2 + return (z**a / (sqrt(pi) * 2**a * gamma(a + Integer(3) / Integer(2))) - struve_L(a + 1, z) + struve_L(a - 1, z)) / 2 def _print_latex_(self, a, z): """ @@ -1431,6 +1437,7 @@ def _print_latex_(self, a, z): """ return r"L_{{%s}}({%s})" % (a, z) + struve_L = Function_Struve_L() @@ -1518,6 +1525,7 @@ def _derivative_(self, nu, z, diff_param): else: raise NotImplementedError('derivative with respect to order') + hankel1 = Function_Hankel1() @@ -1605,6 +1613,7 @@ def _derivative_(self, nu, z, diff_param): else: raise NotImplementedError('derivative with respect to order') + hankel2 = Function_Hankel2() @@ -1704,6 +1713,7 @@ def _derivative_(self, n, z, diff_param): else: raise NotImplementedError('derivative with respect to order') + spherical_bessel_J = SphericalBesselJ() @@ -1803,6 +1813,7 @@ def _derivative_(self, n, z, diff_param): else: raise NotImplementedError('derivative with respect to order') + spherical_bessel_Y = SphericalBesselY() @@ -1899,6 +1910,7 @@ def _derivative_(self, n, z, diff_param): else: raise NotImplementedError('derivative with respect to order') + spherical_hankel1 = SphericalHankel1() @@ -2007,6 +2019,7 @@ def _derivative_(self, n, z, diff_param): else: raise NotImplementedError('derivative with respect to order') + spherical_hankel2 = SphericalHankel2() @@ -2053,4 +2066,3 @@ def spherical_bessel_f(F, n, z): return quotient * Fz finally: ctx.prec = prec - diff --git a/src/sage/functions/exp_integral.py b/src/sage/functions/exp_integral.py index 4a1a897ade0..7ef74d9ed49 100644 --- a/src/sage/functions/exp_integral.py +++ b/src/sage/functions/exp_integral.py @@ -1497,7 +1497,7 @@ def exponential_integral_1(x, n=0): ....: n = 2^ZZ.random_element(14) ....: x = exponential_integral_1(a, n) ....: y = exponential_integral_1(S(a), n) - ....: c = RDF(2 * max(1.0, y[0])) + ....: c = RDF(4 * max(1.0, y[0])) ....: for i in range(n): ....: e = float(abs(S(x[i]) - y[i]) << prec) ....: if e >= c: diff --git a/src/sage/functions/hyperbolic.py b/src/sage/functions/hyperbolic.py index 58f3eb0c846..2ca5284f505 100644 --- a/src/sage/functions/hyperbolic.py +++ b/src/sage/functions/hyperbolic.py @@ -80,6 +80,7 @@ def __init__(self): """ GinacFunction.__init__(self, "sinh", latex_name=r"\sinh") + sinh = Function_sinh() @@ -116,6 +117,7 @@ def __init__(self): """ GinacFunction.__init__(self, "cosh", latex_name=r"\cosh") + cosh = Function_cosh() @@ -180,6 +182,7 @@ def __init__(self): """ GinacFunction.__init__(self, "tanh", latex_name=r"\tanh") + tanh = Function_tanh() @@ -235,6 +238,7 @@ def _eval_numpy_(self, x): """ return 1.0 / tanh(x) + coth = Function_coth() @@ -288,6 +292,7 @@ def _eval_numpy_(self, x): """ return 1.0 / cosh(x) + sech = Function_sech() @@ -339,6 +344,7 @@ def _eval_numpy_(self, x): """ return 1.0 / sinh(x) + csch = Function_csch() @@ -403,7 +409,8 @@ def __init__(self): GinacFunction.__init__(self, "arcsinh", latex_name=r"\operatorname{arsinh}", conversions=dict(maxima='asinh', sympy='asinh', fricas='asinh', - giac='asinh')) + giac='asinh', mathematica='ArcSinh')) + arcsinh = asinh = Function_arcsinh() @@ -488,7 +495,8 @@ def __init__(self): GinacFunction.__init__(self, "arccosh", latex_name=r"\operatorname{arcosh}", conversions=dict(maxima='acosh', sympy='acosh', fricas='acosh', - giac='acosh')) + giac='acosh', mathematica='ArcCosh')) + arccosh = acosh = Function_arccosh() @@ -547,7 +555,8 @@ def __init__(self): GinacFunction.__init__(self, "arctanh", latex_name=r"\operatorname{artanh}", conversions=dict(maxima='atanh', sympy='atanh', fricas='atanh', - giac='atanh')) + giac='atanh', mathematica='ArcTanh')) + arctanh = atanh = Function_arctanh() @@ -594,7 +603,8 @@ def __init__(self): """ GinacFunction.__init__(self, "arccoth", latex_name=r"\operatorname{arcoth}", - conversions=dict(maxima='acoth', sympy='acoth', fricas='acoth')) + conversions=dict(maxima='acoth', sympy='acoth', + giac='acoth', fricas='acoth')) def _eval_numpy_(self, x): """ @@ -607,6 +617,7 @@ def _eval_numpy_(self, x): """ return arctanh(1.0 / x) + arccoth = acoth = Function_arccoth() @@ -637,7 +648,8 @@ def __init__(self): """ GinacFunction.__init__(self, "arcsech", latex_name=r"\operatorname{arsech}", - conversions=dict(maxima='asech', sympy='asech', fricas='asech')) + conversions=dict(maxima='asech', sympy='asech', + fricas='asech')) def _eval_numpy_(self, x): """ @@ -651,6 +663,7 @@ def _eval_numpy_(self, x): """ return arccosh(1.0 / x) + arcsech = asech = Function_arcsech() @@ -702,4 +715,5 @@ def _eval_numpy_(self, x): """ return arcsinh(1.0 / x) + arccsch = acsch = Function_arccsch() diff --git a/src/sage/functions/orthogonal_polys.py b/src/sage/functions/orthogonal_polys.py index 9bb670ff510..4c6650f5311 100644 --- a/src/sage/functions/orthogonal_polys.py +++ b/src/sage/functions/orthogonal_polys.py @@ -304,8 +304,7 @@ from sage.misc.latex import latex from sage.rings.all import ZZ, QQ, RR, CC from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing -from sage.rings.real_mpfr import is_RealField -from sage.rings.complex_mpfr import is_ComplexField +import sage.rings.abc from sage.symbolic.function import BuiltinFunction, GinacFunction from sage.symbolic.expression import Expression @@ -672,7 +671,7 @@ def _evalf_(self, n, x, **kwds): except KeyError: real_parent = parent(x) - if not is_RealField(real_parent) and not is_ComplexField(real_parent): + if not isinstance(real_parent, (sage.rings.abc.RealField, sage.rings.abc.ComplexField)): # parent is not a real or complex field: figure out a good parent if x in RR: x = RR(x) @@ -681,7 +680,7 @@ def _evalf_(self, n, x, **kwds): x = CC(x) real_parent = CC - if not is_RealField(real_parent) and not is_ComplexField(real_parent): + if not isinstance(real_parent, (sage.rings.abc.RealField, sage.rings.abc.ComplexField)): raise TypeError("cannot evaluate chebyshev_T with parent {}".format(real_parent)) from sage.libs.mpmath.all import call as mpcall @@ -1031,7 +1030,7 @@ def _evalf_(self, n, x, **kwds): except KeyError: real_parent = parent(x) - if not is_RealField(real_parent) and not is_ComplexField(real_parent): + if not isinstance(real_parent, (sage.rings.abc.RealField, sage.rings.abc.ComplexField)): # parent is not a real or complex field: figure out a good parent if x in RR: x = RR(x) @@ -1040,7 +1039,7 @@ def _evalf_(self, n, x, **kwds): x = CC(x) real_parent = CC - if not is_RealField(real_parent) and not is_ComplexField(real_parent): + if not isinstance(real_parent, (sage.rings.abc.RealField, sage.rings.abc.ComplexField)): raise TypeError("cannot evaluate chebyshev_U with parent {}".format(real_parent)) from sage.libs.mpmath.all import call as mpcall @@ -2083,7 +2082,7 @@ class Func_ultraspherical(GinacFunction): 32*t^3 - 12*t sage: _ = var('x') sage: for N in range(100): - ....: n = ZZ.random_element().abs() + 5 + ....: n = ZZ.random_element(5, 5001) ....: a = QQ.random_element().abs() + 5 ....: assert ((n+1)*ultraspherical(n+1,a,x) - 2*x*(n+a)*ultraspherical(n,a,x) + (n+2*a-1)*ultraspherical(n-1,a,x)).expand().is_zero() sage: ultraspherical(5,9/10,3.1416) diff --git a/src/sage/functions/special.py b/src/sage/functions/special.py index 21d8c67c607..97070d07d9e 100644 --- a/src/sage/functions/special.py +++ b/src/sage/functions/special.py @@ -158,8 +158,8 @@ # https://www.gnu.org/licenses/ # **************************************************************************** +import sage.rings.abc from sage.rings.integer import Integer -from sage.rings.complex_mpfr import ComplexField from sage.misc.latex import latex from sage.rings.integer_ring import ZZ from sage.symbolic.constants import pi @@ -362,10 +362,9 @@ def elliptic_j(z, prec=53): sage: (-elliptic_j(tau, 100).real().round())^(1/3) 640320 """ - CC = z.parent() - from sage.rings.complex_mpfr import is_ComplexField - if not is_ComplexField(CC): + if not isinstance(CC, sage.rings.abc.ComplexField): + from sage.rings.complex_mpfr import ComplexField CC = ComplexField(prec) try: z = CC(z) diff --git a/src/sage/functions/trig.py b/src/sage/functions/trig.py index fbee1cd0cc8..a705648a8ce 100644 --- a/src/sage/functions/trig.py +++ b/src/sage/functions/trig.py @@ -118,7 +118,9 @@ def __init__(self): sin(1/42*pi) """ GinacFunction.__init__(self, 'sin', latex_name=r"\sin", - conversions=dict(maxima='sin',mathematica='Sin',giac='sin')) + conversions=dict(maxima='sin', mathematica='Sin', + giac='sin', fricas='sin', sympy='sin')) + sin = Function_sin() @@ -181,7 +183,9 @@ def __init__(self): -cos(1/42*pi) """ GinacFunction.__init__(self, 'cos', latex_name=r"\cos", - conversions=dict(maxima='cos',mathematica='Cos',giac='cos')) + conversions=dict(maxima='cos', mathematica='Cos', + giac='cos', fricas='cos', sympy='cos')) + cos = Function_cos() @@ -243,8 +247,10 @@ def __init__(self): """ GinacFunction.__init__(self, 'tan', latex_name=r"\tan") + tan = Function_tan() + class Function_cot(GinacFunction): def __init__(self): r""" @@ -337,6 +343,7 @@ def _eval_numpy_(self, x): """ return 1.0 / tan(x) + cot = Function_cot() @@ -406,8 +413,10 @@ def _eval_numpy_(self, x): """ return 1 / cos(x) + sec = Function_sec() + class Function_csc(GinacFunction): def __init__(self): r""" @@ -474,8 +483,10 @@ def _eval_numpy_(self, x): """ return 1 / sin(x) + csc = Function_csc() + ################################### # Inverse Trigonometric Functions # ################################### @@ -535,10 +546,14 @@ def __init__(self): 1.57079632679490 - 1.37285914424258*I """ GinacFunction.__init__(self, 'arcsin', latex_name=r"\arcsin", - conversions=dict(maxima='asin', sympy='asin', fricas="asin", giac="asin")) + conversions=dict(maxima='asin', sympy='asin', + mathematica='ArcSin', + fricas="asin", giac="asin")) + arcsin = asin = Function_arcsin() + class Function_arccos(GinacFunction): def __init__(self): """ @@ -596,10 +611,14 @@ def __init__(self): 1.37285914424258*I """ GinacFunction.__init__(self, 'arccos', latex_name=r"\arccos", - conversions=dict(maxima='acos', sympy='acos', fricas='acos', giac='acos')) + conversions=dict(maxima='acos', sympy='acos', + mathematica='ArcCos', + fricas='acos', giac='acos')) + arccos = acos = Function_arccos() + class Function_arctan(GinacFunction): def __init__(self): """ @@ -664,10 +683,14 @@ def __init__(self): 1/2*pi """ GinacFunction.__init__(self, 'arctan', latex_name=r"\arctan", - conversions=dict(maxima='atan', sympy='atan', fricas='atan', giac='atan')) + conversions=dict(maxima='atan', sympy='atan', + mathematica='ArcTan', + fricas='atan', giac='atan')) + arctan = atan = Function_arctan() + class Function_arccot(GinacFunction): def __init__(self): """ @@ -714,7 +737,8 @@ def __init__(self): """ GinacFunction.__init__(self, 'arccot', latex_name=r"\operatorname{arccot}", - conversions=dict(maxima='acot', sympy='acot', fricas='acot',giac='acot')) + conversions=dict(maxima='acot', sympy='acot', + fricas='acot', giac='acot')) def _eval_numpy_(self, x): """ @@ -725,10 +749,12 @@ def _eval_numpy_(self, x): sage: arccot(a) array([0.46364761, 0.32175055, 0.24497866]) """ - return math.pi/2 - arctan(x) + return math.pi / 2 - arctan(x) + arccot = acot = Function_arccot() + class Function_arccsc(GinacFunction): def __init__(self): """ @@ -770,7 +796,8 @@ def __init__(self): (0.45227844715119064-0.5306375309525178j) """ GinacFunction.__init__(self, 'arccsc', latex_name=r"\operatorname{arccsc}", - conversions=dict(maxima='acsc', sympy='acsc', fricas='acsc', giac='acsc')) + conversions=dict(maxima='acsc', sympy='acsc', + fricas='acsc', giac='acsc')) def _eval_numpy_(self, x): """ @@ -781,10 +808,12 @@ def _eval_numpy_(self, x): sage: arccsc(a) array([0.52359878, 0.33983691, 0.25268026]) """ - return arcsin(1.0/x) + return arcsin(1.0 / x) + arccsc = acsc = Function_arccsc() + class Function_arcsec(GinacFunction): def __init__(self): """ @@ -828,7 +857,8 @@ def __init__(self): (1.118517879643706+0.5306375309525178j) """ GinacFunction.__init__(self, 'arcsec', latex_name=r"\operatorname{arcsec}", - conversions=dict(maxima='asec', sympy='asec', fricas='asec', giac='asec')) + conversions=dict(maxima='asec', sympy='asec', + fricas='asec', giac='asec')) def _eval_numpy_(self, x): """ @@ -839,10 +869,12 @@ def _eval_numpy_(self, x): sage: arcsec(a) array([1.04719755, 1.23095942, 1.31811607]) """ - return arccos(1.0/x) + return arccos(1.0 / x) + arcsec = asec = Function_arcsec() + class Function_arctan2(GinacFunction): def __init__(self): r""" @@ -961,6 +993,7 @@ def __init__(self): pi """ GinacFunction.__init__(self, 'arctan2', nargs=2, latex_name=r"\arctan", - conversions=dict(maxima='atan2', sympy='atan2')) + conversions=dict(maxima='atan2', sympy='atan2', giac='atan2')) + arctan2 = atan2 = Function_arctan2() diff --git a/src/sage/geometry/polyhedron/backend_cdd.py b/src/sage/geometry/polyhedron/backend_cdd.py index 7b48eb7b45b..3a24dca5cb2 100644 --- a/src/sage/geometry/polyhedron/backend_cdd.py +++ b/src/sage/geometry/polyhedron/backend_cdd.py @@ -21,7 +21,9 @@ from .base import Polyhedron_base from .base_QQ import Polyhedron_QQ -from .base_RDF import Polyhedron_RDF + +from sage.misc.lazy_import import lazy_import +lazy_import('sage.geometry.polyhedron.backend_cdd_rdf', 'Polyhedron_RDF_cdd', deprecation=32592) class Polyhedron_cdd(Polyhedron_base): @@ -458,212 +460,3 @@ def __init__(self, parent, Vrep, Hrep, **kwds): sage: TestSuite(p).run() """ Polyhedron_cdd.__init__(self, parent, Vrep, Hrep, **kwds) - - -class Polyhedron_RDF_cdd(Polyhedron_cdd, Polyhedron_RDF): - """ - Polyhedra over RDF with cdd - - INPUT: - - - ``ambient_dim`` -- integer. The dimension of the ambient space. - - - ``Vrep`` -- a list ``[vertices, rays, lines]`` or ``None``. - - - ``Hrep`` -- a list ``[ieqs, eqns]`` or ``None``. - - EXAMPLES:: - - sage: from sage.geometry.polyhedron.parent import Polyhedra - sage: parent = Polyhedra(RDF, 2, backend='cdd') - sage: from sage.geometry.polyhedron.backend_cdd import Polyhedron_RDF_cdd - sage: Polyhedron_RDF_cdd(parent, [ [(1,0),(0,1),(0,0)], [], []], None, verbose=False) - A 2-dimensional polyhedron in RDF^2 defined as the convex hull of 3 vertices - - TESTS: - - Checks that :trac:`24877` is fixed:: - - sage: n1 = 1045602428815736513789288687833080060779 - sage: n2 = 76591188009721216624438400001815308369088648782156930777145 - sage: n3 = 141046287872967162025203834781636948939209065735662536571684677443277621519222367249160281646288602157866548267640061850035 - sage: n4 = 169296796161110084211548448622149955145002732358082778064645608216077666698460018565094060494217 - sage: verts = [[159852/261157, 227425/261157], - ....: [9/10, 7/10], - ....: [132/179, 143/179], - ....: [8/11, -59/33], - ....: [174/167, 95/167], - ....: [3/2, -1/2], - ....: [-1162016360399650274197433414376009691155/n1, - ....: 1626522696050475596930360993440360903664/n1], - ....: [-112565666321600055047037445519656973805313121630809713051718/n2, - ....: -15318574020578896781701071673537253327221557273483622682053/n2], - ....: [-222823992658914823798345935660863293259608796350232624336738123149601409997996952470726909468671437285720616325991022633438/n3, - ....: (-20857694835570598502487921801401627779907095024585170129381924208334510445828894861553290291713792691651471189597832832973*5)/n3], - ....: [-100432602675156818915933977983765863676402454634873648118147187022041830166292457614016362515164/n4, - ....: -429364759737031049317769174492863890735634068814210512342503744054527903830844433491149538512537/n4]] - sage: P = Polyhedron(verts, base_ring=RDF) - sage: len(P.faces(1)) - 10 - sage: P.n_vertices() - 10 - sage: P.n_facets() - 10 - - Check that :trac:`19803` is fixed:: - - sage: from sage.geometry.polyhedron.parent import Polyhedra - sage: P_cdd = Polyhedra(RDF, 3, 'cdd') - sage: P_cdd([[],[],[]], None) - The empty polyhedron in RDF^3 - sage: Polyhedron(vertices=[], backend='cdd', base_ring=RDF) - The empty polyhedron in RDF^0 - """ - _cdd_type = 'real' - - _cdd_executable = 'cddexec' - - def __init__(self, parent, Vrep, Hrep, **kwds): - """ - The Python constructor. - - See :class:`Polyhedron_base` for a description of the input - data. - - TESTS:: - - sage: p = Polyhedron(backend='cdd', base_ring=RDF) - sage: type(p) - - sage: TestSuite(p).run() - """ - Polyhedron_cdd.__init__(self, parent, Vrep, Hrep, **kwds) - - def _init_from_Vrepresentation_and_Hrepresentation(self, Vrep, Hrep, verbose=False): - """ - Construct polyhedron from Vrepresentation and Hrepresentation data. - - See :class:`Polyhedron_base` for a description of ``Vrep`` and ``Hrep``. - - .. NOTE:: - - The representation is assumed to be correct. - - As long as cdd can obtain a consistent object with Vrepresentation - or Hrepresentation no warning is raised. Consistency is checked by - comparing the output length of Vrepresentation and Hrepresentation - with the input. - - In comparison, the "normal" initialization from Vrepresentation over RDF - expects the output length to be consistent with the computed length - when re-feeding cdd the outputted Hrepresentation. - - EXAMPLES:: - - sage: from sage.geometry.polyhedron.parent import Polyhedra_RDF_cdd - sage: from sage.geometry.polyhedron.backend_cdd import Polyhedron_RDF_cdd - sage: parent = Polyhedra_RDF_cdd(RDF, 1, 'cdd') - sage: Vrep = [[[0.0], [1.0]], [], []] - sage: Hrep = [[[0.0, 1.0], [1.0, -1.0]], []] - sage: p = Polyhedron_RDF_cdd(parent, Vrep, Hrep, - ....: Vrep_minimal=True, Hrep_minimal=True) # indirect doctest - sage: p - A 1-dimensional polyhedron in RDF^1 defined as the convex hull of 2 vertices - - TESTS: - - Test that :trac:`29568` is fixed:: - - sage: P = polytopes.buckyball(exact=False) - sage: Q = P + P.center() - sage: P.is_combinatorially_isomorphic(Q) - True - sage: R = 2*P - sage: P.is_combinatorially_isomorphic(R) - True - - The polyhedron with zero inequalities works correctly; see :trac:`29899`:: - - sage: Vrep = [[], [], [[1.0]]] - sage: Hrep = [[], []] - sage: p = Polyhedron_RDF_cdd(parent, Vrep, Hrep, - ....: Vrep_minimal=True, Hrep_minimal=True) # indirect doctest - sage: p - A 1-dimensional polyhedron in RDF^1 defined as the convex hull of 1 vertex and 1 line - - Test that :trac:`30330` is fixed:: - - sage: P1 = polytopes.regular_polygon(5, exact=False) - sage: P2 = Polyhedron() - sage: P1*P2 - The empty polyhedron in RDF^2 - """ - def parse_Vrep(intro, data): - count = int(data[0][0]) - if count != len(vertices) + len(rays) + len(lines): - # Upstream claims that nothing can be done about these - # cases/that they are features not bugs. Imho, cddlib is - # not really suitable for automatic parsing of its output, - # the implementation backed by doubles has not really been - # optimized for numerical stability, and makes some - # somewhat random numerical choices. (But I am not an - # expert in that field by any means.) See also - # https://github.com/cddlib/cddlib/pull/7. - from warnings import warn - warn("This polyhedron data is numerically complicated; cdd could not convert between the inexact V and H representation without loss of data. The resulting object might show inconsistencies.") - - def parse_Hrep(intro, data): - count = int(data[0][0]) - infinite_count = len([d for d in data[1:] if d[0] == '1' and all(c == '0' for c in d[1:])]) - if count - infinite_count != len(ieqs) + len(eqns): - # Upstream claims that nothing can be done about these - # cases/that they are features not bugs. Imho, cddlib is - # not really suitable for automatic parsing of its output, - # the implementation backed by doubles has not really been - # optimized for numerical stability, and makes some - # somewhat random numerical choices. (But I am not an - # expert in that field by any means.) - from warnings import warn - warn("This polyhedron data is numerically complicated; cdd could not convert between the inexact V and H representation without loss of data. The resulting object might show inconsistencies.") - - def try_init(rep): - if rep == "Vrep": - from .cdd_file_format import cdd_Vrepresentation - s = cdd_Vrepresentation(self._cdd_type, vertices, rays, lines) - else: - # We have to add a trivial inequality, in case the polyhedron is the universe. - new_ieqs = ieqs + ((1,) + tuple(0 for _ in range(self.ambient_dim())),) - - from .cdd_file_format import cdd_Hrepresentation - s = cdd_Hrepresentation(self._cdd_type, new_ieqs, eqns) - - s = self._run_cdd(s, '--redcheck', verbose=verbose) - s = self._run_cdd(s, '--repall', verbose=verbose) - Polyhedron_cdd._parse_block(s.splitlines(), 'V-representation', parse_Vrep) - Polyhedron_cdd._parse_block(s.splitlines(), 'H-representation', parse_Hrep) - self._init_from_cdd_output(s) - - from warnings import catch_warnings, simplefilter - - vertices, rays, lines = (tuple(x) for x in Vrep) - ieqs, eqns = (tuple(x) for x in Hrep) - - if not (vertices or rays or lines): - # cdd refuses to handle empty polyhedra. - self._init_empty_polyhedron() - return - - # We prefer the shorter representation. - # Note that for the empty polyhedron we prefer Hrepresentation. - prim = "Hrep" if len(ieqs) <= len(vertices) + len(rays) else "Vrep" - sec = "Vrep" if len(ieqs) <= len(vertices) + len(rays) else "Hrep" - - with catch_warnings(): - # Raise an error and try the other representation in case of - # numerical inconsistency. - simplefilter("error") - try: - try_init(prim) - except UserWarning: - simplefilter("once") # Only print the first warning. - try_init(sec) diff --git a/src/sage/geometry/polyhedron/backend_cdd_rdf.py b/src/sage/geometry/polyhedron/backend_cdd_rdf.py new file mode 100644 index 00000000000..2f3795a4b0f --- /dev/null +++ b/src/sage/geometry/polyhedron/backend_cdd_rdf.py @@ -0,0 +1,227 @@ +r""" +The cdd backend for polyhedral computations, floating point version +""" +# **************************************************************************** +# Copyright (C) 2011-2014 Volker Braun +# 2018 Timo Kaufmann +# 2018 Julian Rüth +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# https://www.gnu.org/licenses/ +# **************************************************************************** + + +from .backend_cdd import Polyhedron_cdd +from .base_RDF import Polyhedron_RDF + + +class Polyhedron_RDF_cdd(Polyhedron_cdd, Polyhedron_RDF): + """ + Polyhedra over RDF with cdd + + INPUT: + + - ``ambient_dim`` -- integer. The dimension of the ambient space. + + - ``Vrep`` -- a list ``[vertices, rays, lines]`` or ``None``. + + - ``Hrep`` -- a list ``[ieqs, eqns]`` or ``None``. + + EXAMPLES:: + + sage: from sage.geometry.polyhedron.parent import Polyhedra + sage: parent = Polyhedra(RDF, 2, backend='cdd') + sage: from sage.geometry.polyhedron.backend_cdd_rdf import Polyhedron_RDF_cdd + sage: Polyhedron_RDF_cdd(parent, [ [(1,0),(0,1),(0,0)], [], []], None, verbose=False) + A 2-dimensional polyhedron in RDF^2 defined as the convex hull of 3 vertices + + TESTS: + + Checks that :trac:`24877` is fixed:: + + sage: n1 = 1045602428815736513789288687833080060779 + sage: n2 = 76591188009721216624438400001815308369088648782156930777145 + sage: n3 = 141046287872967162025203834781636948939209065735662536571684677443277621519222367249160281646288602157866548267640061850035 + sage: n4 = 169296796161110084211548448622149955145002732358082778064645608216077666698460018565094060494217 + sage: verts = [[159852/261157, 227425/261157], + ....: [9/10, 7/10], + ....: [132/179, 143/179], + ....: [8/11, -59/33], + ....: [174/167, 95/167], + ....: [3/2, -1/2], + ....: [-1162016360399650274197433414376009691155/n1, + ....: 1626522696050475596930360993440360903664/n1], + ....: [-112565666321600055047037445519656973805313121630809713051718/n2, + ....: -15318574020578896781701071673537253327221557273483622682053/n2], + ....: [-222823992658914823798345935660863293259608796350232624336738123149601409997996952470726909468671437285720616325991022633438/n3, + ....: (-20857694835570598502487921801401627779907095024585170129381924208334510445828894861553290291713792691651471189597832832973*5)/n3], + ....: [-100432602675156818915933977983765863676402454634873648118147187022041830166292457614016362515164/n4, + ....: -429364759737031049317769174492863890735634068814210512342503744054527903830844433491149538512537/n4]] + sage: P = Polyhedron(verts, base_ring=RDF) + sage: len(P.faces(1)) + 10 + sage: P.n_vertices() + 10 + sage: P.n_facets() + 10 + + Check that :trac:`19803` is fixed:: + + sage: from sage.geometry.polyhedron.parent import Polyhedra + sage: P_cdd = Polyhedra(RDF, 3, 'cdd') + sage: P_cdd([[],[],[]], None) + The empty polyhedron in RDF^3 + sage: Polyhedron(vertices=[], backend='cdd', base_ring=RDF) + The empty polyhedron in RDF^0 + """ + _cdd_type = 'real' + + _cdd_executable = 'cddexec' + + def __init__(self, parent, Vrep, Hrep, **kwds): + """ + The Python constructor. + + See :class:`Polyhedron_base` for a description of the input + data. + + TESTS:: + + sage: p = Polyhedron(backend='cdd', base_ring=RDF) + sage: type(p) + + sage: TestSuite(p).run() + """ + Polyhedron_cdd.__init__(self, parent, Vrep, Hrep, **kwds) + + def _init_from_Vrepresentation_and_Hrepresentation(self, Vrep, Hrep, verbose=False): + """ + Construct polyhedron from Vrepresentation and Hrepresentation data. + + See :class:`Polyhedron_base` for a description of ``Vrep`` and ``Hrep``. + + .. NOTE:: + + The representation is assumed to be correct. + + As long as cdd can obtain a consistent object with Vrepresentation + or Hrepresentation no warning is raised. Consistency is checked by + comparing the output length of Vrepresentation and Hrepresentation + with the input. + + In comparison, the "normal" initialization from Vrepresentation over RDF + expects the output length to be consistent with the computed length + when re-feeding cdd the outputted Hrepresentation. + + EXAMPLES:: + + sage: from sage.geometry.polyhedron.parent import Polyhedra_RDF_cdd + sage: from sage.geometry.polyhedron.backend_cdd_rdf import Polyhedron_RDF_cdd + sage: parent = Polyhedra_RDF_cdd(RDF, 1, 'cdd') + sage: Vrep = [[[0.0], [1.0]], [], []] + sage: Hrep = [[[0.0, 1.0], [1.0, -1.0]], []] + sage: p = Polyhedron_RDF_cdd(parent, Vrep, Hrep, + ....: Vrep_minimal=True, Hrep_minimal=True) # indirect doctest + sage: p + A 1-dimensional polyhedron in RDF^1 defined as the convex hull of 2 vertices + + TESTS: + + Test that :trac:`29568` is fixed:: + + sage: P = polytopes.buckyball(exact=False) + sage: Q = P + P.center() + sage: P.is_combinatorially_isomorphic(Q) + True + sage: R = 2*P + sage: P.is_combinatorially_isomorphic(R) + True + + The polyhedron with zero inequalities works correctly; see :trac:`29899`:: + + sage: Vrep = [[], [], [[1.0]]] + sage: Hrep = [[], []] + sage: p = Polyhedron_RDF_cdd(parent, Vrep, Hrep, + ....: Vrep_minimal=True, Hrep_minimal=True) # indirect doctest + sage: p + A 1-dimensional polyhedron in RDF^1 defined as the convex hull of 1 vertex and 1 line + + Test that :trac:`30330` is fixed:: + + sage: P1 = polytopes.regular_polygon(5, exact=False) + sage: P2 = Polyhedron() + sage: P1*P2 + The empty polyhedron in RDF^2 + """ + def parse_Vrep(intro, data): + count = int(data[0][0]) + if count != len(vertices) + len(rays) + len(lines): + # Upstream claims that nothing can be done about these + # cases/that they are features not bugs. Imho, cddlib is + # not really suitable for automatic parsing of its output, + # the implementation backed by doubles has not really been + # optimized for numerical stability, and makes some + # somewhat random numerical choices. (But I am not an + # expert in that field by any means.) See also + # https://github.com/cddlib/cddlib/pull/7. + from warnings import warn + warn("This polyhedron data is numerically complicated; cdd could not convert between the inexact V and H representation without loss of data. The resulting object might show inconsistencies.") + + def parse_Hrep(intro, data): + count = int(data[0][0]) + infinite_count = len([d for d in data[1:] if d[0] == '1' and all(c == '0' for c in d[1:])]) + if count - infinite_count != len(ieqs) + len(eqns): + # Upstream claims that nothing can be done about these + # cases/that they are features not bugs. Imho, cddlib is + # not really suitable for automatic parsing of its output, + # the implementation backed by doubles has not really been + # optimized for numerical stability, and makes some + # somewhat random numerical choices. (But I am not an + # expert in that field by any means.) + from warnings import warn + warn("This polyhedron data is numerically complicated; cdd could not convert between the inexact V and H representation without loss of data. The resulting object might show inconsistencies.") + + def try_init(rep): + if rep == "Vrep": + from .cdd_file_format import cdd_Vrepresentation + s = cdd_Vrepresentation(self._cdd_type, vertices, rays, lines) + else: + # We have to add a trivial inequality, in case the polyhedron is the universe. + new_ieqs = ieqs + ((1,) + tuple(0 for _ in range(self.ambient_dim())),) + + from .cdd_file_format import cdd_Hrepresentation + s = cdd_Hrepresentation(self._cdd_type, new_ieqs, eqns) + + s = self._run_cdd(s, '--redcheck', verbose=verbose) + s = self._run_cdd(s, '--repall', verbose=verbose) + Polyhedron_cdd._parse_block(s.splitlines(), 'V-representation', parse_Vrep) + Polyhedron_cdd._parse_block(s.splitlines(), 'H-representation', parse_Hrep) + self._init_from_cdd_output(s) + + from warnings import catch_warnings, simplefilter + + vertices, rays, lines = (tuple(x) for x in Vrep) + ieqs, eqns = (tuple(x) for x in Hrep) + + if not (vertices or rays or lines): + # cdd refuses to handle empty polyhedra. + self._init_empty_polyhedron() + return + + # We prefer the shorter representation. + # Note that for the empty polyhedron we prefer Hrepresentation. + prim = "Hrep" if len(ieqs) <= len(vertices) + len(rays) else "Vrep" + sec = "Vrep" if len(ieqs) <= len(vertices) + len(rays) else "Hrep" + + with catch_warnings(): + # Raise an error and try the other representation in case of + # numerical inconsistency. + simplefilter("error") + try: + try_init(prim) + except UserWarning: + simplefilter("once") # Only print the first warning. + try_init(sec) diff --git a/src/sage/geometry/polyhedron/backend_field.py b/src/sage/geometry/polyhedron/backend_field.py index d0f50782016..4ddf271143e 100644 --- a/src/sage/geometry/polyhedron/backend_field.py +++ b/src/sage/geometry/polyhedron/backend_field.py @@ -9,13 +9,13 @@ sage: p0 = (0, 0) sage: p1 = (1, 0) - sage: p2 = (1/2, AA(3).sqrt()/2) - sage: equilateral_triangle = Polyhedron([p0, p1, p2]) - sage: equilateral_triangle.vertices() + sage: p2 = (1/2, AA(3).sqrt()/2) # optional - sage.rings.number_field + sage: equilateral_triangle = Polyhedron([p0, p1, p2]) # optional - sage.rings.number_field + sage: equilateral_triangle.vertices() # optional - sage.rings.number_field (A vertex at (0, 0), A vertex at (1, 0), A vertex at (0.500000000000000?, 0.866025403784439?)) - sage: equilateral_triangle.inequalities() + sage: equilateral_triangle.inequalities() # optional - sage.rings.number_field (An inequality (-1, -0.5773502691896258?) x + 1 >= 0, An inequality (1, -0.5773502691896258?) x + 0 >= 0, An inequality (0, 1.154700538379252?) x + 0 >= 0) @@ -46,22 +46,22 @@ class Polyhedron_field(Polyhedron_base): EXAMPLES:: - sage: p = Polyhedron(vertices=[(0,0),(AA(2).sqrt(),0),(0,AA(3).sqrt())], + sage: p = Polyhedron(vertices=[(0,0),(AA(2).sqrt(),0),(0,AA(3).sqrt())], # optional - sage.rings.number_field ....: rays=[(1,1)], lines=[], backend='field', base_ring=AA) - sage: TestSuite(p).run() + sage: TestSuite(p).run() # optional - sage.rings.number_field TESTS:: - sage: K. = QuadraticField(3) - sage: p = Polyhedron([(0,0), (1,0), (1/2, sqrt3/2)]) - sage: TestSuite(p).run() + sage: K. = QuadraticField(3) # optional - sage.rings.number_field + sage: p = Polyhedron([(0,0), (1,0), (1/2, sqrt3/2)]) # optional - sage.rings.number_field + sage: TestSuite(p).run() # optional - sage.rings.number_field Check that :trac:`19013` is fixed:: - sage: K. = NumberField(x^2-x-1, embedding=1.618) - sage: P1 = Polyhedron([[0,1],[1,1],[1,-phi+1]]) - sage: P2 = Polyhedron(ieqs=[[-1,-phi,0]]) - sage: P1.intersection(P2) + sage: K. = NumberField(x^2-x-1, embedding=1.618) # optional - sage.rings.number_field + sage: P1 = Polyhedron([[0,1],[1,1],[1,-phi+1]]) # optional - sage.rings.number_field + sage: P2 = Polyhedron(ieqs=[[-1,-phi,0]]) # optional - sage.rings.number_field + sage: P1.intersection(P2) # optional - sage.rings.number_field The empty polyhedron in (Number Field in phi with defining polynomial x^2 - x - 1 with phi = 1.618033988749895?)^2 Check that :trac:`28654` is fixed:: @@ -83,10 +83,10 @@ def _is_zero(self, x): EXAMPLES:: - sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) - sage: p._is_zero(0) + sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # optional - sage.rings.number_field + sage: p._is_zero(0) # optional - sage.rings.number_field True - sage: p._is_zero(1/100000) + sage: p._is_zero(1/100000) # optional - sage.rings.number_field False """ return x == 0 @@ -105,10 +105,10 @@ def _is_nonneg(self, x): EXAMPLES:: - sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) - sage: p._is_nonneg(1) + sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # optional - sage.rings.number_field + sage: p._is_nonneg(1) # optional - sage.rings.number_field True - sage: p._is_nonneg(-1/100000) + sage: p._is_nonneg(-1/100000) # optional - sage.rings.number_field False """ return x >= 0 @@ -127,10 +127,10 @@ def _is_positive(self, x): EXAMPLES:: - sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) - sage: p._is_positive(1) + sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # optional - sage.rings.number_field + sage: p._is_positive(1) # optional - sage.rings.number_field True - sage: p._is_positive(0) + sage: p._is_positive(0) # optional - sage.rings.number_field False """ return x > 0 @@ -150,12 +150,12 @@ def _init_from_Vrepresentation_and_Hrepresentation(self, Vrep, Hrep): sage: from sage.geometry.polyhedron.parent import Polyhedra_field sage: from sage.geometry.polyhedron.backend_field import Polyhedron_field - sage: parent = Polyhedra_field(AA, 1, 'field') + sage: parent = Polyhedra_field(AA, 1, 'field') # optional - sage.rings.number_field sage: Vrep = [[[0], [1]], [], []] sage: Hrep = [[[0, 1], [1, -1]], []] - sage: p = Polyhedron_field(parent, Vrep, Hrep, - ....: Vrep_minimal=True, Hrep_minimal=True) # indirect doctest - sage: p + sage: p = Polyhedron_field(parent, Vrep, Hrep, # indirect doctest # optional - sage.rings.number_field + ....: Vrep_minimal=True, Hrep_minimal=True) + sage: p # optional - sage.rings.number_field A 1-dimensional polyhedron in AA^1 defined as the convex hull of 2 vertices """ self._init_Vrepresentation(*Vrep) @@ -234,12 +234,12 @@ def _init_Vrepresentation(self, vertices, rays, lines): sage: from sage.geometry.polyhedron.parent import Polyhedra_field sage: from sage.geometry.polyhedron.backend_field import Polyhedron_field - sage: parent = Polyhedra_field(AA, 1, 'field') + sage: parent = Polyhedra_field(AA, 1, 'field') # optional - sage.rings.number_field sage: Vrep = [[[0], [1]], [], []] sage: Hrep = [[[0, 1], [1, -1]], []] - sage: p = Polyhedron_field(parent, Vrep, Hrep, # indirect doctest + sage: p = Polyhedron_field(parent, Vrep, Hrep, # indirect doctest # optional - sage.rings.number_field ....: Vrep_minimal=True, Hrep_minimal=True) - sage: p.vertices_list() + sage: p.vertices_list() # optional - sage.rings.number_field [[0], [1]] """ self._Vrepresentation = [] @@ -258,13 +258,13 @@ def _init_Vrepresentation_backend(self, Vrep): EXAMPLES:: - sage: p = Polyhedron(vertices=[(0,1/sqrt(2)),(sqrt(2),0),(4,sqrt(5)/6)], + sage: p = Polyhedron(vertices=[(0,1/sqrt(2)),(sqrt(2),0),(4,sqrt(5)/6)], # optional - sage.rings.number_field ....: base_ring=AA, backend='field') # indirect doctest - sage: p.Hrepresentation() + sage: p.Hrepresentation() # optional - sage.rings.number_field (An inequality (-0.1582178750233332?, 1.097777812326429?) x + 0.2237538646678492? >= 0, An inequality (-0.1419794359520263?, -1.698172434277148?) x + 1.200789243901438? >= 0, An inequality (0.3001973109753594?, 0.600394621950719?) x - 0.4245431085692869? >= 0) - sage: p.Vrepresentation() + sage: p.Vrepresentation() # optional - sage.rings.number_field (A vertex at (0.?e-15, 0.707106781186548?), A vertex at (1.414213562373095?, 0), A vertex at (4.000000000000000?, 0.372677996249965?)) @@ -279,12 +279,12 @@ def _init_Hrepresentation(self, inequalities, equations): sage: from sage.geometry.polyhedron.parent import Polyhedra_field sage: from sage.geometry.polyhedron.backend_field import Polyhedron_field - sage: parent = Polyhedra_field(AA, 1, 'field') + sage: parent = Polyhedra_field(AA, 1, 'field') # optional - sage.rings.number_field sage: Vrep = [[[0], [1]], [], []] sage: Hrep = [[[0, 1], [1, -1]], []] - sage: p = Polyhedron_field(parent, Vrep, Hrep, # indirect doctest + sage: p = Polyhedron_field(parent, Vrep, Hrep, # indirect doctest # optional - sage.rings.number_field ....: Vrep_minimal=True, Hrep_minimal=True) - sage: p.inequalities_list() + sage: p.inequalities_list() # optional - sage.rings.number_field [[0, 1], [1, -1]] """ self._Hrepresentation = [] @@ -301,13 +301,13 @@ def _init_Hrepresentation_backend(self, Hrep): EXAMPLES:: - sage: p = Polyhedron(vertices=[(0,1/sqrt(2)),(sqrt(2),0),(4,sqrt(5)/6)], + sage: p = Polyhedron(vertices=[(0,1/sqrt(2)),(sqrt(2),0),(4,sqrt(5)/6)], # optional - sage.rings.number_field ....: base_ring=AA, backend='field') # indirect doctest - sage: p.Hrepresentation() + sage: p.Hrepresentation() # optional - sage.rings.number_field (An inequality (-0.1582178750233332?, 1.097777812326429?) x + 0.2237538646678492? >= 0, An inequality (-0.1419794359520263?, -1.698172434277148?) x + 1.200789243901438? >= 0, An inequality (0.3001973109753594?, 0.600394621950719?) x - 0.4245431085692869? >= 0) - sage: p.Vrepresentation() + sage: p.Vrepresentation() # optional - sage.rings.number_field (A vertex at (0.?e-15, 0.707106781186548?), A vertex at (1.414213562373095?, 0), A vertex at (4.000000000000000?, 0.372677996249965?)) @@ -320,13 +320,13 @@ def _init_empty_polyhedron(self): TESTS:: - sage: empty = Polyhedron(backend='field', base_ring=AA); empty + sage: empty = Polyhedron(backend='field', base_ring=AA); empty # optional - sage.rings.number_field The empty polyhedron in AA^0 - sage: empty.Vrepresentation() + sage: empty.Vrepresentation() # optional - sage.rings.number_field () - sage: empty.Hrepresentation() + sage: empty.Hrepresentation() # optional - sage.rings.number_field (An equation -1 == 0,) - sage: Polyhedron(vertices = [], backend='field') + sage: Polyhedron(vertices=[], backend='field') The empty polyhedron in QQ^0 sage: Polyhedron(backend='field')._init_empty_polyhedron() """ diff --git a/src/sage/geometry/polyhedron/backend_normaliz.py b/src/sage/geometry/polyhedron/backend_normaliz.py index e629fb58abe..d1f30e2d31f 100644 --- a/src/sage/geometry/polyhedron/backend_normaliz.py +++ b/src/sage/geometry/polyhedron/backend_normaliz.py @@ -48,12 +48,12 @@ def _number_field_elements_from_algebraics_list_of_lists_of_lists(listss, **kwds EXAMPLES:: - sage: rt2 = AA(sqrt(2)); rt2 + sage: rt2 = AA(sqrt(2)); rt2 # optional - sage.rings.number_field 1.414213562373095? - sage: rt3 = AA(sqrt(3)); rt3 + sage: rt3 = AA(sqrt(3)); rt3 # optional - sage.rings.number_field 1.732050807568878? sage: from sage.geometry.polyhedron.backend_normaliz import _number_field_elements_from_algebraics_list_of_lists_of_lists - sage: K, results, hom = _number_field_elements_from_algebraics_list_of_lists_of_lists([[[rt2], [1]], [[rt3]], [[1], []]]); results + sage: K, results, hom = _number_field_elements_from_algebraics_list_of_lists_of_lists([[[rt2], [1]], [[rt3]], [[1], []]]); results # optional - sage.rings.number_field [[[-a^3 + 3*a], [1]], [[-a^2 + 2]], [[1], []]] """ from sage.rings.qqbar import number_field_elements_from_algebraics @@ -172,7 +172,7 @@ class Polyhedron_normaliz(Polyhedron_base): Algebraic polyhedra:: - sage: P = Polyhedron(vertices=[[1], [sqrt(2)]], backend='normaliz', verbose=True) # optional - pynormaliz + sage: P = Polyhedron(vertices=[[1], [sqrt(2)]], backend='normaliz', verbose=True) # optional - pynormaliz # optional - sage.rings.number_field # ----8<---- Equivalent Normaliz input file ----8<---- amb_space 1 number_field min_poly (a^2 - 2) embedding [1.414213562373095 +/- 2.99e-16] @@ -183,16 +183,16 @@ class Polyhedron_normaliz(Polyhedron_base): (a) 1 # ----8<-------------------8<-------------------8<---- # Calling PyNormaliz.NmzCone(cone=[], number_field=['a^2 - 2', 'a', '[1.414213562373095 +/- 2.99e-16]'], subspace=[], vertices=[[1, 1], [[[0, 1], [1, 1]], 1]]) - sage: P # optional - pynormaliz + sage: P # optional - pynormaliz # optional - sage.rings.number_field A 1-dimensional polyhedron in (Symbolic Ring)^1 defined as the convex hull of 2 vertices - sage: P.vertices() # optional - pynormaliz + sage: P.vertices() # optional - pynormaliz # optional - sage.rings.number_field (A vertex at (1), A vertex at (sqrt(2))) - sage: P = polytopes.icosahedron(exact=True, backend='normaliz') # optional - pynormaliz - sage: P # optional - pynormaliz + sage: P = polytopes.icosahedron(exact=True, backend='normaliz') # optional - pynormaliz # optional - sage.rings.number_field + sage: P # optional - pynormaliz # optional - sage.rings.number_field A 3-dimensional polyhedron in (Number Field in sqrt5 with defining polynomial x^2 - 5 with sqrt5 = 2.236067977499790?)^3 defined as the convex hull of 12 vertices - sage: x = polygen(ZZ); P = Polyhedron(vertices=[[sqrt(2)], [AA.polynomial_root(x^3-2, RIF(0,3))]], backend='normaliz', verbose=True) # optional - pynormaliz + sage: x = polygen(ZZ); P = Polyhedron(vertices=[[sqrt(2)], [AA.polynomial_root(x^3-2, RIF(0,3))]], backend='normaliz', verbose=True) # optional - pynormaliz # optional - sage.rings.number_field # ----8<---- Equivalent Normaliz input file ----8<---- amb_space 1 number_field min_poly (a^6 - 2) embedding [1.122462048309373 +/- 5.38e-16] @@ -203,9 +203,9 @@ class Polyhedron_normaliz(Polyhedron_base): (a^2) 1 # ----8<-------------------8<-------------------8<---- # Calling PyNormaliz.NmzCone(cone=[], number_field=['a^6 - 2', 'a', '[1.122462048309373 +/- 5.38e-16]'], subspace=[], vertices=[[[[0, 1], [0, 1], [0, 1], [1, 1], [0, 1], [0, 1]], 1], [[[0, 1], [0, 1], [1, 1], [0, 1], [0, 1], [0, 1]], 1]]) - sage: P # optional - pynormaliz + sage: P # optional - pynormaliz # optional - sage.rings.number_field A 1-dimensional polyhedron in (Symbolic Ring)^1 defined as the convex hull of 2 vertices - sage: P.vertices() # optional - pynormaliz + sage: P.vertices() # optional - pynormaliz # optional - sage.rings.number_field (A vertex at (2^(1/3)), A vertex at (sqrt(2))) """ @@ -256,20 +256,20 @@ def _nmz_result(self, normaliz_cone, property): NormalizError: Some error in the normaliz input data detected: Unknown ConeProperty... sage: x = polygen(QQ, 'x') - sage: K. = NumberField(x^3 - 3, embedding=AA(3)**(1/3)) - sage: p = Polyhedron(vertices=[(0,0),(1,1),(a,3),(-1,a**2)], rays=[(-1,-a)], backend='normaliz') # optional - pynormaliz - sage: sorted(p._nmz_result(p._normaliz_cone, 'VerticesOfPolyhedron')) # optional - pynormaliz + sage: K. = NumberField(x^3 - 3, embedding=AA(3)**(1/3)) # optional - sage.rings.number_field + sage: p = Polyhedron(vertices=[(0,0),(1,1),(a,3),(-1,a**2)], rays=[(-1,-a)], backend='normaliz') # optional - pynormaliz # optional - sage.rings.number_field + sage: sorted(p._nmz_result(p._normaliz_cone, 'VerticesOfPolyhedron')) # optional - pynormaliz # optional - sage.rings.number_field [[-1, a^2, 1], [1, 1, 1], [a, 3, 1]] - sage: triangulation_generators = p._nmz_result(p._normaliz_cone, 'Triangulation')[1] # optional - pynormaliz - sage: sorted(triangulation_generators) # optional - pynormaliz + sage: triangulation_generators = p._nmz_result(p._normaliz_cone, 'Triangulation')[1] # optional - pynormaliz # optional - sage.rings.number_field + sage: sorted(triangulation_generators) # optional - pynormaliz # optional - sage.rings.number_field [[-a^2, -3, 0], [-1, a^2, 1], [0, 0, 1], [1, 1, 1], [a, 3, 1]] - sage: p._nmz_result(p._normaliz_cone, 'AffineDim') == 2 # optional - pynormaliz + sage: p._nmz_result(p._normaliz_cone, 'AffineDim') == 2 # optional - pynormaliz # optional - sage.rings.number_field True - sage: p._nmz_result(p._normaliz_cone, 'EmbeddingDim') == 3 # optional - pynormaliz + sage: p._nmz_result(p._normaliz_cone, 'EmbeddingDim') == 3 # optional - pynormaliz # optional - sage.rings.number_field True - sage: p._nmz_result(p._normaliz_cone, 'ExtremeRays') # optional - pynormaliz + sage: p._nmz_result(p._normaliz_cone, 'ExtremeRays') # optional - pynormaliz # optional - sage.rings.number_field [[-1/3*a^2, -1, 0]] - sage: p._nmz_result(p._normaliz_cone, 'MaximalSubspace') # optional - pynormaliz + sage: p._nmz_result(p._normaliz_cone, 'MaximalSubspace') # optional - pynormaliz # optional - sage.rings.number_field [] """ def rational_handler(list): @@ -314,7 +314,7 @@ def _convert_to_pynormaliz(x): TESTS:: - sage: K. = QuadraticField(2) + sage: K. = QuadraticField(2) # optional - sage.rings.number_field sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz as Pn sage: Pn._convert_to_pynormaliz(17) 17 @@ -326,9 +326,9 @@ def _convert_to_pynormaliz(x): [[28, 5]] sage: Pn._convert_to_pynormaliz(28901824309821093821093812093810928309183091832091/5234573685674784567853456543456456786543456765) [[28901824309821093821093812093810928309183091832091, 5234573685674784567853456543456456786543456765]] - sage: Pn._convert_to_pynormaliz(7 + sqrt2) + sage: Pn._convert_to_pynormaliz(7 + sqrt2) # optional - sage.rings.number_field [[7, 1], [1, 1]] - sage: Pn._convert_to_pynormaliz(7/2 + sqrt2) + sage: Pn._convert_to_pynormaliz(7/2 + sqrt2) # optional - sage.rings.number_field [[7, 2], [1, 1]] sage: Pn._convert_to_pynormaliz([[1, 2], (3, 4)]) [[1, 2], [3, 4]] @@ -336,8 +336,8 @@ def _convert_to_pynormaliz(x): Check that :trac:`29836` is fixed:: sage: P = polytopes.simplex(backend='normaliz') # optional - pynormaliz - sage: K. = QuadraticField(2) # optional - pynormaliz - sage: P.dilation(sqrt2) # optional - pynormaliz + sage: K. = QuadraticField(2) # optional - pynormaliz # optional - sage.rings.number_field + sage: P.dilation(sqrt2) # optional - pynormaliz # optional - sage.rings.number_field A 3-dimensional polyhedron in (Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.41...)^4 defined as the convex hull of 4 vertices """ def _QQ_pair(x): @@ -370,16 +370,16 @@ def _init_from_normaliz_data(self, data, normaliz_field=None, verbose=False): [[0, -1, 2], [0, 2, -1]] sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz # optional - pynormaliz - sage: from sage.rings.qqbar import AA # optional - pynormaliz - sage: from sage.rings.number_field.number_field import QuadraticField # optional - pynormaliz + sage: from sage.rings.qqbar import AA # optional - pynormaliz # optional - sage.rings.number_field + sage: from sage.rings.number_field.number_field import QuadraticField # optional - pynormaliz # optional - sage.rings.number_field sage: data = {'number_field': ['a^2 - 2', 'a', '[1.4 +/- 0.1]'], # optional - pynormaliz ....: 'inhom_inequalities': [[-1, 2, 0], [0, 0, 1], [2, -1, 0]]} sage: from sage.geometry.polyhedron.parent import Polyhedra_normaliz # optional - pynormaliz - sage: parent = Polyhedra_normaliz(AA, 2, 'normaliz') # optional - pynormaliz - sage: Polyhedron_normaliz(parent, None, None, normaliz_data=data, # indirect doctest, optional - pynormaliz + sage: parent = Polyhedra_normaliz(AA, 2, 'normaliz') # optional - pynormaliz # optional - sage.rings.number_field + sage: Polyhedron_normaliz(parent, None, None, normaliz_data=data, # indirect doctest, optional - pynormaliz # optional - sage.rings.number_field ....: normaliz_field=QuadraticField(2)) A 2-dimensional polyhedron in AA^2 defined as the convex hull of 1 vertex and 2 rays - sage: _.inequalities_list() # optional - pynormaliz + sage: _.inequalities_list() # optional - pynormaliz # optional - sage.rings.number_field [[0, -1/2, 1], [0, 2, -1]] """ if normaliz_field is None: @@ -434,10 +434,10 @@ def _is_zero(self, x): EXAMPLES:: - sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) - sage: p._is_zero(0) + sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # optional - sage.rings.number_field + sage: p._is_zero(0) # optional - sage.rings.number_field True - sage: p._is_zero(1/100000) + sage: p._is_zero(1/100000) # optional - sage.rings.number_field False """ return x == 0 @@ -456,10 +456,10 @@ def _is_nonneg(self, x): EXAMPLES:: - sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) - sage: p._is_nonneg(1) + sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # optional - sage.rings.number_field + sage: p._is_nonneg(1) # optional - sage.rings.number_field True - sage: p._is_nonneg(-1/100000) + sage: p._is_nonneg(-1/100000) # optional - sage.rings.number_field False """ return x >= 0 @@ -478,10 +478,10 @@ def _is_positive(self, x): EXAMPLES:: - sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) - sage: p._is_positive(1) + sage: p = Polyhedron([(sqrt(3),sqrt(2))], base_ring=AA) # optional - sage.rings.number_field + sage: p._is_positive(1) # optional - sage.rings.number_field True - sage: p._is_positive(0) + sage: p._is_positive(0) # optional - sage.rings.number_field False """ return x > 0 @@ -596,14 +596,14 @@ def _init_from_Hrepresentation(self, ieqs, eqns, minimize=True, verbose=False): Check that :trac:`30248` is fixed, that maps as input works:: - sage: q = Polyhedron(backend='normaliz', base_ring=AA, # optional - pynormaliz + sage: q = Polyhedron(backend='normaliz', base_ring=AA, # optional - pynormaliz # optional - sage.rings.number_field ....: rays=[(0, 0, 1), (0, 1, -1), (1, 0, -1)]) sage: make_new_Hrep = lambda h: tuple(x if i == 0 else -1*x for i, x in enumerate(h._vector)) - sage: new_inequalities = map(make_new_Hrep, q.inequality_generator()) # optional - pynormaliz - sage: new_equations = map(make_new_Hrep, q.equation_generator()) # optional - pynormaliz - sage: parent = q.parent() # optional - pynormaliz - sage: new_q = parent.element_class(parent,None,[new_inequalities,new_equations]) # optional - pynormaliz - sage: new_q # optional - pynormaliz + sage: new_inequalities = map(make_new_Hrep, q.inequality_generator()) # optional - pynormaliz # optional - sage.rings.number_field + sage: new_equations = map(make_new_Hrep, q.equation_generator()) # optional - pynormaliz # optional - sage.rings.number_field + sage: parent = q.parent() # optional - pynormaliz # optional - sage.rings.number_field + sage: new_q = parent.element_class(parent,None,[new_inequalities,new_equations]) # optional - pynormaliz # optional - sage.rings.number_field + sage: new_q # optional - pynormaliz # optional - sage.rings.number_field A 3-dimensional polyhedron in AA^3 defined as the convex hull of 1 vertex and 3 rays """ @@ -929,15 +929,15 @@ def _compute_nmz_data_lists_and_field(self, data_lists, convert_QQ, convert_NF): sage: p._compute_nmz_data_lists_and_field([[[AA(1)]], [[1/2]]], # optional - pynormaliz ....: convert_QQ, convert_NF) (([[1000]], [[500]]), Rational Field) - sage: p._compute_nmz_data_lists_and_field([[[AA(sqrt(2))]], [[1/2]]], # optional - pynormaliz + sage: p._compute_nmz_data_lists_and_field([[[AA(sqrt(2))]], [[1/2]]], # optional - pynormaliz # optional - sage.rings.number_field ....: convert_QQ, convert_NF) ([[[a]], [[1/2]]], Number Field in a with defining polynomial y^2 - 2 with a = 1.414213562373095?) TESTS:: - sage: K. = QuadraticField(-5) - sage: p = Polyhedron(vertices=[(a,1/2),(2,0),(4,5/6)], # indirect doctest # optional - pynormaliz + sage: K. = QuadraticField(-5) # optional - sage.rings.number_field + sage: p = Polyhedron(vertices=[(a,1/2),(2,0),(4,5/6)], # indirect doctest # optional - pynormaliz # optional - sage.rings.number_field ....: base_ring=K, backend='normaliz') Traceback (most recent call last): ... @@ -945,10 +945,10 @@ def _compute_nmz_data_lists_and_field(self, data_lists, convert_QQ, convert_NF): Checks that :trac:`30248` is fixed:: - sage: q = Polyhedron(backend='normaliz', base_ring=AA, # indirect doctest # optional - pynormaliz + sage: q = Polyhedron(backend='normaliz', base_ring=AA, # indirect doctest # optional - pynormaliz # optional - sage.rings.number_field ....: rays=[(0, 0, 1), (0, 1, -1), (1, 0, -1)]); q A 3-dimensional polyhedron in AA^3 defined as the convex hull of 1 vertex and 3 rays - sage: -q # optional - pynormaliz + sage: -q # optional - pynormaliz # optional - sage.rings.number_field A 3-dimensional polyhedron in AA^3 defined as the convex hull of 1 vertex and 3 rays """ from sage.categories.number_fields import NumberFields @@ -1079,7 +1079,7 @@ def _number_field_triple(normaliz_field): sage: from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz as Pn sage: Pn._number_field_triple(QQ) is None True - sage: Pn._number_field_triple(QuadraticField(5)) + sage: Pn._number_field_triple(QuadraticField(5)) # optional - sage.rings.number_field ['a^2 - 5', 'a', '[2.236067977499789 +/- 8.06e-16]'] """ from sage.rings.real_arb import RealBallField @@ -1328,10 +1328,10 @@ def __setstate__(self, state): sage: P2 == P # optional - pynormaliz True - sage: P = polytopes.dodecahedron(backend='normaliz') # optional - pynormaliz - sage: P1 = loads(dumps(P)) # optional - pynormaliz - sage: P2 = Polyhedron_normaliz(P1.parent(), None, None, P1._normaliz_cone, normaliz_field=P1._normaliz_field) # optional - pynormaliz - sage: P == P2 # optional - pynormaliz + sage: P = polytopes.dodecahedron(backend='normaliz') # optional - pynormaliz # optional - sage.rings.number_field + sage: P1 = loads(dumps(P)) # optional - pynormaliz # optional - sage.rings.number_field + sage: P2 = Polyhedron_normaliz(P1.parent(), None, None, P1._normaliz_cone, normaliz_field=P1._normaliz_field) # optional - pynormaliz # optional - sage.rings.number_field + sage: P == P2 # optional - pynormaliz # optional - sage.rings.number_field True Test that :trac:`31820` is fixed:: @@ -1497,8 +1497,8 @@ def _volume_normaliz(self, measure='euclidean'): Check that :trac:`28872` is fixed:: - sage: P = polytopes.dodecahedron(backend='normaliz') # optional - pynormaliz - sage: P.volume(measure='induced_lattice') # optional - pynormaliz + sage: P = polytopes.dodecahedron(backend='normaliz') # optional - pynormaliz # optional - sage.rings.number_field + sage: P.volume(measure='induced_lattice') # optional - pynormaliz # optional - sage.rings.number_field -1056*sqrt5 + 2400 Some sanity checks that the ambient volume works correctly:: diff --git a/src/sage/geometry/polyhedron/base.py b/src/sage/geometry/polyhedron/base.py index d50d33b1053..e2e6772defb 100644 --- a/src/sage/geometry/polyhedron/base.py +++ b/src/sage/geometry/polyhedron/base.py @@ -471,39 +471,6 @@ def set_adjacent(h1, h2): M.set_immutable() return M - def _vertex_adjacency_matrix(self): - """ - Compute the vertex adjacency matrix in case it has not been - computed during initialization. - - EXAMPLES:: - - sage: p = Polyhedron(vertices=[(0,0),(1,0),(0,1)]) - sage: p._vertex_adjacency_matrix() - [0 1 1] - [1 0 1] - [1 1 0] - """ - # TODO: This implementation computes the whole face lattice, - # which is much more information than necessary. - M = matrix(ZZ, self.n_Vrepresentation(), self.n_Vrepresentation(), 0) - - def set_adjacent(v1, v2): - if v1 is v2: - return - i = v1.index() - j = v2.index() - M[i, j] = 1 - M[j, i] = 1 - - face_lattice = self.face_lattice() - for face in face_lattice: - Vrep = face.ambient_Vrepresentation() - if len(Vrep) == 2: - set_adjacent(Vrep[0], Vrep[1]) - M.set_immutable() - return M - def _delete(self): """ Delete this polyhedron. @@ -643,13 +610,13 @@ def change_ring(self, base_ring, backend=None): ... TypeError: cannot change the base ring to the Integer Ring - sage: P = polytopes.regular_polygon(3); P + sage: P = polytopes.regular_polygon(3); P # optional - sage.rings.number_field A 2-dimensional polyhedron in AA^2 defined as the convex hull of 3 vertices - sage: P.vertices() + sage: P.vertices() # optional - sage.rings.number_field (A vertex at (0.?e-16, 1.000000000000000?), A vertex at (0.866025403784439?, -0.500000000000000?), A vertex at (-0.866025403784439?, -0.500000000000000?)) - sage: P.change_ring(QQ) + sage: P.change_ring(QQ) # optional - sage.rings.number_field Traceback (most recent call last): ... TypeError: cannot change the base ring to the Rational Field @@ -662,11 +629,11 @@ def change_ring(self, base_ring, backend=None): base ring from an exact ring into ``RDF`` may cause a loss of data:: - sage: P = Polyhedron([[2/3,0],[6666666666666667/10^16,0]], base_ring=AA); P + sage: P = Polyhedron([[2/3,0],[6666666666666667/10^16,0]], base_ring=AA); P # optional - sage.rings.number_field A 1-dimensional polyhedron in AA^2 defined as the convex hull of 2 vertices - sage: Q = P.change_ring(RDF); Q + sage: Q = P.change_ring(RDF); Q # optional - sage.rings.number_field A 0-dimensional polyhedron in RDF^2 defined as the convex hull of 1 vertex - sage: P.n_vertices() == Q.n_vertices() + sage: P.n_vertices() == Q.n_vertices() # optional - sage.rings.number_field False """ from sage.categories.rings import Rings @@ -2786,7 +2753,7 @@ def vertex_adjacency_matrix(self): sage: P.adjacency_matrix().is_immutable() True """ - return self._vertex_adjacency_matrix() + return self.combinatorial_polyhedron().vertex_adjacency_matrix() adjacency_matrix = vertex_adjacency_matrix @@ -3636,8 +3603,8 @@ def is_compact(self): EXAMPLES:: - sage: p = polytopes.icosahedron() - sage: p.is_compact() + sage: p = polytopes.icosahedron() # optional - sage.rings.number_field + sage: p.is_compact() # optional - sage.rings.number_field True sage: p = Polyhedron(ieqs = [[0,1,0,0],[0,0,1,0],[0,0,0,1],[1,-1,0,0]]) sage: p.is_compact() @@ -3832,8 +3799,8 @@ def is_pyramid(self, certificate=False): True sage: P.is_pyramid(certificate=True) (True, A vertex at (1, 0, 0, 0)) - sage: egyptian_pyramid = polytopes.regular_polygon(4).pyramid() - sage: egyptian_pyramid.is_pyramid() + sage: egyptian_pyramid = polytopes.regular_polygon(4).pyramid() # optional - sage.rings.number_field + sage: egyptian_pyramid.is_pyramid() # optional - sage.rings.number_field True sage: Q = polytopes.octahedron() sage: Q.is_pyramid() @@ -4221,7 +4188,12 @@ def _test_gale_transform(self, tester=None, **options): g = self.gale_transform() P = gale_transform_to_polytope(g, base_ring=self.base_ring(), backend=self.backend()) - tester.assertTrue(self.is_combinatorially_isomorphic(P)) + try: + import sage.graphs.graph + except ImportError: + pass + else: + tester.assertTrue(self.is_combinatorially_isomorphic(P)) @cached_method def normal_fan(self, direction='inner'): @@ -5332,28 +5304,28 @@ def linear_transformation(self, linear_transf, new_base_ring=None): sage: b3_proj = proj_mat * b3; b3_proj A 3-dimensional polyhedron in ZZ^4 defined as the convex hull of 5 vertices - sage: square = polytopes.regular_polygon(4) - sage: square.vertices_list() + sage: square = polytopes.regular_polygon(4) # optional - sage.rings.number_field + sage: square.vertices_list() # optional - sage.rings.number_field [[0, -1], [1, 0], [-1, 0], [0, 1]] - sage: transf = matrix([[1,1],[0,1]]) - sage: sheared = transf * square - sage: sheared.vertices_list() + sage: transf = matrix([[1,1],[0,1]]) # optional - sage.rings.number_field + sage: sheared = transf * square # optional - sage.rings.number_field + sage: sheared.vertices_list() # optional - sage.rings.number_field [[-1, -1], [1, 0], [-1, 0], [1, 1]] - sage: sheared == square.linear_transformation(transf) + sage: sheared == square.linear_transformation(transf) # optional - sage.rings.number_field True Specifying the new base ring may avoid coercion failure:: - sage: K. = QuadraticField(2) - sage: L. = QuadraticField(3) - sage: P = polytopes.cube()*sqrt2 - sage: M = matrix([[sqrt3, 0, 0], [0, sqrt3, 0], [0, 0, 1]]) - sage: P.linear_transformation(M, new_base_ring=K.composite_fields(L)[0]) + sage: K. = QuadraticField(2) # optional - sage.rings.number_field + sage: L. = QuadraticField(3) # optional - sage.rings.number_field + sage: P = polytopes.cube()*sqrt2 # optional - sage.rings.number_field + sage: M = matrix([[sqrt3, 0, 0], [0, sqrt3, 0], [0, 0, 1]]) # optional - sage.rings.number_field + sage: P.linear_transformation(M, new_base_ring=K.composite_fields(L)[0]) # optional - sage.rings.number_field A 3-dimensional polyhedron in (Number Field in sqrt2sqrt3 with defining polynomial x^4 - 10*x^2 + 1 with sqrt2sqrt3 = 0.3178372451957823?)^3 defined as the convex hull of 8 vertices Linear transformation without specified new base ring fails in this case:: - sage: M*P + sage: M*P # optional - sage.rings.number_field Traceback (most recent call last): ... TypeError: unsupported operand parent(s) for *: 'Full MatrixSpace of 3 by 3 dense matrices over Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878?' and 'Full MatrixSpace of 3 by 8 dense matrices over Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095?' @@ -5373,7 +5345,7 @@ def linear_transformation(self, linear_transf, new_base_ring=None): A 3-dimensional polyhedron in RDF^4 defined as the convex hull of 5 vertices sage: (1/1 * proj_mat) * b3 A 3-dimensional polyhedron in QQ^4 defined as the convex hull of 5 vertices - sage: (AA(2).sqrt() * proj_mat) * b3 + sage: (AA(2).sqrt() * proj_mat) * b3 # optional - sage.rings.number_field A 3-dimensional polyhedron in AA^4 defined as the convex hull of 5 vertices Check that zero-matrices act correctly:: @@ -5964,15 +5936,15 @@ def stack(self, face, position=None): (1, 9, 16, 9, 1) sage: stacked_square_large = cube.stack(square_face,position=10) - sage: hexaprism = polytopes.regular_polygon(6).prism() - sage: hexaprism.f_vector() + sage: hexaprism = polytopes.regular_polygon(6).prism() # optional - sage.rings.number_field + sage: hexaprism.f_vector() # optional - sage.rings.number_field (1, 12, 18, 8, 1) - sage: square_face = hexaprism.faces(2)[2] - sage: stacked_hexaprism = hexaprism.stack(square_face) - sage: stacked_hexaprism.f_vector() + sage: square_face = hexaprism.faces(2)[2] # optional - sage.rings.number_field + sage: stacked_hexaprism = hexaprism.stack(square_face) # optional - sage.rings.number_field + sage: stacked_hexaprism.f_vector() # optional - sage.rings.number_field (1, 13, 22, 11, 1) - sage: hexaprism.stack(square_face,position=4) + sage: hexaprism.stack(square_face,position=4) # optional - sage.rings.number_field Traceback (most recent call last): ... ValueError: the chosen position is too large @@ -6319,7 +6291,7 @@ def _test_lawrence(self, tester=None, **options): Check that :trac:`28725` is fixed:: - sage: polytopes.regular_polygon(3)._test_lawrence() + sage: polytopes.regular_polygon(3)._test_lawrence() # optional - sage.rings.number_field Check that :trac:`30293` is fixed:: @@ -6370,12 +6342,17 @@ def _test_lawrence(self, tester=None, **options): with warnings.catch_warnings(): warnings.simplefilter("error") try: + from sage.rings.real_double_field import RDF + two = RDF(2.0) # Implicitly checks :trac:`30328`. - R = self.lawrence_extension(2.0*v - self.center()) + R = self.lawrence_extension(two * v - self.center()) tester.assertEqual(self.dim() + 1, R.dim()) tester.assertEqual(self.n_vertices() + 2, R.n_vertices()) tester.assertTrue(Q.is_combinatorially_isomorphic(R)) + except ImportError: + # RDF not available + pass except UserWarning: # Data is numerically complicated. pass @@ -6446,8 +6423,8 @@ def barycentric_subdivision(self, subdivision_frac=None): sage: P.barycentric_subdivision() A 2-dimensional polyhedron in QQ^3 defined as the convex hull of 6 vertices - sage: P = polytopes.regular_polygon(4, base_ring=QQ) - sage: P.barycentric_subdivision() + sage: P = polytopes.regular_polygon(4, base_ring=QQ) # optional - sage.rings.number_field + sage: P.barycentric_subdivision() # optional - sage.rings.number_field A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 8 vertices @@ -6663,31 +6640,31 @@ def hasse_diagram(self): EXAMPLES:: - sage: P = polytopes.regular_polygon(4).pyramid() - sage: D = P.hasse_diagram(); D + sage: P = polytopes.regular_polygon(4).pyramid() # optional - sage.rings.number_field + sage: D = P.hasse_diagram(); D # optional - sage.rings.number_field Digraph on 20 vertices - sage: D.degree_polynomial() + sage: D.degree_polynomial() # optional - sage.rings.number_field x^5 + x^4*y + x*y^4 + y^5 + 4*x^3*y + 8*x^2*y^2 + 4*x*y^3 Faces of an mutable polyhedron are not hashable. Hence those are not suitable as vertices of the hasse diagram. Use the combinatorial polyhedron instead:: - sage: P = polytopes.regular_polygon(4).pyramid() - sage: parent = P.parent() - sage: parent = parent.change_ring(QQ, backend='ppl') - sage: Q = parent._element_constructor_(P, mutable=True) - sage: Q.hasse_diagram() + sage: P = polytopes.regular_polygon(4).pyramid() # optional - sage.rings.number_field + sage: parent = P.parent() # optional - sage.rings.number_field + sage: parent = parent.change_ring(QQ, backend='ppl') # optional - sage.rings.number_field + sage: Q = parent._element_constructor_(P, mutable=True) # optional - sage.rings.number_field + sage: Q.hasse_diagram() # optional - sage.rings.number_field Traceback (most recent call last): ... TypeError: mutable polyhedra are unhashable - sage: C = Q.combinatorial_polyhedron() - sage: D = C.hasse_diagram() - sage: set(D.vertices()) == set(range(20)) + sage: C = Q.combinatorial_polyhedron() # optional - sage.rings.number_field + sage: D = C.hasse_diagram() # optional - sage.rings.number_field + sage: set(D.vertices()) == set(range(20)) # optional - sage.rings.number_field True sage: def index_to_combinatorial_face(n): ....: return C.face_by_face_lattice_index(n) - sage: D.relabel(index_to_combinatorial_face, inplace=True) - sage: D.vertices() + sage: D.relabel(index_to_combinatorial_face, inplace=True) # optional - sage.rings.number_field + sage: D.vertices() # optional - sage.rings.number_field [A -1-dimensional face of a 3-dimensional combinatorial polyhedron, A 0-dimensional face of a 3-dimensional combinatorial polyhedron, A 0-dimensional face of a 3-dimensional combinatorial polyhedron, @@ -6708,7 +6685,7 @@ def hasse_diagram(self): A 2-dimensional face of a 3-dimensional combinatorial polyhedron, A 2-dimensional face of a 3-dimensional combinatorial polyhedron, A 3-dimensional face of a 3-dimensional combinatorial polyhedron] - sage: D.degree_polynomial() + sage: D.degree_polynomial() # optional - sage.rings.number_field x^5 + x^4*y + x*y^4 + y^5 + 4*x^3*y + 8*x^2*y^2 + 4*x*y^3 """ @@ -7374,8 +7351,13 @@ def _test_combinatorial_face_as_combinatorial_polyhedron(self, tester=None, **op D2 = f2.as_combinatorial_polyhedron(quotient=True).dual() D1._test_bitsets(tester, **options) D2._test_bitsets(tester, **options) - tester.assertTrue(P.combinatorial_polyhedron().vertex_facet_graph().is_isomorphic(D1.vertex_facet_graph())) - tester.assertTrue(P.combinatorial_polyhedron().vertex_facet_graph().is_isomorphic(D2.vertex_facet_graph())) + try: + import sage.graphs.graph + except ImportError: + pass + else: + tester.assertTrue(P.combinatorial_polyhedron().vertex_facet_graph().is_isomorphic(D1.vertex_facet_graph())) + tester.assertTrue(P.combinatorial_polyhedron().vertex_facet_graph().is_isomorphic(D2.vertex_facet_graph())) @cached_method(do_pickle=True) def f_vector(self, num_threads=None, parallelization_depth=None): @@ -7915,7 +7897,7 @@ def _test_pyramid(self, tester=None, **options): TESTS: - sage: polytopes.regular_polygon(4)._test_pyramid() + sage: polytopes.regular_polygon(4)._test_pyramid() # optional - sage.rings.number_field """ if tester is None: tester = self._tester(**options) @@ -7955,7 +7937,12 @@ def check_pyramid_certificate(P, cert): tester.assertTrue(b) check_pyramid_certificate(polar_pyr, cert) - tester.assertTrue(pyr_polar.is_combinatorially_isomorphic(pyr_polar)) + try: + import sage.graphs.graph + except ImportError: + pass + else: + tester.assertTrue(pyr_polar.is_combinatorially_isomorphic(pyr_polar)) # Basic properties of the pyramid. @@ -8179,10 +8166,10 @@ def one_point_suspension(self, vertex): sage: ops_cube.f_vector() (1, 9, 24, 24, 9, 1) - sage: pentagon = polytopes.regular_polygon(5) - sage: v = pentagon.vertices()[0] - sage: ops_pentagon = pentagon.one_point_suspension(v) - sage: ops_pentagon.f_vector() + sage: pentagon = polytopes.regular_polygon(5) # optional - sage.rings.number_field + sage: v = pentagon.vertices()[0] # optional - sage.rings.number_field + sage: ops_pentagon = pentagon.one_point_suspension(v) # optional - sage.rings.number_field + sage: ops_pentagon.f_vector() # optional - sage.rings.number_field (1, 6, 12, 8, 1) It works with a polyhedral face as well:: @@ -8229,10 +8216,10 @@ def face_split(self, face): EXAMPLES:: - sage: pentagon = polytopes.regular_polygon(5) - sage: f = pentagon.faces(1)[0] - sage: fsplit_pentagon = pentagon.face_split(f) - sage: fsplit_pentagon.f_vector() + sage: pentagon = polytopes.regular_polygon(5) # optional - sage.rings.number_field + sage: f = pentagon.faces(1)[0] # optional - sage.rings.number_field + sage: fsplit_pentagon = pentagon.face_split(f) # optional - sage.rings.number_field + sage: fsplit_pentagon.f_vector() # optional - sage.rings.number_field (1, 7, 14, 9, 1) TESTS: @@ -8307,7 +8294,7 @@ def render_solid(self, **kwds): sage: p = polytopes.hypercube(3) sage: p_solid = p.render_solid(opacity = .7) sage: type(p_solid) - + """ proj = self.projection() if self.ambient_dim() == 3: @@ -8611,13 +8598,13 @@ def volume(self, measure='ambient', engine='auto', **kwds): If the base ring is exact, the answer is exact:: - sage: P5 = polytopes.regular_polygon(5) - sage: P5.volume() + sage: P5 = polytopes.regular_polygon(5) # optional - sage.rings.number_field + sage: P5.volume() # optional - sage.rings.number_field 2.377641290737884? - sage: polytopes.icosahedron().volume() + sage: polytopes.icosahedron().volume() # optional - sage.rings.number_field 5/12*sqrt5 + 5/4 - sage: numerical_approx(_) # abs tol 1e9 + sage: numerical_approx(_) # abs tol 1e9 # optional - sage.rings.number_field 2.18169499062491 When considering lower-dimensional polytopes, we can ask for the @@ -8635,20 +8622,20 @@ def volume(self, measure='ambient', engine='auto', **kwds): sage: P.volume(measure='induced_rational') # optional -- latte_int 1 - sage: S = polytopes.regular_polygon(6); S + sage: S = polytopes.regular_polygon(6); S # optional - sage.rings.number_field A 2-dimensional polyhedron in AA^2 defined as the convex hull of 6 vertices - sage: edge = S.faces(1)[4].as_polyhedron() - sage: edge.vertices() + sage: edge = S.faces(1)[4].as_polyhedron() # optional - sage.rings.number_field + sage: edge.vertices() # optional - sage.rings.number_field (A vertex at (0.866025403784439?, 1/2), A vertex at (0, 1)) - sage: edge.volume() + sage: edge.volume() # optional - sage.rings.number_field 0 - sage: edge.volume(measure='induced') + sage: edge.volume(measure='induced') # optional - sage.rings.number_field 1 sage: P = Polyhedron(backend='normaliz',vertices=[[1,0,0],[0,0,1],[-1,1,1],[-1,2,0]]) # optional - pynormaliz sage: P.volume() # optional - pynormaliz 0 - sage: P.volume(measure='induced') # optional - pynormaliz + sage: P.volume(measure='induced') # optional - pynormaliz # optional - sage.rings.number_field 2.598076211353316? sage: P.volume(measure='induced',engine='normaliz') # optional - pynormaliz 2.598076211353316 @@ -8665,12 +8652,12 @@ def volume(self, measure='ambient', engine='auto', **kwds): sage: P.volume(measure='induced_lattice',engine='latte') # optional - latte_int 3 - sage: Dexact = polytopes.dodecahedron() - sage: v = Dexact.faces(2)[0].as_polyhedron().volume(measure='induced', engine='internal'); v + sage: Dexact = polytopes.dodecahedron() # optional - sage.rings.number_field + sage: v = Dexact.faces(2)[0].as_polyhedron().volume(measure='induced', engine='internal'); v # optional - sage.rings.number_field 1.53406271079097? - sage: v = Dexact.faces(2)[4].as_polyhedron().volume(measure='induced', engine='internal'); v + sage: v = Dexact.faces(2)[4].as_polyhedron().volume(measure='induced', engine='internal'); v # optional - sage.rings.number_field 1.53406271079097? - sage: RDF(v) # abs tol 1e-9 + sage: RDF(v) # abs tol 1e-9 # optional - sage.rings.number_field 1.53406271079044 sage: Dinexact = polytopes.dodecahedron(exact=False) @@ -8681,13 +8668,13 @@ def volume(self, measure='ambient', engine='auto', **kwds): True sage: I = Polyhedron([[-3, 0], [0, 9]]) - sage: I.volume(measure='induced') + sage: I.volume(measure='induced') # optional - sage.rings.number_field 9.48683298050514? sage: I.volume(measure='induced_rational') # optional -- latte_int 3 sage: T = Polyhedron([[3, 0, 0], [0, 4, 0], [0, 0, 5]]) - sage: T.volume(measure='induced') + sage: T.volume(measure='induced') # optional - sage.rings.number_field 13.86542462386205? sage: T.volume(measure='induced_rational') # optional -- latte_int 1/2 @@ -8929,8 +8916,8 @@ def integrate(self, function, measure='ambient', **kwds): Testing a polytope with non-rational vertices:: - sage: P = polytopes.icosahedron() - sage: P.integrate(x^2*y^2*z^2) # optional - latte_int + sage: P = polytopes.icosahedron() # optional - sage.rings.number_field + sage: P.integrate(x^2*y^2*z^2) # optional - latte_int # optional - sage.rings.number_field Traceback (most recent call last): ... TypeError: the base ring must be ZZ, QQ, or RDF @@ -9506,7 +9493,7 @@ def is_lattice_polytope(self): sage: polytopes.cross_polytope(3).is_lattice_polytope() True - sage: polytopes.regular_polygon(5).is_lattice_polytope() + sage: polytopes.regular_polygon(5).is_lattice_polytope() # optional - sage.rings.number_field False """ if not self.is_compact(): @@ -10624,10 +10611,12 @@ def is_combinatorially_isomorphic(self, other, algorithm='bipartite_graph'): All the faces of the 3-dimensional permutahedron are either combinatorially isomorphic to a square or a hexagon:: - sage: H = polytopes.regular_polygon(6) + sage: H = polytopes.regular_polygon(6) # optional - sage.rings.number_field sage: S = polytopes.hypercube(2) sage: P = polytopes.permutahedron(4) - sage: all(F.as_polyhedron().is_combinatorially_isomorphic(S) or F.as_polyhedron().is_combinatorially_isomorphic(H) for F in P.faces(2)) + sage: all(F.as_polyhedron().is_combinatorially_isomorphic(S) # optional - sage.rings.number_field + ....: or F.as_polyhedron().is_combinatorially_isomorphic(H) + ....: for F in P.faces(2)) True Checking that a regular simplex intersected with its reflection @@ -10644,7 +10633,7 @@ def is_combinatorially_isomorphic(self, other, algorithm='bipartite_graph'): ....: return C.intersection(H) sage: [simplex_intersection(k).is_combinatorially_isomorphic(cube_intersection(k)) for k in range(2,5)] [True, True, True] - sage: simplex_intersection(2).is_combinatorially_isomorphic(polytopes.regular_polygon(6)) + sage: simplex_intersection(2).is_combinatorially_isomorphic(polytopes.regular_polygon(6)) # optional - sage.rings.number_field True sage: simplex_intersection(3).is_combinatorially_isomorphic(polytopes.octahedron()) True @@ -10737,6 +10726,11 @@ def _test_is_combinatorially_isomorphic(self, tester=None, **options): # Avoid very long doctests. return + try: + import sage.graphs.graph + except ImportError: + return + tester.assertTrue(self.is_combinatorially_isomorphic(ZZ(4)*self)) if self.n_vertices(): tester.assertTrue(self.is_combinatorially_isomorphic(self + self.center())) diff --git a/src/sage/geometry/polyhedron/base_ZZ.py b/src/sage/geometry/polyhedron/base_ZZ.py index 8015f360560..bbfdd42d8fd 100644 --- a/src/sage/geometry/polyhedron/base_ZZ.py +++ b/src/sage/geometry/polyhedron/base_ZZ.py @@ -80,7 +80,7 @@ def is_lattice_polytope(self): sage: polytopes.cross_polytope(3).is_lattice_polytope() True - sage: polytopes.regular_polygon(5).is_lattice_polytope() + sage: polytopes.regular_polygon(5).is_lattice_polytope() # optional - sage.rings.number_field False TESTS: diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd index 4fc293961c5..2d88b7c7496 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pxd @@ -71,7 +71,7 @@ cdef class CombinatorialPolyhedron(SageObject): cdef inline int _compute_ridges(self, dual) except -1: return self._compute_edges_or_ridges(dual, False) - cdef int _compute_edges_or_ridges(self, bint dual, bint do_edges) except -1 + cdef int _compute_edges_or_ridges(self, int dual, bint do_edges) except -1 cdef size_t _compute_edges_or_ridges_with_iterator( self, FaceIterator face_iter, const bint do_atom_rep, const bint do_f_vector, size_t ***edges_pt, size_t *counter_pt, size_t *current_length_pt, diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx index 85131c81ad6..524933a01a8 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/base.pyx @@ -600,14 +600,16 @@ cdef class CombinatorialPolyhedron(SageObject): TESTS:: - sage: P = polytopes.permutahedron(4) - sage: C = CombinatorialPolyhedron(P) - sage: C1 = loads(C.dumps()) - sage: it = C.face_iter() - sage: it1 = C1.face_iter() - sage: tup = tuple((face.ambient_Vrepresentation(), face.ambient_Hrepresentation()) for face in it) - sage: tup1 = tuple((face.ambient_Vrepresentation(), face.ambient_Hrepresentation()) for face in it1) - sage: tup == tup1 + sage: P = polytopes.permutahedron(4) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: C1 = loads(C.dumps()) # optional - sage.combinat + sage: it = C.face_iter() # optional - sage.combinat + sage: it1 = C1.face_iter() # optional - sage.combinat + sage: tup = tuple((face.ambient_Vrepresentation(), # optional - sage.combinat + ....: face.ambient_Hrepresentation()) for face in it) + sage: tup1 = tuple((face.ambient_Vrepresentation(), # optional - sage.combinat + ....: face.ambient_Hrepresentation()) for face in it1) + sage: tup == tup1 # optional - sage.combinat True sage: P = polytopes.cyclic_polytope(4,10) @@ -705,9 +707,9 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(3) - sage: C = CombinatorialPolyhedron(P) - sage: C.Hrepresentation() + sage: P = polytopes.permutahedron(3) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: C.Hrepresentation() # optional - sage.combinat (An inequality (1, 1, 0) x - 3 >= 0, An inequality (-1, -1, 0) x + 5 >= 0, An inequality (0, 1, 0) x - 1 >= 0, @@ -1060,10 +1062,10 @@ cdef class CombinatorialPolyhedron(SageObject): :: - sage: P = polytopes.permutahedron(5, backend='field') - sage: C = P.combinatorial_polyhedron() - sage: C.incidence_matrix.clear_cache() - sage: C.incidence_matrix() == P.incidence_matrix() + sage: P = polytopes.permutahedron(5, backend='field') # optional - sage.combinat + sage: C = P.combinatorial_polyhedron() # optional - sage.combinat + sage: C.incidence_matrix.clear_cache() # optional - sage.combinat + sage: C.incidence_matrix() == P.incidence_matrix() # optional - sage.combinat True The incidence matrix is consistent with @@ -1183,19 +1185,7 @@ cdef class CombinatorialPolyhedron(SageObject): ('a', 'c'), ('a', 'b')) """ - if self._edges is NULL: - # compute the edges. - if not self.is_bounded(): - self._compute_edges(dual=False) - elif self.n_Vrepresentation() > self.n_facets()*self.n_facets(): - # This is a wild estimate - # that in this case it is better not to use the dual. - self._compute_edges(dual=False) - else: - # In most bounded cases, one should use the dual. - self._compute_edges(dual=True) - if self._edges is NULL: - raise ValueError('could not determine edges') + self._compute_edges(-1) # Mapping the indices of the Vrep to the names, if requested. if self.Vrep() is not None and names is True: @@ -1245,6 +1235,53 @@ cdef class CombinatorialPolyhedron(SageObject): graph = vertex_graph + @cached_method + def vertex_adjacency_matrix(self): + """ + Return the binary matrix of vertex adjacencies. + + .. SEEALSO:: + + :meth:`~sage.geometry.polyhedron.base.Polyhedron_base.vertex_adjacency_matrix`. + + EXAMPLES:: + + sage: P = polytopes.cube() + sage: C = P.combinatorial_polyhedron() + sage: C.vertex_adjacency_matrix() + [0 1 0 1 0 1 0 0] + [1 0 1 0 0 0 1 0] + [0 1 0 1 0 0 0 1] + [1 0 1 0 1 0 0 0] + [0 0 0 1 0 1 0 1] + [1 0 0 0 1 0 1 0] + [0 1 0 0 0 1 0 1] + [0 0 1 0 1 0 1 0] + + TESTS:: + + sage: CombinatorialPolyhedron(-1).vertex_adjacency_matrix() + [] + sage: CombinatorialPolyhedron(0).vertex_adjacency_matrix() + [0] + sage: polytopes.cube().vertex_adjacency_matrix().is_immutable() + True + """ + from sage.rings.integer_ring import ZZ + from sage.matrix.constructor import matrix + cdef Matrix_integer_dense adjacency_matrix = matrix( + ZZ, self.n_Vrepresentation(), self.n_Vrepresentation(), 0) + cdef size_t i, a, b + + self._compute_edges(-1) + for i in range(self._n_edges): + a = self._get_edge(self._edges, i, 0) + b = self._get_edge(self._edges, i, 1) + adjacency_matrix.set_unsafe_si(a, b, 1) + adjacency_matrix.set_unsafe_si(b, a, 1) + adjacency_matrix.set_immutable() + return adjacency_matrix + def edge_graph(self, names=True): r""" Return the edge graph. @@ -1294,11 +1331,11 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(2) - sage: C = CombinatorialPolyhedron(P) - sage: C.ridges() + sage: P = polytopes.permutahedron(2) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: C.ridges() # optional - sage.combinat ((An inequality (1, 0) x - 1 >= 0, An inequality (-1, 0) x + 2 >= 0),) - sage: C.ridges(add_equations=True) + sage: C.ridges(add_equations=True) # optional - sage.combinat (((An inequality (1, 0) x - 1 >= 0, An equation (1, 1) x - 3 == 0), (An inequality (-1, 0) x + 2 >= 0, An equation (1, 1) x - 3 == 0)),) @@ -1369,19 +1406,7 @@ cdef class CombinatorialPolyhedron(SageObject): from sage.misc.superseded import deprecation deprecation(31834, "the keyword ``add_equalities`` is deprecated; use ``add_equations``", 3) add_equations = True - if self._ridges is NULL: - # compute the ridges. - if not self.is_bounded(): - self._compute_ridges(dual=False) - elif self.n_Vrepresentation()*self.n_Vrepresentation() < self.n_facets(): - # This is a wild estimate - # that in this case it is better to use the dual. - self._compute_ridges(dual=True) - else: - # In most bounded cases, one should not use the dual. - self._compute_ridges(dual=False) - if self._ridges is NULL: - raise ValueError('could not determine ridges') + self._compute_ridges(-1) n_ridges = self._n_ridges # Mapping the indices of the Vepr to the names, if requested. @@ -1608,9 +1633,9 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(5) - sage: C = CombinatorialPolyhedron(P) - sage: C.f_vector() + sage: P = polytopes.permutahedron(5) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: C.f_vector() # optional - sage.combinat (1, 120, 240, 150, 30, 1) sage: P = polytopes.cyclic_polytope(6,10) @@ -1620,9 +1645,9 @@ cdef class CombinatorialPolyhedron(SageObject): Using two threads:: - sage: P = polytopes.permutahedron(5) - sage: C = CombinatorialPolyhedron(P) - sage: C.f_vector(num_threads=2) + sage: P = polytopes.permutahedron(5) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: C.f_vector(num_threads=2) # optional - sage.combinat (1, 120, 240, 150, 30, 1) TESTS:: @@ -2320,15 +2345,15 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(4) - sage: C = CombinatorialPolyhedron(P) - sage: C.join_of_Vrep(0,1) + sage: P = polytopes.permutahedron(4) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: C.join_of_Vrep(0,1) # optional - sage.combinat A 1-dimensional face of a 3-dimensional combinatorial polyhedron - sage: C.join_of_Vrep(0,11).ambient_V_indices() + sage: C.join_of_Vrep(0,11).ambient_V_indices() # optional - sage.combinat (0, 1, 10, 11, 12, 13) - sage: C.join_of_Vrep(8).ambient_V_indices() + sage: C.join_of_Vrep(8).ambient_V_indices() # optional - sage.combinat (8,) - sage: C.join_of_Vrep().ambient_V_indices() + sage: C.join_of_Vrep().ambient_V_indices() # optional - sage.combinat () """ return self.face_iter().join_of_Vrep(*indices) @@ -2343,19 +2368,19 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.dodecahedron() - sage: C = CombinatorialPolyhedron(P) - sage: C.meet_of_Hrep(0) + sage: P = polytopes.dodecahedron() # optional - sage.rings.number_field + sage: C = CombinatorialPolyhedron(P) # optional - sage.rings.number_field + sage: C.meet_of_Hrep(0) # optional - sage.rings.number_field A 2-dimensional face of a 3-dimensional combinatorial polyhedron - sage: C.meet_of_Hrep(0).ambient_H_indices() + sage: C.meet_of_Hrep(0).ambient_H_indices() # optional - sage.rings.number_field (0,) - sage: C.meet_of_Hrep(0,1).ambient_H_indices() + sage: C.meet_of_Hrep(0,1).ambient_H_indices() # optional - sage.rings.number_field (0, 1) - sage: C.meet_of_Hrep(0,2).ambient_H_indices() + sage: C.meet_of_Hrep(0,2).ambient_H_indices() # optional - sage.rings.number_field (0, 2) - sage: C.meet_of_Hrep(0,2,3).ambient_H_indices() + sage: C.meet_of_Hrep(0,2,3).ambient_H_indices() # optional - sage.rings.number_field (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11) - sage: C.meet_of_Hrep().ambient_H_indices() + sage: C.meet_of_Hrep().ambient_H_indices() # optional - sage.rings.number_field () """ return self.face_iter().meet_of_Hrep(*indices) @@ -2382,38 +2407,38 @@ cdef class CombinatorialPolyhedron(SageObject): EXAMPLES:: - sage: P = polytopes.permutahedron(5) - sage: C = CombinatorialPolyhedron(P) - sage: it = C.face_iter(dimension=2) - sage: face = next(it); face + sage: P = polytopes.permutahedron(5) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: it = C.face_iter(dimension=2) # optional - sage.combinat + sage: face = next(it); face # optional - sage.combinat A 2-dimensional face of a 4-dimensional combinatorial polyhedron - sage: face.ambient_Vrepresentation() + sage: face.ambient_Vrepresentation() # optional - sage.combinat (A vertex at (1, 3, 2, 5, 4), A vertex at (2, 3, 1, 5, 4), A vertex at (3, 1, 2, 5, 4), A vertex at (3, 2, 1, 5, 4), A vertex at (2, 1, 3, 5, 4), A vertex at (1, 2, 3, 5, 4)) - sage: face = next(it); face + sage: face = next(it); face # optional - sage.combinat A 2-dimensional face of a 4-dimensional combinatorial polyhedron - sage: face.ambient_Vrepresentation() + sage: face.ambient_Vrepresentation() # optional - sage.combinat (A vertex at (2, 1, 4, 5, 3), A vertex at (3, 2, 4, 5, 1), A vertex at (3, 1, 4, 5, 2), A vertex at (1, 3, 4, 5, 2), A vertex at (1, 2, 4, 5, 3), A vertex at (2, 3, 4, 5, 1)) - sage: face.ambient_Hrepresentation() + sage: face.ambient_Hrepresentation() # optional - sage.combinat (An inequality (0, 0, -1, -1, 0) x + 9 >= 0, An inequality (0, 0, 0, -1, 0) x + 5 >= 0, An equation (1, 1, 1, 1, 1) x - 15 == 0) - sage: face.ambient_H_indices() + sage: face.ambient_H_indices() # optional - sage.combinat (25, 29, 30) - sage: face = next(it); face + sage: face = next(it); face # optional - sage.combinat A 2-dimensional face of a 4-dimensional combinatorial polyhedron - sage: face.ambient_H_indices() + sage: face.ambient_H_indices() # optional - sage.combinat (24, 29, 30) - sage: face.ambient_V_indices() + sage: face.ambient_V_indices() # optional - sage.combinat (32, 89, 90, 94) sage: C = CombinatorialPolyhedron([[0,1,2],[0,1,3],[0,2,3],[1,2,3]]) @@ -2508,9 +2533,9 @@ cdef class CombinatorialPolyhedron(SageObject): sage: C.face_lattice().is_isomorphic(C1.face_lattice()) True - sage: P = polytopes.permutahedron(5) - sage: C = CombinatorialPolyhedron(P) - sage: C.face_lattice() + sage: P = polytopes.permutahedron(5) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: C.face_lattice() # optional - sage.combinat Finite lattice containing 542 elements TESTS:: @@ -2520,9 +2545,9 @@ cdef class CombinatorialPolyhedron(SageObject): sage: C.face_lattice().is_isomorphic(P.face_lattice()) True - sage: P = polytopes.permutahedron(4) - sage: C = CombinatorialPolyhedron(P) - sage: C.face_lattice().is_isomorphic(P.face_lattice()) + sage: P = polytopes.permutahedron(4) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: C.face_lattice().is_isomorphic(P.face_lattice()) # optional - sage.combinat True """ from sage.combinat.posets.lattices import FiniteLatticePoset @@ -2731,13 +2756,13 @@ cdef class CombinatorialPolyhedron(SageObject): sage: [face.ambient_V_indices() for face in chain] [(15,), (6, 15), (5, 6, 14, 15), (0, 5, 6, 7, 8, 9, 14, 15)] - sage: P = polytopes.permutahedron(4) - sage: C = P.combinatorial_polyhedron() - sage: chain = C.a_maximal_chain(); chain + sage: P = polytopes.permutahedron(4) # optional - sage.combinat + sage: C = P.combinatorial_polyhedron() # optional - sage.combinat + sage: chain = C.a_maximal_chain(); chain # optional - sage.combinat [A 0-dimensional face of a 3-dimensional combinatorial polyhedron, A 1-dimensional face of a 3-dimensional combinatorial polyhedron, A 2-dimensional face of a 3-dimensional combinatorial polyhedron] - sage: [face.ambient_V_indices() for face in chain] + sage: [face.ambient_V_indices() for face in chain] # optional - sage.combinat [(16,), (15, 16), (8, 9, 14, 15, 16, 17)] sage: P = Polyhedron(rays=[[1,0]], lines=[[0,1]]) @@ -3207,11 +3232,12 @@ cdef class CombinatorialPolyhedron(SageObject): self._f_vector = tuple(smallInteger(f_vector[i]) for i in range(dim+2)) - cdef int _compute_edges_or_ridges(self, bint dual, bint do_edges) except -1: + cdef int _compute_edges_or_ridges(self, int dual, bint do_edges) except -1: r""" Compute the edges of the polyhedron if ``edges`` else the ridges. If ``dual``, use the face iterator in dual mode, else in non-dual. + If ``dual`` is ``-1`` determine this automatically. If the ``f_vector`` is unkown computes it as well if computing the edges in non-dual mode or the ridges in dual-mode. @@ -3221,6 +3247,27 @@ cdef class CombinatorialPolyhedron(SageObject): if (self._edges is not NULL and do_edges) or (self._ridges is not NULL and not do_edges): return 0 # There is no need to recompute. + if dual == -1: + # Determine whether to use dual mode or not. + if not self.is_bounded(): + dual = 0 + elif do_edges: + if self.n_Vrepresentation() > self.n_facets()*self.n_facets(): + # This is a wild estimate + # that in this case it is better not to use the dual. + dual = 0 + else: + # In most bounded cases, one should use the dual. + dual = 1 + else: + if self.n_Vrepresentation()*self.n_Vrepresentation() < self.n_facets(): + # This is a wild estimate + # that in this case it is better to use the dual. + dual = 1 + else: + # In most bounded cases, one should not use the dual. + dual = 0 + cdef MemoryAllocator mem = MemoryAllocator() cdef FaceIterator face_iter cdef int dim = self.dimension() @@ -3295,6 +3342,12 @@ cdef class CombinatorialPolyhedron(SageObject): self._mem_tuple += (mem,) sig_unblock() + if do_edges and self._edges is NULL: + raise ValueError('could not determine edges') + elif not do_edges and self._ridges is NULL: + raise ValueError('could not determine ridges') + + cdef size_t _compute_edges_or_ridges_with_iterator( self, FaceIterator face_iter, const bint do_atom_rep, const bint do_f_vector, size_t ***edges_pt, size_t *counter_pt, size_t *current_length_pt, @@ -3493,14 +3546,15 @@ cdef class CombinatorialPolyhedron(SageObject): TESTS:: - sage: P = polytopes.permutahedron(4) - sage: C = CombinatorialPolyhedron(P) - sage: it = C.face_iter() - sage: tup = tuple((face.ambient_Vrepresentation(),face.ambient_Hrepresentation()) for face in it) - sage: rg = range(1,sum(C.f_vector()) - 1) - sage: tup2 = tuple((C.face_by_face_lattice_index(i).ambient_Vrepresentation(), + sage: P = polytopes.permutahedron(4) # optional - sage.combinat + sage: C = CombinatorialPolyhedron(P) # optional - sage.combinat + sage: it = C.face_iter() # optional - sage.combinat + sage: tup = tuple((face.ambient_Vrepresentation(), # optional - sage.combinat + ....: face.ambient_Hrepresentation()) for face in it) + sage: rg = range(1,sum(C.f_vector()) - 1) # optional - sage.combinat + sage: tup2 = tuple((C.face_by_face_lattice_index(i).ambient_Vrepresentation(), # optional - sage.combinat ....: C.face_by_face_lattice_index(i).ambient_Hrepresentation()) for i in rg) - sage: sorted(tup) == sorted(tup2) + sage: sorted(tup) == sorted(tup2) # optional - sage.combinat True sage: P = polytopes.cyclic_polytope(4,10) diff --git a/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx b/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx index eb1666b99f6..35f8902ad0a 100644 --- a/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx +++ b/src/sage/geometry/polyhedron/combinatorial_polyhedron/conversions.pyx @@ -33,9 +33,9 @@ Obtain the Vrepresentation of a polyhedron as facet-incidences stored in sage: from sage.geometry.polyhedron.combinatorial_polyhedron.conversions \ ....: import incidence_matrix_to_bit_rep_of_Vrep - sage: P = polytopes.associahedron(['A',4]) - sage: face_list = incidence_matrix_to_bit_rep_of_Vrep(P.incidence_matrix()) - sage: face_list.compute_dimension() + sage: P = polytopes.associahedron(['A',4]) # optional - sage.combinat + sage: face_list = incidence_matrix_to_bit_rep_of_Vrep(P.incidence_matrix()) # optional - sage.combinat + sage: face_list.compute_dimension() # optional - sage.combinat 4 Obtain the facets of a polyhedron as :class:`~sage.geometry.polyhedron.combinatorial_polyhedron.list_of_faces.ListOfFaces` from a facet list:: diff --git a/src/sage/geometry/polyhedron/constructor.py b/src/sage/geometry/polyhedron/constructor.py index 2df40ce6c59..4606d979cfb 100644 --- a/src/sage/geometry/polyhedron/constructor.py +++ b/src/sage/geometry/polyhedron/constructor.py @@ -131,7 +131,7 @@ sage: type(v) sage: type( v() ) - + sage: v.polyhedron() A 2-dimensional polyhedron in QQ^2 defined as the convex hull of 2 vertices and 2 rays sage: r = next(trunc_quadr.ray_generator()) @@ -177,8 +177,8 @@ exact way to work with roots in Sage is the :mod:`Algebraic Real Field ` :: - sage: triangle = Polyhedron([(0,0), (1,0), (1/2, sqrt(3)/2)], base_ring=AA) - sage: triangle.Hrepresentation() + sage: triangle = Polyhedron([(0,0), (1,0), (1/2, sqrt(3)/2)], base_ring=AA) # optional - sage.rings.number_field # optional - sage.symbolic + sage: triangle.Hrepresentation() # optional - sage.rings.number_field # optional - sage.symbolic (An inequality (-1, -0.5773502691896258?) x + 1 >= 0, An inequality (1, -0.5773502691896258?) x + 0 >= 0, An inequality (0, 1.154700538379252?) x + 0 >= 0) @@ -187,20 +187,20 @@ symbolic ring element and, therefore, the polyhedron defined over the symbolic ring. This is currently not supported as SR is not exact:: - sage: Polyhedron([(0,0), (1,0), (1/2, sqrt(3)/2)]) + sage: Polyhedron([(0,0), (1,0), (1/2, sqrt(3)/2)]) # optional - sage.symbolic Traceback (most recent call last): ... ValueError: no default backend for computations with Symbolic Ring - sage: SR.is_exact() + sage: SR.is_exact() # optional - sage.symbolic False Even faster than all algebraic real numbers (the field ``AA``) is to take the smallest extension field. For the equilateral triangle, that would be:: - sage: K. = NumberField(x^2 - 3, embedding=AA(3)**(1/2)) - sage: Polyhedron([(0,0), (1,0), (1/2, sqrt3/2)]) + sage: K. = NumberField(x^2 - 3, embedding=AA(3)**(1/2)) # optional - sage.rings.number_field + sage: Polyhedron([(0,0), (1,0), (1/2, sqrt3/2)]) # optional - sage.rings.number_field A 2-dimensional polyhedron in (Number Field in sqrt3 with defining polynomial x^2 - 3 with sqrt3 = 1.732050807568878?)^2 defined as the convex hull of 3 vertices .. WARNING:: @@ -443,24 +443,25 @@ def Polyhedron(vertices=None, rays=None, lines=None, by the cyclic shifts of `(0, \pm 1, \pm (1+\sqrt(5))/2)`, cf. :wikipedia:`Regular_icosahedron`. It needs a number field:: - sage: R0. = QQ[] - sage: R1. = NumberField(r0^2-5, embedding=AA(5)**(1/2)) - sage: gold = (1+r1)/2 - sage: v = [[0, 1, gold], [0, 1, -gold], [0, -1, gold], [0, -1, -gold]] - sage: pp = Permutation((1, 2, 3)) - sage: icosah = Polyhedron([(pp^2).action(w) for w in v] - ....: + [pp.action(w) for w in v] + v, base_ring=R1) - sage: len(icosah.faces(2)) + sage: R0. = QQ[] # optional - sage.rings.number_field + sage: R1. = NumberField(r0^2-5, embedding=AA(5)**(1/2)) # optional - sage.rings.number_field + sage: gold = (1+r1)/2 # optional - sage.rings.number_field + sage: v = [[0, 1, gold], [0, 1, -gold], [0, -1, gold], [0, -1, -gold]] # optional - sage.rings.number_field + sage: pp = Permutation((1, 2, 3)) # optional - sage.combinat # optional - sage.rings.number_field + sage: icosah = Polyhedron( # optional - sage.combinat # optional - sage.rings.number_field + ....: [(pp^2).action(w) for w in v] + [pp.action(w) for w in v] + v, + ....: base_ring=R1) + sage: len(icosah.faces(2)) # optional - sage.combinat # optional - sage.rings.number_field 20 When the input contains elements of a Number Field, they require an embedding:: - sage: K = NumberField(x^2-2,'s') - sage: s = K.0 - sage: L = NumberField(x^3-2,'t') - sage: t = L.0 - sage: P = Polyhedron(vertices = [[0,s],[t,0]]) + sage: K = NumberField(x^2-2,'s') # optional - sage.rings.number_field + sage: s = K.0 # optional - sage.rings.number_field + sage: L = NumberField(x^3-2,'t') # optional - sage.rings.number_field + sage: t = L.0 # optional - sage.rings.number_field + sage: P = Polyhedron(vertices = [[0,s],[t,0]]) # optional - sage.rings.number_field Traceback (most recent call last): ... ValueError: invalid base ring diff --git a/src/sage/geometry/polyhedron/double_description.py b/src/sage/geometry/polyhedron/double_description.py index ee8cb5a7e86..c1c94a9b8f9 100644 --- a/src/sage/geometry/polyhedron/double_description.py +++ b/src/sage/geometry/polyhedron/double_description.py @@ -28,10 +28,10 @@ `\RR`, for example:: sage: from sage.geometry.polyhedron.double_description import StandardAlgorithm - sage: A = matrix(AA, [(1,0,1), (0,1,1), (-AA(2).sqrt(),-AA(3).sqrt(),1), + sage: A = matrix(AA, [(1,0,1), (0,1,1), (-AA(2).sqrt(),-AA(3).sqrt(),1), # optional - sage.rings.number_field ....: (-AA(3).sqrt(),-AA(2).sqrt(),1)]) - sage: alg = StandardAlgorithm(A) - sage: alg.run().R + sage: alg = StandardAlgorithm(A) # optional - sage.rings.number_field + sage: alg.run().R # optional - sage.rings.number_field [(-0.4177376677004119?, 0.5822623322995881?, 0.4177376677004119?), (-0.2411809548974793?, -0.2411809548974793?, 0.2411809548974793?), (0.07665629029830300?, 0.07665629029830300?, 0.2411809548974793?), @@ -411,11 +411,12 @@ def matrix_space(self, nrows, ncols): sage: DD.matrix_space(3,2) Full MatrixSpace of 3 by 2 dense matrices over Rational Field - sage: K. = QuadraticField(2) - sage: A = matrix([[1,sqrt2],[2,0]]) - sage: DD, _ = Problem(A).initial_pair() - sage: DD.matrix_space(1,2) - Full MatrixSpace of 1 by 2 dense matrices over Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095? + sage: K. = QuadraticField(2) # optional - sage.rings.number_field + sage: A = matrix([[1,sqrt2],[2,0]]) # optional - sage.rings.number_field + sage: DD, _ = Problem(A).initial_pair() # optional - sage.rings.number_field + sage: DD.matrix_space(1,2) # optional - sage.rings.number_field + Full MatrixSpace of 1 by 2 dense matrices + over Number Field in sqrt2 with defining polynomial x^2 - 2 with sqrt2 = 1.414213562373095? """ return MatrixSpace(self.problem.base_ring(), nrows, ncols) @@ -596,9 +597,9 @@ def base_ring(self): EXAMPLES:: - sage: A = matrix(AA, [(1, 1), (-1, 1)]) + sage: A = matrix(AA, [(1, 1), (-1, 1)]) # optional - sage.rings.number_field sage: from sage.geometry.polyhedron.double_description import Problem - sage: Problem(A).base_ring() + sage: Problem(A).base_ring() # optional - sage.rings.number_field Algebraic Real Field """ return self._field diff --git a/src/sage/geometry/polyhedron/face.py b/src/sage/geometry/polyhedron/face.py index 2d127ceda1c..9d1f53343e7 100644 --- a/src/sage/geometry/polyhedron/face.py +++ b/src/sage/geometry/polyhedron/face.py @@ -952,7 +952,19 @@ def affine_tangent_cone(self): A ray in the direction (0, 0, 1), A vertex at (1, 0, -1), A ray in the direction (-1, 0, 0)) + + TESTS: + + Check that :trac:`32658` is fixed:: + + sage: P = polytopes.hypercube(2) + sage: P.faces(-1)[0].affine_tangent_cone() + Traceback (most recent call last): + ... + ValueError: affine tangent cone of the empty face not defined """ + if self.dim() == -1: + raise ValueError("affine tangent cone of the empty face not defined") parent = self.polyhedron().parent() new_ieqs = [H for H in self.ambient_Hrepresentation() if H.is_inequality()] diff --git a/src/sage/geometry/polyhedron/palp_database.py b/src/sage/geometry/polyhedron/palp_database.py index a9bd90eca8b..1ec027f9482 100644 --- a/src/sage/geometry/polyhedron/palp_database.py +++ b/src/sage/geometry/polyhedron/palp_database.py @@ -88,7 +88,7 @@ class PALPreader(SageObject): [-1, -1] in Ambient free module of rank 2 over the principal ideal domain Integer Ring sage: type(_) - + """ def __init__(self, dim, data_basename=None, output='Polyhedron'): diff --git a/src/sage/geometry/polyhedron/parent.py b/src/sage/geometry/polyhedron/parent.py index 2c1614ed87d..48bed4a9553 100644 --- a/src/sage/geometry/polyhedron/parent.py +++ b/src/sage/geometry/polyhedron/parent.py @@ -14,6 +14,7 @@ from sage.structure.unique_representation import UniqueRepresentation from sage.modules.free_module import FreeModule, is_FreeModule from sage.misc.cachefunc import cached_method, cached_function +from sage.misc.lazy_import import lazy_import from sage.rings.integer_ring import ZZ from sage.rings.rational_field import QQ from sage.rings.real_double import RDF @@ -1133,7 +1134,8 @@ def _make_Line(self, polyhedron, data): -from sage.geometry.polyhedron.backend_cdd import Polyhedron_QQ_cdd, Polyhedron_RDF_cdd +from sage.geometry.polyhedron.backend_cdd import Polyhedron_QQ_cdd +lazy_import('sage.geometry.polyhedron.backend_cdd_rdf', 'Polyhedron_RDF_cdd') from sage.geometry.polyhedron.backend_ppl import Polyhedron_ZZ_ppl, Polyhedron_QQ_ppl from sage.geometry.polyhedron.backend_normaliz import Polyhedron_normaliz, Polyhedron_ZZ_normaliz, Polyhedron_QQ_normaliz from sage.geometry.polyhedron.backend_polymake import Polyhedron_polymake diff --git a/src/sage/geometry/polyhedron/plot.py b/src/sage/geometry/polyhedron/plot.py index a7976de6d2e..9a6a759eb93 100644 --- a/src/sage/geometry/polyhedron/plot.py +++ b/src/sage/geometry/polyhedron/plot.py @@ -1009,7 +1009,7 @@ def render_solid_3d(self, **kwds): sage: p = polytopes.hypercube(3).projection() sage: p_solid = p.render_solid_3d(opacity = .7) sage: type(p_solid) - + """ polys = self.polygons N = max([-1] + [i for p in polys for i in p]) + 1 diff --git a/src/sage/geometry/polyhedron/representation.py b/src/sage/geometry/polyhedron/representation.py index 9b4cb1586d2..443bea9224a 100644 --- a/src/sage/geometry/polyhedron/representation.py +++ b/src/sage/geometry/polyhedron/representation.py @@ -231,7 +231,7 @@ def vector(self, base_ring=None): sage: v() (-1, -1, 0) sage: type(v()) - + Conversion to a different base ring can be forced with the optional argument:: diff --git a/src/sage/graphs/base/c_graph.pyx b/src/sage/graphs/base/c_graph.pyx index a3b122c9d81..515ca3076ff 100644 --- a/src/sage/graphs/base/c_graph.pyx +++ b/src/sage/graphs/base/c_graph.pyx @@ -4400,11 +4400,18 @@ cdef class CGraphBackend(GenericGraphBackend): sage: Graph(graphs.CubeGraph(3)).is_connected() True + + TESTS:: + + sage: P = posets.PentagonPoset() + sage: H = P._hasse_diagram + sage: H._backend.is_connected() + True """ cdef int v_int cdef CGraph cg = self.cg() - if cg.num_edges() < cg.num_verts - 1: + if cg.num_arcs < cg.num_verts - 1: return False v_int = bitset_first(cg.active_vertices) diff --git a/src/sage/graphs/convexity_properties.pyx b/src/sage/graphs/convexity_properties.pyx index 3fea9e872d1..c260daff32e 100644 --- a/src/sage/graphs/convexity_properties.pyx +++ b/src/sage/graphs/convexity_properties.pyx @@ -1,3 +1,4 @@ +# cython: binding=True r""" Convexity properties of graphs @@ -11,6 +12,7 @@ the following methods: :meth:`ConvexityProperties.hull` | Return the convex hull of a set of vertices :meth:`ConvexityProperties.hull_number` | Compute the hull number of a graph and a corresponding generating set + :meth:`geodetic_closure`| Return the geodetic closure of a set of vertices These methods can be used through the :class:`ConvexityProperties` object returned by :meth:`Graph.convexity_properties`. @@ -23,12 +25,16 @@ Methods ------- """ -############################################################################## +# **************************************************************************** # Copyright (C) 2011 Nathann Cohen -# Distributed under the terms of the GNU General Public License (GPL) -# The full text of the GPL is available at: -# http://www.gnu.org/licenses/ -############################################################################## +# 2021 David Coudert +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# https://www.gnu.org/licenses/ +# **************************************************************************** from sage.data_structures.binary_matrix cimport * from sage.numerical.backends.generic_backend cimport GenericBackend @@ -36,6 +42,13 @@ from sage.numerical.backends.generic_backend import get_solver from sage.graphs.distances_all_pairs cimport c_distances_all_pairs from cysignals.memory cimport sig_free from cysignals.signals cimport sig_on, sig_off +from memory_allocator cimport MemoryAllocator +from libc.stdint cimport uint32_t +from sage.graphs.base.static_sparse_graph cimport (short_digraph, + init_short_digraph, + free_short_digraph, + out_degree, + simple_BFS) cdef class ConvexityProperties: r""" @@ -476,3 +489,189 @@ cdef class ConvexityProperties: constraint.append(i) return self._integers_to_vertices(constraint) + + +def geodetic_closure(G, S): + r""" + Return the geodetic closure of the set of vertices `S` in `G`. + + The geodetic closure `g(S)` of a subset of vertices `S` of a graph `G` is in + [HLT1993]_ as the set of all vertices that lie on a shortest `u-v` path for + any pair of vertices `u,v \in S`. We assume that `g(\emptyset) = \emptyset` + and that `g(\{u\}) = \{u\}` for any `u` in `G`. + + .. WARNING:: + + This operation is **not** a closure function. Indeed, a closure function + must satisfy the property that `f(f(X))` should be equal to `f(X)`, + which is not always the case here. The term ``closure`` is used here to + follow the terminology of the domain. See for instance [HLT1993]_. + + Here, we implement a simple algorithm to determine this set. Roughly, for + each vertex `u \in S`, the algorithm first performs a breadth first search + from `u` to get distances, and then identifies the vertices of `G` lying on + a shortest path from `u` to any `v\in S` using a reversal traversal from + vertices in `S`. This algorithm has time complexity in `O(|S|(n + m))` and + space complexity in `O(n + m)`. + + INPUT: + + - ``G`` -- a Sage graph + + - ``S`` -- a subset of vertices of `G` + + EXAMPLES: + + The vertices of the Petersen graph can be obtained by a geodetic closure of + four of its vertices:: + + sage: from sage.graphs.convexity_properties import geodetic_closure + sage: G = graphs.PetersenGraph() + sage: geodetic_closure(G, [0, 2, 8, 9]) + [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + + The vertices of a 2D grid can be obtained by a geodetic closure of + two vertices:: + + sage: G = graphs.Grid2dGraph(4, 4) + sage: c = G.geodetic_closure([(0, 0), (3, 3)]) + sage: len(c) == G.order() + True + + If two vertices belong to different connected components of a graph, their + geodetic closure is trivial:: + + sage: G = Graph([(0, 1), (2, 3)]) + sage: geodetic_closure(G, [0, 2]) + [0, 2] + + The geodetic closure does not satisfy the closure function property that + `f(f(X))` should be equal to `f(X)`:: + + sage: G = graphs.DiamondGraph() + sage: G.subdivide_edge((1, 2), 1) + sage: geodetic_closure(G, [0, 3]) + [0, 1, 2, 3] + sage: geodetic_closure(G, geodetic_closure(G, [0, 3])) + [0, 1, 2, 3, 4] + + TESTS:: + + sage: G = graphs.DiamondGraph() + sage: geodetic_closure(G, []) + [] + sage: geodetic_closure(G, [1]) + [1] + sage: S = geodetic_closure(G, list(G)) + sage: all(u in G for u in S) and len(S) == G.order() + True + sage: S = geodetic_closure(G, G) + sage: all(u in G for u in S) and len(S) == G.order() + True + sage: geodetic_closure(G, [1, 'foo']) + Traceback (most recent call last): + ... + ValueError: S is not a subset of vertices of the graph + sage: geodetic_closure(digraphs.Path(3), [0, 1]) + Traceback (most recent call last): + ... + NotImplementedError: the geodetic closure of digraphs has not been implemented yet + """ + if G.is_directed(): + raise NotImplementedError("the geodetic closure of digraphs has not been implemented yet") + S = list(S) + if not S: + return [] + elif any(v not in G for v in S): + raise ValueError("S is not a subset of vertices of the graph") + elif len(S) == 1 or len(S) == G.order(): + return S + elif not G.is_connected(): + L = [] + for g in G.connected_components_subgraphs(): + Sg = [u for u in S if u in g] + L.extend(geodetic_closure(g, Sg)) + return L + + cdef int n = G.order() + cdef int nS = len(S) + cdef list int_to_vertex = list(G) + cdef dict vertex_to_int = {u: i for i, u in enumerate(int_to_vertex)} + cdef list S_int = [vertex_to_int[u] for u in S] + + # Copy the graph as a short digraph + cdef short_digraph sd + init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_vertex) + + # Allocate some data structures + cdef MemoryAllocator mem = MemoryAllocator() + cdef uint32_t * distances = mem.malloc(n * sizeof(uint32_t)) + cdef uint32_t * waiting_list = mem.malloc(n * sizeof(uint32_t)) + if not distances or not waiting_list: + free_short_digraph(sd) + raise MemoryError() + cdef bitset_t seen + cdef bitset_t visited + cdef bitset_t closure + bitset_init(seen, n) + bitset_init(visited, n) + bitset_init(closure, n) + + cdef int ui, vi, xi, yi, i_begin, i_end, i, j, k + + # Vertices in S are in the closure + bitset_clear(closure) + for ui in S_int: + bitset_add(closure, ui) + + # We now explore geodesics between vertices in S, and we avoid visiting + # twice the geodesics between u and v + for i in range(nS - 1): + ui = S_int[i] + + # Compute distances from ui using BFS + _ = simple_BFS(sd, ui, distances, NULL, waiting_list, seen) + + # Perform a reverse BFS from vertices in S, following only vertices + # along a shortest path from ui to identify vertices of the geodetic + # closure. + bitset_clear(visited) + i_begin = 0 + i_end = 0 + for j in range(i + 1, nS): + vi = S_int[j] + if not bitset_in(seen, vi) or bitset_in(visited, vi): + # vi is not reachable from ui using BFS or has already been + # considered for the geodetic closure from ui + continue + + # We explore all vertices on a shortest path from ui to vi + waiting_list[i_end] = vi + i_end += 1 + bitset_add(visited, vi) + + while i_begin < i_end: + xi = waiting_list[i_begin] + i_begin += 1 + + for k in range(out_degree(sd, xi)): + yi = sd.neighbors[xi][k] + if distances[xi] == distances[yi] + 1: + # yi in on a shortest path to ui + if not bitset_in(visited, yi): + waiting_list[i_end] = yi + i_end += 1 + bitset_add(visited, yi) + + # Now, visited contains all vertices on geodesics from ui to any other + # vertex in S + bitset_union(closure, closure, visited) + + cdef list ret = [int_to_vertex[ui] for ui in range(n) if bitset_in(closure, ui)] + + bitset_free(seen) + bitset_free(visited) + bitset_free(closure) + free_short_digraph(sd) + + return ret diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index 2ab81f802b2..d0850f13357 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -2470,14 +2470,23 @@ def set_embedding(self, embedding): """ Set a combinatorial embedding dictionary to ``_embedding`` attribute. - Dictionary is organized with vertex labels as keys and a list of each - vertex's neighbors in clockwise order. + The dictionary ``embedding`` represents a combinatorial embedding of + ``self`` and is organized as a mapping from vertex labels to list of + vertex neighbors in clockwise order. - Dictionary is error-checked for validity. + Parameter ``embedding`` is error-checked for validity. + + .. WARNING:: + + Combinatorial embeddings are defined for simple graphs only (i.e., + without loops or multiple edges). Therefore, an error is raised when + this method is used for a graph with loops or multiple edges. INPUT: - - ``embedding`` -- a dictionary + - ``embedding`` -- dictionary representing a combinatorial embedding of + ``self``. Format: "{v1: [v2,v3], v2: [v1], v3: [v1]}" (clockwise + ordering of neighbors at each vertex). EXAMPLES:: @@ -2487,7 +2496,21 @@ def set_embedding(self, embedding): Traceback (most recent call last): ... ValueError: vertices in ['s'] from the embedding do not belong to the graph + + TESTS:: + + sage: G = Graph([(0, 0)], loops=True) + sage: G.set_embedding({0: [0]}) + Traceback (most recent call last): + ... + ValueError: This method is not known to work on graphs with loops. Perhaps this method can be updated to handle them, but in the meantime if you want to use it please disallow loops using allow_loops(). + sage: G = Graph([(0, 1), (0, 1)], multiedges=True) + sage: G.set_embedding({0: [1], 1: [0]}) + Traceback (most recent call last): + ... + ValueError: This method is not known to work on graphs with multiedges. Perhaps this method can be updated to handle them, but in the meantime if you want to use it please disallow multiedges using allow_multiple_edges(). """ + self._scream_if_not_simple() self._check_embedding_validity(embedding, boolean=False) self._embedding = embedding @@ -3492,7 +3515,7 @@ def antisymmetric(self): True """ if not self._directed: - # An undirected graph is antisymmetric only if all it's edges are + # An undirected graph is antisymmetric only if all its edges are # loops return self.size() == len(self.loop_edges()) if self.has_loops(): @@ -6331,8 +6354,11 @@ def edge_disjoint_spanning_trees(self, k, root=None, solver=None, verbose=0): By Edmond's theorem, a graph which is `k`-connected always has `k` edge-disjoint arborescences, regardless of the root we pick:: - sage: g = digraphs.RandomDirectedGNP(28, .3) # reduced from 30 to 28, cf. #9584 + sage: g = digraphs.RandomDirectedGNP(11, .3) # reduced from 30 to 11, cf. #32169 sage: k = Integer(g.edge_connectivity()) + sage: while not k: + ....: g = digraphs.RandomDirectedGNP(11, .3) + ....: k = Integer(g.edge_connectivity()) sage: arborescences = g.edge_disjoint_spanning_trees(k) # long time (up to 15s on sage.math, 2011) sage: all(a.is_directed_acyclic() for a in arborescences) # long time True @@ -6341,7 +6367,9 @@ def edge_disjoint_spanning_trees(self, k, root=None, solver=None, verbose=0): In the undirected case, we can only ensure half of it:: - sage: g = graphs.RandomGNP(30, .3) + sage: g = graphs.RandomGNP(14, .3) # reduced from 30 to 14, see #32169 + sage: while not g.is_biconnected(): + ....: g = graphs.RandomGNP(14, .3) sage: k = Integer(g.edge_connectivity()) // 2 sage: trees = g.edge_disjoint_spanning_trees(k) sage: all(t.is_tree() for t in trees) @@ -23560,18 +23588,18 @@ def edge_polytope(self, backend=None): sage: P.is_combinatorially_isomorphic(polytopes.cross_polytope(3)) True - The EP of a graph with edges is isomorphic - to the product of it's connected components with edges:: + The EP of a graph is isomorphic to the subdirect sum of + its connected components EPs:: - sage: n = randint(5, 12) - sage: G = Graph() - sage: while not G.num_edges(): - ....: G = graphs.RandomGNP(n, 0.2) + sage: n = randint(3, 6) + sage: G1 = graphs.RandomGNP(n, 0.2) + sage: n = randint(3, 6) + sage: G2 = graphs.RandomGNP(n, 0.2) + sage: G = G1.disjoint_union(G2) sage: P = G.edge_polytope() - sage: components = [G.subgraph(c).edge_polytope() - ....: for c in G.connected_components() - ....: if G.subgraph(c).num_edges()] - sage: P.is_combinatorially_isomorphic(product(components)) + sage: P1 = G1.edge_polytope() + sage: P2 = G2.edge_polytope() + sage: P.is_combinatorially_isomorphic(P1.subdirect_sum(P2)) True All trees on `n` vertices have isomorphic EPs:: @@ -23662,18 +23690,18 @@ def symmetric_edge_polytope(self, backend=None): sage: P.dim() == n - G.connected_components_number() True - The SEP of a graph with edges is isomorphic - to the product of it's connected components with edges:: + The SEP of a graph is isomorphic to the subdirect sum of + its connected components SEP's:: - sage: n = randint(5, 12) - sage: G = Graph() - sage: while not G.num_edges(): - ....: G = graphs.RandomGNP(n, 0.2) + sage: n = randint(3, 6) + sage: G1 = graphs.RandomGNP(n, 0.2) + sage: n = randint(3, 6) + sage: G2 = graphs.RandomGNP(n, 0.2) + sage: G = G1.disjoint_union(G2) sage: P = G.symmetric_edge_polytope() - sage: components = [G.subgraph(c).symmetric_edge_polytope() - ....: for c in G.connected_components() - ....: if G.subgraph(c).num_edges()] - sage: P.is_combinatorially_isomorphic(product(components)) + sage: P1 = G1.symmetric_edge_polytope() + sage: P2 = G2.symmetric_edge_polytope() + sage: P.is_combinatorially_isomorphic(P1.subdirect_sum(P2)) True All trees on `n` vertices have isomorphic SEPs:: diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index 36346cdaec7..4d37caa6bbb 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -9429,6 +9429,7 @@ def bipartite_double(self, extended=False): from sage.graphs.connectivity import is_triconnected from sage.graphs.comparability import is_comparability from sage.graphs.comparability import is_permutation + from sage.graphs.convexity_properties import geodetic_closure from sage.graphs.domination import is_dominating from sage.graphs.domination import is_redundant from sage.graphs.domination import private_neighbors @@ -9482,7 +9483,8 @@ def bipartite_double(self, extended=False): "edge_isoperimetric_number" : "Expansion properties", "vertex_isoperimetric_number" : "Expansion properties", "fractional_chromatic_number" : "Coloring", - "fractional_chromatic_index" : "Coloring" + "fractional_chromatic_index" : "Coloring", + "geodetic_closure" : "Leftovers" } __doc__ = __doc__.replace("{INDEX_OF_METHODS}",gen_thematic_rest_table_index(Graph,_additional_categories)) diff --git a/src/sage/graphs/tutte_polynomial.py b/src/sage/graphs/tutte_polynomial.py index f01a21437f9..297b1347481 100644 --- a/src/sage/graphs/tutte_polynomial.py +++ b/src/sage/graphs/tutte_polynomial.py @@ -544,10 +544,12 @@ def tutte_polynomial(G, edge_selector=None, cache=None): + 105*x^2*y^2 + 65*x*y^3 + 35*y^4 + 180*x^3 + 240*x^2*y + 171*x*y^2 + 75*y^3 + 120*x^2 + 168*x*y + 84*y^2 + 36*x + 36*y - The Tutte polynomial of `G` evaluated at (1,1) is the number of + The Tutte polynomial of a connected graph `G` evaluated at (1,1) is the number of spanning trees of `G`:: sage: G = graphs.RandomGNP(10,0.6) + sage: while not G.is_connected(): + ....: G = graphs.RandomGNP(10,0.6) sage: G.tutte_polynomial()(1,1) == G.spanning_trees_count() True diff --git a/src/sage/groups/abelian_gps/abelian_group.py b/src/sage/groups/abelian_gps/abelian_group.py index 00cf0f3c9d7..1c9ce29e858 100644 --- a/src/sage/groups/abelian_gps/abelian_group.py +++ b/src/sage/groups/abelian_gps/abelian_group.py @@ -974,9 +974,9 @@ def gens_orders(self): sage: F = AbelianGroup(3, [2], names='abc') sage: list(map(type, F.gens_orders())) - [, - , - ] + [, + , + ] """ return self._gens_orders @@ -1022,9 +1022,9 @@ def invariants(self): sage: F = AbelianGroup(3, [2], names='abc') sage: list(map(type, F.gens_orders())) - [, - , - ] + [, + , + ] """ # TODO: deprecate return self.gens_orders() diff --git a/src/sage/groups/additive_abelian/qmodnz.py b/src/sage/groups/additive_abelian/qmodnz.py index 344344234a6..6fdb3838fd2 100644 --- a/src/sage/groups/additive_abelian/qmodnz.py +++ b/src/sage/groups/additive_abelian/qmodnz.py @@ -31,7 +31,8 @@ from sage.structure.parent import Parent from sage.structure.unique_representation import UniqueRepresentation -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.categories.commutative_additive_groups import CommutativeAdditiveGroups from .qmodnz_element import QmodnZ_Element diff --git a/src/sage/groups/conjugacy_classes.py b/src/sage/groups/conjugacy_classes.py index c3a3a8460c7..fd79d60ee5b 100644 --- a/src/sage/groups/conjugacy_classes.py +++ b/src/sage/groups/conjugacy_classes.py @@ -437,7 +437,7 @@ def cardinality(self): sage: cc.cardinality() 3840 sage: type(cc.cardinality()) - + """ return self._gap_().Size().sage() diff --git a/src/sage/groups/finitely_presented.py b/src/sage/groups/finitely_presented.py index ee364c289b0..10f52fc6d80 100644 --- a/src/sage/groups/finitely_presented.py +++ b/src/sage/groups/finitely_presented.py @@ -75,7 +75,7 @@ sage: a.gap().Order() 2 sage: type(_) # note that the above output is not a Sage integer - + You can use call syntax to replace the generators with a set of arbitrary ring elements. For example, take the free abelian group @@ -397,7 +397,7 @@ def wrap_FpGroup(libgap_fpgroup): sage: P = F / libgap([ a_cubed ]); P sage: type(P) - + Now wrap it:: @@ -775,7 +775,7 @@ class FinitelyPresentedGroup(GroupMixinLibGAP, UniqueRepresentation, sage: H.gap() sage: type(_) - + """ Element = FinitelyPresentedGroupElement diff --git a/src/sage/groups/free_group.py b/src/sage/groups/free_group.py index e3c3f785b7b..68c0f909bf0 100644 --- a/src/sage/groups/free_group.py +++ b/src/sage/groups/free_group.py @@ -322,7 +322,7 @@ def Tietze(self): sage: type(a.Tietze()) <... 'tuple'> sage: type(a.Tietze()[0]) - + """ tl = self.gap().TietzeWordAbstractWord() return tuple(tl.sage()) @@ -709,7 +709,7 @@ def wrap_FreeGroup(libgap_free_group): sage: F = libgap.FreeGroup(['a', 'b']) sage: type(F) - + Now wrap it:: diff --git a/src/sage/groups/libgap_morphism.py b/src/sage/groups/libgap_morphism.py index 86a16984e0c..75785e2e382 100644 --- a/src/sage/groups/libgap_morphism.py +++ b/src/sage/groups/libgap_morphism.py @@ -133,7 +133,7 @@ class GroupMorphism_libgap(Morphism): CompositionMapping( [ (6,7,8,10,9)(11,13,14,12,15)(16,19,20,18,17)(21,25,22,24,23) ] -> [ [ [ Z(5)^0, 0*Z(5) ], [ Z(5)^0, Z(5)^0 ] ] ], ) sage: type(_) - + sage: F = GF(7); MS = MatrixSpace(F,2,2) sage: F.multiplicative_generator() diff --git a/src/sage/groups/libgap_wrapper.pyx b/src/sage/groups/libgap_wrapper.pyx index 451cb5c65c2..01776f0df18 100644 --- a/src/sage/groups/libgap_wrapper.pyx +++ b/src/sage/groups/libgap_wrapper.pyx @@ -27,7 +27,7 @@ its output via LibGAP:: sage: FooGroup() sage: type(FooGroup().gap()) - + The element class is a subclass of :class:`~sage.structure.element.MultiplicativeGroupElement`. To use @@ -285,7 +285,7 @@ class ParentLibGAP(SageObject): sage: G.gap().parent() C library interface to GAP sage: type(G.gap()) - + This can be useful, for example, to call GAP functions that are not wrapped in Sage:: @@ -325,7 +325,7 @@ class ParentLibGAP(SageObject): TESTS:: sage: type(G.ngens()) - + """ return Integer(len(self.gens())) @@ -504,14 +504,14 @@ cdef class ElementLibGAP(MultiplicativeGroupElement): sage: xg a*b*a^-1*b^-1 sage: type(xg) - + TESTS:: sage: libgap(FreeGroup('a, b').an_element()) a*b sage: type(libgap(FreeGroup('a, b').an_element())) - + """ return self._libgap diff --git a/src/sage/groups/misc_gps/argument_groups.py b/src/sage/groups/misc_gps/argument_groups.py index 818185f783e..1cf801fad85 100644 --- a/src/sage/groups/misc_gps/argument_groups.py +++ b/src/sage/groups/misc_gps/argument_groups.py @@ -1534,7 +1534,7 @@ def _act_on_(self, other, is_left): sage: S(-1) * int(4) -4 sage: type(_) - + sage: S(-1) * QQ(4) -4 sage: _.parent() @@ -1641,7 +1641,7 @@ def __init__(self, category): sage: from sage.groups.misc_gps.argument_groups import SignGroup sage: S = SignGroup() sage: S.base() # indirect doctest - + """ return super(SignGroup, self).__init__(base=int, category=category) diff --git a/src/sage/groups/perm_gps/permgroup.py b/src/sage/groups/perm_gps/permgroup.py index 11b640c7c45..f91dcd8fcca 100644 --- a/src/sage/groups/perm_gps/permgroup.py +++ b/src/sage/groups/perm_gps/permgroup.py @@ -2852,7 +2852,7 @@ def _subgroup_constructor(self, libgap_group): sage: g = g1*g2 sage: Hgap = G.gap().Subgroup([g.gap()]) sage: type(Hgap) - + sage: H = G._subgroup_constructor(Hgap); H Subgroup generated by [(1,6,21,12,20,17)(2,10,15,9,11,5)(3,14,8)(4,18)(7,16)] of (The projective general unitary group of degree 3 over Finite Field of size 2) """ diff --git a/src/sage/groups/perm_gps/permgroup_element.pyx b/src/sage/groups/perm_gps/permgroup_element.pyx index 31e6ccce5ec..33057e459ef 100644 --- a/src/sage/groups/perm_gps/permgroup_element.pyx +++ b/src/sage/groups/perm_gps/permgroup_element.pyx @@ -1560,7 +1560,7 @@ cdef class PermutationGroupElement(MultiplicativeGroupElement): sage: t=PermutationGroupElement(L).multiplicative_order(); t 1492182350939279320058875736615841068547583863326864530410 sage: type(t) - + """ order = None cdef long long order_c = 1 diff --git a/src/sage/groups/perm_gps/permgroup_morphism.py b/src/sage/groups/perm_gps/permgroup_morphism.py index 29521593601..55ceb218817 100644 --- a/src/sage/groups/perm_gps/permgroup_morphism.py +++ b/src/sage/groups/perm_gps/permgroup_morphism.py @@ -117,11 +117,10 @@ def image(self, J): sage: G = L.galois_group() sage: D4 = DihedralGroup(4) sage: h = D4.isomorphism_to(G) - sage: h.image(D4) - Subgroup generated by [(1,2)(3,4)(5,7)(6,8), (1,6,4,7)(2,5,3,8)] of (Galois group 8T4 ([4]2) with order 8 of x^8 + 4*x^7 + 12*x^6 + 22*x^5 + 23*x^4 + 14*x^3 + 28*x^2 + 24*x + 16) - sage: r, s = D4.gens() - sage: h.image(r) - (1,6,4,7)(2,5,3,8) + sage: h.image(D4).is_isomorphic(G) + True + sage: all(h.image(g) in G for g in D4.gens()) + True """ H = self.codomain() if J in self.domain(): diff --git a/src/sage/groups/perm_gps/permgroup_named.py b/src/sage/groups/perm_gps/permgroup_named.py index f1c8c715889..5010e958a3c 100644 --- a/src/sage/groups/perm_gps/permgroup_named.py +++ b/src/sage/groups/perm_gps/permgroup_named.py @@ -2127,9 +2127,9 @@ def cardinality(self): TESTS:: sage: type(TransitiveGroups(12).cardinality()) - + sage: type(TransitiveGroups(0).cardinality()) - + """ # gap.NrTransitiveGroups(0) fails, so Sage needs to handle this @@ -2519,9 +2519,9 @@ def cardinality(self): TESTS:: sage: type(PrimitiveGroups(12).cardinality()) - + sage: type(PrimitiveGroups(0).cardinality()) - + Check for :trac:`31774`:: diff --git a/src/sage/interfaces/axiom.py b/src/sage/interfaces/axiom.py index 50991843902..d46b67bbb32 100644 --- a/src/sage/interfaces/axiom.py +++ b/src/sage/interfaces/axiom.py @@ -132,7 +132,7 @@ sage: f = axiom('(x^5 - y^5)^10000') # not tested Interrupting Axiom... ... - : Ctrl-c pressed while running Axiom + : Ctrl-c pressed while running Axiom :: diff --git a/src/sage/interfaces/chomp.py b/src/sage/interfaces/chomp.py index 4d5f1ba4570..f15dc29adcc 100644 --- a/src/sage/interfaces/chomp.py +++ b/src/sage/interfaces/chomp.py @@ -138,7 +138,8 @@ def __call__(self, program, complex, subcomplex=None, **kwds): from sage.topology.simplicial_complex import SimplicialComplex, Simplex from sage.homology.chain_complex import HomologyGroup from subprocess import Popen, PIPE - from sage.rings.all import QQ, ZZ + from sage.rings.integer_ring import ZZ + from sage.rings.rational_field import QQ from sage.modules.all import VectorSpace, vector from sage.combinat.free_module import CombinatorialFreeModule diff --git a/src/sage/interfaces/fricas.py b/src/sage/interfaces/fricas.py index 98e452513cf..514f02fccd4 100644 --- a/src/sage/interfaces/fricas.py +++ b/src/sage/interfaces/fricas.py @@ -1308,7 +1308,7 @@ def _parse_and_eval(s, start=0): sage: FriCASElement._parse_and_eval('(a "(b c)")') Traceback (most recent call last): ... - TypeError: cannot coerce arguments: no canonical coercion from to Symbolic Ring + TypeError: cannot coerce arguments: no canonical coercion from to Symbolic Ring """ a = start diff --git a/src/sage/interfaces/giac.py b/src/sage/interfaces/giac.py index 0a2fc56812a..8e0ff6843fb 100644 --- a/src/sage/interfaces/giac.py +++ b/src/sage/interfaces/giac.py @@ -856,7 +856,7 @@ def __float__(self): sage: float(giac(1/2)) 0.5 sage: type(_) - + """ return float(giac.eval('evalf(%s)' % self.name())) diff --git a/src/sage/interfaces/gp.py b/src/sage/interfaces/gp.py index 7a4c1b90603..48fe1a16158 100644 --- a/src/sage/interfaces/gp.py +++ b/src/sage/interfaces/gp.py @@ -913,7 +913,7 @@ def _sage_(self): sage: s.sage() 'foo' sage: type(s.sage()) - + """ if self.is_string(): return str(self) diff --git a/src/sage/interfaces/lie.py b/src/sage/interfaces/lie.py index deb16fdfe27..43c3ec3fdd2 100644 --- a/src/sage/interfaces/lie.py +++ b/src/sage/interfaces/lie.py @@ -209,7 +209,7 @@ sage: b = a.sage(); b # optional - lie 1234 sage: type(b) # optional - lie - + Vectors:: @@ -226,7 +226,7 @@ [1 2] [3 4] sage: type(b) # optional - lie - + Polynomials:: @@ -234,7 +234,7 @@ sage: b = a.sage(); b # optional - lie -2*x0^2*x1 + x0*x1^2 sage: type(b) # optional - lie - + Text:: diff --git a/src/sage/interfaces/macaulay2.py b/src/sage/interfaces/macaulay2.py index 1d942d497d7..07811a8c974 100644 --- a/src/sage/interfaces/macaulay2.py +++ b/src/sage/interfaces/macaulay2.py @@ -1562,7 +1562,8 @@ def _sage_(self): #Handle the ZZ/n case ambient = self.ambient() if ambient.external_string() == 'ZZ': - from sage.rings.all import ZZ, GF + from sage.rings.integer_ring import ZZ + from sage.rings.finite_rings.finite_field_constructor import GF external_string = self.external_string() zz, n = external_string.split("/") @@ -1600,7 +1601,8 @@ def _sage_(self): return PolynomialRing(base_ring, order=order, names=gens) elif cls_str == "GaloisField": - from sage.rings.all import ZZ, GF + from sage.rings.integer_ring import ZZ + from sage.rings.finite_rings.finite_field_constructor import GF gf, n = repr_str.split(" ") n = ZZ(n) if n.is_prime(): diff --git a/src/sage/interfaces/maxima_abstract.py b/src/sage/interfaces/maxima_abstract.py index 3fe2dd7bbab..917059de0ab 100644 --- a/src/sage/interfaces/maxima_abstract.py +++ b/src/sage/interfaces/maxima_abstract.py @@ -1216,18 +1216,18 @@ def _sage_(self): sage: b = a._sage_(); b sqrt(2) + 2.5 sage: type(b) - + We illustrate an automatic coercion:: sage: c = b + sqrt(3); c sqrt(3) + sqrt(2) + 2.5 sage: type(c) - + sage: d = sqrt(3) + b; d sqrt(3) + sqrt(2) + 2.5 sage: type(d) - + sage: a = sage.calculus.calculus.maxima('x^(sqrt(y)+%pi) + sin(%e + %pi)') sage: a._sage_() diff --git a/src/sage/interfaces/polymake.py b/src/sage/interfaces/polymake.py index 4111116598c..632455564b2 100644 --- a/src/sage/interfaces/polymake.py +++ b/src/sage/interfaces/polymake.py @@ -2174,17 +2174,17 @@ def _eval_line(self, line, allow_use_file=True, wait_for_prompt=True, restart_if work in an interactive session and often in doc tests, too. However, sometimes it hangs, and therefore we remove it from the tests, for now:: - sage: c = polymake.cube(15) # optional - polymake - sage: polymake.eval('print {}->F_VECTOR;'.format(c.name()), timeout=1) # not tested # optional - polymake + sage: c = polymake.cube(15) # optional - polymake_expect + sage: polymake.eval('print {}->F_VECTOR;'.format(c.name()), timeout=1) # not tested # optional - polymake_expect Traceback (most recent call last): ... RuntimeError: Polymake fails to respond timely We verify that after the timeout, polymake is still able to give answers:: - sage: c # optional - polymake + sage: c # optional - polymake_expect cube of dimension 15 - sage: c.N_VERTICES # optional - polymake + sage: c.N_VERTICES # optional - polymake_expect 32768 Note, however, that the recovery after a timeout is not perfect. diff --git a/src/sage/interfaces/qepcad.py b/src/sage/interfaces/qepcad.py index 29baa767b4e..3007961aad6 100644 --- a/src/sage/interfaces/qepcad.py +++ b/src/sage/interfaces/qepcad.py @@ -2253,7 +2253,7 @@ def exactly_k(self, k, v, formula, allow_multi=False): sage: qf.exactly_k(0, b, a*b == 1) (A b)[~a b = 1] """ - from sage.all import ZZ + from sage.rings.integer_ring import ZZ k = ZZ(k) if k < 0: raise ValueError("negative k in exactly_k quantifier") diff --git a/src/sage/interfaces/singular.py b/src/sage/interfaces/singular.py index d9c0a90fb08..4c5cf3dfd6b 100644 --- a/src/sage/interfaces/singular.py +++ b/src/sage/interfaces/singular.py @@ -1608,7 +1608,7 @@ def sage_global_ring(self): # extract the ring of coefficients singular = self.parent() charstr = singular.eval('charstr(basering)').split(',',1) - from sage.all import ZZ + from sage.rings.integer_ring import ZZ is_extension = len(charstr)==2 if charstr[0] in ['integer', 'ZZ']: br = ZZ @@ -1994,7 +1994,7 @@ def _sage_(self, R=None): sage: singular(5).sage() 5 sage: type(singular(int(5)).sage()) - + """ typ = self.type() diff --git a/src/sage/libs/coxeter3/coxeter_group.py b/src/sage/libs/coxeter3/coxeter_group.py index b4118ca9592..20441104bff 100644 --- a/src/sage/libs/coxeter3/coxeter_group.py +++ b/src/sage/libs/coxeter3/coxeter_group.py @@ -158,13 +158,27 @@ def simple_reflections(self): sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3 sage: s = W.simple_reflections() # optional - coxeter3 sage: s[2]*s[1]*s[2] # optional - coxeter3 - [2, 1, 2] + [1, 2, 1] """ - from sage.combinat.family import Family + from sage.sets.family import Family return Family(self.index_set(), lambda i: self.element_class(self, [i])) gens = simple_reflections + def from_reduced_word(self, w): + """ + Return an element of ``self`` from its (reduced) word. + + EXAMPLES:: + + sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3 + sage: W.from_reduced_word([1, 3]) # optional - coxeter3 + [1, 3] + sage: W.from_reduced_word([3, 1]) # optional - coxeter3 + [1, 3] + """ + return self.element_class(self, w) + def rank(self): """ Return the rank of this Coxeter group, that is, the number of generators. @@ -393,7 +407,7 @@ def parabolic_kazhdan_lusztig_polynomial(self, u, v, J, constant_term_one=True): sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3 sage: type(W.parabolic_kazhdan_lusztig_polynomial([2],[],[1])) # optional - coxeter3 - + """ u = self(u) v = self(v) @@ -419,9 +433,21 @@ def __init__(self, parent, x): sage: W = CoxeterGroup(['A', 3], implementation='coxeter3') # optional - coxeter3 sage: W([2,1,2]) # optional - coxeter3 [1, 2, 1] + + Check that :trac:`32266` is fixed:: + + sage: A3 = CoxeterGroup('A3', implementation='coxeter3') # optional - coxeter3 + sage: s1,s2,s3 = A3.simple_reflections() # optional - coxeter3 + sage: s1*s3 # optional - coxeter3 + [1, 3] + sage: s3*s1 # optional - coxeter3 + [1, 3] + sage: s3*s1 == s1*s3 # optional - coxeter3 + True """ if not isinstance(x, CoxGroupElement): x = CoxGroupElement(parent._coxgroup, x).reduced() + x = x.normal_form() ElementWrapper.__init__(self, parent, x) def __iter__(self): @@ -446,7 +472,7 @@ def coatoms(self): sage: W = CoxeterGroup(['B', 3], implementation='coxeter3') # optional - coxeter3 sage: w = W([1,2,3]) # optional - coxeter3 sage: w.coatoms() # optional - coxeter3 - [[2, 3], [1, 3], [1, 2]] + [[2, 3], [3, 1], [1, 2]] """ W = self.parent() return [W(w) for w in self.value.coatoms()] @@ -528,6 +554,8 @@ def _mul_(self, y): [] sage: s[1]*s[2]*s[1] # optional - coxeter3 [1, 2, 1] + sage: s[2]*s[1]*s[2] # optional - coxeter3 + [1, 2, 1] """ return self.__class__(self.parent(), self.value * y.value) diff --git a/src/sage/libs/ecl.pyx b/src/sage/libs/ecl.pyx index a0237505d91..85dc3d1e564 100644 --- a/src/sage/libs/ecl.pyx +++ b/src/sage/libs/ecl.pyx @@ -1296,7 +1296,7 @@ cdef class EclListIterator: sage: from sage.libs.ecl import * sage: I=EclListIterator(EclObject("(1 2 3)")) sage: type(I) - + sage: [i for i in I] [, , ] sage: [i for i in EclObject("(1 2 3)")] @@ -1318,7 +1318,7 @@ cdef class EclListIterator: sage: from sage.libs.ecl import * sage: I=EclListIterator(EclObject("(1 2 3)")) sage: type(I) - + """ if not o.listp(): diff --git a/src/sage/libs/eclib/homspace.pyx b/src/sage/libs/eclib/homspace.pyx index 900aa7834a9..d12f35dc82f 100644 --- a/src/sage/libs/eclib/homspace.pyx +++ b/src/sage/libs/eclib/homspace.pyx @@ -23,7 +23,7 @@ cdef class ModularSymbols: sage: M = CremonaModularSymbols(225) sage: type(M) - + """ def __init__(self, long level, int sign=0, bint cuspidal=False, int verbose=0): """ @@ -242,7 +242,7 @@ cdef class ModularSymbols: sage: M = CremonaModularSymbols(37) sage: t = M.sparse_hecke_matrix(2); type(t) - + sage: print(t) [ 3 0 0 0 0] [-1 -1 1 1 0] diff --git a/src/sage/libs/eclib/mat.pyx b/src/sage/libs/eclib/mat.pyx index d740a695654..2ad3474b221 100644 --- a/src/sage/libs/eclib/mat.pyx +++ b/src/sage/libs/eclib/mat.pyx @@ -21,7 +21,7 @@ cdef class Matrix: sage: M = CremonaModularSymbols(225) sage: t = M.hecke_matrix(2) sage: type(t) - + sage: t 61 x 61 Cremona matrix over Rational Field @@ -30,7 +30,7 @@ cdef class Matrix: sage: t = CremonaModularSymbols(11).hecke_matrix(2); t 3 x 3 Cremona matrix over Rational Field sage: type(t) - + """ def __repr__(self): """ @@ -204,12 +204,12 @@ cdef class Matrix: [ 0 1] [ 1 -1] sage: type(s) - + sage: s = t.sage_matrix_over_ZZ(sparse=False); s [ 0 1] [ 1 -1] sage: type(s) - + """ cdef long n = self.nrows() cdef long i, j, k diff --git a/src/sage/libs/eclib/mwrank.pyx b/src/sage/libs/eclib/mwrank.pyx index 2d10fd76180..0c20771d558 100644 --- a/src/sage/libs/eclib/mwrank.pyx +++ b/src/sage/libs/eclib/mwrank.pyx @@ -202,7 +202,7 @@ cdef class _bigint: sage: _bigint('123') 123 sage: type(_bigint(123)) - + """ s = str(x) if s.isdigit() or s[0] == "-" and s[1:].isdigit(): @@ -357,7 +357,7 @@ cdef class _Curvedata: # cython class wrapping eclib's Curvedata class sage: E.silverman_bound() 6.52226179519101... sage: type(E.silverman_bound()) - + """ return Curvedata_silverman_bound(self.x) @@ -570,7 +570,7 @@ cdef class _mw: sage: EQ [] sage: type(EQ) - + sage: E = _Curvedata(0,0,1,-7,6) sage: EQ = _mw(E) diff --git a/src/sage/libs/gap/libgap.pyx b/src/sage/libs/gap/libgap.pyx index 9f9f62be13a..6a9d4b2ceee 100644 --- a/src/sage/libs/gap/libgap.pyx +++ b/src/sage/libs/gap/libgap.pyx @@ -12,7 +12,7 @@ EXAMPLES:: sage: a 10 sage: type(a) - + sage: a*a 100 sage: timeit('a*a') # random output @@ -35,7 +35,7 @@ objects to GAP objects, for example strings to strings:: sage: libgap('List([1..10], i->i^2)') "List([1..10], i->i^2)" sage: type(_) - + You can usually use the :meth:`~sage.libs.gap.element.GapElement.sage` method to convert the resulting GAP element back to its Sage @@ -44,7 +44,7 @@ equivalent:: sage: a.sage() 10 sage: type(_) - + sage: libgap.eval('5/3 + 7*E(3)').sage() 7*zeta3 + 5/3 @@ -93,7 +93,7 @@ can be used as follows:: sage: lst = libgap([1,5,7]); lst [ 1, 5, 7 ] sage: type(lst) - + sage: len(lst) 3 sage: lst[0] @@ -101,7 +101,7 @@ can be used as follows:: sage: [ x^2 for x in lst ] [1, 25, 49] sage: type(_[0]) - + Note that you can access the elements of GAP ``List`` objects as you would expect from Python (with indexing starting at 0), but the @@ -637,7 +637,7 @@ class Gap(Parent): EXAMPLES:: sage: type(libgap) - + sage: type(libgap._get_object()) """ diff --git a/src/sage/libs/giac/giac.pyx b/src/sage/libs/giac/giac.pyx index abd6438744e..916b66f3bd1 100644 --- a/src/sage/libs/giac/giac.pyx +++ b/src/sage/libs/giac/giac.pyx @@ -1457,7 +1457,7 @@ cdef class Pygen(GiacMethods_base): sage: a=libgiac('10'); b=libgiac('2**300') sage: a;type(ZZ(a)) 10 - + sage: next_prime(b) 2037035976334486086268445688409378161051468393665936250636140449354381299763336706183397533 sage: c=libgiac('2 % nextprime(2**40)') diff --git a/src/sage/libs/lcalc/lcalc_Lfunction.pyx b/src/sage/libs/lcalc/lcalc_Lfunction.pyx index 7e54d7e78d5..58deb827aa9 100644 --- a/src/sage/libs/lcalc/lcalc_Lfunction.pyx +++ b/src/sage/libs/lcalc/lcalc_Lfunction.pyx @@ -455,7 +455,7 @@ cdef class Lfunction_I(Lfunction): sage: chi = DirichletGroup(5)[2] #This is a quadratic character sage: L=Lfunction_from_character(chi, type="int") sage: type(L) - + """ Lfunction.__init__(self, name, what_type_L, dirichlet_coefficient, period, Q, OMEGA, gamma,lambd, pole,residue) self._repr += " with integer Dirichlet coefficients" @@ -591,7 +591,7 @@ cdef class Lfunction_D(Lfunction): sage: chi = DirichletGroup(5)[2] #This is a quadratic character sage: L=Lfunction_from_character(chi, type="double") sage: type(L) - + """ Lfunction.__init__(self, name, what_type_L, dirichlet_coefficient, period, Q, OMEGA, gamma,lambd, pole,residue) self._repr += " with real Dirichlet coefficients" @@ -731,7 +731,7 @@ cdef class Lfunction_C: sage: chi = DirichletGroup(5)[1] sage: L=Lfunction_from_character(chi, type="complex") sage: type(L) - + """ Lfunction.__init__(self, name, what_type_L, dirichlet_coefficient, period, Q, OMEGA, gamma,lambd, pole,residue) self._repr += " with complex Dirichlet coefficients" diff --git a/src/sage/libs/linkages/padics/Polynomial_shared.pxi b/src/sage/libs/linkages/padics/Polynomial_shared.pxi index 7c66463ac12..738ab9bf457 100644 --- a/src/sage/libs/linkages/padics/Polynomial_shared.pxi +++ b/src/sage/libs/linkages/padics/Polynomial_shared.pxi @@ -29,7 +29,8 @@ AUTHORS: from cpython.list cimport * from sage.rings.integer cimport Integer from sage.rings.rational cimport Rational -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.ext.stdsage cimport PY_NEW from copy import copy from sage.rings.padics.common_conversion cimport cconv_mpz_t_out_shared, cconv_mpz_t_shared, cconv_mpq_t_out_shared, cconv_mpq_t_shared, cconv_shared diff --git a/src/sage/libs/lrcalc/lrcalc.pyx b/src/sage/libs/lrcalc/lrcalc.pyx index 1cf67dc15ab..b591081ec4c 100644 --- a/src/sage/libs/lrcalc/lrcalc.pyx +++ b/src/sage/libs/lrcalc/lrcalc.pyx @@ -297,7 +297,7 @@ def test_skewtab_to_SkewTableau(outer, inner): cdef dict sf_hashtab_to_dict(hashtab *ht): """ Return a dictionary representing a Schur function. The keys are - partitions and the values are integers . + partitions and the values are integers . EXAMPLES:: @@ -320,7 +320,7 @@ cdef dict sf_hashtab_to_dict(hashtab *ht): cdef dict schubert_hashtab_to_dict(hashtab *ht): """ Return a dictionary corresponding to a Schubert polynomial whose keys - are permutations and whose values are integers . + are permutations and whose values are integers . EXAMPLES:: @@ -341,7 +341,7 @@ cdef dict schubert_hashtab_to_dict(hashtab *ht): cdef dict vp_hashtab_to_dict(hashtab *ht): """ Return a dictionary corresponding to the coproduct of a Schur function whose keys are - pairs of partitions and whose values are integers . + pairs of partitions and whose values are integers . EXAMPLES:: diff --git a/src/sage/libs/mpmath/ext_main.pyx b/src/sage/libs/mpmath/ext_main.pyx index 5821be79073..379971de1a3 100644 --- a/src/sage/libs/mpmath/ext_main.pyx +++ b/src/sage/libs/mpmath/ext_main.pyx @@ -1965,7 +1965,7 @@ cdef class mpf(mpf_base): sage: mpf(-500.5).man 1001 sage: type(_) - + """ return self._mpf_[1] diff --git a/src/sage/libs/mpmath/utils.pyx b/src/sage/libs/mpmath/utils.pyx index d6c9eeea75d..ea5aa54bfc8 100644 --- a/src/sage/libs/mpmath/utils.pyx +++ b/src/sage/libs/mpmath/utils.pyx @@ -402,11 +402,11 @@ def call(func, *args, **kwargs): sage: a.call(a.polylog, 2, 1/2, parent=CC) 0.582240526465012 sage: type(_) - + sage: a.call(a.polylog, 2, 1/2, parent=RDF) 0.5822405264650125 sage: type(_) - + Check that :trac:`11885` is fixed:: diff --git a/src/sage/libs/ntl/ntl_GF2.pyx b/src/sage/libs/ntl/ntl_GF2.pyx index 2a03e7723b4..b899f21548f 100644 --- a/src/sage/libs/ntl/ntl_GF2.pyx +++ b/src/sage/libs/ntl/ntl_GF2.pyx @@ -250,7 +250,7 @@ def unpickle_class_value(cls, x): sage: sage.libs.ntl.ntl_GF2.unpickle_class_value(ntl.GF2,1) 1 sage: type(sage.libs.ntl.ntl_GF2.unpickle_class_value(ntl.GF2,1)) - + """ return cls(x) @@ -263,7 +263,7 @@ def unpickle_class_args(cls, x): sage: sage.libs.ntl.ntl_GF2.unpickle_class_args(ntl.GF2,[1]) 1 sage: type(sage.libs.ntl.ntl_GF2.unpickle_class_args(ntl.GF2,[1])) - + """ return cls(*x) diff --git a/src/sage/libs/ntl/ntl_GF2E.pyx b/src/sage/libs/ntl/ntl_GF2E.pyx index 748449f9c25..252851d40ed 100644 --- a/src/sage/libs/ntl/ntl_GF2E.pyx +++ b/src/sage/libs/ntl/ntl_GF2E.pyx @@ -403,7 +403,7 @@ cdef class ntl_GF2E(object): sage: a.rep() [1 0 0 0 0 0 1 1] sage: type(a.rep()) - + """ cdef ntl_GF2X x = ntl_GF2X.__new__(ntl_GF2X) x.x = GF2E_rep(self.x) diff --git a/src/sage/libs/ntl/ntl_ZZ.pyx b/src/sage/libs/ntl/ntl_ZZ.pyx index 16d04663efa..e132e997e01 100644 --- a/src/sage/libs/ntl/ntl_ZZ.pyx +++ b/src/sage/libs/ntl/ntl_ZZ.pyx @@ -293,7 +293,7 @@ cdef class ntl_ZZ(object): sage: n=ntl.ZZ(2983) sage: type(n._integer_()) - + AUTHOR: Joel B. Mohler """ @@ -403,7 +403,7 @@ def unpickle_class_value(cls, x): sage: sage.libs.ntl.ntl_ZZ.unpickle_class_value(ntl.ZZ, 3) 3 sage: type(sage.libs.ntl.ntl_ZZ.unpickle_class_value(ntl.ZZ, 3)) - + """ return cls(x) @@ -416,7 +416,7 @@ def unpickle_class_args(cls, x): sage: sage.libs.ntl.ntl_ZZ.unpickle_class_args(ntl.ZZ, [3]) 3 sage: type(sage.libs.ntl.ntl_ZZ.unpickle_class_args(ntl.ZZ, [3])) - + """ return cls(*x) diff --git a/src/sage/libs/ntl/ntl_ZZX.pyx b/src/sage/libs/ntl/ntl_ZZX.pyx index 3aea4aca9fc..cee8c5422e6 100644 --- a/src/sage/libs/ntl/ntl_ZZX.pyx +++ b/src/sage/libs/ntl/ntl_ZZX.pyx @@ -226,7 +226,7 @@ cdef class ntl_ZZX(object): sage: x[0] 129381729371289371237128318293718237 sage: type(x[0]) - + sage: x[1] 2 sage: x[2] @@ -278,7 +278,7 @@ cdef class ntl_ZZX(object): sage: L = x.list(); L [129381729371289371237128318293718237, 2, -3, 0, 4] sage: type(L[0]) - + sage: x = ntl.ZZX() sage: L = x.list(); L [] diff --git a/src/sage/libs/ntl/ntl_ZZ_p.pyx b/src/sage/libs/ntl/ntl_ZZ_p.pyx index 4fab1d1a7cb..114963b1882 100644 --- a/src/sage/libs/ntl/ntl_ZZ_p.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_p.pyx @@ -414,7 +414,7 @@ cdef class ntl_ZZ_p(object): sage: x.lift() 8 sage: type(x.lift()) - + """ cdef ntl_ZZ r = ntl_ZZ() self.c.restore_c() @@ -452,12 +452,12 @@ cdef class ntl_ZZ_p(object): sage: x.lift_centered() 8 sage: type(x.lift_centered()) - + sage: x = ntl.ZZ_p(12, 18) sage: x.lift_centered() -6 sage: type(x.lift_centered()) - + """ cdef ntl_ZZ r = self.lift() cdef ntl_ZZ m = self.modulus() @@ -476,7 +476,7 @@ cdef class ntl_ZZ_p(object): 8 sage: type(x._integer_()) - + """ self.c.restore_c() cdef ZZ_c rep = ZZ_p_rep(self.x) @@ -493,7 +493,7 @@ cdef class ntl_ZZ_p(object): sage: c = ntl.ZZ_pContext(20) sage: n = ntl.ZZ_p(2983, c) sage: type(n._sage_()) - + sage: n 3 diff --git a/src/sage/libs/ntl/ntl_ZZ_pContext.pyx b/src/sage/libs/ntl/ntl_ZZ_pContext.pyx index 0c8995608fd..008e6abd8eb 100644 --- a/src/sage/libs/ntl/ntl_ZZ_pContext.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_pContext.pyx @@ -95,7 +95,7 @@ cdef class ntl_ZZ_pContext_class(object): sage: c = ntl.ZZ_pContext(10^30) sage: type(c.modulus()) - + sage: c.modulus() == 10^30 True """ diff --git a/src/sage/libs/ntl/ntl_ZZ_pE.pyx b/src/sage/libs/ntl/ntl_ZZ_pE.pyx index f46b28f95b5..c2802a3391b 100644 --- a/src/sage/libs/ntl/ntl_ZZ_pE.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_pE.pyx @@ -296,7 +296,7 @@ cdef class ntl_ZZ_pE(object): sage: i [9 1] sage: type(i) - + """ return self.get_as_ZZ_pX() @@ -350,6 +350,6 @@ def make_ZZ_pE(x, c): sage: sage.libs.ntl.ntl_ZZ_pE.make_ZZ_pE([4,3], c) [4 3] sage: type(sage.libs.ntl.ntl_ZZ_pE.make_ZZ_pE([4,3], c)) - + """ return ntl_ZZ_pE(x, c) diff --git a/src/sage/libs/ntl/ntl_ZZ_pEX.pyx b/src/sage/libs/ntl/ntl_ZZ_pEX.pyx index 983bbbe826a..4d48f32025b 100644 --- a/src/sage/libs/ntl/ntl_ZZ_pEX.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_pEX.pyx @@ -1251,6 +1251,6 @@ def make_ZZ_pEX(v, modulus): sage: sage.libs.ntl.ntl_ZZ_pEX.make_ZZ_pEX([a,b,b], c) [[3 2] [1 2] [1 2]] sage: type(sage.libs.ntl.ntl_ZZ_pEX.make_ZZ_pEX([a,b,b], c)) - + """ return ntl_ZZ_pEX(v, modulus) diff --git a/src/sage/libs/ntl/ntl_ZZ_pX.pyx b/src/sage/libs/ntl/ntl_ZZ_pX.pyx index d7fb124c62a..bd34a79c85c 100644 --- a/src/sage/libs/ntl/ntl_ZZ_pX.pyx +++ b/src/sage/libs/ntl/ntl_ZZ_pX.pyx @@ -312,7 +312,7 @@ cdef class ntl_ZZ_pX(object): sage: x.list() [1, 3, 5] sage: type(x.list()[0]) - + """ # could be sped up. self.c.restore_c() diff --git a/src/sage/libs/ntl/ntl_mat_ZZ.pyx b/src/sage/libs/ntl/ntl_mat_ZZ.pyx index db14f86b71d..c9f054602e8 100644 --- a/src/sage/libs/ntl/ntl_mat_ZZ.pyx +++ b/src/sage/libs/ntl/ntl_mat_ZZ.pyx @@ -453,7 +453,7 @@ cdef class ntl_mat_ZZ(object): sage: M.charpoly() [-2 -5 1] sage: type(_) - + sage: M.determinant() -2 """ diff --git a/src/sage/libs/pari/convert_sage.pyx b/src/sage/libs/pari/convert_sage.pyx index c8918beb653..62fe5185cfb 100644 --- a/src/sage/libs/pari/convert_sage.pyx +++ b/src/sage/libs/pari/convert_sage.pyx @@ -251,7 +251,7 @@ cpdef gen_to_sage(Gen z, locals=None): sage: s = pari('"foo"').sage(); s 'foo' sage: type(s) - + """ cdef GEN g = z.g cdef long t = typ(g) diff --git a/src/sage/libs/singular/ring.pyx b/src/sage/libs/singular/ring.pyx index 63b63070cd2..9c3ee22c533 100644 --- a/src/sage/libs/singular/ring.pyx +++ b/src/sage/libs/singular/ring.pyx @@ -31,7 +31,7 @@ from sage.libs.singular.decl cimport rDefault, GFInfo, ZnmInfo, nInitChar, AlgEx from sage.rings.integer cimport Integer from sage.rings.integer_ring cimport IntegerRing_class from sage.rings.integer_ring import ZZ -from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing +import sage.rings.abc from sage.rings.number_field.number_field_base cimport NumberField from sage.rings.rational_field import RationalField from sage.rings.finite_rings.finite_field_base import FiniteField as FiniteField_generic @@ -324,7 +324,7 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: _ring = rDefault (_cf ,nvars, _names, nblcks, _order, _block0, _block1, _wvhdl) - elif is_IntegerModRing(base_ring): + elif isinstance(base_ring, sage.rings.abc.IntegerModRing): ch = base_ring.characteristic() if ch < 2: @@ -422,7 +422,7 @@ cdef class ring_wrapper_Py(object): sage: from sage.libs.singular.ring import ring_wrapper_Py sage: ring_wrapper_Py - + """ cdef ring* _ring diff --git a/src/sage/libs/singular/singular.pyx b/src/sage/libs/singular/singular.pyx index c736d56b0c0..cba2147c0ab 100644 --- a/src/sage/libs/singular/singular.pyx +++ b/src/sage/libs/singular/singular.pyx @@ -58,7 +58,7 @@ cdef Rational si2sa_QQ(number *n, number **nn, ring *_ring): sage: P(-1/3).lc() -1/3 sage: type(P(3).lc()) - + """ cdef number *nom cdef number *denom @@ -115,7 +115,7 @@ cdef Integer si2sa_ZZ(number *n, ring *_ring): sage: P(-1234567890).lc() -1234567890 sage: type(P(3).lc()) - + """ cdef Integer z z = Integer() @@ -172,7 +172,7 @@ cdef FFgf2eE si2sa_GFqNTLGF2E(number *n, ring *_ring, Cache_ntl_gf2e cache): sage: f.lc() a^11 + a^10 + a^8 + a^7 + a^6 + a^5 + a^2 + a sage: type(f.lc()) - + """ cdef poly *z cdef long c @@ -207,7 +207,7 @@ cdef object si2sa_GFq_generic(number *n, ring *_ring, object base): sage: f.lc() a^12 + a^11 + a^9 + a^8 + a^7 + 2*a^6 + a^5 sage: type(f.lc()) - + Try the largest characteristic which Singular supports:: diff --git a/src/sage/manifolds/calculus_method.py b/src/sage/manifolds/calculus_method.py index e4d3919e67c..f5830c0bc45 100644 --- a/src/sage/manifolds/calculus_method.py +++ b/src/sage/manifolds/calculus_method.py @@ -52,7 +52,7 @@ def _SR_to_Sympy(expression): sage: a = x^2 + sin(x)^2; a x^2 + sin(x)^2 sage: type(a) - + sage: b = _SR_to_Sympy(a); b x**2 + sin(x)**2 sage: type(b) @@ -89,7 +89,7 @@ def _Sympy_to_SR(expression): sage: from sage.manifolds.calculus_method import _Sympy_to_SR, _SR_to_Sympy sage: a = x^2 + sin(x)^2 sage: type(a) - + sage: b = _SR_to_Sympy(a); b x**2 + sin(x)**2 sage: type(b) diff --git a/src/sage/manifolds/chart.py b/src/sage/manifolds/chart.py index e0630722d3e..8c4e2028aa6 100644 --- a/src/sage/manifolds/chart.py +++ b/src/sage/manifolds/chart.py @@ -206,7 +206,7 @@ class Chart(UniqueRepresentation, SageObject): :mod:`sage.symbolic.expression`):: sage: type(z1) - + In addition to the Python variable name provided in the operator ``<.,.>``, the coordinates are accessible by their indices:: @@ -1502,7 +1502,7 @@ def calculus_method(self): sage: f.expr() x^2 + cos(y)*sin(x) sage: type(f.expr()) - + sage: parent(f.expr()) Symbolic Ring sage: f.display() @@ -1733,7 +1733,7 @@ class RealChart(Chart): :mod:`sage.symbolic.expression`):: sage: type(th) - + sage: latex(th) {\theta} sage: assumptions(th) diff --git a/src/sage/manifolds/chart_func.py b/src/sage/manifolds/chart_func.py index 1c4bf0080c1..6ffc287ca09 100644 --- a/src/sage/manifolds/chart_func.py +++ b/src/sage/manifolds/chart_func.py @@ -134,7 +134,7 @@ class ChartFunction(AlgebraElement, ModuleElementWithMutability): expression:: sage: type(f.expr()) - + A SymPy expression can also be asked for:: @@ -207,7 +207,7 @@ class ChartFunction(AlgebraElement, ModuleElementWithMutability): sage: f0(x,y) = x^2 + 3*y + 1 sage: type(f0) - + sage: f0 (x, y) |--> x^2 + 3*y + 1 sage: f0(x,y) @@ -495,7 +495,7 @@ def expr(self, method=None): sage: f.expr() x^2 + y sage: type(f.expr()) - + Asking for the SymPy expression:: @@ -3057,7 +3057,7 @@ def expr(self, method=None): sage: f.expr() (x - y, x*y, cos(x)*e^y) sage: type(f.expr()[0]) - + A SymPy output:: diff --git a/src/sage/manifolds/continuous_map.py b/src/sage/manifolds/continuous_map.py index 6f060ca13b9..a6356e77f11 100644 --- a/src/sage/manifolds/continuous_map.py +++ b/src/sage/manifolds/continuous_map.py @@ -1503,7 +1503,7 @@ def expr(self, chart1=None, chart2=None): sage: Phi.expr() # equivalent to above since 'uv' and 'xyz' are default charts (u*v, u/v, u + v) sage: type(Phi.expr()[0]) - + Expressions in other charts:: diff --git a/src/sage/manifolds/differentiable/chart.py b/src/sage/manifolds/differentiable/chart.py index 47dd4efd2ec..86a39667cd8 100644 --- a/src/sage/manifolds/differentiable/chart.py +++ b/src/sage/manifolds/differentiable/chart.py @@ -198,7 +198,7 @@ class DiffChart(Chart): :mod:`sage.symbolic.expression`):: sage: type(z1) - + In addition to the Python variable name provided in the operator ``<.,.>``, the coordinates are accessible by their indices:: @@ -829,7 +829,7 @@ class RealDiffChart(DiffChart, RealChart): :mod:`sage.symbolic.expression`):: sage: type(th) - + sage: latex(th) {\theta} sage: assumptions(th) diff --git a/src/sage/manifolds/differentiable/curve.py b/src/sage/manifolds/differentiable/curve.py index 7eb04fc8125..5b12e9d0469 100644 --- a/src/sage/manifolds/differentiable/curve.py +++ b/src/sage/manifolds/differentiable/curve.py @@ -805,6 +805,23 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, prange=None, g = c.plot(color='green', style=':', thickness=3, aspect_ratio=1) sphinx_plot(g) + Cardioid defined in terms of polar coordinates and plotted with respect + to Cartesian coordinates, as an example of use of the optional argument + ``chart``:: + + sage: E. = EuclideanSpace(coordinates='polar') + sage: c = E.curve((1 + cos(ph), ph), (ph, 0, 2*pi)) + sage: c.plot(chart=E.cartesian_coordinates(), aspect_ratio=1) + Graphics object consisting of 1 graphics primitive + + .. PLOT:: + + E = EuclideanSpace(2, coordinates='polar') + r, ph = E.polar_coordinates()[:] + c = E.curve((1 + cos(ph), ph), (ph, 0, 2*pi)) + g = c.plot(chart=E.cartesian_coordinates(), aspect_ratio=1) + sphinx_plot(g) + Plot via a mapping to another manifold: loxodrome of a sphere viewed in `\RR^3`:: @@ -925,21 +942,8 @@ def plot(self, chart=None, ambient_coords=None, mapping=None, prange=None, # # The coordinate expression of the effective curve # - canon_chart = self._domain.canonical_chart() - transf = None - for chart_pair in eff_curve._coord_expression: - if chart_pair == (canon_chart, chart): - transf = eff_curve._coord_expression[chart_pair] - break - else: - # Search for a subchart - for chart_pair in eff_curve._coord_expression: - for schart in chart._subcharts: - if chart_pair == (canon_chart, schart): - transf = eff_curve._coord_expression[chart_pair] - if transf is None: - raise ValueError("No expression has been found for " + - "{} in terms of {}".format(self, chart)) + transf = eff_curve.coord_functions(chart1=self._domain.canonical_chart(), + chart2=chart) # # List of points for the plot curve # diff --git a/src/sage/manifolds/differentiable/diff_map.py b/src/sage/manifolds/differentiable/diff_map.py index fce91145ed5..7f0c09a6b7c 100644 --- a/src/sage/manifolds/differentiable/diff_map.py +++ b/src/sage/manifolds/differentiable/diff_map.py @@ -760,7 +760,7 @@ def differential_functions(self, chart1=None, chart2=None): sage: JJ[2,0] 2*x sage: type(JJ[2,0]) - + sage: bool( JJ[2,0] == J[2][0].expr() ) True diff --git a/src/sage/manifolds/differentiable/examples/euclidean.py b/src/sage/manifolds/differentiable/examples/euclidean.py index bedc6ece275..b0659787b0e 100644 --- a/src/sage/manifolds/differentiable/examples/euclidean.py +++ b/src/sage/manifolds/differentiable/examples/euclidean.py @@ -57,7 +57,7 @@ sage: y y sage: type(y) - + sage: assumptions() [x is real, y is real] diff --git a/src/sage/manifolds/differentiable/examples/real_line.py b/src/sage/manifolds/differentiable/examples/real_line.py index 09c38be8f8d..15b11a84dc1 100644 --- a/src/sage/manifolds/differentiable/examples/real_line.py +++ b/src/sage/manifolds/differentiable/examples/real_line.py @@ -123,7 +123,7 @@ class OpenInterval(DifferentiableManifold): t sage: t = I.canonical_coordinate() sage: type(t) - + However, it can be obtained in the same step as the interval construction by means of the shortcut ``I.``:: @@ -132,7 +132,7 @@ class OpenInterval(DifferentiableManifold): sage: t t sage: type(t) - + The trick is performed by the Sage preparser:: @@ -577,7 +577,7 @@ def canonical_coordinate(self): sage: I.canonical_coordinate() t sage: type(I.canonical_coordinate()) - + sage: I.canonical_coordinate().is_real() True @@ -777,7 +777,7 @@ class RealLine(OpenInterval): t sage: t = R.canonical_coordinate() sage: type(t) - + However, it can be obtained in the same step as the real line construction by means of the shortcut ``R.``:: @@ -786,7 +786,7 @@ class RealLine(OpenInterval): sage: t t sage: type(t) - + The trick is performed by Sage preparser:: diff --git a/src/sage/manifolds/differentiable/manifold.py b/src/sage/manifolds/differentiable/manifold.py index 7766ebb6543..659c84b2d0c 100644 --- a/src/sage/manifolds/differentiable/manifold.py +++ b/src/sage/manifolds/differentiable/manifold.py @@ -70,7 +70,7 @@ sage: y y sage: type(y) - + The South pole is the point of coordinates `(x,y)=(0,0)` in the above chart:: diff --git a/src/sage/manifolds/differentiable/scalarfield.py b/src/sage/manifolds/differentiable/scalarfield.py index 5885f1fb624..ba66d50ad20 100644 --- a/src/sage/manifolds/differentiable/scalarfield.py +++ b/src/sage/manifolds/differentiable/scalarfield.py @@ -209,7 +209,7 @@ class DiffScalarField(ScalarField): sage: f.expr(c_uv) (u^2 + v^2)/(u^2 + v^2 + 1) sage: type(f.expr(c_uv)) - + The method :meth:`~sage.manifolds.scalarfield.ScalarField.coord_function` returns instead a function of the chart coordinates, i.e. an instance of diff --git a/src/sage/manifolds/manifold.py b/src/sage/manifolds/manifold.py index 2645de657c9..1b62341fc84 100644 --- a/src/sage/manifolds/manifold.py +++ b/src/sage/manifolds/manifold.py @@ -60,7 +60,7 @@ sage: y y sage: type(y) - + The South pole is the point of coordinates `(x, y) = (0, 0)` in the above chart:: @@ -1550,7 +1550,7 @@ def chart(self, coordinates='', names=None, calc_method=None, sage: y y sage: type(y) - + But a shorter way to proceed is to use the operator ``<,>`` in the left-hand side of the chart declaration (there is then no need to @@ -2511,7 +2511,7 @@ def set_calculus_method(self, method): sage: f.expr() x^2 + cos(y)*sin(x) sage: type(f.expr()) - + sage: parent(f.expr()) Symbolic Ring sage: f.display() diff --git a/src/sage/manifolds/scalarfield.py b/src/sage/manifolds/scalarfield.py index 29378d6a872..8409ed656b3 100644 --- a/src/sage/manifolds/scalarfield.py +++ b/src/sage/manifolds/scalarfield.py @@ -211,7 +211,7 @@ class ScalarField(CommutativeAlgebraElement, ModuleElementWithMutability): sage: f.expr(c_uv) (u^2 + v^2)/(u^2 + v^2 + 1) sage: type(f.expr(c_uv)) - + The method :meth:`coord_function` returns instead a function of the chart coordinates, i.e. an instance of @@ -1844,7 +1844,7 @@ def expr(self, chart=None, from_chart=None): backend used for coordinate computations:: sage: type(f.expr()) - + sage: M.set_calculus_method('sympy') sage: type(f.expr()) diff --git a/src/sage/matrix/action.pyx b/src/sage/matrix/action.pyx index 14d2d5cc414..6d4d7853b5f 100644 --- a/src/sage/matrix/action.pyx +++ b/src/sage/matrix/action.pyx @@ -66,7 +66,12 @@ from .matrix_space import MatrixSpace, is_MatrixSpace from sage.modules.free_module import FreeModule, is_FreeModule from sage.structure.coerce cimport coercion_model from sage.categories.homset import Hom, End -from sage.schemes.generic.homset import SchemeHomset_generic, SchemeHomset_points + + +try: + from sage.schemes.generic.homset import SchemeHomset_generic, SchemeHomset_points +except ImportError: + SchemeHomset_generic = SchemeHomset_points = () cdef class MatrixMulAction(Action): diff --git a/src/sage/matrix/matrix0.pyx b/src/sage/matrix/matrix0.pyx index 41b8da5f415..bf0b0bff73c 100644 --- a/src/sage/matrix/matrix0.pyx +++ b/src/sage/matrix/matrix0.pyx @@ -44,7 +44,7 @@ from sage.categories.integral_domains import IntegralDomains from sage.rings.ring cimport CommutativeRing from sage.rings.ring import is_Ring -from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing +import sage.rings.abc from sage.rings.integer_ring import is_IntegerRing import sage.modules.free_module @@ -78,7 +78,7 @@ cdef class Matrix(sage.structure.element.Matrix): [1.0 2.0 3.0] [4.0 5.0 6.0] sage: type(a) - + sage: parent(a) Full MatrixSpace of 2 by 3 dense matrices over Complex Double Field @@ -112,7 +112,7 @@ cdef class Matrix(sage.structure.element.Matrix): sage: import sage.matrix.matrix0 sage: A = sage.matrix.matrix0.Matrix(MatrixSpace(QQ,2)) sage: type(A) - + """ P = parent self._parent = P @@ -885,11 +885,11 @@ cdef class Matrix(sage.structure.element.Matrix): sage: M = MatrixSpace(GF(2), 3, 3, implementation='generic') sage: m = M(range(9)) sage: type(m) - + sage: parent(m) Full MatrixSpace of 3 by 3 dense matrices over Finite Field of size 2 (using Matrix_generic_dense) sage: type(m[:2,:2]) - + sage: parent(m[:2,:2]) Full MatrixSpace of 2 by 2 dense matrices over Finite Field of size 2 (using Matrix_generic_dense) """ @@ -4830,7 +4830,10 @@ cdef class Matrix(sage.structure.element.Matrix): sage: B.multiplicative_order() 1 - sage: E = MatrixSpace(GF(11^2,'e'),5).random_element() + sage: M = MatrixSpace(GF(11^2,'e'),5) + sage: E = M.random_element() + sage: while E.det() == 0: + ....: E = M.random_element() sage: (E^E.multiplicative_order()).is_one() True @@ -5563,13 +5566,13 @@ cdef class Matrix(sage.structure.element.Matrix): sage: m = matrix(Zmod(49),2,[2,1,3,3]) sage: type(m) - + sage: ~m [ 1 16] [48 17] sage: m = matrix(Zmod(2^100),2,[2,1,3,3]) sage: type(m) - + sage: (~m)*m [1 0] [0 1] @@ -5749,7 +5752,7 @@ cdef class Matrix(sage.structure.element.Matrix): R = self.base_ring() if algorithm is None and R in _Fields: return ~self - elif algorithm is None and is_IntegerModRing(R): + elif algorithm is None and isinstance(R, sage.rings.abc.IntegerModRing): # Finite fields are handled above. # This is "easy" in that we either get an error or # the right answer. Note that of course there diff --git a/src/sage/matrix/matrix2.pyx b/src/sage/matrix/matrix2.pyx index d4a8ec9d3a1..75d8dc56424 100644 --- a/src/sage/matrix/matrix2.pyx +++ b/src/sage/matrix/matrix2.pyx @@ -62,6 +62,7 @@ AUTHORS: - Michael Jung (2020-10-02): added Bär-Faddeev-LeVerrier algorithm for the Pfaffian +- Moritz Firsching(2020-10-05): added ``quantum_determinant`` """ # **************************************************************************** @@ -94,7 +95,7 @@ from sage.rings.complex_double import CDF from sage.rings.real_mpfr import RealField from sage.rings.complex_mpfr import ComplexField from sage.rings.finite_rings.integer_mod_ring import IntegerModRing -from sage.misc.derivative import multi_derivative +import sage.rings.abc from sage.arith.numerical_approx cimport digits_to_bits from copy import copy @@ -822,8 +823,7 @@ cdef class Matrix(Matrix1): if not K.is_integral_domain(): # The non-integral-domain case is handled almost entirely # separately. - from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing - if is_IntegerModRing(K): + if isinstance(K, sage.rings.abc.IntegerModRing): from sage.libs.pari import pari A = pari(self.lift()) b = pari(B).lift() @@ -1985,7 +1985,6 @@ cdef class Matrix(Matrix1): sage: A.determinant() == B.determinant() True """ - from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing from sage.symbolic.ring import is_SymbolicExpressionRing cdef Py_ssize_t n @@ -2031,7 +2030,7 @@ cdef class Matrix(Matrix1): return d # Special case for Z/nZ or GF(p): - if is_IntegerModRing(R) and self.is_dense(): + if isinstance(R, sage.rings.abc.IntegerModRing) and self.is_dense(): import sys # If the characteristic is prime and smaller than a machine # word, use PARI. @@ -2113,6 +2112,84 @@ cdef class Matrix(Matrix1): self.swap_rows(level, i) return d + def quantum_determinant(self, q=None): + r""" + Return the quantum deteminant of ``self``. + + The quantum determinant of a matrix `M = (m_{ij})_{i,j=1}^n` + is defined by + + .. MATH:: + + \det_q(M) = + \sum_{\sigma \in S_n} (-q)^{\ell(\sigma)} M_{\sigma(i),j}, + + where `S_n` is the symmetric group on `\{1, \ldots, n\}` and + `\ell(\sigma)` denotes the length of `\sigma` written as simple + transpositions (equivalently the number of inversions when + written in one-line notation). + + INPUT: + + - ``q`` -- the parameter `q`; the default is `q \in F[q]`, + where `F` is the base ring of ``self`` + + EXAMPLES:: + + sage: A = matrix([[SR(f'a{i}{j}') for i in range(2)] + ....: for j in range(2)]); A + [a00 a10] + [a01 a11] + sage: A.quantum_determinant() + -a01*a10*q + a00*a11 + + sage: A = matrix([[SR(f'a{i}{j}') for i in range(3)] + ....: for j in range(3)]) + sage: A.quantum_determinant() + -a02*a11*a20*q^3 + (a01*a12*a20 + a02*a10*a21)*q^2 + + (-a00*a12*a21 - a01*a10*a22)*q + a00*a11*a22 + + sage: R. = LaurentPolynomialRing(ZZ) + sage: MS = MatrixSpace(Integers(8), 3) + sage: A = MS([1,7,3, 1,1,1, 3,4,5]) + sage: A.det() + 6 + sage: A.quantum_determinant(q^-2) + 7*q^-6 + q^-4 + q^-2 + 5 + + sage: S. = PolynomialRing(GF(7)) + sage: R. = LaurentPolynomialRing(S) + sage: MS = MatrixSpace(S, 3, sparse=True) + sage: A = MS([[x, y, 3], [4, 2+y, x^2], [0, 1-x, x+y]]) + sage: A.det() + x^4 - x^3 + x^2*y + x*y^2 + 2*x^2 - 2*x*y + 3*y^2 + 2*x - 2 + sage: A.quantum_determinant() + (2*x - 2)*q^2 + (x^4 - x^3 + 3*x*y + 3*y^2)*q + x^2*y + x*y^2 + 2*x^2 + 2*x*y + sage: A.quantum_determinant(int(2)) + 2*x^4 - 2*x^3 + x^2*y + x*y^2 + 2*x^2 + x*y - y^2 + x - 1 + sage: A.quantum_determinant(q*x + q^-1*y) + (2*x*y^2 - 2*y^2)*q^-2 + (x^4*y - x^3*y + 3*x*y^2 + 3*y^3)*q^-1 + + (-2*x^2*y + x*y^2 + 2*x^2 - 2*x*y) + + (x^5 - x^4 + 3*x^2*y + 3*x*y^2)*q + (2*x^3 - 2*x^2)*q^2 + """ + cdef Py_ssize_t n = self._ncols + + if self._nrows != n: + raise ValueError("self must be a square matrix") + + if q is None: + from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing + q = PolynomialRing(self.base_ring(), 'q').gen() + + from sage.misc.misc_c import prod + from sage.combinat.permutation import Permutations + cdef Py_ssize_t i + return sum((-q)**s.number_of_inversions() + * prod(self.get_unsafe(s[i] - 1, i) for i in range(n)) + for s in Permutations(n)) + + qdet = quantum_determinant + def pfaffian(self, algorithm=None, check=True): r""" Return the Pfaffian of ``self``, assuming that ``self`` is an @@ -2851,7 +2928,7 @@ cdef class Matrix(Matrix1): sage: M = MatrixSpace(RR, 2) sage: A = M(range(2^2)) sage: type(A) - + sage: A.charpoly('x') x^2 - 3.00000000000000*x - 2.00000000000000 sage: A.charpoly('y') @@ -14723,6 +14800,8 @@ cdef class Matrix(Matrix1): for i from 0 <= i < size: PyList_Append(M,f(PyList_GET_ITEM(L,i))) + from sage.rings.finite_rings.integer_mod_ring import IntegerModRing + return MatrixSpace(IntegerModRing(2), nrows=self._nrows,ncols=self._ncols).matrix(M) @@ -15123,6 +15202,7 @@ cdef class Matrix(Matrix1): sage: v.derivative(x,x) (0, 0, 2) """ + from sage.misc.derivative import multi_derivative return multi_derivative(self, args) def exp(self): @@ -15150,7 +15230,7 @@ cdef class Matrix(Matrix1): [ 1/11*(sqrt(33)*e^sqrt(33) - sqrt(33))*e^(-1/2*sqrt(33) + 5/2) 1/22*((sqrt(33) + 11)*e^sqrt(33) - sqrt(33) + 11)*e^(-1/2*sqrt(33) + 5/2)] sage: type(a.exp()) - + sage: a=matrix([[1/2,2/3],[3/4,4/5]]) sage: a.exp() diff --git a/src/sage/matrix/matrix_complex_ball_dense.pyx b/src/sage/matrix/matrix_complex_ball_dense.pyx index 4a3fd675681..4bd1313506d 100644 --- a/src/sage/matrix/matrix_complex_ball_dense.pyx +++ b/src/sage/matrix/matrix_complex_ball_dense.pyx @@ -143,7 +143,7 @@ cdef class Matrix_complex_ball_dense(Matrix_dense): sage: a = Matrix_complex_ball_dense.__new__( # indirect doctest ....: Matrix_complex_ball_dense, Mat(CBF, 2), 0, 0, 0) sage: type(a) - + """ sig_str("Arb exception") acb_mat_init(self.value, self._nrows, self._ncols) diff --git a/src/sage/matrix/matrix_cyclo_dense.pyx b/src/sage/matrix/matrix_cyclo_dense.pyx index eef7a331ee7..1845be41cbd 100644 --- a/src/sage/matrix/matrix_cyclo_dense.pyx +++ b/src/sage/matrix/matrix_cyclo_dense.pyx @@ -96,7 +96,7 @@ cdef class Matrix_cyclo_dense(Matrix_dense): sage: from sage.matrix.matrix_cyclo_dense import Matrix_cyclo_dense sage: A = Matrix_cyclo_dense.__new__(Matrix_cyclo_dense, MatrixSpace(CyclotomicField(3),2), [0,1,2,3], True, True) sage: type(A) - + Note that the entries of A haven't even been set yet above; that doesn't happen until ``__init__`` is called:: diff --git a/src/sage/matrix/matrix_gap.pyx b/src/sage/matrix/matrix_gap.pyx index 0fff7a1f006..4a19dd4904e 100644 --- a/src/sage/matrix/matrix_gap.pyx +++ b/src/sage/matrix/matrix_gap.pyx @@ -27,13 +27,13 @@ cdef class Matrix_gap(Matrix_dense): sage: m1 = M([1, 0, 2, -3]) sage: m2 = M([2, 2, 5, -1]) sage: type(m1) - + sage: m1 * m2 [ 2 2] [-11 7] sage: type(m1 * m2) - + sage: M = MatrixSpace(QQ, 5, 3, implementation='gap') sage: m = M(range(15)) @@ -94,11 +94,11 @@ cdef class Matrix_gap(Matrix_dense): [2 0] [0 2] sage: type(M(0)) - + sage: type(M(1)) - + sage: type(M(2)) - + sage: M = MatrixSpace(QQ, 2, 3, implementation='gap') sage: M(0) @@ -175,7 +175,7 @@ cdef class Matrix_gap(Matrix_dense): sage: m [ [ 1, 2 ], [ 2, 1 ] ] sage: type(m) - + sage: m.MatrixAutomorphisms() Group([ (1,2) ]) diff --git a/src/sage/matrix/matrix_generic_dense.pyx b/src/sage/matrix/matrix_generic_dense.pyx index 3f01179dd14..7c0058db1d2 100644 --- a/src/sage/matrix/matrix_generic_dense.pyx +++ b/src/sage/matrix/matrix_generic_dense.pyx @@ -27,7 +27,7 @@ cdef class Matrix_generic_dense(matrix_dense.Matrix_dense): sage: A = random_matrix(Integers(25)['x'], 2) sage: type(A) - + sage: TestSuite(A).run() Test comparisons:: @@ -270,7 +270,7 @@ cdef class Matrix_generic_dense(matrix_dense.Matrix_dense): [ x y] [x^2 y^2] sage: type(a) - + sage: a*a [ x^2*y + x^2 y^3 + x*y] [x^2*y^2 + x^3 y^4 + x^2*y] diff --git a/src/sage/matrix/matrix_gfpn_dense.pyx b/src/sage/matrix/matrix_gfpn_dense.pyx index 32b77a861fa..1115e7b2c87 100644 --- a/src/sage/matrix/matrix_gfpn_dense.pyx +++ b/src/sage/matrix/matrix_gfpn_dense.pyx @@ -345,7 +345,7 @@ cdef class Matrix_gfpn_dense(Matrix_dense): [1 2 3] [4 0 1] sage: type(M) - + The documentation of the ``__init__`` methods shows further ways of creating a :class:`Matrix_gfpn_dense` instance. @@ -565,7 +565,7 @@ cdef class Matrix_gfpn_dense(Matrix_dense): sage: F. = GF(9) sage: M = MatrixSpace(F,3)(sorted(list(F))) sage: type(M) - + sage: M # indirect doctest [ 0 1 2] [ z z + 1 z + 2] @@ -709,7 +709,7 @@ cdef class Matrix_gfpn_dense(Matrix_dense): [ 2*z^2 + z 2*z 2*z^2 + 2*z + 1 2*z^2 + 1 2*z^2 + 2*z + 1 2*z^2 + z] [ 2*z + 1 z^2 + z z^2 z^2 2*z^2 + 2*z z + 1] sage: type(M) - + sage: MS.random_element(nonzero=True) [ 2*z 1 z^2 + 2*z + 1 2*z^2 + z + 1 z^2 z^2 + z + 1] [ 2*z^2 + 2*z 2*z^2 + z + 2 2*z + 1 z^2 + 2*z 2*z^2 + 2*z z^2] @@ -1732,11 +1732,11 @@ cdef class Matrix_gfpn_dense(Matrix_dense): implementation of dense matrices:: sage: type(M) - + sage: MS = MatrixSpace(M.base_ring(), M.nrows(), M.ncols(), implementation='generic') sage: X = MS(M) sage: type(X) - + sage: X.echelon_form() [ 0 1 0 0 0 0 0 0 0 4*x + 4] [ 0 0 1 0 0 0 0 0 0 4*x + 2] @@ -1876,7 +1876,7 @@ def mtx_unpickle(f, int nr, int nc, data, bint m): [ 6 7 8 9 10] [12 11 10 9 8] sage: type(N) - + We demonstrate that a slightly different pickle format can be understood as well, that was at some point used by some optional package:: diff --git a/src/sage/matrix/matrix_integer_dense.pyx b/src/sage/matrix/matrix_integer_dense.pyx index 5422d985eee..c9dcecdef47 100644 --- a/src/sage/matrix/matrix_integer_dense.pyx +++ b/src/sage/matrix/matrix_integer_dense.pyx @@ -216,7 +216,7 @@ cdef class Matrix_integer_dense(Matrix_dense): sage: from sage.matrix.matrix_integer_dense import Matrix_integer_dense sage: a = Matrix_integer_dense.__new__(Matrix_integer_dense, Mat(ZZ,3), 0,0,0) sage: type(a) - + TESTS:: @@ -1303,7 +1303,7 @@ cdef class Matrix_integer_dense(Matrix_dense): sage: M = MatrixSpace(ZZ, 2) sage: A = M(range(0, 2^2)) sage: type(A) - + sage: A.charpoly('x') x^2 - 3*x - 2 sage: A.charpoly('y') @@ -5546,7 +5546,7 @@ cdef class Matrix_integer_dense(Matrix_dense): sage: A = matrix(ZZ, 2, 3, range(6)) sage: type(A) - + sage: B = A.transpose() sage: print(B) [0 3] @@ -5592,7 +5592,7 @@ cdef class Matrix_integer_dense(Matrix_dense): sage: A = matrix(2,3,range(6)) sage: type(A) - + sage: A.antitranspose() [5 2] [4 1] @@ -5645,7 +5645,7 @@ cdef class Matrix_integer_dense(Matrix_dense): sage: pari(a) [1, 2; 3, 4] sage: type(pari(a)) - + """ return integer_matrix(self._matrix, 0) diff --git a/src/sage/matrix/matrix_mod2_dense.pyx b/src/sage/matrix/matrix_mod2_dense.pyx index 8f1374eb39f..d583e5fa2e7 100644 --- a/src/sage/matrix/matrix_mod2_dense.pyx +++ b/src/sage/matrix/matrix_mod2_dense.pyx @@ -17,7 +17,7 @@ EXAMPLES:: sage: a.rank() 2 sage: type(a) - + sage: a[0,0] = 1 sage: a.rank() 3 @@ -237,7 +237,7 @@ cdef class Matrix_mod2_dense(matrix_dense.Matrix_dense): # dense or sparse EXAMPLES:: sage: type(random_matrix(GF(2),2,2)) - + sage: Matrix(GF(2),3,3,1) [1 0 0] @@ -1528,7 +1528,7 @@ cdef class Matrix_mod2_dense(matrix_dense.Matrix_dense): # dense or sparse Traceback (most recent call last): ... TypeError: right must either be a matrix or a vector. Not - + """ cdef Matrix_mod2_dense other diff --git a/src/sage/matrix/matrix_modn_dense_double.pyx b/src/sage/matrix/matrix_modn_dense_double.pyx index cb8f2a09e24..dfd27b78db2 100644 --- a/src/sage/matrix/matrix_modn_dense_double.pyx +++ b/src/sage/matrix/matrix_modn_dense_double.pyx @@ -68,7 +68,7 @@ cdef class Matrix_modn_dense_double(Matrix_modn_dense_template): sage: A = random_matrix(IntegerModRing(2^16), 4, 4) sage: type(A[0,0]) - + """ self._get_template = self._base_ring.zero() # note that INTEGER_MOD_INT32_LIMIT is ceil(sqrt(2^31-1)) < 2^23 diff --git a/src/sage/matrix/matrix_modn_dense_float.pyx b/src/sage/matrix/matrix_modn_dense_float.pyx index 8a215de6f66..9435794c4c1 100644 --- a/src/sage/matrix/matrix_modn_dense_float.pyx +++ b/src/sage/matrix/matrix_modn_dense_float.pyx @@ -63,7 +63,7 @@ cdef class Matrix_modn_dense_float(Matrix_modn_dense_template): sage: A = random_matrix(GF(7), 4, 4) sage: type(A[0,0]) - + """ self._get_template = self._base_ring.zero() diff --git a/src/sage/matrix/matrix_modn_dense_template.pxi b/src/sage/matrix/matrix_modn_dense_template.pxi index a04d3874a0f..010365d76f5 100644 --- a/src/sage/matrix/matrix_modn_dense_template.pxi +++ b/src/sage/matrix/matrix_modn_dense_template.pxi @@ -475,13 +475,13 @@ cdef class Matrix_modn_dense_template(Matrix_dense): sage: A = random_matrix(GF(3),1000,1000) sage: type(A) - + sage: A = random_matrix(Integers(10),1000,1000) sage: type(A) - + sage: A = random_matrix(Integers(2^16),1000,1000) sage: type(A) - + TESTS:: @@ -1350,7 +1350,7 @@ cdef class Matrix_modn_dense_template(Matrix_dense): sage: M = MatrixSpace(Integers(37), 2) sage: A = M(range(0, 2^2)) sage: type(A) - + sage: A.charpoly('x').variables() (x,) sage: A.charpoly('y').variables() diff --git a/src/sage/matrix/matrix_modn_sparse.pyx b/src/sage/matrix/matrix_modn_sparse.pyx index 9762f857e7c..fb9c6736ea0 100644 --- a/src/sage/matrix/matrix_modn_sparse.pyx +++ b/src/sage/matrix/matrix_modn_sparse.pyx @@ -16,7 +16,7 @@ EXAMPLES:: [3 4 5] [6 7 8] sage: type(a) - + sage: parent(a) Full MatrixSpace of 3 by 3 sparse matrices over Ring of integers modulo 37 sage: a^2 @@ -359,13 +359,13 @@ cdef class Matrix_modn_sparse(matrix_sparse.Matrix_sparse): [ 9 12 15] [19 26 33] sage: type(c) - + sage: a = matrix(GF(2), 20, 20, sparse=True) sage: a*a == a._matrix_times_matrix_dense(a) True sage: type(a._matrix_times_matrix_dense(a)) - + """ cdef Matrix_modn_sparse right cdef matrix_dense.Matrix_dense ans diff --git a/src/sage/matrix/matrix_rational_dense.pyx b/src/sage/matrix/matrix_rational_dense.pyx index bf343014db5..25976778ec7 100644 --- a/src/sage/matrix/matrix_rational_dense.pyx +++ b/src/sage/matrix/matrix_rational_dense.pyx @@ -109,7 +109,7 @@ from sage.rings.integer cimport Integer from sage.rings.ring import is_Ring from sage.rings.integer_ring import ZZ, is_IntegerRing from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF -from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing +import sage.rings.abc from sage.rings.rational_field import QQ from sage.arith.all import gcd @@ -139,7 +139,7 @@ cdef class Matrix_rational_dense(Matrix_dense): sage: from sage.matrix.matrix_rational_dense import Matrix_rational_dense sage: a = Matrix_rational_dense.__new__(Matrix_rational_dense, Mat(ZZ,3), 0,0,0) sage: type(a) - + .. WARNING:: @@ -1022,7 +1022,7 @@ cdef class Matrix_rational_dense(Matrix_dense): sage: M = MatrixSpace(QQ, 2) sage: A = M(range(0, 2^2)) sage: type(A) - + sage: A.charpoly('x') x^2 - 3*x - 2 sage: A.charpoly('y') @@ -1487,7 +1487,7 @@ cdef class Matrix_rational_dense(Matrix_dense): return A from .matrix_modn_dense_double import MAX_MODULUS - if is_IntegerModRing(R) and R.order() < MAX_MODULUS: + if isinstance(R, sage.rings.abc.IntegerModRing) and R.order() < MAX_MODULUS: b = R.order() A, d = self._clear_denom() if not b.gcd(d).is_one(): @@ -2548,7 +2548,7 @@ cdef class Matrix_rational_dense(Matrix_dense): sage: A = matrix(QQ, 2, 3, range(6)) sage: type(A) - + sage: B = A.transpose() sage: print(B) [0 3] @@ -2599,7 +2599,7 @@ cdef class Matrix_rational_dense(Matrix_dense): sage: A = matrix(QQ,2,3,range(6)) sage: type(A) - + sage: A.antitranspose() [5 2] [4 1] diff --git a/src/sage/matrix/matrix_rational_sparse.pyx b/src/sage/matrix/matrix_rational_sparse.pyx index b00416b8e92..aa92bf206a7 100644 --- a/src/sage/matrix/matrix_rational_sparse.pyx +++ b/src/sage/matrix/matrix_rational_sparse.pyx @@ -229,7 +229,7 @@ cdef class Matrix_rational_sparse(Matrix_sparse): [ 9 12 15] [19 26 33] sage: type(c) - + """ cdef Matrix_rational_sparse right cdef Matrix_rational_dense ans @@ -620,9 +620,9 @@ cdef class Matrix_rational_sparse(Matrix_sparse): EXAMPLES:: sage: a = matrix(QQ,2,[1..4],sparse=True); type(a) - + sage: type(a.dense_matrix()) - + sage: a.dense_matrix() [1 2] [3 4] diff --git a/src/sage/matrix/matrix_space.py b/src/sage/matrix/matrix_space.py index 47766db0c46..99e57196f3f 100644 --- a/src/sage/matrix/matrix_space.py +++ b/src/sage/matrix/matrix_space.py @@ -236,7 +236,7 @@ def get_matrix_class(R, nrows, ncols, sparse, implementation): except ImportError: pass - if sage.rings.finite_rings.integer_mod_ring.is_IntegerModRing(R): + if isinstance(R, sage.rings.abc.IntegerModRing): from . import matrix_modn_dense_double, matrix_modn_dense_float if R.order() < matrix_modn_dense_float.MAX_MODULUS: return matrix_modn_dense_float.Matrix_modn_dense_float @@ -326,7 +326,7 @@ def get_matrix_class(R, nrows, ncols, sparse, implementation): if implementation is not None: raise ValueError("cannot choose an implementation for sparse matrices") - if sage.rings.finite_rings.integer_mod_ring.is_IntegerModRing(R) and R.order() < matrix_modn_sparse.MAX_MODULUS: + if isinstance(R, sage.rings.abc.IntegerModRing) and R.order() < matrix_modn_sparse.MAX_MODULUS: return matrix_modn_sparse.Matrix_modn_sparse if sage.rings.rational_field.is_RationalField(R): @@ -968,8 +968,11 @@ def _get_action_(self, S, op, self_on_left): Left scalar multiplication by Integer Ring on Full MatrixSpace of 2 by 3 dense matrices over Rational Field """ try: - from sage.schemes.generic.homset import SchemeHomset_generic - from sage.schemes.generic.homset import SchemeHomset_points + try: + from sage.schemes.generic.homset import SchemeHomset_generic + from sage.schemes.generic.homset import SchemeHomset_points + except ImportError: + SchemeHomset_generic = SchemeHomset_points = None if op is operator.mul: from . import action as matrix_action if self_on_left: diff --git a/src/sage/matrix/matrix_sparse.pyx b/src/sage/matrix/matrix_sparse.pyx index ac795c9b71e..0d8c4abb46e 100644 --- a/src/sage/matrix/matrix_sparse.pyx +++ b/src/sage/matrix/matrix_sparse.pyx @@ -176,7 +176,7 @@ cdef class Matrix_sparse(matrix.Matrix): sage: A = matrix(QQ['x,y'], 2, [0,-1,2,-2], sparse=True) sage: type(A) - + sage: B = matrix(QQ['x,y'], 2, [-1,-1,-2,-2], sparse=True) sage: A * B [2 2] @@ -239,7 +239,7 @@ cdef class Matrix_sparse(matrix.Matrix): sage: A = matrix(QQ['x,y'], 2, [0,-1,2,-2], sparse=True) sage: type(A) - + sage: B = matrix(QQ['x,y'], 2, [-1,-1,-2,-2], sparse=True) sage: A._multiply_classical_with_cache(B) [2 2] diff --git a/src/sage/matrix/matrix_symbolic_dense.pyx b/src/sage/matrix/matrix_symbolic_dense.pyx index f67a25e9ccb..ded3a0dc0a1 100644 --- a/src/sage/matrix/matrix_symbolic_dense.pyx +++ b/src/sage/matrix/matrix_symbolic_dense.pyx @@ -264,7 +264,7 @@ cdef class Matrix_symbolic_dense(Matrix_generic_dense): sage: spectrum = am.eigenvectors_left() sage: symbolic_evalue = spectrum[2][0] sage: type(symbolic_evalue) - + sage: symbolic_evalue 1/2*sqrt(5) - 1/2 @@ -484,7 +484,7 @@ cdef class Matrix_symbolic_dense(Matrix_generic_dense): sage: M = MatrixSpace(SR, 2) sage: A = M(range(0, 2^2)) sage: type(A) - + sage: A.charpoly('x') x^2 - 3*x - 2 sage: A.charpoly('y') diff --git a/src/sage/matrix/misc.pyx b/src/sage/matrix/misc.pyx index 9008edf5920..c7fc1c70161 100644 --- a/src/sage/matrix/misc.pyx +++ b/src/sage/matrix/misc.pyx @@ -40,7 +40,7 @@ from sage.rings.rational_field import QQ from sage.rings.integer cimport Integer from sage.arith.all import previous_prime, CRT_basis -from sage.rings.real_mpfr import is_RealField +from sage.rings.real_mpfr cimport RealField_class from sage.rings.real_mpfr cimport RealNumber @@ -510,7 +510,7 @@ def hadamard_row_bound_mpfr(Matrix A): ... OverflowError: cannot convert float infinity to integer """ - if not is_RealField(A.base_ring()): + if not isinstance(A.base_ring(), RealField_class): raise TypeError("A must have base field an mpfr real field.") cdef RealNumber a, b diff --git a/src/sage/matrix/special.py b/src/sage/matrix/special.py index 5e56ddeebea..bcb0b0293af 100644 --- a/src/sage/matrix/special.py +++ b/src/sage/matrix/special.py @@ -399,9 +399,9 @@ def random_matrix(ring, nrows, ncols=None, algorithm='randomize', implementation sage: K. = FiniteField(2^8) sage: type(random_matrix(K, 2, 5)) - + sage: type(random_matrix(K, 2, 5, implementation="generic")) - + Random rational matrices. Now ``num_bound`` and ``den_bound`` control the generation of random elements, by specifying limits on the absolute value of diff --git a/src/sage/matroids/catalog.py b/src/sage/matroids/catalog.py index d6a35bd6091..f80d1741248 100644 --- a/src/sage/matroids/catalog.py +++ b/src/sage/matroids/catalog.py @@ -38,7 +38,8 @@ from sage.matrix.constructor import Matrix from sage.graphs.all import graphs -from sage.rings.all import ZZ, GF +from sage.rings.integer_ring import ZZ +from sage.rings.finite_rings.finite_field_constructor import GF from sage.schemes.all import ProjectiveSpace import sage.matroids.matroid diff --git a/src/sage/matroids/constructor.py b/src/sage/matroids/constructor.py index bf1f6d5c298..bdf12b12891 100644 --- a/src/sage/matroids/constructor.py +++ b/src/sage/matroids/constructor.py @@ -105,7 +105,8 @@ from sage.matrix.constructor import Matrix from sage.graphs.all import Graph from sage.structure.element import is_Matrix -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.categories.all import Fields, Rings from sage.rings.finite_rings.finite_field_base import FiniteField import sage.matroids.matroid diff --git a/src/sage/misc/abstract_method.py b/src/sage/misc/abstract_method.py index fdfde979b96..49dc59ba9fa 100644 --- a/src/sage/misc/abstract_method.py +++ b/src/sage/misc/abstract_method.py @@ -125,9 +125,7 @@ def abstract_method(f=None, optional=False): The syntax ``@abstract_method`` w.r.t. @abstract_method(optional = True) is achieved by a little trick which we test here:: - sage: abstract_method(optional = True) # py2 - at ...> - sage: abstract_method(optional = True) # py3 + sage: abstract_method(optional = True) . at ...> sage: abstract_method(optional = True)(banner) diff --git a/src/sage/misc/bindable_class.py b/src/sage/misc/bindable_class.py index bf56d7272b8..c776faf7257 100644 --- a/src/sage/misc/bindable_class.py +++ b/src/sage/misc/bindable_class.py @@ -210,18 +210,6 @@ class BoundClass(functools.partial): sage: g() 8 - The following has incorrect syntax and thus a ``DeprecationWarning``:: - - sage: class mypartial(functools.partial): - ....: def __init__(self, f, i, j): - ....: functools.partial.__init__(self, f, i, j) - sage: g = mypartial(f, 2, 3) # py2; on Python 3 this is an error - Traceback (most recent call last): - ... - DeprecationWarning: object.__init__() takes no parameters - sage: g() - 8 - The following has correct syntax and no ``DeprecationWarning``:: sage: class mynewpartial(functools.partial): diff --git a/src/sage/misc/c3_controlled.pyx b/src/sage/misc/c3_controlled.pyx index d2ca1fe5784..3e70e529ad2 100644 --- a/src/sage/misc/c3_controlled.pyx +++ b/src/sage/misc/c3_controlled.pyx @@ -70,13 +70,7 @@ algorithm easily fails if the order of the bases is not chosen consistently (here for ``A2`` w.r.t. ``A1``):: sage: class B6(A1,A2): pass - sage: class B7(B6,A5): pass # py2 - Traceback (most recent call last): - ... - TypeError: Error when calling the metaclass bases - Cannot create a consistent method resolution - order (MRO) for bases ... - sage: class B7(B6,A5): pass # py3 + sage: class B7(B6,A5): pass Traceback (most recent call last): ... TypeError: Cannot create a consistent method resolution diff --git a/src/sage/misc/classcall_metaclass.pyx b/src/sage/misc/classcall_metaclass.pyx index eb8f75a5094..464a3ea93ec 100644 --- a/src/sage/misc/classcall_metaclass.pyx +++ b/src/sage/misc/classcall_metaclass.pyx @@ -391,9 +391,7 @@ cdef class ClasscallMetaclass(NestedClassMetaclass): sage: bind = obj.Inner calling __classget__(, <__main__.Outer object at 0x...>, ) - sage: bind # py2 - - sage: bind # py3 + sage: bind functools.partial(, <__main__.Outer object at 0x...>) """ if cls.classget: diff --git a/src/sage/misc/functional.py b/src/sage/misc/functional.py index c1f895c217c..45d74ea749a 100644 --- a/src/sage/misc/functional.py +++ b/src/sage/misc/functional.py @@ -809,9 +809,7 @@ def xinterval(a, b): EXAMPLES:: - sage: I = xinterval(2,5); I # py2 - xrange(2, 6) - sage: I = xinterval(2,5); I # py3 + sage: I = xinterval(2,5); I range(2, 6) sage: 5 in I True diff --git a/src/sage/misc/latex.py b/src/sage/misc/latex.py index 3aa015bb062..56a47ea4513 100644 --- a/src/sage/misc/latex.py +++ b/src/sage/misc/latex.py @@ -31,9 +31,7 @@ import shutil from subprocess import call, PIPE -from sage.misc import sage_eval from sage.misc.cachefunc import cached_function, cached_method -from sage.misc.sage_ostools import have_program from sage.misc.temporary_file import tmp_dir from sage.structure.sage_object import SageObject @@ -82,6 +80,7 @@ def have_latex() -> bool: sage: have_latex() # random True """ + from sage.misc.sage_ostools import have_program return have_program('latex') @@ -99,6 +98,7 @@ def have_pdflatex() -> bool: sage: have_pdflatex() # random True """ + from sage.misc.sage_ostools import have_program return have_program('pdflatex') @@ -116,6 +116,7 @@ def have_xelatex() -> bool: sage: have_xelatex() # random True """ + from sage.misc.sage_ostools import have_program return have_program('xelatex') @@ -133,6 +134,7 @@ def have_dvipng() -> bool: sage: have_dvipng() # random True """ + from sage.misc.sage_ostools import have_program return have_program('dvipng') @@ -151,6 +153,7 @@ def have_convert() -> bool: sage: have_convert() # random True """ + from sage.misc.sage_ostools import have_program return have_program('convert') @@ -1015,6 +1018,7 @@ def _latex_preparse(self, s, locals): sage: sage.misc.latex.Latex()._latex_preparse(r'\sage{s}', locals()) '2' """ + from sage.misc.sage_eval import sage_eval i0 = -1 while True: i = s.find('\\sage{') @@ -1028,7 +1032,7 @@ def _latex_preparse(self, s, locals): var = t[:j] try: - k = str(latex(sage_eval.sage_eval(var, locals))) + k = str(latex(sage_eval(var, locals))) except Exception as msg: print(msg) k = '\\mbox{\\rm [%s undefined]}' % var diff --git a/src/sage/misc/latex_macros.py b/src/sage/misc/latex_macros.py index 21b7fab46b4..24d2eee43cb 100644 --- a/src/sage/misc/latex_macros.py +++ b/src/sage/misc/latex_macros.py @@ -16,10 +16,7 @@ LaTeX macros is used in the file ``sage.docs.conf`` to add to the preambles of both the LaTeX file used to build the PDF version of the documentation -and the LaTeX file used to build the HTML version. The list of -MathJax macros is used in the file -``sagenb/notebook/tutorial.py`` to define MathJax macros for use -in the live documentation (and also in the notebook). +and the LaTeX file used to build the HTML version. Any macro defined here may be used in docstrings or in the tutorial (or other pieces of documentation). In a docstring, for example, diff --git a/src/sage/misc/lazy_import.pyx b/src/sage/misc/lazy_import.pyx index 7e8b731965a..4d4ee94bbe9 100644 --- a/src/sage/misc/lazy_import.pyx +++ b/src/sage/misc/lazy_import.pyx @@ -31,7 +31,8 @@ it is actually resolved after the startup, so that the developer knows that (s)he can remove the flag:: sage: ZZ - Option ``at_startup=True`` for lazy import ZZ not needed anymore + doctest:warning... + UserWarning: Option ``at_startup=True`` for lazy import ZZ not needed anymore Integer Ring .. SEEALSO:: :func:`lazy_import`, :class:`LazyImport` @@ -63,6 +64,7 @@ cdef extern from *: import os import pickle +from warnings import warn import inspect from . import sageinspect @@ -79,11 +81,15 @@ cdef inline obj(x): # boolean to determine whether Sage is still starting up cdef bint startup_guard = True +cdef bint finish_startup_called = False + cpdef finish_startup(): """ + Finish the startup phase. + This function must be called exactly once at the end of the Sage - import process + import process (:mod:`~sage.all`). TESTS:: @@ -93,9 +99,27 @@ cpdef finish_startup(): ... AssertionError: finish_startup() must be called exactly once """ - global startup_guard + global startup_guard, finish_startup_called assert startup_guard, 'finish_startup() must be called exactly once' startup_guard = False + finish_startup_called = True + + +cpdef ensure_startup_finished(): + """ + Make sure that the startup phase is finished. + + In contrast to :func:`finish_startup`, this function can + be called repeatedly. + + TESTS:: + + sage: from sage.misc.lazy_import import ensure_startup_finished + sage: ensure_startup_finished() + """ + global startup_guard + startup_guard = False + cpdef bint is_during_startup(): """ @@ -114,6 +138,7 @@ cpdef bint is_during_startup(): global startup_guard return startup_guard + cpdef test_fake_startup(): """ For testing purposes only. @@ -125,12 +150,14 @@ cpdef test_fake_startup(): sage: sage.misc.lazy_import.test_fake_startup() sage: lazy_import('sage.rings.all', 'ZZ', 'my_ZZ') sage: my_ZZ(123) - Resolving lazy import ZZ during startup + doctest:warning... + UserWarning: Resolving lazy import ZZ during startup 123 sage: sage.misc.lazy_import.finish_startup() """ - global startup_guard + global startup_guard, finish_startup_called startup_guard = True + finish_startup_called = False @cython.final @@ -207,18 +234,20 @@ cdef class LazyImport(object): Integer Ring sage: my_integer_ring._object is None False - sage: my_integer_ring = LazyImport('sage.rings.all', 'ZZ', at_startup=True) - sage: my_integer_ring - Option ``at_startup=True`` for lazy import ZZ not needed anymore - Integer Ring + sage: my_rats = LazyImport('sage.rings.rational_field', 'QQ', at_startup=True) + sage: my_rats + doctest:warning... + UserWarning: Option ``at_startup=True`` for lazy import QQ not needed anymore + Rational Field """ if self._object is not None: return self._object if startup_guard and not self._at_startup: - print(f"Resolving lazy import {self._name} during startup") + warn(f"Resolving lazy import {self._name} during startup") elif self._at_startup and not startup_guard: - print(f"Option ``at_startup=True`` for lazy import {self._name} not needed anymore") + if finish_startup_called: + warn(f"Option ``at_startup=True`` for lazy import {self._name} not needed anymore") try: self._object = getattr(__import__(self._module, {}, {}, [self._name]), self._name) @@ -466,13 +495,9 @@ cdef class LazyImport(object): sage: Foo().my_method() <__main__.Foo object at ...> - sage: Foo.my_method # py2 - - sage: Foo.my_method # py3 + sage: Foo.my_method - sage: Foo().my_method # py2 - > - sage: Foo().my_method # py3 + sage: Foo().my_method > When a :class:`LazyImport` method is a method (or attribute) @@ -498,9 +523,7 @@ cdef class LazyImport(object): We access the ``plot`` method:: - sage: Bar.plot # py2 - - sage: Bar.plot # py3 + sage: Bar.plot Now ``plot`` has been replaced in the dictionary of ``Foo``:: @@ -823,12 +846,7 @@ cdef class LazyImport(object): sage: sage.all.foo = 10 sage: lazy_import('sage.all', 'foo') - sage: oct(foo) # py2 - doctest:warning...: - DeprecationWarning: use the method .oct instead - See https://trac.sagemath.org/26756 for details. - '12' - sage: oct(foo) # py3 + sage: oct(foo) '0o12' """ return self.get_object().__oct__() @@ -839,12 +857,7 @@ cdef class LazyImport(object): sage: sage.all.foo = 10 sage: lazy_import('sage.all', 'foo') - sage: hex(foo) # py2 - doctest:warning...: - DeprecationWarning: use the method .hex instead - See https://trac.sagemath.org/26756 for details. - 'a' - sage: hex(foo) # py3 + sage: hex(foo) '0xa' """ return self.get_object().__hex__() diff --git a/src/sage/misc/misc.py b/src/sage/misc/misc.py index efaa182f0d9..fbebd99b3a3 100644 --- a/src/sage/misc/misc.py +++ b/src/sage/misc/misc.py @@ -803,6 +803,8 @@ def __rmul__(self, left): EXAMPLES:: sage: A = random_matrix(ZZ, 4) + sage: while A.rank() != 4: + ....: A = random_matrix(ZZ, 4) sage: B = random_matrix(ZZ, 4) sage: temp = A * BackslashOperator() sage: temp.left is A diff --git a/src/sage/misc/remote_file.py b/src/sage/misc/remote_file.py index ec8b1194b4e..092640cc9e6 100644 --- a/src/sage/misc/remote_file.py +++ b/src/sage/misc/remote_file.py @@ -38,8 +38,7 @@ def get_remote_file(filename, verbose=True): # IMPORTANT -- urllib takes a long time to load, # so do not import it in the module scope. - # import compatible with py2 and py3 - req = Request(filename, headers={"User-Agent":"sage-doctest"}) + req = Request(filename, headers={"User-Agent": "sage-doctest"}) if verbose: print("Loading started") diff --git a/src/sage/misc/rest_index_of_methods.py b/src/sage/misc/rest_index_of_methods.py index 337d91c554f..b059887b014 100644 --- a/src/sage/misc/rest_index_of_methods.py +++ b/src/sage/misc/rest_index_of_methods.py @@ -233,9 +233,7 @@ def list_of_subfunctions(root, only_local_functions=True): sage: class A: ....: x = staticmethod(Graph.order) - sage: list_of_subfunctions(A) # py2 - ([], {: 'x'}) - sage: list_of_subfunctions(A) # py3 + sage: list_of_subfunctions(A) ([], {: 'x'}) diff --git a/src/sage/misc/sage_eval.py b/src/sage/misc/sage_eval.py index 5f2b50ab625..029ed54df20 100644 --- a/src/sage/misc/sage_eval.py +++ b/src/sage/misc/sage_eval.py @@ -2,17 +2,18 @@ Evaluating a String in Sage """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2006 William Stein # # Distributed under the terms of the GNU General Public License (GPL) # -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** from copy import copy import sage.repl.preparse as preparser + def sage_eval(source, locals=None, cmds='', preparse=True): r""" Obtain a Sage object from the input string by evaluating it using @@ -90,9 +91,7 @@ def sage_eval(source, locals=None, cmds='', preparse=True): :: sage: x = 5 - sage: eval('4/3 + x', {'x': 25}) # py2 - 26 - sage: eval('4//3 + x', {'x': 25}) # py3 + sage: eval('4//3 + x', {'x': 25}) 26 sage: sage_eval('4/3 + x', locals={'x': 25}) 79/3 diff --git a/src/sage/misc/sage_unittest.py b/src/sage/misc/sage_unittest.py index 18827dfd118..c6c6d2741dc 100644 --- a/src/sage/misc/sage_unittest.py +++ b/src/sage/misc/sage_unittest.py @@ -610,7 +610,7 @@ def _test_pickling(self, **options): :func:`dumps`, :func:`loads` """ tester = instance_tester(self, **options) - from sage.misc.all import loads, dumps + from sage.misc.persist import loads, dumps tester.assertEqual(loads(dumps(self._instance)), self._instance) def _test_new(self, **options): diff --git a/src/sage/misc/sagedoc.py b/src/sage/misc/sagedoc.py index 01e4ec4bcc1..e3821e84e76 100644 --- a/src/sage/misc/sagedoc.py +++ b/src/sage/misc/sagedoc.py @@ -1052,12 +1052,7 @@ def search_src(string, extra1='', extra2='', extra3='', extra4='', The following produces an error because the string 'fetch(' is a malformed regular expression:: - sage: print(search_src(" fetch(", "def", interact=False)) # py2 - Traceback (most recent call last): - ... - error: unbalanced parenthesis - - sage: print(search_src(" fetch(", "def", interact=False)) # py3 + sage: print(search_src(" fetch(", "def", interact=False)) Traceback (most recent call last): ... error: missing ), unterminated subpattern at position 6 @@ -1106,8 +1101,7 @@ def search_src(string, extra1='', extra2='', extra3='', extra4='', misc/sagedoc.py:... len(search_src("matrix", interact=False).splitlines()) # random # long time misc/sagedoc.py:... len(search_src("matrix", module="sage.calculus", interact=False).splitlines()) # random misc/sagedoc.py:... len(search_src("matrix", path_re="calc", interact=False).splitlines()) > 15 - misc/sagedoc.py:... print(search_src(" fetch(", "def", interact=False)) # py2 - misc/sagedoc.py:... print(search_src(" fetch(", "def", interact=False)) # py3 + misc/sagedoc.py:... print(search_src(" fetch(", "def", interact=False)) misc/sagedoc.py:... print(search_src(r" fetch\(", "def", interact=False)) # random # long time misc/sagedoc.py:... print(search_src(r" fetch\(", "def", "pyx", interact=False)) # random # long time misc/sagedoc.py:... s = search_src('Matrix', path_re='matrix', interact=False); s.find('x') > 0 diff --git a/src/sage/misc/sageinspect.py b/src/sage/misc/sageinspect.py index d079f9e6931..2ff2762f156 100644 --- a/src/sage/misc/sageinspect.py +++ b/src/sage/misc/sageinspect.py @@ -334,11 +334,8 @@ def _extract_embedded_signature(docstring, name): ... sage: _extract_embedded_signature(MainClass.NestedClass.NestedSubClass.dummy.__doc__, 'dummy')[1] ArgSpec(args=['self', 'x', 'r'], varargs='args', keywords='kwds', defaults=((1, 2, 3.4),)) - sage: _extract_embedded_signature(range.__call__.__doc__, '__call__') # py2 - ('x.__call__(...) <==> x(...)', None) - sage: _extract_embedded_signature(range.__call__.__doc__, '__call__') # py3 + sage: _extract_embedded_signature(range.__call__.__doc__, '__call__') ('Call self as a function.', None) - """ # If there is an embedded signature, it is in the first line L = docstring.split(os.linesep, 1) @@ -502,14 +499,10 @@ def visit_Name(self, node): sage: import ast, sage.misc.sageinspect as sms sage: visitor = sms.SageArgSpecVisitor() sage: vis = lambda x: visitor.visit_Name(ast.parse(x).body[0].value) - sage: [vis(n) for n in ['True', 'False', 'None', 'foo', 'bar']] # py2 - [True, False, None, 'foo', 'bar'] - sage: [type(vis(n)) for n in ['True', 'False', 'None', 'foo', 'bar']] # py2 - [, , , , ] - sage: [vis(n) for n in ['foo', 'bar']] # py3 + sage: [vis(n) for n in ['foo', 'bar']] ['foo', 'bar'] - sage: [type(vis(n)) for n in ['foo', 'bar']] # py3 - [, ] + sage: [type(vis(n)) for n in ['foo', 'bar']] + [, ] """ return node.id @@ -587,9 +580,7 @@ def visit_Num(self, node): sage: import ast, sage.misc.sageinspect as sms sage: visitor = sms.SageArgSpecVisitor() sage: vis = lambda x: visitor.visit_Num(ast.parse(x).body[0].value) - sage: [vis(n) for n in ['123', '0.0', str(-pi.n())]] # py2 - [123, 0.0, -3.14159265358979] - sage: [vis(n) for n in ['123', '0.0']] # py3 + sage: [vis(n) for n in ['123', '0.0']] [123, 0.0] .. NOTE:: @@ -809,9 +800,7 @@ def visit_BinOp(self, node): sage: import ast, sage.misc.sageinspect as sms sage: visitor = sms.SageArgSpecVisitor() sage: vis = lambda x: visitor.visit(ast.parse(x).body[0].value) - sage: [vis(d) for d in ['(3+(2*4))', '7|8', '5^3', '7/3', '7//3', '3<<4']] #indirect doctest # py2 - [11, 15, 6, 2, 2, 48] - sage: [vis(d) for d in ['(3+(2*4))', '7|8', '5^3', '7/3', '7//3', '3<<4']] #indirect doctest # py3 + sage: [vis(d) for d in ['(3+(2*4))', '7|8', '5^3', '7/3', '7//3', '3<<4']] #indirect doctest [11, 15, 6, 2.3333333333333335, 2, 48] """ op = node.op.__class__.__name__ @@ -1119,8 +1108,7 @@ def _sage_getargspec_from_ast(source): sage: from_ast(s) ArgSpec(args=['a', 'b', 'c', 'd'], varargs=None, keywords=None, defaults=(2, {'a': [4, 5.5, False]}, (None, True))) sage: context = {} - sage: exec compile(s, '', 'single') in context # py2 - sage: exec(compile(s, '', 'single'), context) # py3 + sage: exec(compile(s, '', 'single'), context) sage: inspect.getargspec(context['f']) ArgSpec(args=['a', 'b', 'c', 'd'], varargs=None, keywords=None, defaults=(2, {'a': [4, 5.5, False]}, (None, True))) sage: from_ast(s) == inspect.getargspec(context['f']) @@ -1207,12 +1195,8 @@ def _sage_getargspec_cython(source): Some input that is malformed in Python 2 but well formed in Cython or Python 3 is correctly parsed:: - sage: def dummy_python(self, *args, x=1): pass # py2 - Traceback (most recent call last): - ... - SyntaxError: invalid ... - sage: def dummy_python(self, *args, x=1): pass # py3 - sage: sgc("def dummy_python(self, *args, x=1): pass") # py3 + sage: def dummy_python(self, *args, x=1): pass + sage: sgc("def dummy_python(self, *args, x=1): pass") ArgSpec(args=['self', 'x'], varargs='args', keywords=None, defaults=(1,)) sage: cython("def dummy_cython(self, *args, x=1): pass") sage: sgc("def dummy_cython(self, *args, x=1): pass") @@ -1423,6 +1407,7 @@ def sage_getfile(obj): return sourcefile[:-len(loadable_module_extension())]+os.path.extsep+'pyx' return sourcefile + def sage_getargspec(obj): r""" Return the names and default values of a function's arguments. @@ -1701,6 +1686,7 @@ def foo(x, a='\')"', b={not (2+1==3):'bar'}): return defaults = None return inspect.ArgSpec(args, varargs, varkw, defaults) + def formatannotation(annotation, base_module=None): """ This is taken from Python 3.7's inspect.py; the only change is to @@ -1742,6 +1728,7 @@ def formatannotation(annotation, base_module=None): return annotation.__module__+'.'+annotation.__qualname__ return repr(annotation) + def sage_formatargspec(args, varargs=None, varkw=None, defaults=None, kwonlyargs=(), kwonlydefaults={}, annotations={}, formatarg=str, @@ -2317,7 +2304,7 @@ def sage_getsourcelines(obj): ...) sage: x = var('x') sage: lines, lineno = sage_getsourcelines(x); lines[0:5] - ['cdef class Expression(CommutativeRingElement):\n', + ['cdef class Expression(...):\n', '\n', ' cdef GEx _gobj\n', '\n', diff --git a/src/sage/modular/abvar/abvar_newform.py b/src/sage/modular/abvar/abvar_newform.py index 21a1758283a..67c478511f3 100644 --- a/src/sage/modular/abvar/abvar_newform.py +++ b/src/sage/modular/abvar/abvar_newform.py @@ -14,7 +14,8 @@ ########################################################################### from sage.misc.lazy_import import lazy_import -from sage.rings.all import QQ, ZZ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.modular.modform.element import Newform from sage.modular.arithgroup.all import is_Gamma0, is_Gamma1, is_GammaH diff --git a/src/sage/modular/abvar/finite_subgroup.py b/src/sage/modular/abvar/finite_subgroup.py index 3c2aefc0ab9..471386f3575 100644 --- a/src/sage/modular/abvar/finite_subgroup.py +++ b/src/sage/modular/abvar/finite_subgroup.py @@ -774,7 +774,7 @@ def invariants(self): ... ValueError: object is immutable; please change a copy instead. sage: type(v[0]) - + :: diff --git a/src/sage/modular/abvar/morphism.py b/src/sage/modular/abvar/morphism.py index 99bbd68af9d..d8676e7db00 100644 --- a/src/sage/modular/abvar/morphism.py +++ b/src/sage/modular/abvar/morphism.py @@ -40,7 +40,8 @@ ########################################################################### from sage.categories.morphism import Morphism as base_Morphism -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ import sage.modules.matrix_morphism import sage.matrix.matrix_space as matrix_space @@ -796,7 +797,7 @@ def index(self): sage: t.index() 997 sage: type(t.index()) - + """ return self.__n diff --git a/src/sage/modular/abvar/torsion_point.py b/src/sage/modular/abvar/torsion_point.py index 56150c69943..a7cdd54ff3a 100644 --- a/src/sage/modular/abvar/torsion_point.py +++ b/src/sage/modular/abvar/torsion_point.py @@ -87,7 +87,7 @@ def element(self): sage: v = (G.0-G.1).element(); v (1/3, -1/5) sage: type(v) - + """ return self.__element diff --git a/src/sage/modular/all.py b/src/sage/modular/all.py index 2532c33e107..cfccb18e65f 100644 --- a/src/sage/modular/all.py +++ b/src/sage/modular/all.py @@ -20,11 +20,12 @@ from .cusps import Cusp, Cusps -from .dims import (dimension_cusp_forms, - dimension_new_cusp_forms, - dimension_eis, - dimension_modular_forms, - sturm_bound) +lazy_import('sage.modular.dims', ('dimension_cusp_forms', + 'dimension_new_cusp_forms', + 'dimension_eis', + 'dimension_modular_forms', + 'sturm_bound'), + deprecation=(32647, 'removed from main namespace')) from .etaproducts import (EtaGroup, EtaProduct, EtaGroupElement, AllCusps, CuspFamily) diff --git a/src/sage/modular/arithgroup/arithgroup_element.pyx b/src/sage/modular/arithgroup/arithgroup_element.pyx index 1fff86aa7ab..b2e034bb5e7 100644 --- a/src/sage/modular/arithgroup/arithgroup_element.pyx +++ b/src/sage/modular/arithgroup/arithgroup_element.pyx @@ -254,7 +254,7 @@ cdef class ArithmeticSubgroupElement(MultiplicativeGroupElement): [4 5] [3 4] sage: type(x.matrix()) - + """ return self.__x diff --git a/src/sage/modular/arithgroup/arithgroup_generic.py b/src/sage/modular/arithgroup/arithgroup_generic.py index bb7973f64cc..e7d0673902d 100644 --- a/src/sage/modular/arithgroup/arithgroup_generic.py +++ b/src/sage/modular/arithgroup/arithgroup_generic.py @@ -952,7 +952,7 @@ def is_congruence(self): def genus(self): r""" - Return the genus of the modular curve of self. + Return the genus of the modular curve of ``self``. EXAMPLES:: @@ -960,6 +960,7 @@ def genus(self): 0 sage: Gamma1(31).genus() 26 + sage: from sage.modular.dims import dimension_cusp_forms sage: Gamma1(157).genus() == dimension_cusp_forms(Gamma1(157), 2) True sage: GammaH(7, [2]).genus() @@ -968,10 +969,7 @@ def genus(self): [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 2, 2] sage: [n for n in [1..200] if Gamma0(n).genus() == 1] [11, 14, 15, 17, 19, 20, 21, 24, 27, 32, 36, 49] - - """ - return ZZ(1 + (self.projective_index()) / ZZ(12) - (self.nu2())/ZZ(4) - (self.nu3())/ZZ(3) - self.ncusps()/ZZ(2)) def farey_symbol(self): diff --git a/src/sage/modular/arithgroup/congroup_gamma0.py b/src/sage/modular/arithgroup/congroup_gamma0.py index f1fc3f493d8..16390a280ab 100644 --- a/src/sage/modular/arithgroup/congroup_gamma0.py +++ b/src/sage/modular/arithgroup/congroup_gamma0.py @@ -75,7 +75,7 @@ class Gamma0_class(GammaH_class): sage: a = Gamma0(1).dimension_cusp_forms(2); a 0 sage: type(a) - + sage: Gamma0(5).dimension_cusp_forms(0) 0 sage: Gamma0(20).dimension_cusp_forms(1) diff --git a/src/sage/modular/dims.py b/src/sage/modular/dims.py index 9ad307a4937..4262e6c6b6c 100644 --- a/src/sage/modular/dims.py +++ b/src/sage/modular/dims.py @@ -265,32 +265,25 @@ def dimension_new_cusp_forms(X, k=2, p=0): EXAMPLES:: + sage: from sage.modular.dims import dimension_new_cusp_forms sage: dimension_new_cusp_forms(100,2) 1 - :: - sage: dimension_new_cusp_forms(Gamma0(100),2) 1 sage: dimension_new_cusp_forms(Gamma0(100),4) 5 - :: - sage: dimension_new_cusp_forms(Gamma1(100),2) 141 sage: dimension_new_cusp_forms(Gamma1(100),4) 463 - :: - sage: dimension_new_cusp_forms(DirichletGroup(100).1^2,2) 2 sage: dimension_new_cusp_forms(DirichletGroup(100).1^2,4) 8 - :: - sage: sum(dimension_new_cusp_forms(e,3) for e in DirichletGroup(30)) 12 sage: dimension_new_cusp_forms(Gamma1(30),3) @@ -315,8 +308,7 @@ def dimension_new_cusp_forms(X, k=2, p=0): return Gamma1(N).dimension_new_cusp_forms(k, eps=X, p=p) elif isinstance(X, (int, Integer)): return Gamma0(X).dimension_new_cusp_forms(k, p=p) - else: - raise TypeError("X (=%s) must be an integer, a Dirichlet character or a congruence subgroup of type Gamma0, Gamma1 or GammaH" % X) + raise TypeError(f"X (={X}) must be an integer, a Dirichlet character or a congruence subgroup of type Gamma0, Gamma1 or GammaH") def dimension_cusp_forms(X, k=2): @@ -333,25 +325,20 @@ def dimension_cusp_forms(X, k=2): EXAMPLES:: + sage: from sage.modular.dims import dimension_cusp_forms sage: dimension_cusp_forms(5,4) 1 - :: - sage: dimension_cusp_forms(Gamma0(11),2) 1 sage: dimension_cusp_forms(Gamma1(13),2) 2 - :: - sage: dimension_cusp_forms(DirichletGroup(13).0^2,2) 1 sage: dimension_cusp_forms(DirichletGroup(13).0,3) 1 - :: - sage: dimension_cusp_forms(Gamma0(11),2) 1 sage: dimension_cusp_forms(Gamma0(11),0) @@ -363,8 +350,6 @@ def dimension_cusp_forms(X, k=2): sage: dimension_cusp_forms(Gamma0(1),4) 0 - :: - sage: dimension_cusp_forms(Gamma0(389),2) 32 sage: dimension_cusp_forms(Gamma0(389),4) @@ -374,8 +359,6 @@ def dimension_cusp_forms(X, k=2): sage: dimension_cusp_forms(Gamma0(11),1) 0 - :: - sage: dimension_cusp_forms(Gamma1(11),2) 1 sage: dimension_cusp_forms(Gamma1(1),12) @@ -385,8 +368,6 @@ def dimension_cusp_forms(X, k=2): sage: dimension_cusp_forms(Gamma1(1),4) 0 - :: - sage: dimension_cusp_forms(Gamma1(389),2) 6112 sage: dimension_cusp_forms(Gamma1(389),4) @@ -394,13 +375,9 @@ def dimension_cusp_forms(X, k=2): sage: dimension_cusp_forms(Gamma1(2005),2) 159201 - :: - sage: dimension_cusp_forms(Gamma1(11),1) 0 - :: - sage: e = DirichletGroup(13).0 sage: e.order() 12 @@ -426,9 +403,8 @@ def dimension_cusp_forms(X, k=2): return X.dimension_cusp_forms(k) elif isinstance(X, (int, Integer)): return Gamma0(X).dimension_cusp_forms(k) - else: - raise TypeError("argument 1 must be a Dirichlet character, an integer " - "or a finite index subgroup of SL2Z") + raise TypeError("argument 1 must be a Dirichlet character, an integer " + "or a finite index subgroup of SL2Z") def dimension_eis(X, k=2): @@ -445,11 +421,10 @@ def dimension_eis(X, k=2): EXAMPLES:: + sage: from sage.modular.dims import dimension_eis sage: dimension_eis(5,4) 2 - :: - sage: dimension_eis(Gamma0(11),2) 1 sage: dimension_eis(Gamma1(13),2) @@ -457,8 +432,6 @@ def dimension_eis(X, k=2): sage: dimension_eis(Gamma1(2006),2) 3711 - :: - sage: e = DirichletGroup(13).0 sage: e.order() 12 @@ -467,8 +440,6 @@ def dimension_eis(X, k=2): sage: dimension_eis(e^2,2) 2 - :: - sage: e = DirichletGroup(13).0 sage: e.order() 12 @@ -479,8 +450,6 @@ def dimension_eis(X, k=2): sage: dimension_eis(e,13) 2 - :: - sage: G = DirichletGroup(20) sage: dimension_eis(G.0,3) 4 @@ -489,8 +458,6 @@ def dimension_eis(X, k=2): sage: dimension_eis(G.1^2,2) 6 - :: - sage: G = DirichletGroup(200) sage: e = prod(G.gens(), G(1)) sage: e.conductor() @@ -498,8 +465,7 @@ def dimension_eis(X, k=2): sage: dimension_eis(e,2) 4 - :: - + sage: from sage.modular.dims import dimension_modular_forms sage: dimension_modular_forms(Gamma1(4), 11) 6 """ @@ -509,8 +475,7 @@ def dimension_eis(X, k=2): return Gamma1(X.modulus()).dimension_eis(k, X) elif isinstance(X, (int, Integer)): return Gamma0(X).dimension_eis(k) - else: - raise TypeError("argument in dimension_eis must be an integer, a Dirichlet character, or a finite index subgroup of SL2Z (got %s)" % X) + raise TypeError(f"argument in dimension_eis must be an integer, a Dirichlet character, or a finite index subgroup of SL2Z (got {X})") def dimension_modular_forms(X, k=2): @@ -527,6 +492,7 @@ def dimension_modular_forms(X, k=2): EXAMPLES:: + sage: from sage.modular.dims import dimension_modular_forms sage: dimension_modular_forms(Gamma0(11),2) 2 sage: dimension_modular_forms(Gamma0(11),0) @@ -542,8 +508,10 @@ def dimension_modular_forms(X, k=2): sage: e = DirichletGroup(20).1 sage: dimension_modular_forms(e,3) 9 + sage: from sage.modular.dims import dimension_cusp_forms sage: dimension_cusp_forms(e,3) 3 + sage: from sage.modular.dims import dimension_eis sage: dimension_eis(e,3) 6 sage: dimension_modular_forms(11,2) @@ -576,6 +544,7 @@ def sturm_bound(level, weight=2): EXAMPLES:: + sage: from sage.modular.dims import sturm_bound sage: sturm_bound(11,2) 2 sage: sturm_bound(389,2) @@ -592,8 +561,6 @@ def sturm_bound(level, weight=2): if is_ArithmeticSubgroup(level): if level.is_congruence(): return level.sturm_bound(weight) - else: - raise ValueError("no Sturm bound defined for noncongruence " - "subgroups") + raise ValueError("no Sturm bound defined for noncongruence subgroups") if isinstance(level, (int, Integer)): return Gamma0(level).sturm_bound(weight) diff --git a/src/sage/modular/dirichlet.py b/src/sage/modular/dirichlet.py index 1cb1a7dd803..b5dfc048cbd 100644 --- a/src/sage/modular/dirichlet.py +++ b/src/sage/modular/dirichlet.py @@ -68,7 +68,7 @@ from sage.categories.map import Map from sage.rings.rational_field import is_RationalField -from sage.rings.complex_mpfr import is_ComplexField +import sage.rings.abc from sage.rings.qqbar import is_AlgebraicField from sage.rings.ring import is_Ring @@ -787,7 +787,7 @@ def conductor(self): sage: G. = DirichletGroup(20) sage: type(G(1).conductor()) - + """ if self.modulus() == 1 or self.is_trivial(): return rings.Integer(1) @@ -1153,7 +1153,7 @@ def _pari_init_(self): # now compute the input for pari (list of exponents) P = self.parent() - if is_ComplexField(P.base_ring()): + if isinstance(P.base_ring(), sage.rings.abc.ComplexField): zeta = P.zeta() zeta_argument = zeta.argument() v = [int(x.argument() / zeta_argument) for x in values_on_gens] @@ -1345,7 +1345,7 @@ def gauss_sum(self, a=1): K = G.base_ring() chi = self m = G.modulus() - if is_ComplexField(K): + if isinstance(K, sage.rings.abc.ComplexField): return self.gauss_sum_numerical(a=a) elif is_AlgebraicField(K): L = K @@ -1422,7 +1422,7 @@ def gauss_sum_numerical(self, prec=53, a=1): """ G = self.parent() K = G.base_ring() - if is_ComplexField(K): + if isinstance(K, sage.rings.abc.ComplexField): def phi(t): return t @@ -2138,7 +2138,7 @@ def element(self): """ P = self.parent() M = P._module - if is_ComplexField(P.base_ring()): + if isinstance(P.base_ring(), sage.rings.abc.ComplexField): zeta = P.zeta() zeta_argument = zeta.argument() v = M([int(round(x.argument() / zeta_argument)) @@ -2607,7 +2607,7 @@ def _zeta_powers(self): w = [a] zeta = self.zeta() zeta_order = self.zeta_order() - if is_ComplexField(R): + if isinstance(R, sage.rings.abc.ComplexField): for i in range(1, zeta_order): a = a * zeta a._set_multiplicative_order(zeta_order / gcd(zeta_order, i)) diff --git a/src/sage/modular/hecke/algebra.py b/src/sage/modular/hecke/algebra.py index 2e8506d4599..ffd6364c8bc 100644 --- a/src/sage/modular/hecke/algebra.py +++ b/src/sage/modular/hecke/algebra.py @@ -32,7 +32,8 @@ from sage.arith.all import lcm, gcd from sage.misc.latex import latex from sage.matrix.matrix_space import MatrixSpace -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.structure.element import Element from sage.structure.unique_representation import CachedRepresentation from sage.misc.cachefunc import cached_method diff --git a/src/sage/modular/hecke/element.py b/src/sage/modular/hecke/element.py index 35053b87675..7f0ca936ccf 100644 --- a/src/sage/modular/hecke/element.py +++ b/src/sage/modular/hecke/element.py @@ -113,7 +113,7 @@ def element(self): sage: z = BrandtModule(37)([0,1,-1]).element(); z (0, 1, -1) sage: type(z) - + """ try: return self.__element @@ -130,11 +130,11 @@ def _vector_(self, R=None): sage: v = BrandtModule(37)([0,1,-1]); v (0, 1, -1) sage: type(v._vector_()) - + sage: type(vector(v)) - + sage: type(vector(v, GF(2))) - + """ if R is None: return self.__element diff --git a/src/sage/modular/local_comp/liftings.py b/src/sage/modular/local_comp/liftings.py index e862031f4b2..f3bf799ae88 100644 --- a/src/sage/modular/local_comp/liftings.py +++ b/src/sage/modular/local_comp/liftings.py @@ -53,7 +53,7 @@ def lift_to_gamma1(g, m, n): sage: assert matrix(Zmod(11), 2, n) == matrix(Zmod(11),2,m) sage: assert matrix(Zmod(17), 2, [n[0], 0, n[2], n[3]]) == 1 sage: type(lift_to_gamma1([10,11,3,11],19,5)[0]) - + Tests with `m = 1` and with `n = 1`:: @@ -95,7 +95,7 @@ def lift_matrix_to_sl2z(A, N): sage: lift_matrix_to_sl2z([10, 11, 3, 11], 19) [29, 106, 3, 11] sage: type(_[0]) - + sage: lift_matrix_to_sl2z([2,0,0,1], 5) Traceback (most recent call last): ... @@ -130,7 +130,7 @@ def lift_gen_to_gamma1(m, n): [1 6] [0 1] sage: type(lift_gen_to_gamma1(9, 8)[0]) - + """ return lift_to_gamma1([0,-1,1,0], m, n) @@ -150,7 +150,7 @@ def lift_uniformiser_odd(p, u, n): sage: lift_uniformiser_odd(3, 2, 11) [432, 377, 165, 144] sage: type(lift_uniformiser_odd(3, 2, 11)[0]) - + """ g = lift_gen_to_gamma1(p**u, n) return [p * g[0], g[1], p * g[2], g[3]] @@ -175,7 +175,7 @@ def lift_ramified(g, p, u, n): sage: lift_ramified([8,2,12,2], 3, 2, 23) [323, 110, -133584, -45493] sage: type(lift_ramified([8,2,12,2], 3, 2, 23)[0]) - + """ a, b, c, d = lift_to_gamma1(g, p**u, n) r = crt((c - g[2]) / p**u * inverse_mod(a, p), 0, p, n) diff --git a/src/sage/modular/modform/ambient_R.py b/src/sage/modular/modform/ambient_R.py index a09a61f1b39..9bac23c8970 100644 --- a/src/sage/modular/modform/ambient_R.py +++ b/src/sage/modular/modform/ambient_R.py @@ -95,6 +95,7 @@ def _compute_q_expansion_basis(self, prec=None): sage: S = M.cuspidal_subspace() sage: 0 in [f.valuation() for f in S.basis()] False + sage: from sage.modular.dims import dimension_cusp_forms sage: len(S.basis()) == dimension_cusp_forms(Gamma1(29), 2) True """ diff --git a/src/sage/modular/modform/constructor.py b/src/sage/modular/modform/constructor.py index e330afb2361..2b9b59085f3 100644 --- a/src/sage/modular/modform/constructor.py +++ b/src/sage/modular/modform/constructor.py @@ -83,10 +83,10 @@ def canonical_parameters(group, level, weight, base_ring): sage: v = canonical_parameters(5, 5, int(7), ZZ); v (5, Congruence Subgroup Gamma0(5), 7, Integer Ring) sage: type(v[0]), type(v[1]), type(v[2]), type(v[3]) - (, + (, , - , - ) + , + ) sage: canonical_parameters( 5, 7, 7, ZZ ) Traceback (most recent call last): ... diff --git a/src/sage/modular/modform/eis_series.py b/src/sage/modular/modform/eis_series.py index adf7ec610c7..4f2e0ed878a 100644 --- a/src/sage/modular/modform/eis_series.py +++ b/src/sage/modular/modform/eis_series.py @@ -12,7 +12,7 @@ # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.misc.all import cputime +from sage.misc.misc import cputime import sage.modular.dirichlet as dirichlet from sage.modular.arithgroup.congroup_gammaH import GammaH_class from sage.rings.all import Integer, CyclotomicField, ZZ, QQ diff --git a/src/sage/modular/modform/numerical.py b/src/sage/modular/modform/numerical.py index 0d467ef2c0b..f09aca90239 100644 --- a/src/sage/modular/modform/numerical.py +++ b/src/sage/modular/modform/numerical.py @@ -444,7 +444,7 @@ def systems_of_eigenvalues(self, bound): EXAMPLES:: - sage: numerical_eigenforms(61).systems_of_eigenvalues(10) # rel tol 1e-12 + sage: numerical_eigenforms(61).systems_of_eigenvalues(10) # rel tol 1e-11 [ [-1.4811943040920152, 0.8060634335253695, 3.1563251746586642, 0.6751308705666477], [-1.0, -2.0000000000000027, -3.000000000000003, 1.0000000000000044], @@ -471,7 +471,7 @@ def systems_of_abs(self, bound): EXAMPLES:: - sage: numerical_eigenforms(61).systems_of_abs(10) # rel tol 1e-12 + sage: numerical_eigenforms(61).systems_of_abs(10) # rel tol 1e-11 [ [0.3111078174659775, 2.903211925911551, 2.525427560843529, 3.214319743377552], [1.0, 2.0000000000000027, 3.000000000000003, 1.0000000000000044], diff --git a/src/sage/modular/modform/ring.py b/src/sage/modular/modform/ring.py index 0bc05f3880a..c32b0ccbe55 100644 --- a/src/sage/modular/modform/ring.py +++ b/src/sage/modular/modform/ring.py @@ -698,6 +698,7 @@ def generators(self, maxweight=8, prec=10, start_gens=[], start_weight=2): 3 sage: [k for k, _ in v] [2, 2, 4] + sage: from sage.modular.dims import dimension_modular_forms sage: dimension_modular_forms(11,2) 2 sage: dimension_modular_forms(11,4) diff --git a/src/sage/modular/modform/space.py b/src/sage/modular/modform/space.py index afeb682bca2..497fb2e78bf 100644 --- a/src/sage/modular/modform/space.py +++ b/src/sage/modular/modform/space.py @@ -394,7 +394,7 @@ def __normalize_prec(self, prec): :: sage: type(N._ModularFormsSpace__normalize_prec(int(3))) - + """ if prec is None: prec = self.prec() diff --git a/src/sage/modular/modsym/boundary.py b/src/sage/modular/modsym/boundary.py index 89357424952..f8550d0f05f 100644 --- a/src/sage/modular/modsym/boundary.py +++ b/src/sage/modular/modsym/boundary.py @@ -541,7 +541,7 @@ def __call__(self, x): sage: B(7) Traceback (most recent call last): ... - TypeError: Coercion of 7 (of type ) into Space of Boundary Modular Symbols for Congruence Subgroup Gamma0(15) of weight 2 over Rational Field not (yet) defined. + TypeError: Coercion of 7 (of type ) into Space of Boundary Modular Symbols for Congruence Subgroup Gamma0(15) of weight 2 over Rational Field not (yet) defined. """ from .ambient import ModularSymbolsAmbient if isinstance(x, int) and x == 0: diff --git a/src/sage/modular/modsym/manin_symbol_list.py b/src/sage/modular/modsym/manin_symbol_list.py index 6dae77db4c7..dc4226b5db5 100644 --- a/src/sage/modular/modsym/manin_symbol_list.py +++ b/src/sage/modular/modsym/manin_symbol_list.py @@ -351,7 +351,7 @@ def manin_symbol(self, i): sage: s = m.manin_symbol(3); s [Y^2,(1,2)] sage: type(s) - + """ return self.element_class(self, self._symbol_list[i]) diff --git a/src/sage/modular/modsym/modsym.py b/src/sage/modular/modsym/modsym.py index 58a0d64b8b5..ee49b9c9abd 100644 --- a/src/sage/modular/modsym/modsym.py +++ b/src/sage/modular/modsym/modsym.py @@ -112,7 +112,7 @@ def canonical_parameters(group, weight, sign, base_ring): sage: p1 == p2 True sage: type(p1[1]) - + """ sign = rings.Integer(sign) if not (sign in [-1,0,1]): diff --git a/src/sage/modular/overconvergent/hecke_series.py b/src/sage/modular/overconvergent/hecke_series.py index 220d34696e6..eb5cf8b362c 100644 --- a/src/sage/modular/overconvergent/hecke_series.py +++ b/src/sage/modular/overconvergent/hecke_series.py @@ -66,8 +66,8 @@ # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# **************************************************************************** from sage.functions.all import floor, ceil from sage.arith.all import valuation @@ -75,7 +75,7 @@ from sage.rings.finite_rings.finite_field_constructor import GF from sage.modular.modform.all import ModularForms, ModularFormsRing, delta_qexp, eisenstein_series_qexp from sage.modular.dims import dimension_modular_forms -from sage.misc.functional import dimension,transpose,charpoly +from sage.misc.functional import dimension, transpose, charpoly from sage.matrix.constructor import matrix, random_matrix from sage.matrix.matrix_space import MatrixSpace from sage.misc.misc import cputime @@ -858,6 +858,7 @@ def compute_Wi(k,p,h,hj,E4,E6): sage: E4 = eisenstein_series_qexp(4, prec, K=S, normalization="constant") sage: E6 = eisenstein_series_qexp(6, prec, K=S, normalization="constant") sage: h = delta_qexp(prec, K=S) / E6^2 + sage: from sage.modular.dims import dimension_modular_forms sage: j = dimension_modular_forms(1, k - (p-1)) sage: hj = h**j sage: c = compute_Wi(k,p,h,hj,E4,E6); c diff --git a/src/sage/modular/overconvergent/weightspace.py b/src/sage/modular/overconvergent/weightspace.py index 08aacc88588..14515dda101 100644 --- a/src/sage/modular/overconvergent/weightspace.py +++ b/src/sage/modular/overconvergent/weightspace.py @@ -447,7 +447,7 @@ def one_over_Lvalue(self): sage: pAdicWeightSpace(11)(0).one_over_Lvalue() 0 sage: type(_) - + """ if self.is_trivial(): return ZZ(0) diff --git a/src/sage/modular/pollack_stevens/padic_lseries.py b/src/sage/modular/pollack_stevens/padic_lseries.py index 5dd019eee93..4a3beb12fdf 100644 --- a/src/sage/modular/pollack_stevens/padic_lseries.py +++ b/src/sage/modular/pollack_stevens/padic_lseries.py @@ -21,7 +21,8 @@ # **************************************************************************** from sage.rings.padics.all import pAdicField -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.rings.power_series_ring import PowerSeriesRing from sage.arith.all import binomial, kronecker from sage.rings.padics.precision_error import PrecisionError diff --git a/src/sage/modular/pollack_stevens/sigma0.py b/src/sage/modular/pollack_stevens/sigma0.py index 687b3c0644e..fa2f4ac7d81 100644 --- a/src/sage/modular/pollack_stevens/sigma0.py +++ b/src/sage/modular/pollack_stevens/sigma0.py @@ -288,7 +288,7 @@ def matrix(self): sage: type(s) sage: type(sm) - + sage: s == sm True """ diff --git a/src/sage/modular/pollack_stevens/space.py b/src/sage/modular/pollack_stevens/space.py index e4cb161ce07..f52d609b6e7 100644 --- a/src/sage/modular/pollack_stevens/space.py +++ b/src/sage/modular/pollack_stevens/space.py @@ -823,7 +823,7 @@ def cusps_from_mat(g): You can also just give the matrix of ``g``:: sage: type(g) - + sage: cusps_from_mat(g.matrix()) (+Infinity, 0) diff --git a/src/sage/modular/quatalg/brandt.py b/src/sage/modular/quatalg/brandt.py index 81a775c99c4..cad5e086785 100644 --- a/src/sage/modular/quatalg/brandt.py +++ b/src/sage/modular/quatalg/brandt.py @@ -1023,7 +1023,7 @@ def hecke_matrix(self, n, algorithm='default', sparse=False, B=None): [ 6 6] [ 2 10] sage: type(t) - + sage: B.hecke_matrix(19, algorithm='direct', B=2) [ 8 12] [ 4 16] @@ -1079,9 +1079,9 @@ def _compute_hecke_matrix_prime(self, p, sparse=False, B=None): [1 0 2] [1 2 0] sage: type(t) - + sage: type(B._compute_hecke_matrix_prime(2,sparse=True)) - + """ return self._compute_hecke_matrix_directly(n=p, B=B, sparse=sparse) @@ -1106,9 +1106,9 @@ def _compute_hecke_matrix_directly(self, n, B=None, sparse=False): [1 0 2] [1 2 0] sage: type(t) - + sage: type(B._compute_hecke_matrix_directly(2,sparse=True)) - + You can't compute the Hecke operator for n not coprime to the level using this function:: @@ -1685,7 +1685,7 @@ def benchmark_sage(levels, silent=False): ('sage', 43, 2, ...) ('sage', 97, 2, ...) """ - from sage.misc.all import cputime + from sage.misc.misc import cputime ans = [] for p, M in levels: t = cputime() diff --git a/src/sage/modules/fg_pid/fgp_element.py b/src/sage/modules/fg_pid/fgp_element.py index f6f03acd16c..a862cb04530 100644 --- a/src/sage/modules/fg_pid/fgp_element.py +++ b/src/sage/modules/fg_pid/fgp_element.py @@ -440,7 +440,7 @@ def additive_order(self): sage: Q.0.additive_order() 12 sage: type(Q.0.additive_order()) - + sage: Q.1.additive_order() +Infinity """ @@ -448,7 +448,9 @@ def additive_order(self): I = Q.invariants() v = self.vector() - from sage.rings.all import infinity, Mod, Integer + from sage.rings.infinity import infinity + from sage.rings.finite_rings.integer_mod import Mod + from sage.rings.integer import Integer from sage.arith.all import lcm n = Integer(1) for i, a in enumerate(I): diff --git a/src/sage/modules/fg_pid/fgp_module.py b/src/sage/modules/fg_pid/fgp_module.py index 009d8679e21..bb2bd6e7148 100644 --- a/src/sage/modules/fg_pid/fgp_module.py +++ b/src/sage/modules/fg_pid/fgp_module.py @@ -215,8 +215,9 @@ from sage.structure.sequence import Sequence from .fgp_element import DEBUG, FGP_Element from .fgp_morphism import FGP_Morphism, FGP_Homset -from sage.rings.all import Integer, ZZ -from sage.arith.all import lcm +from sage.rings.integer_ring import ZZ +from sage.rings.integer import Integer +from sage.arith.functions import lcm from sage.misc.cachefunc import cached_method from sage.matrix.constructor import matrix @@ -1223,7 +1224,7 @@ def gens_vector(self, x, reduce=False): """ x = self(x) v = x.vector() * self.smith_to_gens() - from sage.rings.all import infinity + from sage.rings.infinity import infinity if reduce and self.base_ring() == ZZ: orders = [g.order() for g in self.gens()] v = v.parent()([v[i] if orders[i] == infinity @@ -1740,7 +1741,7 @@ def cardinality(self): return self.__cardinality except AttributeError: pass - from sage.rings.all import infinity + from sage.rings.infinity import infinity from sage.misc.misc_c import prod v = self.invariants() self.__cardinality = infinity if 0 in v else prod(v) diff --git a/src/sage/modules/fg_pid/fgp_morphism.py b/src/sage/modules/fg_pid/fgp_morphism.py index 2bca2484d8a..8eaf32ed7bd 100644 --- a/src/sage/modules/fg_pid/fgp_morphism.py +++ b/src/sage/modules/fg_pid/fgp_morphism.py @@ -507,10 +507,10 @@ def __init__(self, X, Y, category=None): if category is None: from sage.modules.free_module import is_FreeModule if is_FreeModule(X) and is_FreeModule(Y): - from sage.all import FreeModules + from sage.categories.all import FreeModules category = FreeModules(X.base_ring()) else: - from sage.all import Modules + from sage.categories.all import Modules category = Modules(X.base_ring()) Homset.__init__(self, X, Y, category) diff --git a/src/sage/modules/filtered_vector_space.py b/src/sage/modules/filtered_vector_space.py index 4d0e451806e..dd6608c6161 100644 --- a/src/sage/modules/filtered_vector_space.py +++ b/src/sage/modules/filtered_vector_space.py @@ -218,7 +218,7 @@ def normalize_degree(deg): sage: from sage.modules.filtered_vector_space import normalize_degree sage: type(normalize_degree(int(1))) - + sage: normalize_degree(oo) +Infinity """ diff --git a/src/sage/modules/free_module.py b/src/sage/modules/free_module.py index 57c10114174..1e3c73da128 100644 --- a/src/sage/modules/free_module.py +++ b/src/sage/modules/free_module.py @@ -170,9 +170,10 @@ from sage.modules.module import Module import sage.rings.finite_rings.finite_field_constructor as finite_field import sage.rings.ring as ring +import sage.rings.abc import sage.rings.integer_ring import sage.rings.rational_field -import sage.rings.finite_rings.integer_mod_ring +import sage.rings.abc import sage.rings.infinity import sage.rings.integer from sage.categories.principal_ideal_domains import PrincipalIdealDomains @@ -253,7 +254,7 @@ def create_object(self, version, key): elif base_ring in PrincipalIdealDomains(): return FreeModule_ambient_pid(base_ring, rank, sparse=sparse) - elif isinstance(base_ring, sage.rings.number_field.order.Order) \ + elif isinstance(base_ring, sage.rings.abc.Order) \ and base_ring.is_maximal() and base_ring.class_number() == 1: return FreeModule_ambient_pid(base_ring, rank, sparse=sparse) @@ -7434,7 +7435,7 @@ def element_class(R, is_sparse): elif sage.rings.rational_field.is_RationalField(R) and not is_sparse: from .vector_rational_dense import Vector_rational_dense return Vector_rational_dense - elif sage.rings.finite_rings.integer_mod_ring.is_IntegerModRing(R) and not is_sparse: + elif isinstance(R, sage.rings.abc.IntegerModRing) and not is_sparse: from .vector_mod2_dense import Vector_mod2_dense if R.order() == 2: return Vector_mod2_dense @@ -7443,9 +7444,9 @@ def element_class(R, is_sparse): return Vector_modn_dense else: return free_module_element.FreeModuleElement_generic_dense - elif sage.rings.real_double.is_RealDoubleField(R) and not is_sparse: + elif isinstance(R, sage.rings.abc.RealDoubleField) and not is_sparse: return sage.modules.vector_real_double_dense.Vector_real_double_dense - elif sage.rings.complex_double.is_ComplexDoubleField(R) and not is_sparse: + elif isinstance(R, sage.rings.abc.ComplexDoubleField) and not is_sparse: return sage.modules.vector_complex_double_dense.Vector_complex_double_dense elif sage.symbolic.ring.is_SymbolicExpressionRing(R) and not is_sparse: import sage.modules.vector_symbolic_dense diff --git a/src/sage/modules/free_module_element.pyx b/src/sage/modules/free_module_element.pyx index 2075d07c0ae..43b8d2f8952 100644 --- a/src/sage/modules/free_module_element.pyx +++ b/src/sage/modules/free_module_element.pyx @@ -123,7 +123,6 @@ from sage.rings.infinity import Infinity, AnInfinity from sage.rings.integer_ring import ZZ from sage.rings.real_double import RDF from sage.rings.complex_double import CDF -from sage.misc.derivative import multi_derivative from sage.rings.ring cimport Ring from sage.rings.integer cimport Integer, smallInteger @@ -914,7 +913,7 @@ cdef class FreeModuleElement(Vector): # abstract base class sage: v = sage.modules.free_module_element.FreeModuleElement(QQ^3) sage: type(v) - + """ self._parent = parent self._degree = parent.degree() @@ -1735,7 +1734,7 @@ cdef class FreeModuleElement(Vector): # abstract base class sage: F. = PolynomialRing(QQ, 'y') sage: type(vector(F, [0]*4, sparse=True)) - + sage: vector(F, [0,0,0,y]) == vector(F, [0,0,0,y]) True sage: vector(F, [0,0,0,0]) == vector(F, [0,2,0,y]) @@ -1928,7 +1927,7 @@ cdef class FreeModuleElement(Vector): # abstract base class sage: P. = QQ[] sage: v = vector([x,y,z], sparse=True) sage: type(v) - + sage: a = v.list(); a [x, y, z] sage: a[0] = x*y; v @@ -3968,6 +3967,7 @@ cdef class FreeModuleElement(Vector): # abstract base class sage: v.derivative(x,x) (0, 0, 2) """ + from sage.misc.derivative import multi_derivative return multi_derivative(self, args) diff = derivative @@ -4012,7 +4012,7 @@ cdef class FreeModuleElement(Vector): # abstract base class sage: vec (0.5, 0.3333333333333334, 0.4596976941318602) sage: type(vec) - + sage: answers [(0.5, 5.55111512312578...e-15, 21, 0), (0.3333333333333..., 3.70074341541719...e-15, 21, 0), (0.45969769413186..., 5.10366964392284...e-15, 21, 0)] @@ -4169,7 +4169,7 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): EXAMPLES:: sage: type(vector(RR, [-1,0,2/3,pi,oo])) - + We can initialize with lists, tuples and derived types:: @@ -4418,7 +4418,7 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): sage: P. = QQ[] sage: v = vector([x,y,z]) sage: type(v) - + sage: a = v.list(); a [x, y, z] sage: a[0] = x*y; v @@ -5114,7 +5114,7 @@ cdef class FreeModuleElement_generic_sparse(FreeModuleElement): sage: M = FreeModule(R, 3, sparse=True) * (1/x) sage: v = M([-x^2, 3/x, 0]) sage: type(v) - + sage: a = v.list() sage: a [-x^2, 3/x, 0] diff --git a/src/sage/modules/module.pyx b/src/sage/modules/module.pyx index 5f3b4e0d467..62c6636fe0b 100644 --- a/src/sage/modules/module.pyx +++ b/src/sage/modules/module.pyx @@ -120,7 +120,7 @@ cdef class Module(Parent): sage: from sage.modules.module import Module sage: M = Module(ZZ) sage: type(M) - + """ from sage.categories.modules import Modules diff --git a/src/sage/modules/tensor_operations.py b/src/sage/modules/tensor_operations.py index 3550946581b..ce3bd555434 100644 --- a/src/sage/modules/tensor_operations.py +++ b/src/sage/modules/tensor_operations.py @@ -171,7 +171,7 @@ class VectorCollection(FreeModule_ambient_field): ((1, 0), (0, 1), (1, 2)) sage: r = R._vectors[0] sage: type(r) - + sage: r.parent() is R True sage: r.is_immutable() diff --git a/src/sage/modules/vector_complex_double_dense.pyx b/src/sage/modules/vector_complex_double_dense.pyx index 74c9dd75b11..c823e685abd 100644 --- a/src/sage/modules/vector_complex_double_dense.pyx +++ b/src/sage/modules/vector_complex_double_dense.pyx @@ -7,7 +7,7 @@ EXAMPLES:: sage: v (1.0 - 1.0*I, 2.0 + 3.141592653589793*I, 3.0 + 5.0*I) sage: type(v) - + sage: parent(v) Vector space of dimension 3 over Complex Double Field sage: v[0] = 5 diff --git a/src/sage/modules/vector_double_dense.pyx b/src/sage/modules/vector_double_dense.pyx index 83334163bea..d5559a07fb0 100644 --- a/src/sage/modules/vector_double_dense.pyx +++ b/src/sage/modules/vector_double_dense.pyx @@ -10,7 +10,7 @@ EXAMPLES:: sage: v (1.0 - 1.0*I, 2.0 + 3.141592653589793*I, 3.0 + 5.0*I) sage: type(v) - + sage: parent(v) Vector space of dimension 3 over Complex Double Field sage: v[0] = 5 diff --git a/src/sage/modules/vector_mod2_dense.pyx b/src/sage/modules/vector_mod2_dense.pyx index 3c08d14f2d7..47f41853f98 100644 --- a/src/sage/modules/vector_mod2_dense.pyx +++ b/src/sage/modules/vector_mod2_dense.pyx @@ -59,7 +59,7 @@ cdef class Vector_mod2_dense(free_module_element.FreeModuleElement): sage: VS([0,0,1]) (0, 0, 1) sage: type(_) - + """ cdef Vector_mod2_dense y y = Vector_mod2_dense.__new__(Vector_mod2_dense) @@ -114,7 +114,7 @@ cdef class Vector_mod2_dense(free_module_element.FreeModuleElement): sage: VS([0,0,1]) (0, 0, 1) sage: type(_) - + """ self._degree = degree self._parent = parent @@ -131,7 +131,7 @@ cdef class Vector_mod2_dense(free_module_element.FreeModuleElement): sage: VS((0,0,1/3)) (0, 0, 1) sage: type(_) - + """ self._entries = NULL self._is_immutable = 0 @@ -146,7 +146,7 @@ cdef class Vector_mod2_dense(free_module_element.FreeModuleElement): sage: VS((0,0,1/3)) (0, 0, 1) sage: type(_) - + sage: VS((0,0,int(3))) (0, 0, 1) sage: VS((0,0,3)) diff --git a/src/sage/modules/vector_modn_dense.pyx b/src/sage/modules/vector_modn_dense.pyx index d04604c5be3..9efa2d09753 100644 --- a/src/sage/modules/vector_modn_dense.pyx +++ b/src/sage/modules/vector_modn_dense.pyx @@ -5,7 +5,7 @@ EXAMPLES:: sage: v = vector(Integers(8),[1,2,3,4,5]) sage: type(v) - + sage: v (1, 2, 3, 4, 5) sage: 3*v @@ -64,13 +64,13 @@ TESTS:: sage: K = GF(previous_prime(2^31)) sage: v = vector(K, [42]); type(v[0]) - + sage: ~v[0] 2096353084 sage: K = GF(next_prime(2^31)) sage: v = vector(K, [42]); type(v[0]) - + sage: ~v[0] 1482786336 diff --git a/src/sage/modules/vector_real_double_dense.pyx b/src/sage/modules/vector_real_double_dense.pyx index 883a6195ca3..59bb8f4e23a 100644 --- a/src/sage/modules/vector_real_double_dense.pyx +++ b/src/sage/modules/vector_real_double_dense.pyx @@ -7,7 +7,7 @@ EXAMPLES:: sage: v (1.0, 3.141592653589793, 1.414213562373095) sage: type(v) - + sage: parent(v) Vector space of dimension 3 over Real Double Field sage: v[0] = 5 diff --git a/src/sage/modules/vector_space_morphism.py b/src/sage/modules/vector_space_morphism.py index 7c2104b1f17..1a1fde6eb5a 100644 --- a/src/sage/modules/vector_space_morphism.py +++ b/src/sage/modules/vector_space_morphism.py @@ -688,8 +688,10 @@ def linear_transformation(arg0, arg1=None, arg2=None, side='left'): from sage.modules.module import is_VectorSpace from sage.modules.free_module import VectorSpace from sage.categories.homset import Hom - from sage.symbolic.ring import SR - from sage.modules.vector_callable_symbolic_dense import Vector_callable_symbolic_dense + try: + from sage.modules.vector_callable_symbolic_dense import Vector_callable_symbolic_dense + except ImportError: + Vector_callable_symbolic_dense = () if not side in ['left', 'right']: raise ValueError("side must be 'left' or 'right', not {0}".format(side)) @@ -734,6 +736,7 @@ def linear_transformation(arg0, arg1=None, arg2=None, side='left'): elif isinstance(arg2, (list, tuple)): pass elif isinstance(arg2, Vector_callable_symbolic_dense): + from sage.symbolic.ring import SR args = arg2.parent().base_ring()._arguments exprs = arg2.change_ring(SR) m = len(args) diff --git a/src/sage/modules/with_basis/morphism.py b/src/sage/modules/with_basis/morphism.py index 6658aa547ac..184b09a94e3 100644 --- a/src/sage/modules/with_basis/morphism.py +++ b/src/sage/modules/with_basis/morphism.py @@ -1312,16 +1312,11 @@ def __init__(self, domain, matrix, codomain=None, category=None, side="left"): True sage: TestSuite(phi).run(skip=["_test_pickling"]) - Pickling fails (:trac:`17957`) because ``phi._on_basis`` is - currently a ``dict.__getitem__`` which is not picklable in Python 2:: + Pickling works (:trac:`17957`) in Python 3:: sage: phi._on_basis - sage: dumps(phi._on_basis) # py2 - Traceback (most recent call last): - ... - TypeError: expected string or Unicode object, NoneType found - sage: loads(dumps(phi)) == phi # py3 + sage: loads(dumps(phi)) == phi True The matrix is stored in the morphism, as if it was for an diff --git a/src/sage/modules/with_basis/representation.py b/src/sage/modules/with_basis/representation.py index a767525664b..e6f97d219a5 100644 --- a/src/sage/modules/with_basis/representation.py +++ b/src/sage/modules/with_basis/representation.py @@ -7,13 +7,13 @@ - Siddharth Singh (2020-03-21): Signed Representation """ -#################################################################################### +############################################################################## # Copyright (C) 2015 Travis Scrimshaw # # Distributed under the terms of the GNU General Public License (GPL) # The full text of the GPL is available at: # http://www.gnu.org/licenses/ -#################################################################################### +############################################################################## from sage.misc.abstract_method import abstract_method from sage.structure.element import Element @@ -154,7 +154,7 @@ def twisted_invariant_module(self, chi, G=None, **kwargs): Create the isotypic component of the action of ``G`` on ``self`` with irreducible character given by ``chi``. - .. SEEALSO: + .. SEEALSO:: - :class:`~sage.modules.with_basis.invariant.FiniteDimensionalTwistedInvariantModule` @@ -1026,7 +1026,7 @@ class SignRepresentationCoxeterGroup(SignRepresentation_abstract): def _default_sign(self, elem): """ Return the sign of the element - + INPUT: - ``elem`` -- the element of the group @@ -1039,5 +1039,4 @@ def _default_sign(self, elem): sage: V._default_sign(elem) 1 """ - return -1 if elem.length() % 2 == 1 else 1 - + return -1 if elem.length() % 2 else 1 diff --git a/src/sage/plot/contour_plot.py b/src/sage/plot/contour_plot.py index b1d9533c90f..27577d396d6 100644 --- a/src/sage/plot/contour_plot.py +++ b/src/sage/plot/contour_plot.py @@ -1217,8 +1217,8 @@ def f(x,y): options.pop('contours', None) incol = options.pop('fillcolor', 'blue') bordercol = options.pop('cmap', [None])[0] - from sage.symbolic.expression import is_Expression - if not is_Expression(f): + from sage.structure.element import Expression + if not isinstance(f, Expression): return region_plot(lambda x, y: f(x, y) < 0, xrange, yrange, borderwidth=linewidths, borderstyle=linestyles, incol=incol, bordercol=bordercol, @@ -1499,7 +1499,7 @@ def region_plot(f, xrange, yrange, plot_points, incol, outcol, bordercol, """ from sage.plot.all import Graphics from sage.plot.misc import setup_for_eval_on_grid - from sage.symbolic.expression import is_Expression + from sage.structure.element import Expression from warnings import warn import numpy @@ -1507,10 +1507,10 @@ def region_plot(f, xrange, yrange, plot_points, incol, outcol, bordercol, f = [f] feqs = [equify(g) for g in f - if is_Expression(g) and g.operator() is operator.eq + if isinstance(g, Expression) and g.operator() is operator.eq and not equify(g).is_zero()] f = [equify(g) for g in f - if not (is_Expression(g) and g.operator() is operator.eq)] + if not (isinstance(g, Expression) and g.operator() is operator.eq)] neqs = len(feqs) if neqs > 1: warn("There are at least 2 equations; " @@ -1620,8 +1620,8 @@ def equify(f): -1 """ from sage.calculus.all import symbolic_expression - from sage.symbolic.expression import is_Expression - if not is_Expression(f): + from sage.structure.element import Expression + if not isinstance(f, Expression): return lambda x, y: -1 if f(x, y) else 1 op = f.operator() diff --git a/src/sage/plot/plot3d/plot3d.py b/src/sage/plot/plot3d/plot3d.py index 06dd6a9df65..9678373657c 100644 --- a/src/sage/plot/plot3d/plot3d.py +++ b/src/sage/plot/plot3d/plot3d.py @@ -304,10 +304,10 @@ def to_cartesian(self, func, params=None): Graphics3d Object """ - from sage.symbolic.expression import is_Expression + from sage.structure.element import Expression from sage.rings.real_mpfr import is_RealNumber from sage.rings.integer import is_Integer - if params is not None and (is_Expression(func) or is_RealNumber(func) or is_Integer(func)): + if params is not None and (isinstance(func, Expression) or is_RealNumber(func) or is_Integer(func)): return self.transform(**{ self.dep_var: func, self.indep_vars[0]: params[0], diff --git a/src/sage/probability/random_variable.py b/src/sage/probability/random_variable.py index 5355636aa56..47d108996f0 100644 --- a/src/sage/probability/random_variable.py +++ b/src/sage/probability/random_variable.py @@ -15,10 +15,10 @@ # https://www.gnu.org/licenses/ # **************************************************************************** +import sage.rings.abc from sage.structure.parent import Parent from sage.functions.log import log from sage.functions.all import sqrt -from sage.rings.real_mpfr import (RealField, is_RealField) from sage.rings.rational_field import is_RationalField from sage.sets.set import Set from pprint import pformat @@ -83,6 +83,7 @@ def __init__(self, X, f, codomain=None, check=False): if check: raise NotImplementedError("Not implemented") if codomain is None: + from sage.rings.real_mpfr import RealField RR = RealField() else: RR = codomain @@ -337,8 +338,9 @@ def __init__(self, X, P, codomain=None, check=False): 1.50000000000000 """ if codomain is None: + from sage.rings.real_mpfr import RealField codomain = RealField() - if not is_RealField(codomain) and not is_RationalField(codomain): + if not isinstance(codomain, sage.rings.abc.RealField) and not is_RationalField(codomain): raise TypeError("Argument codomain (= %s) must be the reals or rationals" % codomain) if check: one = sum(P.values()) diff --git a/src/sage/quadratic_forms/special_values.py b/src/sage/quadratic_forms/special_values.py index 47f8ec3008f..e7b4c425866 100644 --- a/src/sage/quadratic_forms/special_values.py +++ b/src/sage/quadratic_forms/special_values.py @@ -9,13 +9,12 @@ from sage.combinat.combinat import bernoulli_polynomial from sage.misc.functional import denominator -from sage.rings.all import RealField from sage.arith.all import kronecker_symbol, bernoulli, factorial, fundamental_discriminant from sage.rings.infinity import infinity from sage.rings.integer_ring import ZZ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.rational_field import QQ -from sage.rings.real_mpfr import is_RealField +import sage.rings.abc from sage.symbolic.constants import pi, I # ---------------- The Gamma Function ------------------ @@ -278,9 +277,10 @@ def quadratic_L_function__numerical(n, d, num_terms=1000): ....: print("Oops! We have a problem at d = {}: exact = {}, numerical = {}".format(d, RR(quadratic_L_function__exact(1, d)), RR(quadratic_L_function__numerical(1, d)))) """ # Set the correct precision if it is given (for n). - if is_RealField(n.parent()): + if isinstance(n.parent(), sage.rings.abc.RealField): R = n.parent() else: + from sage.rings.real_mpfr import RealField R = RealField() if n < 0: diff --git a/src/sage/quivers/path_semigroup.py b/src/sage/quivers/path_semigroup.py index 7426132d4ec..d4e05928d85 100644 --- a/src/sage/quivers/path_semigroup.py +++ b/src/sage/quivers/path_semigroup.py @@ -543,7 +543,7 @@ def cardinality(self): ... ValueError: the underlying quiver has cycles, thus, there may be an infinity of directed paths """ - from sage.all import ZZ + from sage.rings.integer_ring import ZZ if self._quiver.is_directed_acyclic() and not self._quiver.has_loops(): return ZZ(len(self)) from sage.rings.infinity import Infinity diff --git a/src/sage/repl/display/fancy_repr.py b/src/sage/repl/display/fancy_repr.py index 2642b091f14..a606b5ef277 100644 --- a/src/sage/repl/display/fancy_repr.py +++ b/src/sage/repl/display/fancy_repr.py @@ -200,10 +200,7 @@ def __call__(self, obj, p, cycle): if not p.toplevel(): # Do not print the help for matrices inside containers return False - try: - from sage.matrix.matrix1 import Matrix - except ModuleNotFoundError: - return False + from sage.structure.element import Matrix if not isinstance(obj, Matrix): return False from sage.matrix.constructor import options diff --git a/src/sage/repl/preparse.py b/src/sage/repl/preparse.py index 1226196294e..1569ddbebdf 100644 --- a/src/sage/repl/preparse.py +++ b/src/sage/repl/preparse.py @@ -2021,6 +2021,13 @@ def implicit_mul(code, level=5): sage: implicit_mul('3λ') '3*λ' + + Check support for complex literals (:trac:`30477`):: + + sage: implicit_mul('2r-1JR') + '2r-1JR' + sage: implicit_mul('1E3 + 0.3E-3rj') + '1e3 + 0.3e-3rj' """ from keyword import iskeyword keywords_py2 = ['print', 'exec'] @@ -2042,8 +2049,8 @@ def re_no_keyword(pattern, code): no_mul_token = " '''_no_mult_token_''' " code = re.sub(r'\b0x', r'0%sx' % no_mul_token, code) # hex digits code = re.sub(r'( *)time ', r'\1time %s' % no_mul_token, code) # first word may be magic 'time' - code = re.sub(r'\b(\d+(?:\.\d+)?(?:e\d+)?)([rR]\b)', r'\1%s\2' % no_mul_token, code) # exclude such things as 10r - code = re.sub(r'\b(\d+(?:\.\d+)?)e([-\d])', r'\1%se%s\2' % (no_mul_token, no_mul_token), code) # exclude such things as 1e5 + code = re.sub(r'\b(\d+(?:\.\d+)?(?:e\d+)?)(rj?\b|j?r\b)', r'\1%s\2' % no_mul_token, code, flags=re.I) # exclude such things as 10r, 10rj, 10jr + code = re.sub(r'\b(\d+(?:\.\d+)?)e([-\d])', r'\1%se%s\2' % (no_mul_token, no_mul_token), code, flags=re.I) # exclude such things as 1e5 code = re_no_keyword(r'\b((?:\d+(?:\.\d+)?)|(?:%s[0-9eEpn]*\b)) *([^\W\d(]\w*)\b' % numeric_literal_prefix, code) if level >= 2: code = re.sub(r'(\%\(L\d+\))s', r'\1%ss%s' % (no_mul_token, no_mul_token), code) # literal strings diff --git a/src/sage/rings/abc.pxd b/src/sage/rings/abc.pxd index ea998549070..5b2aec37eff 100644 --- a/src/sage/rings/abc.pxd +++ b/src/sage/rings/abc.pxd @@ -5,6 +5,11 @@ cdef class RealField(Field): pass +cdef class RealIntervalField(Field): + + pass + + cdef class RealDoubleField(Field): pass diff --git a/src/sage/rings/abc.pyx b/src/sage/rings/abc.pyx index c65e03d9ed0..2c5e2253150 100644 --- a/src/sage/rings/abc.pyx +++ b/src/sage/rings/abc.pyx @@ -10,6 +10,22 @@ cdef class RealField(Field): pass +class RealBallField(Field): + r""" + Abstract base class for :class:`~sage.rings.real_arb.RealBallField`. + """ + + pass + + +cdef class RealIntervalField(Field): + r""" + Abstract base class for :class:`~sage.rings.real_mpfi.RealIntervalField_class`. + """ + + pass + + cdef class RealDoubleField(Field): r""" Abstract base class for :class:`~sage.rings.real_double.RealDoubleField_class`. @@ -26,9 +42,40 @@ cdef class ComplexField(Field): pass +class ComplexBallField(Field): + r""" + Abstract base class for :class:`~sage.rings.complex_arb.ComplexBallField`. + """ + + pass + + +class ComplexIntervalField(Field): + r""" + Abstract base class for :class:`~sage.rings.complex_interval_field.ComplexIntervalField_class`. + """ + + pass + + cdef class ComplexDoubleField(Field): r""" Abstract base class for :class:`~sage.rings.complex_double.ComplexDoubleField_class`. """ pass + + +class IntegerModRing: + r""" + Abstract base class for :class:`~sage.rings.finite_rings.integer_mod_ring.IntegerModRing_generic`. + """ + + pass + +class Order: + r""" + Abstract base class for :class:`~sage.rings.number_field.order.Order`. + """ + + pass diff --git a/src/sage/rings/asymptotic/asymptotic_ring.py b/src/sage/rings/asymptotic/asymptotic_ring.py index a474bf4d1eb..f7e3d0c235e 100644 --- a/src/sage/rings/asymptotic/asymptotic_ring.py +++ b/src/sage/rings/asymptotic/asymptotic_ring.py @@ -2601,7 +2601,7 @@ def substitute(self, rules=None, domain=None, **kwds): ... TypeError: Cannot substitute u in u since it is neither an asymptotic expansion nor a string - (but a ). + (but a ). :: diff --git a/src/sage/rings/cfinite_sequence.py b/src/sage/rings/cfinite_sequence.py index c7821c2a387..b73764ce5d2 100644 --- a/src/sage/rings/cfinite_sequence.py +++ b/src/sage/rings/cfinite_sequence.py @@ -776,7 +776,7 @@ def series(self, n): sage: s = r.series(4); s x + 2*x^2 + 3*x^3 + 4*x^4 + O(x^5) sage: type(s) - + """ R = LaurentSeriesRing(QQ, 'x', default_prec=n) return R(self.ogf()) diff --git a/src/sage/rings/complex_arb.pyx b/src/sage/rings/complex_arb.pyx index 9aa6ba15d7b..4e09e548f0a 100644 --- a/src/sage/rings/complex_arb.pyx +++ b/src/sage/rings/complex_arb.pyx @@ -147,6 +147,7 @@ from cysignals.signals cimport sig_on, sig_str, sig_off, sig_error import sage.categories.fields +cimport sage.rings.abc cimport sage.rings.rational from cpython.float cimport PyFloat_AS_DOUBLE @@ -301,7 +302,8 @@ cdef int acb_calc_func_callback(acb_ptr out, const acb_t inp, void * param, finally: sig_on() -class ComplexBallField(UniqueRepresentation, Field): + +class ComplexBallField(UniqueRepresentation, sage.rings.abc.ComplexBallField): r""" An approximation of the field of complex numbers using pairs of mid-rad intervals. @@ -2476,7 +2478,7 @@ cdef class ComplexBall(RingElement): sage: CBF(sqrt(2)).contains_exact(sqrt(2)) Traceback (most recent call last): ... - TypeError: unsupported type: + TypeError: unsupported type: """ cdef fmpz_t tmpz cdef fmpq_t tmpq @@ -3643,11 +3645,13 @@ cdef class ComplexBall(RingElement): sage: CBF(1/2, 3).zetaderiv(1) [0.191759884092721...] + [-0.073135728865928...]*I + sage: CBF(2).zetaderiv(3) + [-6.0001458028430...] """ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing Pol = PolynomialRing(self._parent, 'x') ser = Pol([self, 1])._zeta_series(k + 1) - return ser[k] + return ser[k]*ZZ.coerce(k).factorial() def lambert_w(self, branch=0): r""" diff --git a/src/sage/rings/complex_double.pyx b/src/sage/rings/complex_double.pyx index aa45ef96602..9038f2dd14f 100644 --- a/src/sage/rings/complex_double.pyx +++ b/src/sage/rings/complex_double.pyx @@ -23,7 +23,7 @@ EXAMPLES:: sage: CDF Complex Double Field sage: type(CDF.0) - + sage: ComplexDoubleElement(sqrt(2),3) 1.4142135623730951 + 3.0*I sage: parent(CDF(-2)) @@ -111,18 +111,28 @@ from sage.structure.richcmp cimport rich_to_bool cimport gmpy2 gmpy2.import_gmpy2() + def is_ComplexDoubleField(x): """ Return ``True`` if ``x`` is the complex double field. + This function is deprecated. Use :func:`isinstance` with + :class:`~sage.rings.abc.ComplexDoubleField` instead. + EXAMPLES:: sage: from sage.rings.complex_double import is_ComplexDoubleField sage: is_ComplexDoubleField(CDF) + doctest:warning... + DeprecationWarning: is_ComplexDoubleField is deprecated; + use isinstance(..., sage.rings.abc.ComplexDoubleField) instead + See https://trac.sagemath.org/32610 for details. True sage: is_ComplexDoubleField(ComplexField(53)) False """ + from sage.misc.superseded import deprecation + deprecation(32610, 'is_ComplexDoubleField is deprecated; use isinstance(..., sage.rings.abc.ComplexDoubleField) instead') return isinstance(x, ComplexDoubleField_class) diff --git a/src/sage/rings/complex_interval_field.py b/src/sage/rings/complex_interval_field.py index cee580b22a3..013977aa338 100644 --- a/src/sage/rings/complex_interval_field.py +++ b/src/sage/rings/complex_interval_field.py @@ -40,6 +40,7 @@ from .integer_ring import ZZ from .rational_field import QQ from .ring import Field +import sage.rings.abc from . import integer from . import complex_interval import weakref @@ -56,12 +57,19 @@ def is_ComplexIntervalField(x): sage: from sage.rings.complex_interval_field import is_ComplexIntervalField as is_CIF sage: is_CIF(CIF) + doctest:warning... + DeprecationWarning: is_ComplexIntervalField is deprecated; + use isinstance(..., sage.rings.abc.ComplexIntervalField) instead + See https://trac.sagemath.org/32612 for details. True sage: is_CIF(CC) False """ + from sage.misc.superseded import deprecation + deprecation(32612, 'is_ComplexIntervalField is deprecated; use isinstance(..., sage.rings.abc.ComplexIntervalField) instead') return isinstance(x, ComplexIntervalField_class) + cache = {} def ComplexIntervalField(prec=53, names=None): """ @@ -93,7 +101,7 @@ def ComplexIntervalField(prec=53, names=None): return C -class ComplexIntervalField_class(Field): +class ComplexIntervalField_class(sage.rings.abc.ComplexIntervalField): """ The field of complex (interval) numbers. diff --git a/src/sage/rings/complex_mpc.pyx b/src/sage/rings/complex_mpc.pyx index 04e8019bb2e..e7f287aa9c9 100644 --- a/src/sage/rings/complex_mpc.pyx +++ b/src/sage/rings/complex_mpc.pyx @@ -409,7 +409,7 @@ cdef class MPComplexField_class(sage.rings.ring.Field): sage: C20(i*4, 7) Traceback (most recent call last): ... - TypeError: unable to coerce to a ComplexNumber: + TypeError: unable to coerce to a ComplexNumber: Each part can be set with strings (written in base ten):: diff --git a/src/sage/rings/complex_mpfr.pyx b/src/sage/rings/complex_mpfr.pyx index e3f609a43c6..b419914f23f 100644 --- a/src/sage/rings/complex_mpfr.pyx +++ b/src/sage/rings/complex_mpfr.pyx @@ -157,22 +157,33 @@ def is_ComplexNumber(x): """ return isinstance(x, ComplexNumber) + def is_ComplexField(x): """ Check if ``x`` is a :class:`complex field `. + This function is deprecated. Use :func:`isinstance` with + :class:`~sage.rings.abc.ComplexField` instead. + EXAMPLES:: sage: from sage.rings.complex_mpfr import is_ComplexField as is_CF sage: is_CF(ComplexField()) + doctest:warning... + DeprecationWarning: is_ComplexField is deprecated; + use isinstance(..., sage.rings.abc.ComplexField) instead + See https://trac.sagemath.org/32610 for details. True sage: is_CF(ComplexField(12)) True sage: is_CF(CC) True """ + from sage.misc.superseded import deprecation + deprecation(32610, 'is_ComplexField is deprecated; use isinstance(..., sage.rings.abc.ComplexField) instead') return isinstance(x, ComplexField_class) + cache = {} def ComplexField(prec=53, names=None): """ @@ -543,7 +554,7 @@ class ComplexField_class(sage.rings.abc.ComplexField): RR = self._real_field() if RR.has_coerce_map_from(S): return RRtoCC(RR, self) * RR._internal_coerce_map_from(S) - if is_ComplexField(S): + if isinstance(S, ComplexField_class): if self._prec <= S._prec: return self._generic_coerce_map(S) else: @@ -1382,11 +1393,11 @@ cdef class ComplexNumber(sage.structure.element.FieldElement): sage: pari(a).type() 't_COMPLEX' sage: type(pari(a)) - + sage: a.__pari__() 2.00000000000000 + 1.00000000000000*I sage: type(a.__pari__()) - + sage: a = CC(pi) sage: pari(a) 3.14159265358979 diff --git a/src/sage/rings/continued_fraction.py b/src/sage/rings/continued_fraction.py index 7e4611e435f..cf5f8b1f9eb 100644 --- a/src/sage/rings/continued_fraction.py +++ b/src/sage/rings/continued_fraction.py @@ -2051,7 +2051,7 @@ def __init__(self, w, value=None, check=True): sage: w = words.ThueMorseWord([int(1), int(2)]) sage: t = continued_fraction(w) sage: type(t.quotient(1)) - + """ ContinuedFraction_base.__init__(self) self._w = w @@ -2157,7 +2157,7 @@ def _Integer_quotient(self, n): sage: t.quotient(1) 2 sage: type(t.quotient(1)) # indirect doctest - + """ return Integer(self._w[n]) @@ -2407,7 +2407,7 @@ def continued_fraction_list(x, type="std", partial_convergents=False, sage: a = 1.575709393346379 sage: type(a) - + sage: continued_fraction_list(a) [1, 1, 1, 2, 1, 4, 18, 1, 5, 2, 25037802, 7, 1, 3, 1, 28, 1, 8, 2] diff --git a/src/sage/rings/fast_arith.pyx b/src/sage/rings/fast_arith.pyx index aecfdf6bb0f..1eab26ba803 100644 --- a/src/sage/rings/fast_arith.pyx +++ b/src/sage/rings/fast_arith.pyx @@ -96,9 +96,9 @@ cpdef prime_range(start, stop=None, algorithm=None, bint py_ints=False): sage: prime_range(10**30,10**30+100,"pari_isprime") [1000000000000000000000000000057, 1000000000000000000000000000099] sage: type(prime_range(8)[0]) - + sage: type(prime_range(8,algorithm="pari_isprime")[0]) - + .. NOTE:: diff --git a/src/sage/rings/finite_rings/element_base.pyx b/src/sage/rings/finite_rings/element_base.pyx index d4c06183317..492a30983c9 100755 --- a/src/sage/rings/finite_rings/element_base.pyx +++ b/src/sage/rings/finite_rings/element_base.pyx @@ -339,7 +339,7 @@ cdef class FinitePolyExtElement(FiniteRingElement): sage: t_element 3*b^2 + 2*b + 4 sage: type(t_element) - + """ if var is None: var = self.parent().variable_name() diff --git a/src/sage/rings/finite_rings/element_givaro.pyx b/src/sage/rings/finite_rings/element_givaro.pyx index 82f4bb2e99a..e28808d84bf 100644 --- a/src/sage/rings/finite_rings/element_givaro.pyx +++ b/src/sage/rings/finite_rings/element_givaro.pyx @@ -300,7 +300,7 @@ cdef class Cache_givaro(Cache_base): sage: e.parent() is k True sage: type(e) - + sage: P. = PowerSeriesRing(GF(3^3, 'a')) sage: P.random_element(5).parent() is P @@ -1413,7 +1413,7 @@ cdef class FiniteField_givaroElement(FinitePolyExtElement): sage: b._log_to_int() 5 sage: type(b._log_to_int()) - + """ return Integer(self._cache.log_to_int(self.element)) @@ -1494,7 +1494,7 @@ cdef class FiniteField_givaroElement(FinitePolyExtElement): sage: f = (b^2+1).polynomial(); f b + 4 sage: type(f) - + sage: parent(f) Univariate Polynomial Ring in b over Finite Field of size 5 """ diff --git a/src/sage/rings/finite_rings/element_pari_ffelt.pyx b/src/sage/rings/finite_rings/element_pari_ffelt.pyx index 57baa162b0b..95922cd42d0 100644 --- a/src/sage/rings/finite_rings/element_pari_ffelt.pyx +++ b/src/sage/rings/finite_rings/element_pari_ffelt.pyx @@ -98,7 +98,7 @@ cdef class FiniteFieldElement_pari_ffelt(FinitePolyExtElement): sage: a = K.gen(); a a sage: type(a) - + TESTS:: diff --git a/src/sage/rings/finite_rings/finite_field_base.pyx b/src/sage/rings/finite_rings/finite_field_base.pyx index 39e73253dcd..5fc4a0e6d4d 100644 --- a/src/sage/rings/finite_rings/finite_field_base.pyx +++ b/src/sage/rings/finite_rings/finite_field_base.pyx @@ -40,6 +40,7 @@ from sage.misc.persist import register_unpickle_override from sage.misc.cachefunc import cached_method from sage.misc.prandom import randrange from sage.rings.integer cimport Integer +import sage.rings.abc from sage.misc.superseded import deprecation_cython as deprecation # Copied from sage.misc.fast_methods, used in __hash__() below. @@ -1342,10 +1343,9 @@ cdef class FiniteField(Field): False """ from sage.rings.integer_ring import ZZ - from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing if R is int or R is long or R is ZZ: return True - if is_IntegerModRing(R) and self.characteristic().divides(R.characteristic()): + if isinstance(R, sage.rings.abc.IntegerModRing) and self.characteristic().divides(R.characteristic()): return R.hom((self.one(),), check=False) if is_FiniteField(R): if R is self: diff --git a/src/sage/rings/finite_rings/finite_field_constructor.py b/src/sage/rings/finite_rings/finite_field_constructor.py index 0980ff8dbdf..d7b4e15985f 100644 --- a/src/sage/rings/finite_rings/finite_field_constructor.py +++ b/src/sage/rings/finite_rings/finite_field_constructor.py @@ -284,7 +284,7 @@ class FiniteFieldFactory(UniqueFactory): sage: f = K.modulus(); f x^5 + 4*x + 1 sage: type(f) - + By default, the given generator is not guaranteed to be primitive (a generator of the multiplicative group), use diff --git a/src/sage/rings/finite_rings/finite_field_givaro.py b/src/sage/rings/finite_rings/finite_field_givaro.py index e686ef8424b..dbeddd8705e 100644 --- a/src/sage/rings/finite_rings/finite_field_givaro.py +++ b/src/sage/rings/finite_rings/finite_field_givaro.py @@ -152,7 +152,7 @@ def characteristic(self): sage: p = GF(19^5,'a').characteristic(); p 19 sage: type(p) - + """ return Integer(self._cache.characteristic()) @@ -169,7 +169,7 @@ def order(self): sage: n = GF(19^5,'a').order(); n 2476099 sage: type(n) - + """ return self._cache.order() @@ -218,7 +218,7 @@ def random_element(self, *args, **kwds): sage: e.parent() is k True sage: type(e) - + sage: P. = PowerSeriesRing(GF(3^3, 'a')) sage: P.random_element(5).parent() is P diff --git a/src/sage/rings/finite_rings/hom_finite_field_givaro.pyx b/src/sage/rings/finite_rings/hom_finite_field_givaro.pyx index 28c8b3935c0..698c54e71b5 100644 --- a/src/sage/rings/finite_rings/hom_finite_field_givaro.pyx +++ b/src/sage/rings/finite_rings/hom_finite_field_givaro.pyx @@ -204,13 +204,13 @@ cdef class FrobeniusEndomorphism_givaro(FrobeniusEndomorphism_finite_field): sage: Frob = k.frobenius_endomorphism(); Frob Frobenius endomorphism t |--> t^5 on Finite Field in t of size 5^3 sage: type(Frob) - + sage: k. = GF(5^20) sage: Frob = k.frobenius_endomorphism(); Frob Frobenius endomorphism t |--> t^5 on Finite Field in t of size 5^20 sage: type(Frob) - + """ if not isinstance(domain, FiniteField_givaro): raise TypeError("The domain is not an instance of FiniteField_givaro") diff --git a/src/sage/rings/finite_rings/integer_mod.pyx b/src/sage/rings/finite_rings/integer_mod.pyx index 4089c437934..ab92c9a8ecb 100644 --- a/src/sage/rings/finite_rings/integer_mod.pyx +++ b/src/sage/rings/finite_rings/integer_mod.pyx @@ -1347,7 +1347,7 @@ cdef class IntegerMod_abstract(FiniteRingElement): The 'extend' option is not implemented (yet). - NOTES: + NOTE: - If `n = 0`: diff --git a/src/sage/rings/finite_rings/integer_mod_ring.py b/src/sage/rings/finite_rings/integer_mod_ring.py index c704b2a2eb7..28fb2736491 100644 --- a/src/sage/rings/finite_rings/integer_mod_ring.py +++ b/src/sage/rings/finite_rings/integer_mod_ring.py @@ -64,6 +64,7 @@ from sage.arith.all import factor, primitive_root, CRT_basis import sage.rings.ring as ring +import sage.rings.abc from . import integer_mod import sage.rings.integer as integer import sage.rings.integer_ring as integer_ring @@ -243,11 +244,18 @@ def is_IntegerModRing(x): """ Return ``True`` if ``x`` is an integer modulo ring. + This function is deprecated. Use :func:`isinstance` with + :class:`sage.rings.abc.IntegerModRing` instead. + EXAMPLES:: sage: from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing sage: R = IntegerModRing(17) sage: is_IntegerModRing(R) + doctest:warning... + DeprecationWarning: the function is_IntegerModRing is deprecated. + Use isinstance(..., sage.rings.abc.IntegerModRing) instead. + See https://trac.sagemath.org/32606 for details. True sage: is_IntegerModRing(GF(13)) True @@ -258,6 +266,9 @@ def is_IntegerModRing(x): sage: is_IntegerModRing(ZZ) False """ + from sage.misc.superseded import deprecation + deprecation(32606, "the function is_IntegerModRing is deprecated. " + "Use isinstance(..., sage.rings.abc.IntegerModRing) instead.") return isinstance(x, IntegerModRing_generic) @@ -297,7 +308,7 @@ def _unit_gens_primepowercase(p, r): @richcmp_method -class IntegerModRing_generic(quotient_ring.QuotientRing_generic): +class IntegerModRing_generic(quotient_ring.QuotientRing_generic, sage.rings.abc.IntegerModRing): """ The ring of integers modulo `N`. diff --git a/src/sage/rings/finite_rings/residue_field.pyx b/src/sage/rings/finite_rings/residue_field.pyx index 007a68e4c0f..62bebc2303b 100644 --- a/src/sage/rings/finite_rings/residue_field.pyx +++ b/src/sage/rings/finite_rings/residue_field.pyx @@ -963,7 +963,7 @@ cdef class ReductionMap(Map): sage: K = R.fraction_field() sage: f = k.convert_map_from(K) sage: type(f) - + sage: f(1/t) a^4 + a sage: f(1/h) @@ -1143,7 +1143,7 @@ cdef class ResidueFieldHomomorphism_global(RingHomomorphism): From: Maximal Order in Cyclotomic Field of order 5 and degree 4 To: Residue field in a of Fractional ideal (7) sage: type(phi) - + sage: R. = GF(2)[]; P = R.ideal(t^7 + t^6 + t^5 + t^4 + 1) sage: k = P.residue_field(); f = k.coerce_map_from(R) @@ -1606,7 +1606,7 @@ class ResidueFiniteField_prime_modn(ResidueField_generic, FiniteField_prime_modn 2 sage: V = k.vector_space(map=False); v = V([3]) sage: type(k.convert_map_from(V)) - + sage: k(v) # indirect doctest 3 @@ -1698,7 +1698,7 @@ class ResidueFiniteField_pari_ffelt(ResidueField_generic, FiniteField_pari_ffelt 6677 sage: V = ff.vector_space(map=False); v = V([3,-2]) sage: type(ff.convert_map_from(V)) - + sage: ff(v) # indirect doctest 10005*alpha + 3 @@ -1800,7 +1800,7 @@ class ResidueFiniteField_givaro(ResidueField_generic, FiniteField_givaro): 2*abar + 4 sage: V = k.vector_space(map=False); v = V([3,-2]) sage: type(k.convert_map_from(V)) - + sage: k(v) # indirect doctest 59*abar + 3 @@ -1906,7 +1906,7 @@ class ResidueFiniteField_ntl_gf2e(ResidueField_generic, FiniteField_ntl_gf2e): 2*abar + 4 sage: V = k.vector_space(map=False); v = V([3,-2]) sage: type(k.convert_map_from(V)) - + sage: k(v) # indirect doctest 59*abar + 3 diff --git a/src/sage/rings/fraction_field.py b/src/sage/rings/fraction_field.py index c5b5c55a785..8d8d4c49c80 100644 --- a/src/sage/rings/fraction_field.py +++ b/src/sage/rings/fraction_field.py @@ -948,7 +948,7 @@ def __init__(self, R, sage: R. = QQ[]; K = R.fraction_field() sage: K._element_class - + """ FractionField_generic.__init__(self, R, element_class) diff --git a/src/sage/rings/fraction_field_FpT.pyx b/src/sage/rings/fraction_field_FpT.pyx index 7ad2a7359ab..b81535fe5bd 100644 --- a/src/sage/rings/fraction_field_FpT.pyx +++ b/src/sage/rings/fraction_field_FpT.pyx @@ -1033,7 +1033,7 @@ cdef class Polyring_FpT_coerce(RingHomomorphism): From: Univariate Polynomial Ring in t over Finite Field of size 5 To: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 sage: type(f) - + TESTS:: @@ -1222,7 +1222,7 @@ cdef class FpT_Polyring_section(Section): From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 To: Univariate Polynomial Ring in t over Finite Field of size 5 sage: type(f) - + .. WARNING:: @@ -1351,7 +1351,7 @@ cdef class Fp_FpT_coerce(RingHomomorphism): From: Finite Field of size 5 To: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 sage: type(f) - + TESTS:: @@ -1524,7 +1524,7 @@ cdef class FpT_Fp_section(Section): From: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 5 To: Finite Field of size 5 sage: type(f) - + .. WARNING:: @@ -1673,7 +1673,7 @@ cdef class ZZ_FpT_coerce(RingHomomorphism): From: Integer Ring To: Fraction Field of Univariate Polynomial Ring in t over Finite Field of size 17 sage: type(f) - + TESTS:: diff --git a/src/sage/rings/fraction_field_element.pyx b/src/sage/rings/fraction_field_element.pyx index 4206b1dd4d8..4d1235c88c4 100644 --- a/src/sage/rings/fraction_field_element.pyx +++ b/src/sage/rings/fraction_field_element.pyx @@ -861,15 +861,15 @@ cdef class FractionFieldElement(FieldElement): sage: a = x^2; a x^2 sage: type(a.numerator()) - + sage: type(a.denominator()) - + sage: a = x^(-2); a 1/x^2 sage: type(a.numerator()) - + sage: type(a.denominator()) - + sage: x^0 1 sage: ((x+y)/(x-y))^2 diff --git a/src/sage/rings/function_field/ideal.py b/src/sage/rings/function_field/ideal.py index 4230b3780a0..8c40ae37398 100644 --- a/src/sage/rings/function_field/ideal.py +++ b/src/sage/rings/function_field/ideal.py @@ -99,6 +99,8 @@ from sage.structure.factorization import Factorization from sage.structure.unique_representation import UniqueRepresentation +from sage.arith.power import generic_power + from sage.modules.free_module_element import vector from sage.categories.monoids import Monoids @@ -1228,6 +1230,12 @@ def __init__(self, ring, hnf, denominator=1): # for fast multiplication with other ideal. self._kummer_form = None + # tuple of at most two gens: + # the first gen is an element of the base ring of the maximal order + # the second gen is the vector form of an element of the maximal order + # if the second gen is zero, the tuple has only the first gen. + self._gens_two_vecs = None + def __bool__(self): """ Test if this ideal is zero. @@ -1514,6 +1522,20 @@ def _mul_(self, other): elif other._kummer_form is not None: p, q = other._kummer_form vecs = list(p * self._hnf) + [mul(q, v) for v in self._hnf] + elif self._gens_two_vecs is not None: + if len(self._gens_two_vecs) == 1: + g1, = self._gens_two_vecs + vecs = list(g1 * other._hnf) + else: + g1, g2 = self._gens_two_vecs + vecs = list(g1 * other._hnf) + [mul(g2, v) for v in other._hnf] + elif other._gens_two_vecs is not None: + if len(other._gens_two_vecs) == 1: + g1, = other._gens_two_vecs + vecs = list(g1 * self._hnf) + else: + g1, g2 = other._gens_two_vecs + vecs = list(g1 * self._hnf) + [mul(g2, v) for v in self._hnf] else: vecs = [mul(r1,r2) for r1 in self._hnf for r2 in other._hnf] @@ -2138,6 +2160,52 @@ def __init__(self, ring, hnf, denominator=1): """ FunctionFieldIdeal_polymod.__init__(self, ring, hnf, denominator) + def __pow__(self, mod): + """ + Return ``self`` to the power of ``mod``. + + If a two-generators representation of ``self`` is known, it is used + to speed up powering. + + EXAMPLES:: + + sage: K. = FunctionField(GF(2)); _. = K[] + sage: L. = K.extension(Y^7 - x^3*Y - x) + sage: O = L.maximal_order() + sage: I = O.ideal(y) + sage: J = O.ideal(x + y) + sage: S = I / J + sage: a = S^100 + sage: _ = S.gens_two() + sage: b = S^100 # faster + sage: b == I^100 / J^100 + True + sage: b == a + True + """ + if mod > 2 and self._gens_two_vecs is not None: + O = self._ring + mul = O._mul_vecs + R = self._hnf.base_ring() + n = self._hnf.ncols() + + I = matrix.identity(R, n) + + if len(self._gens_two_vecs) == 1: + p, = self._gens_two_vecs + ppow = p**mod + J = [ppow * v for v in I] + else: + p, q = self._gens_two_vecs + q = sum(e1 * e2 for e1,e2 in zip(O.basis(), q)) + ppow = p**mod + qpow = O._coordinate_vector(q**mod) + J = [ppow * v for v in I] + [mul(qpow,v) for v in I] + + return O._ideal_from_vectors_and_denominator(J, self._denominator**mod) + + return generic_power(self, mod) + def gens(self): """ Return a set of generators of this ideal. @@ -2171,26 +2239,6 @@ def gens_two(self): If the ideal is principal, one generator *may* be returned. - ALGORITHM: - - At most two generators are required to generate ideals in - Dedekind domains. - - Lemma 4.7.9, algorithm 4.7.10, and exercise 4.29 of [Coh1993]_ - tell us that for an integral ideal `I` in a number field, if - we pick `a` such that `\gcd(N(I), N(a)/N(I)) = 1`, then `a` - and `N(I)` generate the ideal. `N()` is the norm, and this - result (presumably) generalizes to function fields. - - After computing `N(I)`, we search exhaustively to find `a`. - - .. TODO:: - - Always return a single generator for a principal ideal. - - Testing for principality is not trivial. Algorithm 6.5.10 - of [Coh1993]_ could probably be adapted for function fields. - EXAMPLES:: sage: K. = FunctionField(GF(2)); _. = K[] @@ -2220,10 +2268,30 @@ def gens_two(self): @cached_method def _gens_two(self): - """ + r""" Return a set of two generators of the integral ideal, that is the denominator times this fractional ideal. + ALGORITHM: + + At most two generators are required to generate ideals in + Dedekind domains. + + Lemma 4.7.9, algorithm 4.7.10, and exercise 4.29 of [Coh1993]_ + tell us that for an integral ideal `I` in a number field, if + we pick `a` such that `\gcd(N(I), N(a)/N(I)) = 1`, then `a` + and `N(I)` generate the ideal. `N()` is the norm, and this + result (presumably) generalizes to function fields. + + After computing `N(I)`, we search exhaustively to find `a`. + + .. TODO:: + + Always return a single generator for a principal ideal. + + Testing for principality is not trivial. Algorithm 6.5.10 + of [Coh1993]_ could probably be adapted for function fields. + EXAMPLES:: sage: K. = FunctionField(GF(4)); _. = K[] @@ -2247,8 +2315,10 @@ def _gens_two(self): g1 = F(_g1) g2 = sum([c1*c2 for c1,c2 in zip(_g2, O.basis())]) if g2: + self._gens_two_vecs = (_g1, _g2) return (g1,g2) else: + self._gens_two_vecs = (_g1,) return (g1,) ### start to search for two generators @@ -2260,14 +2330,16 @@ def _gens_two(self): norm *= e if norm.is_constant(): # unit ideal + self._gens_two_vecs = (1,) return (F(1),) # one generator; see .ideal_below() - l = hnf[0][0] - p = l.degree() - l = F(l) + _l = hnf[0][0] + p = _l.degree() + l = F(_l) if self._hnf == O.ideal(l)._hnf: # principal ideal + self._gens_two_vecs = (_l,) return (l,) R = hnf.base_ring() @@ -2286,6 +2358,7 @@ def check(alpha): # Trial 1: search for alpha among generators for alpha in basis: if check(alpha): + self._gens_two_vecs = (_l, O._coordinate_vector(alpha)) return (l, alpha) # Trial 2: exhaustive search for alpha using only polynomials @@ -2295,6 +2368,7 @@ def check(alpha): for g in G: alpha = sum([R(c1)*c2 for c1,c2 in zip(g, basis)]) if check(alpha): + self._gens_two_vecs = (_l, O._coordinate_vector(alpha)) return (l, alpha) # Trial 3: exhaustive search for alpha using all polynomials @@ -2312,6 +2386,7 @@ def check(alpha): alpha = sum([c1*c2 for c1,c2 in zip(g, basis)]) if check(alpha): + self._gens_two_vecs = (_l, O._coordinate_vector(alpha)) return (l, alpha) # should not reach here diff --git a/src/sage/rings/integer.pyx b/src/sage/rings/integer.pyx index f468b59bf68..56de0fc858a 100644 --- a/src/sage/rings/integer.pyx +++ b/src/sage/rings/integer.pyx @@ -2132,7 +2132,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): 2^I sage: r = 2 ^ int(-3); r; type(r) 1/8 - + sage: f = 2^(sin(x)-cos(x)); f 2^(-cos(x) + sin(x)) sage: f(x=3) @@ -5948,7 +5948,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): sage: m = n.__pari__(); m 9390823 sage: type(m) - + TESTS:: @@ -6187,13 +6187,13 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): TESTS:: sage: type(5.sqrt()) - + sage: type(5.sqrt(prec=53)) - + sage: type((-5).sqrt(prec=53)) - + sage: type(0.sqrt(prec=53)) - + Check that :trac:`9466` and :trac:`26509` are fixed:: @@ -6431,17 +6431,14 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): TESTS:: - sage: 1 << (2^60) # optional - mpir - Traceback (most recent call last): - ... - MemoryError: failed to allocate ... bytes # 64-bit - OverflowError: Python int too large to convert to C long # 32-bit - - sage: 1 << (2^60) # optional - gmp - Traceback (most recent call last): - ... - RuntimeError: Aborted # 64-bit - OverflowError: Python int too large to convert to C long # 32-bit + sage: try: + ....: print('Possible error output from gmp') + ....: 1 << (2^60) + ....: except (MemoryError, OverflowError, RuntimeError): + ....: pass + ....: else: + ....: print("Failed to raise exception") + Possible error output from gmp... """ cdef long n @@ -6794,7 +6791,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): """ return self - def binomial(self, m, algorithm='mpir'): + def binomial(self, m, algorithm='gmp'): """ Return the binomial coefficient "self choose m". @@ -6802,9 +6799,9 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): - ``m`` -- an integer - - ``algorithm`` -- ``'mpir'`` (default) or ``'pari'``; ``'mpir'`` is - faster for small ``m``, and ``'pari'`` tends to be faster for - large ``m`` + - ``algorithm`` -- ``'gmp'`` (default), ``'mpir'`` (an alias for + ``gmp``), or ``'pari'``; ``'gmp'`` is faster for small ``m``, + and ``'pari'`` tends to be faster for large ``m`` OUTPUT: @@ -6885,7 +6882,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): return self # now call the various backend - if algorithm == 'mpir': + if algorithm == 'gmp' or algorithm == 'mpir': x = PY_NEW(Integer) if mpz_fits_ulong_p(mm.value): sig_on() @@ -6897,7 +6894,7 @@ cdef class Integer(sage.structure.element.EuclideanDomainElement): elif algorithm == 'pari': return the_integer_ring(self.__pari__().binomial(mm)) else: - raise ValueError("algorithm must be one of: 'pari', 'mpir'") + raise ValueError("algorithm must be one of: 'pari' or 'gmp' (alias: 'mpir')") cdef int mpz_set_str_python(mpz_ptr z, char* s, int base) except -1: @@ -7058,7 +7055,7 @@ def GCD_list(v): sage: w = GCD_list([3,9,30]); w 3 sage: type(w) - + Check that the bug reported in :trac:`3118` has been fixed:: @@ -7072,7 +7069,7 @@ def GCD_list(v): sage: w = GCD_list([int(3), int(9), '30']); w 3 sage: type(w) - + Check that the GCD of the empty list is zero (:trac:`17257`):: @@ -7137,11 +7134,11 @@ cdef class int_to_Z(Morphism): sage: f(5r) 5 sage: type(f(5r)) - + sage: 1 + 2r 3 sage: type(1 + 2r) - + This is intended for internal use by the coercion system, to facilitate fast expressions mixing ints and more complex diff --git a/src/sage/rings/integer_ring.pyx b/src/sage/rings/integer_ring.pyx index 99befbb94a7..f6308251e80 100644 --- a/src/sage/rings/integer_ring.pyx +++ b/src/sage/rings/integer_ring.pyx @@ -26,7 +26,7 @@ other types will also coerce to the integers, when it makes sense. sage: b = Z(5678); b 5678 sage: type(a) - + sage: a + b 6912 sage: Z('94803849083985934859834583945394') @@ -183,7 +183,7 @@ cdef class IntegerRing_class(PrincipalIdealDomain): sage: b = Z(5678); b 5678 sage: type(a) - + sage: a + b 6912 sage: b + a @@ -206,18 +206,18 @@ cdef class IntegerRing_class(PrincipalIdealDomain): sage: a / b 617/2839 sage: type(a/b) - + sage: a/a 1 sage: type(a/a) - + For floor division, use the ``//`` operator instead:: sage: a // b 0 sage: type(a//b) - + Next we illustrate arithmetic with automatic coercion. The types that coerce are: str, int, long, Integer. @@ -1046,7 +1046,7 @@ cdef class IntegerRing_class(PrincipalIdealDomain): (1,) 1 sage: type(ZZ.gens()[0]) - + """ return (self(1), ) @@ -1066,7 +1066,7 @@ cdef class IntegerRing_class(PrincipalIdealDomain): sage: ZZ.gen() 1 sage: type(ZZ.gen()) - + """ if n == 0: return self(1) diff --git a/src/sage/rings/multi_power_series_ring.py b/src/sage/rings/multi_power_series_ring.py index 2b8639ed2a3..a8f8cc47d57 100644 --- a/src/sage/rings/multi_power_series_ring.py +++ b/src/sage/rings/multi_power_series_ring.py @@ -163,7 +163,7 @@ sage: S = PowerSeriesRing(GF(11),2,'x,y'); S Multivariate Power Series Ring in x, y over Finite Field of size 11 sage: type(x) - + sage: type(S(x)) diff --git a/src/sage/rings/number_field/number_field.py b/src/sage/rings/number_field/number_field.py index 3ad7ffa26ef..288ba7c75d5 100644 --- a/src/sage/rings/number_field/number_field.py +++ b/src/sage/rings/number_field/number_field.py @@ -8050,7 +8050,7 @@ def _coerce_map_from_(self, R): sage: S.coerce(-Integer(2)) -2 sage: z = S.coerce(-7/8); z, type(z) - (-7/8, ) + (-7/8, ) sage: S.coerce(y) is y True @@ -8106,13 +8106,13 @@ def _coerce_map_from_(self, R): sage: K. = NumberField(polygen(QQ)^3-2) sage: type(K.coerce_map_from(QQ)) - + Make sure we still get our optimized morphisms for special fields:: sage: K. = NumberField(polygen(QQ)^2-2) sage: type(K.coerce_map_from(QQ)) - + """ if R is int: @@ -9945,16 +9945,13 @@ def hilbert_symbol(self, a, b, P = None): if P.domain() is not self: raise ValueError("Domain of P (=%s) should be self (=%s) in self.hilbert_symbol" % (P, self)) codom = P.codomain() - from sage.rings.complex_mpfr import is_ComplexField - from sage.rings.complex_interval_field import is_ComplexIntervalField - from sage.rings.real_mpfr import is_RealField - from sage.rings.all import (AA, CDF, QQbar, RDF) - if is_ComplexField(codom) or is_ComplexIntervalField(codom) or \ - codom is CDF or codom is QQbar: + from sage.rings.all import (AA, QQbar) + if isinstance(codom, (sage.rings.abc.ComplexField, sage.rings.abc.ComplexDoubleField, sage.rings.abc.ComplexIntervalField)) or \ + codom is QQbar: if P(self.gen()).imag() == 0: raise ValueError("Possibly real place (=%s) given as complex embedding in hilbert_symbol. Is it real or complex?" % P) return 1 - if is_RealField(codom) or codom is RDF or codom is AA: + if isinstance(codom, (sage.rings.abc.RealField, sage.rings.abc.RealDoubleField)) or codom is AA: if P(a) > 0 or P(b) > 0: return 1 return -1 @@ -10397,12 +10394,12 @@ class NumberField_cyclotomic(NumberField_absolute): sage: cf6(z3) zeta6 - 1 sage: type(cf6(z3)) - + sage: cf1 = CyclotomicField(1) ; z1 = cf1.0 sage: cf3(z1) 1 sage: type(cf3(z1)) - + """ def __init__(self, n, names, embedding=None, assume_disc_small=False, maximize_at_primes=None): """ @@ -10432,13 +10429,13 @@ def __init__(self, n, names, embedding=None, assume_disc_small=False, maximize_a :: sage: type(CyclotomicField(4).zero()) - + sage: type(CyclotomicField(6).one()) - + sage: type(CyclotomicField(6).an_element()) - + sage: type(CyclotomicField(15).zero()) - + """ f = QQ['x'].cyclotomic_polynomial(n) if names[0].startswith('zeta'): @@ -11744,9 +11741,9 @@ def __init__(self, polynomial, name=None, latex_name=None, check=True, embedding sage: k. = QuadraticField(7) sage: type(k.zero()) - + sage: type(k.one()) - + sage: TestSuite(k).run() @@ -11958,13 +11955,13 @@ def class_number(self, proof=None): TESTS:: sage: type(QuadraticField(-23,'a').class_number()) - + sage: type(NumberField(x^3 + 23, 'a').class_number()) - + sage: type(NumberField(x^3 + 23, 'a').extension(x^2 + 5, 'b').class_number()) - + sage: type(CyclotomicField(10).class_number()) - + """ proof = proof_flag(proof) @@ -12317,7 +12314,7 @@ def refine_embedding(e, prec=None): return e # We first compute all the embeddings at the new precision: - if sage.rings.real_mpfr.is_RealField(RC) or RC in (RDF, RLF): + if isinstance(RC, (sage.rings.abc.RealField, sage.rings.abc.RealDoubleField)) or RC == RLF: if prec == Infinity: elist = K.embeddings(sage.rings.qqbar.AA) else: diff --git a/src/sage/rings/number_field/number_field_element.pyx b/src/sage/rings/number_field/number_field_element.pyx index c34cfc9e42f..bba2fc46afc 100644 --- a/src/sage/rings/number_field/number_field_element.pyx +++ b/src/sage/rings/number_field/number_field_element.pyx @@ -359,7 +359,7 @@ cdef class NumberFieldElement(FieldElement): sage: cf4(one) 1 sage: type(cf4(1)) - + sage: cf33 = CyclotomicField(33) ; z33 = cf33.0 sage: cf66 = CyclotomicField(66) ; z66 = cf66.0 sage: z33._lift_cyclotomic_element(cf66) @@ -574,7 +574,7 @@ cdef class NumberFieldElement(FieldElement): sage: libgap(E8 + 3/2*E8^2 + 100*E8^7) E(8)+3/2*E(8)^2-100*E(8)^3 sage: type(_) - + Check that :trac:`15276` is fixed:: @@ -3807,7 +3807,7 @@ cdef class NumberFieldElement(FieldElement): sage: b.ord(P) 1 sage: type(b.valuation(P)) - + The function can be applied to elements in relative number fields:: @@ -3945,8 +3945,7 @@ cdef class NumberFieldElement(FieldElement): if a <= Kv.one(): return Kv.zero() ht = a.log() - from sage.rings.real_mpfr import is_RealField - if weighted and not is_RealField(Kv): + if weighted and not isinstance(Kv, sage.rings.abc.RealField): ht*=2 return ht @@ -4829,7 +4828,7 @@ cdef class NumberFieldElement_relative(NumberFieldElement): sage: L. = NumberField([x^2 + 1, x^2 + 2]) sage: type(a) # indirect doctest - + """ NumberFieldElement.__init__(self, parent, f) @@ -5126,7 +5125,7 @@ cdef class OrderElement_absolute(NumberFieldElement_absolute): sage: K. = NumberField(x^3 + 2) sage: O2 = K.order(2*a) sage: type(O2.1) # indirect doctest - + """ K = order.number_field() NumberFieldElement_absolute.__init__(self, K, f) @@ -5230,7 +5229,7 @@ cdef class OrderElement_relative(NumberFieldElement_relative): sage: c = O.1; c (-2*b^2 - 2)*a - 2*b^2 - b sage: type(c) - + """ def __init__(self, order, f): r""" @@ -5238,7 +5237,7 @@ cdef class OrderElement_relative(NumberFieldElement_relative): sage: O = EquationOrder([x^2 + x + 1, x^3 - 2],'a,b') sage: type(O.1) # indirect doctest - + """ K = order.number_field() NumberFieldElement_relative.__init__(self, K, f) diff --git a/src/sage/rings/number_field/number_field_element_quadratic.pyx b/src/sage/rings/number_field/number_field_element_quadratic.pyx index afe40d7ffdb..510d0a4a3ec 100644 --- a/src/sage/rings/number_field/number_field_element_quadratic.pyx +++ b/src/sage/rings/number_field/number_field_element_quadratic.pyx @@ -173,7 +173,7 @@ cdef class NumberFieldElement_quadratic(NumberFieldElement_absolute): sage: F. = QuadraticField(-7) sage: c = a + 7 sage: type(c) # indirect doctest - + """ self.D = parent._D cdef Integer a, b, denom @@ -2612,7 +2612,7 @@ cdef class OrderElement_quadratic(NumberFieldElement_quadratic): sage: OK. = EquationOrder(x^2 + 5) sage: v = OK.1 # indirect doctest sage: type(v) - + """ K = order.number_field() NumberFieldElement_quadratic.__init__(self, K, f) @@ -2878,14 +2878,14 @@ cdef class Z_to_quadratic_field_element(Morphism): sage: K. = QuadraticField(3) sage: phi = K.coerce_map_from(ZZ) # indirect doctest sage: type(phi) - + sage: phi == loads(dumps(phi)) # todo: comparison not implemented True sage: R. = CyclotomicField(6) sage: psi = R.coerce_map_from(ZZ) # indirect doctest sage: type(psi) - + sage: psi == loads(dumps(psi)) # todo: comparison not implemented True """ @@ -2980,14 +2980,14 @@ cdef class Q_to_quadratic_field_element(Morphism): sage: K. = QuadraticField(3) sage: phi = K.coerce_map_from(QQ) # indirect doctest sage: type(phi) - + sage: phi == loads(dumps(phi)) # todo: comparison not implemented True sage: R. = CyclotomicField(6) sage: psi = R.coerce_map_from(QQ) sage: type(psi) - + sage: psi == loads(dumps(psi)) # todo: comparison not implemented True """ diff --git a/src/sage/rings/number_field/number_field_ideal.py b/src/sage/rings/number_field/number_field_ideal.py index 8a27624e577..1f5bca3ce33 100644 --- a/src/sage/rings/number_field/number_field_ideal.py +++ b/src/sage/rings/number_field/number_field_ideal.py @@ -3214,7 +3214,7 @@ def __init__(self, K, M_OK_change, Q, I): From: Number Field in a with defining polynomial x^3 + 4 To: Residue field of Fractional ideal (1/2*a^2 + 1) sage: f.__class__ - + """ self.__M_OK_change = M_OK_change self.__Q = Q @@ -3270,7 +3270,7 @@ def __init__(self, OK, M_OK_map, Q, I): sage: I = K.ideal(1 + a^2/2) sage: f = I.residue_field().lift_map() sage: f.__class__ - + """ self.__I = I self.__OK = OK diff --git a/src/sage/rings/number_field/number_field_rel.py b/src/sage/rings/number_field/number_field_rel.py index 3097a98002d..71760700442 100644 --- a/src/sage/rings/number_field/number_field_rel.py +++ b/src/sage/rings/number_field/number_field_rel.py @@ -1686,7 +1686,7 @@ def pari_absolute_base_polynomial(self): sage: K.pari_absolute_base_polynomial() y^2 + 3 sage: type(K.pari_absolute_base_polynomial()) - + sage: z = ZZ['z'].0 sage: K. = NumberField([z^2 + 2, z^2 + 3, z^2 + 5]); K Number Field in a with defining polynomial z^2 + 2 over its base field @@ -1697,7 +1697,7 @@ def pari_absolute_base_polynomial(self): sage: len(QQ['y'](K.pari_absolute_base_polynomial()).roots(K.base_field())) 4 sage: type(K.pari_absolute_base_polynomial()) - + """ abs_base, from_abs_base, to_abs_base = self.absolute_base_field() return abs_base.pari_polynomial('y') diff --git a/src/sage/rings/number_field/order.py b/src/sage/rings/number_field/order.py index 56ef3d550bb..ec128df7834 100644 --- a/src/sage/rings/number_field/order.py +++ b/src/sage/rings/number_field/order.py @@ -47,6 +47,7 @@ from sage.rings.ring import IntegralDomain from sage.structure.sequence import Sequence from sage.rings.integer_ring import ZZ +import sage.rings.abc from sage.structure.element import is_Element from .number_field_element import OrderElement_absolute, OrderElement_relative @@ -126,7 +127,7 @@ def EquationOrder(f, names, **kwds): return K.order(K.gens()) -class Order(IntegralDomain): +class Order(IntegralDomain, sage.rings.abc.Order): r""" An order in a number field. diff --git a/src/sage/rings/number_field/splitting_field.py b/src/sage/rings/number_field/splitting_field.py index 06edcad31d5..8818e5d1bad 100644 --- a/src/sage/rings/number_field/splitting_field.py +++ b/src/sage/rings/number_field/splitting_field.py @@ -339,7 +339,7 @@ def splitting_field(poly, name, map=False, degree_multiple=None, abort_degree=No To: Number Field in x with defining polynomial x Defn: 1 |--> 1) """ - from sage.misc.all import cputime + from sage.misc.misc import cputime from sage.misc.verbose import verbose degree_multiple = Integer(degree_multiple or 0) diff --git a/src/sage/rings/number_field/totallyreal.pyx b/src/sage/rings/number_field/totallyreal.pyx index 0512f0559fc..4c03dc13284 100644 --- a/src/sage/rings/number_field/totallyreal.pyx +++ b/src/sage/rings/number_field/totallyreal.pyx @@ -105,7 +105,8 @@ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.integer import Integer from sage.rings.integer cimport Integer from sage.rings.integer_ring import IntegerRing -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.misc.misc import cputime from sage.rings.number_field.totallyreal_data import tr_data, int_has_small_square_divisor @@ -237,7 +238,7 @@ def enumerate_totallyreal_fields_prim(n, B, a = [], verbose=0, return_seqs=False sage: enumerate_totallyreal_fields_prim(2, 10) [[5, x^2 - x - 1], [8, x^2 - 2]] sage: type(enumerate_totallyreal_fields_prim(2, 10)[0][1]) - + sage: enumerate_totallyreal_fields_prim(2, 10, return_pari_objects=False)[0][0].parent() Integer Ring sage: enumerate_totallyreal_fields_prim(2, 10, return_pari_objects=False)[0][1].parent() diff --git a/src/sage/rings/number_field/totallyreal_rel.py b/src/sage/rings/number_field/totallyreal_rel.py index e531dcaa126..a5101b2c449 100644 --- a/src/sage/rings/number_field/totallyreal_rel.py +++ b/src/sage/rings/number_field/totallyreal_rel.py @@ -98,7 +98,8 @@ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.number_field.totallyreal import weed_fields, odlyzko_bound_totallyreal, enumerate_totallyreal_fields_prim from sage.libs.pari.all import pari -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ import math import sys @@ -706,7 +707,7 @@ def enumerate_totallyreal_fields_rel(F, m, B, a=[], verbose=0, is set to ``False``:: sage: type(enumerate_totallyreal_fields_rel(F, 2, 2000)[0][1]) - + sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_pari_objects=False)[0][0].parent() Integer Ring sage: enumerate_totallyreal_fields_rel(F, 2, 2000, return_pari_objects=False)[0][1].parent() @@ -938,7 +939,7 @@ def enumerate_totallyreal_fields_all(n, B, verbose=0, return_seqs=False, sage: enumerate_totallyreal_fields_all(2, 10) [[5, x^2 - x - 1], [8, x^2 - 2]] sage: type(enumerate_totallyreal_fields_all(2, 10)[0][1]) - + sage: enumerate_totallyreal_fields_all(2, 10, return_pari_objects=False)[0][1].parent() Univariate Polynomial Ring in x over Rational Field diff --git a/src/sage/rings/padics/CA_template.pxi b/src/sage/rings/padics/CA_template.pxi index 5a3065ff10a..e4c5966ad3a 100644 --- a/src/sage/rings/padics/CA_template.pxi +++ b/src/sage/rings/padics/CA_template.pxi @@ -189,7 +189,7 @@ cdef class CAElement(pAdicTemplateElement): sage: a = ZpCA(5)(-3) sage: type(a) - + sage: loads(dumps(a)) == a True """ @@ -1005,7 +1005,7 @@ cdef class CAElement(pAdicTemplateElement): sage: a.unit_part() 18 + O(17^3) sage: type(a) - + sage: R(0).unit_part() O(17^0) """ @@ -1105,7 +1105,7 @@ cdef class pAdicCoercion_ZZ_CA(RingHomomorphism): EXAMPLES:: sage: f = ZpCA(5).coerce_map_from(ZZ); type(f) - + """ RingHomomorphism.__init__(self, ZZ.Hom(R)) self._zero = R.element_class(R, 0) @@ -1181,7 +1181,7 @@ cdef class pAdicCoercion_ZZ_CA(RingHomomorphism): sage: R = ZpCA(5,4) sage: type(R(10,2)) - + sage: R(10,2) # indirect doctest 2*5 + O(5^2) sage: R(10,3,1) @@ -1255,7 +1255,7 @@ cdef class pAdicConvert_CA_ZZ(RingMap): EXAMPLES:: sage: f = ZpCA(5).coerce_map_from(ZZ).section(); type(f) - + sage: f.category() Category of homsets of sets """ @@ -1300,7 +1300,7 @@ cdef class pAdicConvert_QQ_CA(Morphism): EXAMPLES:: sage: f = ZpCA(5).convert_map_from(QQ); type(f) - + """ Morphism.__init__(self, Hom(QQ, R, SetsWithPartialMaps())) self._zero = R.element_class(R, 0) @@ -1371,7 +1371,7 @@ cdef class pAdicConvert_QQ_CA(Morphism): sage: R = ZpCA(5,4) sage: type(R(10/3,2)) - + sage: R(10/3,2) # indirect doctest 4*5 + O(5^2) sage: R(10/3,3,1) @@ -1436,7 +1436,7 @@ cdef class pAdicCoercion_CA_frac_field(RingHomomorphism): sage: R. = ZqCA(27, implementation='FLINT') sage: K = R.fraction_field() sage: f = K.coerce_map_from(R); type(f) - + """ RingHomomorphism.__init__(self, R.Hom(K)) self._zero = K(0) @@ -1652,7 +1652,7 @@ cdef class pAdicConvert_CA_frac_field(Morphism): sage: R. = ZqCA(27, implementation='FLINT') sage: K = R.fraction_field() sage: f = R.convert_map_from(K); type(f) - + """ Morphism.__init__(self, Hom(K, R, SetsWithPartialMaps())) self._zero = R(0) diff --git a/src/sage/rings/padics/CR_template.pxi b/src/sage/rings/padics/CR_template.pxi index 68c0dc9d194..7318873f9c5 100644 --- a/src/sage/rings/padics/CR_template.pxi +++ b/src/sage/rings/padics/CR_template.pxi @@ -299,7 +299,7 @@ cdef class CRElement(pAdicTemplateElement): sage: a = ZpCR(5)(-3) sage: type(a) - + sage: loads(dumps(a)) == a # indirect doctest True """ @@ -1423,13 +1423,13 @@ cdef class CRElement(pAdicTemplateElement): sage: a.unit_part() 1 + 17 + O(17^4) sage: type(a) - + sage: R = Qp(17,4,'capped-rel') sage: a = R(18*17) sage: a.unit_part() 1 + 17 + O(17^4) sage: type(a) - + sage: a = R(2*17^2); a 2*17^2 + O(17^6) sage: a.unit_part() @@ -1562,7 +1562,7 @@ cdef class pAdicCoercion_ZZ_CR(RingHomomorphism): EXAMPLES:: sage: f = Zp(5).coerce_map_from(ZZ); type(f) - + """ RingHomomorphism.__init__(self, ZZ.Hom(R)) self._zero = R.element_class(R, 0) @@ -1652,7 +1652,7 @@ cdef class pAdicCoercion_ZZ_CR(RingHomomorphism): sage: R = Zp(5,4) sage: type(R(10,2)) - + sage: R(10,2) # indirect doctest 2*5 + O(5^2) sage: R(10,3,1) @@ -1724,7 +1724,7 @@ cdef class pAdicConvert_CR_ZZ(RingMap): EXAMPLES:: sage: f = Qp(5).coerce_map_from(ZZ).section(); type(f) - + sage: f.category() Category of homsets of sets with partial maps sage: Zp(5).coerce_map_from(ZZ).section().category() @@ -1780,7 +1780,7 @@ cdef class pAdicCoercion_QQ_CR(RingHomomorphism): EXAMPLES:: sage: f = Qp(5).coerce_map_from(QQ); type(f) - + """ RingHomomorphism.__init__(self, QQ.Hom(R)) self._zero = R.element_class(R, 0) @@ -1872,7 +1872,7 @@ cdef class pAdicCoercion_QQ_CR(RingHomomorphism): sage: R = Qp(5,4) sage: type(R(10/3,2)) - + sage: R(10/3,2) # indirect doctest 4*5 + O(5^2) sage: R(10/3,3,1) @@ -1944,7 +1944,7 @@ cdef class pAdicConvert_CR_QQ(RingMap): EXAMPLES:: sage: f = Qp(5).coerce_map_from(QQ).section(); type(f) - + sage: f.category() Category of homsets of sets """ @@ -1994,7 +1994,7 @@ cdef class pAdicConvert_QQ_CR(Morphism): EXAMPLES:: sage: f = Zp(5).convert_map_from(QQ); type(f) - + """ Morphism.__init__(self, Hom(QQ, R, SetsWithPartialMaps())) self._zero = R.element_class(R, 0) @@ -2073,7 +2073,7 @@ cdef class pAdicConvert_QQ_CR(Morphism): sage: R = Zp(5,4) sage: type(R(10/3,2)) - + sage: R(10/3,2) # indirect doctest 4*5 + O(5^2) sage: R(10/3,3,1) @@ -2156,7 +2156,7 @@ cdef class pAdicCoercion_CR_frac_field(RingHomomorphism): sage: R. = ZqCR(27, implementation='FLINT') sage: K = R.fraction_field() sage: f = K.coerce_map_from(R); type(f) - + """ RingHomomorphism.__init__(self, R.Hom(K)) self._zero = K(0) @@ -2377,7 +2377,7 @@ cdef class pAdicConvert_CR_frac_field(Morphism): sage: R. = ZqCR(27, implementation='FLINT') sage: K = R.fraction_field() sage: f = R.convert_map_from(K); type(f) - + """ Morphism.__init__(self, Hom(K, R, SetsWithPartialMaps())) self._zero = R(0) diff --git a/src/sage/rings/padics/FM_template.pxi b/src/sage/rings/padics/FM_template.pxi index 16926c3fe86..1dc94645c75 100644 --- a/src/sage/rings/padics/FM_template.pxi +++ b/src/sage/rings/padics/FM_template.pxi @@ -173,7 +173,7 @@ cdef class FMElement(pAdicTemplateElement): sage: a = ZpFM(5)(-3) sage: type(a) - + sage: loads(dumps(a)) == a True """ @@ -795,7 +795,7 @@ cdef class FMElement(pAdicTemplateElement): sage: R(0).unit_part() 0 sage: type(R(5).unit_part()) - + sage: R = ZpFM(5, 5); a = R(75); a.unit_part() 3 """ @@ -890,7 +890,7 @@ cdef class pAdicCoercion_ZZ_FM(RingHomomorphism): EXAMPLES:: sage: f = ZpFM(5).coerce_map_from(ZZ); type(f) - + """ RingHomomorphism.__init__(self, ZZ.Hom(R)) self._zero = R.element_class(R, 0) @@ -972,7 +972,7 @@ cdef class pAdicCoercion_ZZ_FM(RingHomomorphism): sage: R = ZpFM(5,4) sage: type(R(10,2)) - + sage: R(30,2) 5 + 5^2 sage: R(30,3,1) @@ -1030,7 +1030,7 @@ cdef class pAdicConvert_FM_ZZ(RingMap): EXAMPLES:: sage: f = ZpFM(5).coerce_map_from(ZZ).section(); type(f) - + sage: f.category() Category of homsets of sets """ @@ -1075,7 +1075,7 @@ cdef class pAdicConvert_QQ_FM(Morphism): EXAMPLES:: sage: f = ZpFM(5).convert_map_from(QQ); type(f) - + """ Morphism.__init__(self, Hom(QQ, R, SetsWithPartialMaps())) self._zero = R.element_class(R, 0) @@ -1154,7 +1154,7 @@ cdef class pAdicConvert_QQ_FM(Morphism): sage: R = ZpFM(5,4) sage: type(R(1/7,2)) - + sage: R(1/7,2) 3 + 3*5 + 2*5^3 sage: R(1/7,3,1) @@ -1201,7 +1201,7 @@ cdef class pAdicCoercion_FM_frac_field(RingHomomorphism): sage: R. = ZqFM(27) sage: K = R.fraction_field() sage: f = K.coerce_map_from(R); type(f) - + """ RingHomomorphism.__init__(self, R.Hom(K)) self._zero = K(0) @@ -1408,7 +1408,7 @@ cdef class pAdicConvert_FM_frac_field(Morphism): sage: R. = ZqFM(27) sage: K = R.fraction_field() sage: f = R.convert_map_from(K); type(f) - + """ Morphism.__init__(self, Hom(K, R, SetsWithPartialMaps())) self._zero = R(0) diff --git a/src/sage/rings/padics/FP_template.pxi b/src/sage/rings/padics/FP_template.pxi index c7ce3937c0d..a4eed73ced7 100644 --- a/src/sage/rings/padics/FP_template.pxi +++ b/src/sage/rings/padics/FP_template.pxi @@ -290,7 +290,7 @@ cdef class FPElement(pAdicTemplateElement): sage: a = ZpFP(5)(-3) sage: type(a) - + sage: loads(dumps(a)) == a True """ @@ -1152,7 +1152,7 @@ cdef class FPElement(pAdicTemplateElement): ... ValueError: unit part of 0 and infinity not defined sage: type(R(5).unit_part()) - + sage: R = ZpFP(5, 5); a = R(75); a.unit_part() 3 """ @@ -1268,7 +1268,7 @@ cdef class pAdicCoercion_ZZ_FP(RingHomomorphism): EXAMPLES:: sage: f = ZpFP(5).coerce_map_from(ZZ); type(f) - + """ RingHomomorphism.__init__(self, ZZ.Hom(R)) self._zero = R.element_class(R, 0) @@ -1350,7 +1350,7 @@ cdef class pAdicCoercion_ZZ_FP(RingHomomorphism): sage: R = ZpFP(5,4) sage: type(R(10,2)) - + sage: R(30,2) 5 sage: R(30,3,2) @@ -1416,7 +1416,7 @@ cdef class pAdicConvert_FP_ZZ(RingMap): EXAMPLES:: sage: f = ZpFP(5).coerce_map_from(ZZ).section(); type(f) - + sage: f.category() Category of homsets of sets """ @@ -1480,7 +1480,7 @@ cdef class pAdicCoercion_QQ_FP(RingHomomorphism): EXAMPLES:: sage: f = QpFP(5).coerce_map_from(QQ); type(f) - + """ RingHomomorphism.__init__(self, QQ.Hom(R)) self._zero = R.element_class(R, 0) @@ -1571,7 +1571,7 @@ cdef class pAdicCoercion_QQ_FP(RingHomomorphism): sage: R = QpFP(5,4) sage: type(R(10/3,2)) - + sage: R(10/3,2) 4*5 sage: R(10/3,3,1) @@ -1636,7 +1636,7 @@ cdef class pAdicConvert_FP_QQ(RingMap): EXAMPLES:: sage: f = QpFP(5).coerce_map_from(QQ).section(); type(f) - + sage: f.category() Category of homsets of sets with partial maps """ @@ -1684,7 +1684,7 @@ cdef class pAdicConvert_QQ_FP(Morphism): EXAMPLES:: sage: f = ZpFP(5).convert_map_from(QQ); type(f) - + """ Morphism.__init__(self, Hom(QQ, R, SetsWithPartialMaps())) self._zero = R.element_class(R, 0) @@ -1765,7 +1765,7 @@ cdef class pAdicConvert_QQ_FP(Morphism): sage: R = ZpFP(5,4) sage: type(R(1/7,2)) - + sage: R(1/7,2) 3 + 3*5 sage: R(1/7,3,2) @@ -1820,7 +1820,7 @@ cdef class pAdicCoercion_FP_frac_field(RingHomomorphism): sage: R. = ZqFP(27, implementation='FLINT') sage: K = R.fraction_field() sage: f = K.coerce_map_from(R); type(f) - + """ RingHomomorphism.__init__(self, R.Hom(K)) self._zero = K(0) @@ -1997,7 +1997,7 @@ cdef class pAdicConvert_FP_frac_field(Morphism): sage: R. = ZqFP(27, implementation='FLINT') sage: K = R.fraction_field() sage: f = R.convert_map_from(K); type(f) - + """ Morphism.__init__(self, Hom(K, R, SetsWithPartialMaps())) self._zero = R(0) diff --git a/src/sage/rings/padics/factory.py b/src/sage/rings/padics/factory.py index 90c54a2524a..abfce6c44c9 100644 --- a/src/sage/rings/padics/factory.py +++ b/src/sage/rings/padics/factory.py @@ -2534,8 +2534,8 @@ def Zq(q, prec = None, type = 'capped-rel', modulus = None, names=None, prec = Integer(prec) if isinstance(names, (list, tuple)): names = names[0] - from sage.symbolic.expression import is_Expression - if not (modulus is None or is_Polynomial(modulus) or is_Expression(modulus)): + from sage.structure.element import Expression + if not (modulus is None or is_Polynomial(modulus) or isinstance(modulus, Expression)): raise TypeError("modulus must be a polynomial") if names is not None and not isinstance(names, str): names = str(names) @@ -3271,9 +3271,9 @@ def create_key_and_extra_args(self, base, modulus, prec = None, print_mode = Non if print_max_terse_terms is None: print_max_terse_terms = base._printer._max_terse_terms() show_prec = _canonicalize_show_prec(base._prec_type(), print_mode, show_prec) - from sage.symbolic.expression import is_Expression + from sage.structure.element import Expression if check: - if is_Expression(modulus): + if isinstance(modulus, Expression): if len(modulus.variables()) != 1: raise ValueError("symbolic expression must be in only one variable") exact_modulus = modulus.polynomial(base.exact_field()) @@ -3378,8 +3378,8 @@ def create_object(self, version, key, approx_modulus=None, shift_seed=None): if version[0] < 8: (polytype, base, premodulus, approx_modulus, names, prec, halt, print_mode, print_pos, print_sep, print_alphabet, print_max_ram_terms, print_max_unram_terms, print_max_terse_terms, implementation) = key - from sage.symbolic.expression import is_Expression - if is_Expression(premodulus): + from sage.structure.element import Expression + if isinstance(premodulus, Expression): exact_modulus = premodulus.polynomial(base.exact_field()) elif is_Polynomial(premodulus): exact_modulus = premodulus.change_ring(base.exact_field()) diff --git a/src/sage/rings/padics/padic_ZZ_pX_CR_element.pyx b/src/sage/rings/padics/padic_ZZ_pX_CR_element.pyx index 8d44034b121..9d678d0f11d 100644 --- a/src/sage/rings/padics/padic_ZZ_pX_CR_element.pyx +++ b/src/sage/rings/padics/padic_ZZ_pX_CR_element.pyx @@ -1905,7 +1905,7 @@ cdef class pAdicZZpXCRElement(pAdicZZpXElement): sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5 sage: W. = R.ext(f) sage: type(W(0)) - + sage: W(0)^0 1 + O(w^25) sage: W(0)^0 == W(1) diff --git a/src/sage/rings/padics/padic_ZZ_pX_FM_element.pyx b/src/sage/rings/padics/padic_ZZ_pX_FM_element.pyx index c58954582ea..9b660621dea 100644 --- a/src/sage/rings/padics/padic_ZZ_pX_FM_element.pyx +++ b/src/sage/rings/padics/padic_ZZ_pX_FM_element.pyx @@ -718,7 +718,7 @@ cdef class pAdicZZpXFMElement(pAdicZZpXElement): sage: f = x^5 + 75*x^3 - 15*x^2 +125*x - 5 sage: W. = R.ext(f) sage: type(W(0)) - + sage: W(0)^0 1 sage: W(0)^0 == W(1) diff --git a/src/sage/rings/padics/padic_base_leaves.py b/src/sage/rings/padics/padic_base_leaves.py index 4c525237c4f..2a567fce5d4 100644 --- a/src/sage/rings/padics/padic_base_leaves.py +++ b/src/sage/rings/padics/padic_base_leaves.py @@ -92,11 +92,11 @@ sage: (a * b) // 5^3 1 + 2*5 + O(5^2) sage: type((a * b) // 5^3) - + sage: (a * b) / 5^3 1 + 2*5 + O(5^2) sage: type((a * b) / 5^3) - + The fixed modulus type is the leanest of the p-adic rings: it is basically just a wrapper around `\ZZ / p^n \ZZ` diff --git a/src/sage/rings/padics/padic_capped_absolute_element.pyx b/src/sage/rings/padics/padic_capped_absolute_element.pyx index a34e1b27d77..387dd7c8b65 100644 --- a/src/sage/rings/padics/padic_capped_absolute_element.pyx +++ b/src/sage/rings/padics/padic_capped_absolute_element.pyx @@ -44,7 +44,7 @@ cdef class PowComputer_(PowComputer_base): sage: R = ZpCA(5) sage: type(R.prime_pow) - + sage: R.prime_pow._prec_type 'capped-abs' """ diff --git a/src/sage/rings/padics/padic_capped_relative_element.pyx b/src/sage/rings/padics/padic_capped_relative_element.pyx index c59c8e3573b..bea6c17af19 100644 --- a/src/sage/rings/padics/padic_capped_relative_element.pyx +++ b/src/sage/rings/padics/padic_capped_relative_element.pyx @@ -47,7 +47,7 @@ cdef class PowComputer_(PowComputer_base): sage: R = ZpCR(5) sage: type(R.prime_pow) - + sage: R.prime_pow._prec_type 'capped-rel' """ diff --git a/src/sage/rings/padics/padic_fixed_mod_element.pyx b/src/sage/rings/padics/padic_fixed_mod_element.pyx index 4b2723b7a8a..e012cbba9fc 100644 --- a/src/sage/rings/padics/padic_fixed_mod_element.pyx +++ b/src/sage/rings/padics/padic_fixed_mod_element.pyx @@ -44,7 +44,7 @@ cdef class PowComputer_(PowComputer_base): sage: R = ZpFM(5) sage: type(R.prime_pow) - + sage: R.prime_pow._prec_type 'fixed-mod' """ @@ -152,7 +152,7 @@ cdef class pAdicFixedModElement(FMElement): sage: R = Zp(7,4,'fixed-mod'); a = R(8); a.lift() 8 sage: type(a.lift()) - + """ return self.lift_c() diff --git a/src/sage/rings/padics/padic_floating_point_element.pyx b/src/sage/rings/padics/padic_floating_point_element.pyx index 89132c93025..b3eb407918e 100644 --- a/src/sage/rings/padics/padic_floating_point_element.pyx +++ b/src/sage/rings/padics/padic_floating_point_element.pyx @@ -42,7 +42,7 @@ cdef class PowComputer_(PowComputer_base): sage: R = ZpFP(5) sage: type(R.prime_pow) - + sage: R.prime_pow._prec_type 'floating-point' """ diff --git a/src/sage/rings/padics/padic_template_element.pxi b/src/sage/rings/padics/padic_template_element.pxi index f4629a5d598..b30d8cf0ae9 100644 --- a/src/sage/rings/padics/padic_template_element.pxi +++ b/src/sage/rings/padics/padic_template_element.pxi @@ -89,7 +89,7 @@ cdef class pAdicTemplateElement(pAdicGenericElement): sage: a = Zp(5)(1/2,3); a 3 + 2*5 + 2*5^2 + O(5^3) sage: type(a) - + sage: TestSuite(a).run() TESTS:: @@ -888,7 +888,7 @@ cdef class ExpansionIter(object): sage: E = Zp(5,4)(373).expansion() sage: I = iter(E) # indirect doctest sage: type(I) - + """ cdef pAdicTemplateElement elt cdef celement tmp @@ -1021,7 +1021,7 @@ cdef class ExpansionIterable(object): sage: E = Zp(5,4)(373).expansion() # indirect doctest sage: type(E) - + """ cdef pAdicTemplateElement elt cdef celement tmp @@ -1076,13 +1076,13 @@ cdef class ExpansionIterable(object): sage: E = Zp(5,4)(373).expansion() sage: type(iter(E)) - + sage: E = Zp(5,4)(373).expansion(start_val=-1) sage: type(iter(E)) - + sage: E = Zp(5,4)(373).expansion(start_val=1) sage: type(iter(E)) - + """ cdef ExpansionIter expansion = ExpansionIter(self.elt, self.prec, self.mode) if self.val_shift == 0: diff --git a/src/sage/rings/padics/padic_valuation.py b/src/sage/rings/padics/padic_valuation.py index 30689e3d0d0..5e552bd05f6 100644 --- a/src/sage/rings/padics/padic_valuation.py +++ b/src/sage/rings/padics/padic_valuation.py @@ -119,7 +119,8 @@ def create_key_and_extra_args(self, R, prime=None, approximants=None): 2-adic valuation """ - from sage.rings.all import ZZ, QQ + from sage.rings.integer_ring import ZZ + from sage.rings.rational_field import QQ from sage.rings.padics.padic_generic import pAdicGeneric from sage.rings.number_field.number_field import is_NumberField from sage.rings.polynomial.polynomial_quotient_ring import is_PolynomialQuotientRing @@ -389,7 +390,8 @@ def create_object(self, version, key, **extra_args): 5-adic valuation """ - from sage.rings.all import ZZ, QQ + from sage.rings.integer_ring import ZZ + from sage.rings.rational_field import QQ from sage.rings.padics.padic_generic import pAdicGeneric from sage.rings.valuation.valuation_space import DiscretePseudoValuationSpace from sage.rings.polynomial.polynomial_quotient_ring import is_PolynomialQuotientRing @@ -956,7 +958,8 @@ def element_with_valuation(self, v): y^3 + O(y^43) """ - from sage.rings.all import QQ, ZZ + from sage.rings.integer_ring import ZZ + from sage.rings.rational_field import QQ v = QQ(v) if v not in self.value_semigroup(): raise ValueError("%r is not in the value semigroup of %r"%(v, self)) @@ -1327,7 +1330,8 @@ def inverse(self, x, precision): if self(x) > 0 or precision is infinity: raise ValueError("element has no approximate inverse in this ring") - from sage.rings.all import ZZ, QQ + from sage.rings.integer_ring import ZZ + from sage.rings.rational_field import QQ return self.domain()(ZZ(x).inverse_mod(self.p() ** QQ(precision).ceil())) diff --git a/src/sage/rings/padics/pow_computer_ext.pyx b/src/sage/rings/padics/pow_computer_ext.pyx index f4e60ee393b..8c08b52e6d8 100644 --- a/src/sage/rings/padics/pow_computer_ext.pyx +++ b/src/sage/rings/padics/pow_computer_ext.pyx @@ -1813,7 +1813,7 @@ cdef class PowComputer_ZZ_pX_small_Eis(PowComputer_ZZ_pX_small): sage: A = PowComputer_ext_maker(5, 10, 10, 40, False, ntl.ZZ_pX([-5,75,15,0,1],5^10), 'small', 'e',ntl.ZZ_pX([1,-15,-3],5^10)) sage: type(A) - + sage: TestSuite(A).run() """ self._ext_type = 'e' @@ -2244,7 +2244,7 @@ cdef class PowComputer_ZZ_pX_big_Eis(PowComputer_ZZ_pX_big): sage: A = PowComputer_ext_maker(5, 3, 10, 40, False, ntl.ZZ_pX([-5,75,15,0,1],5^10), 'big', 'e',ntl.ZZ_pX([1,-15,-3],5^10)) sage: type(A) - + sage: TestSuite(A).run() """ self._ext_type = 'e' diff --git a/src/sage/rings/padics/pow_computer_flint.pyx b/src/sage/rings/padics/pow_computer_flint.pyx index 4d64096e4ee..9f914defcc6 100644 --- a/src/sage/rings/padics/pow_computer_flint.pyx +++ b/src/sage/rings/padics/pow_computer_flint.pyx @@ -41,7 +41,7 @@ cdef class PowComputer_flint(PowComputer_class): sage: from sage.rings.padics.pow_computer_flint import PowComputer_flint sage: type(PowComputer_flint(5, 20, 20, 20, False)) - + """ # fmpz_init does not allocate memory @@ -204,7 +204,7 @@ cdef class PowComputer_flint_1step(PowComputer_flint): sage: R. = ZZ[]; f = x^3 - 8*x - 2 sage: A = PowComputer_flint_1step(5, 20, 20, 20, False, f) sage: type(A) - + """ cdef Polynomial_integer_dense_flint poly = _poly @@ -467,7 +467,7 @@ cdef class PowComputer_flint_unram(PowComputer_flint_1step): sage: R. = ZZ[]; f = x^3 - 8*x - 2 sage: A = PowComputer_flint_unram(5, 20, 20, 20, False, f) sage: type(A) - + """ # fmpz_init does not allocate memory @@ -579,7 +579,7 @@ cdef class PowComputer_flint_eis(PowComputer_flint_1step): sage: R. = ZZ[]; f = x^3 - 25*x + 5 sage: A = PowComputer_flint_eis(5, 20, 20, 60, False, f) sage: type(A) - + """ PowComputer_flint_1step.__init__(self, prime, cache_limit, prec_cap, ram_prec_cap, in_field, poly) @@ -633,11 +633,11 @@ def PowComputer_flint_maker(prime, cache_limit, prec_cap, ram_prec_cap, in_field sage: from sage.rings.padics.pow_computer_flint import PowComputer_flint_maker sage: R. = ZZ[] sage: A = PowComputer_flint_maker(3, 20, 20, 20, False, x^3 + 2*x + 1, 'capped-rel'); type(A) - + sage: A = PowComputer_flint_maker(3, 20, 20, 20, False, x^3 + 2*x + 1, 'capped-abs'); type(A) - + sage: A = PowComputer_flint_maker(3, 20, 20, 20, False, x^3 + 2*x + 1, 'fixed-mod'); type(A) - + """ if prec_type == 'capped-rel': diff --git a/src/sage/rings/padics/qadic_flint_CA.pyx b/src/sage/rings/padics/qadic_flint_CA.pyx index a1ae9a48c0e..d10e4b3eaff 100644 --- a/src/sage/rings/padics/qadic_flint_CA.pyx +++ b/src/sage/rings/padics/qadic_flint_CA.pyx @@ -14,7 +14,7 @@ cdef class PowComputer_(PowComputer_flint_unram): sage: R. = ZqCA(125) sage: type(R.prime_pow) - + sage: R.prime_pow._prec_type 'capped-abs' """ diff --git a/src/sage/rings/padics/qadic_flint_CR.pyx b/src/sage/rings/padics/qadic_flint_CR.pyx index eaedb7a6c12..dfadaa2f053 100644 --- a/src/sage/rings/padics/qadic_flint_CR.pyx +++ b/src/sage/rings/padics/qadic_flint_CR.pyx @@ -14,7 +14,7 @@ cdef class PowComputer_(PowComputer_flint_unram): sage: R. = ZqCR(125) sage: type(R.prime_pow) - + sage: R.prime_pow._prec_type 'capped-rel' """ diff --git a/src/sage/rings/padics/qadic_flint_FM.pyx b/src/sage/rings/padics/qadic_flint_FM.pyx index 9d192addf2a..4f3afe77e81 100644 --- a/src/sage/rings/padics/qadic_flint_FM.pyx +++ b/src/sage/rings/padics/qadic_flint_FM.pyx @@ -14,7 +14,7 @@ cdef class PowComputer_(PowComputer_flint_unram): sage: R. = ZqFM(125) sage: type(R.prime_pow) - + sage: R.prime_pow._prec_type 'fixed-mod' """ diff --git a/src/sage/rings/padics/qadic_flint_FP.pyx b/src/sage/rings/padics/qadic_flint_FP.pyx index 949e132199c..1e250990c4e 100644 --- a/src/sage/rings/padics/qadic_flint_FP.pyx +++ b/src/sage/rings/padics/qadic_flint_FP.pyx @@ -16,7 +16,7 @@ cdef class PowComputer_(PowComputer_flint_unram): sage: R. = ZqFP(125) sage: type(R.prime_pow) - + sage: R.prime_pow._prec_type 'floating-point' """ diff --git a/src/sage/rings/pari_ring.py b/src/sage/rings/pari_ring.py index 17e5f161473..c46fceed07b 100644 --- a/src/sage/rings/pari_ring.py +++ b/src/sage/rings/pari_ring.py @@ -215,7 +215,7 @@ def random_element(self, x=None, y=None, distribution=None): True """ - from sage.all import ZZ + from sage.rings.integer_ring import ZZ return self(ZZ.random_element(x, y, distribution)) def zeta(self): diff --git a/src/sage/rings/polynomial/laurent_polynomial.pyx b/src/sage/rings/polynomial/laurent_polynomial.pyx index c0229a7b935..78d63fcf8e5 100644 --- a/src/sage/rings/polynomial/laurent_polynomial.pyx +++ b/src/sage/rings/polynomial/laurent_polynomial.pyx @@ -1990,7 +1990,7 @@ cdef class LaurentPolynomial_mpair(LaurentPolynomial): sage: k = tuple(D)[0] sage: v = D[k] sage: type(k), type(v) - (<... 'tuple'>, ) + (<... 'tuple'>, ) sage: LQ(D) x^-1*y sage: tuple(D)[0] is k diff --git a/src/sage/rings/polynomial/multi_polynomial.pyx b/src/sage/rings/polynomial/multi_polynomial.pyx index e4b64c26a68..3f838d69a30 100644 --- a/src/sage/rings/polynomial/multi_polynomial.pyx +++ b/src/sage/rings/polynomial/multi_polynomial.pyx @@ -273,9 +273,9 @@ cdef class MPolynomial(CommutativeRingElement): sage: v = K(0) sage: vf = fast_callable(v) sage: type(v(0r, 0r, 0r)) - + sage: type(vf(0r, 0r, 0r)) - + sage: K. = QQ[] sage: from sage.ext.fast_eval import fast_float sage: fast_float(K(0)).op_list() @@ -313,7 +313,7 @@ cdef class MPolynomial(CommutativeRingElement): sage: R. = PolynomialRing(FiniteField(5)) sage: f = x^3*y^5 + x^7*y sage: type(f) - + sage: f.derivative(x) 2*x^6*y - 2*x^2*y^5 sage: f.derivative(y) @@ -1776,9 +1776,9 @@ cdef class MPolynomial(CommutativeRingElement): sage: x.denominator() 1 sage: type(x.denominator()) - + sage: type(a.denominator()) - + sage: from sage.rings.polynomial.multi_polynomial_element import MPolynomial sage: isinstance(a / b, MPolynomial) False diff --git a/src/sage/rings/polynomial/multi_polynomial_element.py b/src/sage/rings/polynomial/multi_polynomial_element.py index cbade28354c..05ba8094a42 100644 --- a/src/sage/rings/polynomial/multi_polynomial_element.py +++ b/src/sage/rings/polynomial/multi_polynomial_element.py @@ -1002,7 +1002,7 @@ def exponents(self, as_ETuples=True): By default the list of exponents is a list of ETuples:: sage: type(f.exponents()[0]) - + sage: type(f.exponents(as_ETuples=False)[0]) <... 'tuple'> diff --git a/src/sage/rings/polynomial/multi_polynomial_ideal.py b/src/sage/rings/polynomial/multi_polynomial_ideal.py index 6aa72f6dab2..560dcc8c25d 100644 --- a/src/sage/rings/polynomial/multi_polynomial_ideal.py +++ b/src/sage/rings/polynomial/multi_polynomial_ideal.py @@ -249,6 +249,7 @@ from sage.misc.method_decorator import MethodDecorator from sage.rings.integer_ring import ZZ +import sage.rings.abc import sage.rings.polynomial.toy_buchberger as toy_buchberger import sage.rings.polynomial.toy_variety as toy_variety import sage.rings.polynomial.toy_d_basis as toy_d_basis @@ -4288,7 +4289,6 @@ def groebner_basis(self, algorithm='', deg_bound=None, mult_bound=None, prot=Fal sage: I.groebner_basis('magma:GroebnerBasis') # optional - magma [a + (-60)*c^3 + 158/7*c^2 + 8/7*c - 1, b + 30*c^3 + (-79/7)*c^2 + 3/7*c, c^4 + (-10/21)*c^3 + 1/84*c^2 + 1/84*c] """ - from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing @@ -4331,7 +4331,7 @@ def groebner_basis(self, algorithm='', deg_bound=None, mult_bound=None, prot=Fal deg_bound=deg_bound, mult_bound=mult_bound, prot=prot, *args, **kwds)] elif (R.term_order().is_global() - and is_IntegerModRing(B) + and isinstance(B, sage.rings.abc.IntegerModRing) and not B.is_field()): verbose("Warning: falling back to very slow toy implementation.", level=0) diff --git a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx index ec706f3129d..2c69227760c 100644 --- a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx +++ b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx @@ -62,7 +62,7 @@ We show how to construct various multivariate polynomial rings:: sage: P. = Zmod(2521352)[]; P Multivariate Polynomial Ring in x, y, z over Ring of integers modulo 2521352 sage: type(P) - + sage: P. = Zmod(25213521351515232)[]; P Multivariate Polynomial Ring in x, y, z over Ring of integers modulo 25213521351515232 @@ -221,15 +221,14 @@ from sage.rings.polynomial.polydict cimport ETuple from sage.rings.polynomial.polynomial_ring import is_PolynomialRing # base ring imports +import sage.rings.abc from sage.rings.finite_rings.finite_field_prime_modn import FiniteField_prime_modn from sage.rings.rational cimport Rational from sage.rings.rational_field import QQ -from sage.rings.complex_mpfr import is_ComplexField -from sage.rings.real_mpfr import is_RealField +import sage.rings.abc from sage.rings.integer_ring import is_IntegerRing, ZZ from sage.rings.integer cimport Integer from sage.rings.integer import GCD_list -from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing from sage.rings.number_field.number_field_base cimport NumberField from sage.structure.element import coerce_binop @@ -267,12 +266,12 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: MPolynomialRing_libsingular(QQ, 3, ('x', 'y', 'z'), TermOrder('degrevlex', 3)) Multivariate Polynomial Ring in x, y, z over Rational Field sage: type(_) - + sage: P. = QQ[]; P Multivariate Polynomial Ring in x, y, z over Rational Field sage: type(P) - + """ self._ring = NULL @@ -336,7 +335,7 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: P. = Zmod(2521352)[]; P Multivariate Polynomial Ring in x, y, z over Ring of integers modulo 2521352 sage: type(P) - + sage: P. = Zmod(25213521351515232)[]; P Multivariate Polynomial Ring in x, y, z over Ring of integers modulo 25213521351515232 @@ -470,7 +469,7 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: R. = QQ[] sage: type(R) - + sage: R.has_coerce_map_from(ZZ['t']) False sage: R.coerce_map_from(ZZ['x']) @@ -1366,14 +1365,14 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): base_ring = self.base_ring() - if is_RealField(base_ring): + if isinstance(base_ring, sage.rings.abc.RealField): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); precision = base_ring.precision() digits = ceil((2*precision - 2)/7.0) self.__singular = singular.ring("(real,%d,0)"%digits, _vars, order=order) - elif is_ComplexField(base_ring): + elif isinstance(base_ring, sage.rings.abc.ComplexField): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); precision = base_ring.precision() @@ -1407,7 +1406,7 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): elif is_IntegerRing(base_ring): self.__singular = singular.ring("(integer)", _vars, order=order) - elif is_IntegerModRing(base_ring): + elif isinstance(base_ring, sage.rings.abc.IntegerModRing): ch = base_ring.characteristic() if ch.is_power_of(2): exp = ch.nbits() -1 @@ -2380,7 +2379,7 @@ cdef class MPolynomial_libsingular(MPolynomial): sage: g = f^(-1); g 1/(x^3 + y) sage: type(g) - + sage: P. = PolynomialRing(ZZ) sage: P(2)**(-1) diff --git a/src/sage/rings/polynomial/multi_polynomial_ring.py b/src/sage/rings/polynomial/multi_polynomial_ring.py index d4c91fbc3f0..88f7fc4ca51 100644 --- a/src/sage/rings/polynomial/multi_polynomial_ring.py +++ b/src/sage/rings/polynomial/multi_polynomial_ring.py @@ -251,13 +251,13 @@ def __call__(self, x=0, check=True): sage: x,y,z = var('x,y,z') sage: R = QQ['x,y,z'] sage: type(x) - + sage: type(R(x)) - + sage: f = R(x^3 + y^3 - z^3); f x^3 + y^3 - z^3 sage: type(f) - + sage: parent(f) Multivariate Polynomial Ring in x, y, z over Rational Field diff --git a/src/sage/rings/polynomial/multi_polynomial_ring_generic.py b/src/sage/rings/polynomial/multi_polynomial_ring_generic.py deleted file mode 100644 index 06198d9d289..00000000000 --- a/src/sage/rings/polynomial/multi_polynomial_ring_generic.py +++ /dev/null @@ -1,17 +0,0 @@ -""" -TESTS:: - - sage: R. = QQbar[] - sage: from sage.rings.polynomial.multi_polynomial_ring_generic import MPolynomialRing_generic - doctest:...: DeprecationWarning: the module sage.rings.polynomial.multi_polynomial_ring_generic is deprecated, use sage.rings.polynomial.multi_polynomial_ring_base instead. - See https://trac.sagemath.org/25563 for details. - sage: isinstance(R, MPolynomialRing_generic) - True -""" - -from sage.misc.superseded import deprecation -deprecation(25563, "the module sage.rings.polynomial.multi_polynomial_ring_generic is deprecated, " - "use sage.rings.polynomial.multi_polynomial_ring_base instead.") - -from .multi_polynomial_ring_base import MPolynomialRing_base -MPolynomialRing_generic = MPolynomialRing_base diff --git a/src/sage/rings/polynomial/omega.py b/src/sage/rings/polynomial/omega.py index 2406e0e0197..97b97d4fe8c 100644 --- a/src/sage/rings/polynomial/omega.py +++ b/src/sage/rings/polynomial/omega.py @@ -36,25 +36,20 @@ - Daniel Krenn is supported by the Austrian Science Fund (FWF): P 24644-N26. - Functions ========= """ - -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2016 Daniel Krenn # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. -# http://www.gnu.org/licenses/ -#***************************************************************************** - - +# https://www.gnu.org/licenses/ +# **************************************************************************** import operator from sage.misc.cachefunc import cached_function -from sage.misc.superseded import deprecated_function_alias def MacMahonOmega(var, expression, denominator=None, op=operator.ge, @@ -595,6 +590,7 @@ def subs_power(expression, var, exponent): divisible by ``exponent``. """ p = tuple(var.dict().popitem()[0]).index(1) # var is the p-th generator + def subs_e(e): e = list(e) assert e[p] % exponent == 0 @@ -984,5 +980,3 @@ def homogeneous_symmetric_function(j, x): return sum(prod(xx**pp for xx, pp in zip(x, p)) for p in IntegerVectors(j, length=len(x))) - -homogenous_symmetric_function = deprecated_function_alias(30585, homogeneous_symmetric_function) diff --git a/src/sage/rings/polynomial/ore_polynomial_ring.py b/src/sage/rings/polynomial/ore_polynomial_ring.py index 69d218b9cc9..05ebcf6d1c7 100644 --- a/src/sage/rings/polynomial/ore_polynomial_ring.py +++ b/src/sage/rings/polynomial/ore_polynomial_ring.py @@ -21,7 +21,6 @@ # https://www.gnu.org/licenses/ # *************************************************************************** - from sage.misc.prandom import randint from sage.misc.cachefunc import cached_method from sage.rings.infinity import Infinity @@ -338,7 +337,7 @@ def __classcall_private__(cls, base_ring, twist=None, names=None, sparse=False): raise NotImplementedError("sparse Ore polynomial rings are not implemented") from sage.rings.polynomial import skew_polynomial_ring - constructors = [ ] + constructors = [] if derivation is None: if base_ring in _Fields: try: @@ -467,6 +466,7 @@ def _element_constructor_(self, a=None, check=True, construct=False, **kwds): return C(self, a, check=check, construct=construct) if isinstance(a, Element): P = a.parent() + def build(check): if a.is_zero(): return P.zero() @@ -574,7 +574,7 @@ def _coerce_map_from_(self, P): if P.variable_name() == self.variable_name(): return base_ring.has_coerce_map_from(P.base_ring()) - def _repr_(self): + def _repr_(self) -> str: r""" Return a string representation of ``self``. @@ -602,7 +602,7 @@ def _repr_(self): s = "Sparse " + s return s - def _latex_(self): + def _latex_(self) -> str: r""" Return a latex representation of ``self``. @@ -754,34 +754,6 @@ def twisting_morphism(self, n=1): else: raise ValueError("Unexpected error in iterating the twisting morphism: %s", e) - def twist_map(self, n=1): - r""" - Return the twisting endomorphism defining this Ore polynomial ring - iterated ``n`` times or ``None`` if this Ore polynomial ring is not - twisted by an endomorphism. - - This method is deprecated. Use :meth:`twisting_morphism` instead. - - INPUT: - - - ``n`` - an integer (default: 1) - - EXAMPLES:: - - sage: R. = QQ[] - sage: sigma = R.hom([t+1]) - sage: S. = R['x', sigma] - sage: S.twist_map() - ... - DeprecationWarning: The method twist_map is deprecated; use twisting_morphism (same semantic) instead - See https://trac.sagemath.org/29629 for details. - Ring endomorphism of Univariate Polynomial Ring in t over Rational Field - Defn: t |--> t + 1 - """ - from sage.misc.superseded import deprecation - deprecation(29629, "The method twist_map is deprecated; use twisting_morphism (same semantic) instead") - return self.twisting_morphism(n) - def twisting_derivation(self): r""" Return the twisting derivation defining this Ore polynomial ring @@ -846,7 +818,7 @@ def gen(self, n=0): """ if n != 0: raise IndexError("generator %s not defined" % n) - return self.Element(self, [0,1]) + return self.Element(self, [0, 1]) parameter = gen @@ -943,7 +915,7 @@ def ngens(self): """ return 1 - def random_element(self, degree=(-1,2), monic=False, *args, **kwds): + def random_element(self, degree=(-1, 2), monic=False, *args, **kwds): r""" Return a random Ore polynomial in this ring. @@ -1022,11 +994,11 @@ def random_element(self, degree=(-1,2), monic=False, *args, **kwds): degree = randint(*degree) if degree < 0: return self.zero() - coeffs = [ R.random_element(*args, **kwds) for _ in range(degree) ] + coeffs = [R.random_element(*args, **kwds) for _ in range(degree)] if monic: - return self(coeffs + [ R.one() ]) + return self(coeffs + [R.one()]) else: - return self(coeffs + [ R._random_nonzero_element() ]) + return self(coeffs + [R._random_nonzero_element()]) def random_irreducible(self, degree=2, monic=True, *args, **kwds): r""" @@ -1068,11 +1040,11 @@ def random_irreducible(self, degree=2, monic=True, *args, **kwds): raise ValueError("minimum degree must be less or equal than maximum degree") degree = randint(*degree) while True: - irred = self.random_element((degree,degree), monic=monic) + irred = self.random_element((degree, degree), monic=monic) if irred.is_irreducible(): return irred - def is_commutative(self): + def is_commutative(self) -> bool: r""" Return ``True`` if this Ore polynomial ring is commutative, i.e. if the twisting morphism is the identity and the twisting derivation vanishes. @@ -1101,7 +1073,7 @@ def is_commutative(self): """ return self._morphism is None and self._derivation is None - def is_field(self, proof=False): + def is_field(self, proof=False) -> bool: r""" Return always ``False`` since Ore polynomial rings are never fields. diff --git a/src/sage/rings/polynomial/pbori/pbori.pyx b/src/sage/rings/polynomial/pbori/pbori.pyx index b98e726945e..615357f9aac 100644 --- a/src/sage/rings/polynomial/pbori/pbori.pyx +++ b/src/sage/rings/polynomial/pbori/pbori.pyx @@ -1901,7 +1901,7 @@ class BooleanMonomialMonoid(UniqueRepresentation, Monoid_class): sage: M.gens() (x, y) sage: type(M.gen(0)) - + Since :trac:`9138`, boolean monomial monoids are unique parents and are fit into the category framework:: diff --git a/src/sage/rings/polynomial/polynomial_complex_arb.pyx b/src/sage/rings/polynomial/polynomial_complex_arb.pyx index 6f6e45d81ac..3d1f3bebb00 100644 --- a/src/sage/rings/polynomial/polynomial_complex_arb.pyx +++ b/src/sage/rings/polynomial/polynomial_complex_arb.pyx @@ -16,7 +16,7 @@ version 2, or later. TESTS: sage: type(polygen(ComplexBallField(140))) - + sage: Pol. = CBF[] sage: (x+1/2)^3 x^3 + 1.500000000000000*x^2 + 0.7500000000000000*x + 0.1250000000000000 @@ -45,7 +45,7 @@ cdef class Polynomial_complex_arb(Polynomial): sage: Pol. = CBF[] sage: type(x) - + sage: Pol(), Pol(1), Pol([0,1,2]), Pol({1: pi, 3: i}) (0, diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index 31fc3613876..056c39152f0 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -92,7 +92,7 @@ CC = ComplexField() from sage.rings.real_double import RDF from sage.rings.complex_double import CDF -from sage.rings.real_mpfi import is_RealIntervalField +import sage.rings.abc from sage.structure.coerce cimport coercion_model from sage.structure.element import coerce_binop @@ -101,7 +101,6 @@ from sage.structure.element cimport (parent, have_same_parent, from sage.rings.rational_field import QQ, is_RationalField from sage.rings.integer_ring import ZZ, is_IntegerRing -from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing from sage.rings.integer cimport Integer, smallInteger from sage.libs.gmp.mpz cimport * from sage.rings.fraction_field import is_FractionField @@ -213,7 +212,7 @@ cdef class Polynomial(CommutativeAlgebraElement): sage: f = x*y; f y*x sage: type(f) - + sage: p = (y+1)^10; p(1) 1024 @@ -3489,7 +3488,7 @@ cdef class Polynomial(CommutativeAlgebraElement): sage: x.denominator() 1 sage: type(x.denominator()) - + sage: isinstance(x.numerator() / x.denominator(), Polynomial) True sage: isinstance(x.numerator() / R(1), Polynomial) @@ -4386,7 +4385,7 @@ cdef class Polynomial(CommutativeAlgebraElement): n = None - if is_IntegerModRing(R) or is_IntegerRing(R): + if isinstance(R, sage.rings.abc.IntegerModRing) or is_IntegerRing(R): try: G = list(self._pari_with_name().factor()) except PariError: @@ -5711,7 +5710,7 @@ cdef class Polynomial(CommutativeAlgebraElement): sage: f = y^3 + x*y -3*x; f y^3 + x*y - 3*x sage: type(f) - + sage: v = f.list(); v [-3*x, x, 0, 1] sage: v[0] = 10 @@ -7970,7 +7969,7 @@ cdef class Polynomial(CommutativeAlgebraElement): # and complex root isolation and for p-adic factorization if (is_IntegerRing(K) or is_RationalField(K) or is_AlgebraicRealField(K)) and \ - (is_AlgebraicRealField(L) or is_RealIntervalField(L)): + (is_AlgebraicRealField(L) or isinstance(L, sage.rings.abc.RealIntervalField)): from sage.rings.polynomial.real_roots import real_roots @@ -8000,11 +7999,11 @@ cdef class Polynomial(CommutativeAlgebraElement): if (is_IntegerRing(K) or is_RationalField(K) or is_AlgebraicField_common(K) or input_gaussian) and \ - (is_ComplexIntervalField(L) or is_AlgebraicField_common(L)): + (isinstance(L, sage.rings.abc.ComplexIntervalField) or is_AlgebraicField_common(L)): from sage.rings.polynomial.complex_roots import complex_roots - if is_ComplexIntervalField(L): + if isinstance(L, sage.rings.abc.ComplexIntervalField): rts = complex_roots(self, min_prec=L.prec()) elif is_AlgebraicField(L): rts = complex_roots(self, retval='algebraic') @@ -8064,7 +8063,7 @@ cdef class Polynomial(CommutativeAlgebraElement): if K.is_finite(): if multiplicities: raise NotImplementedError("root finding with multiplicities for this polynomial not implemented (try the multiplicities=False option)") - elif is_IntegerModRing(K): + elif isinstance(K, sage.rings.abc.IntegerModRing): # handling via the chinese remainders theorem N = K.cardinality() primes = N.prime_divisors() @@ -9680,9 +9679,9 @@ cdef class Polynomial(CommutativeAlgebraElement): Test the output type when ``certificate=True``:: sage: type((x^2 - 2).is_cyclotomic(certificate=True)) - + sage: type((x -1).is_cyclotomic(certificate=True)) - + Check that the arguments are forwarded when the input is not a polynomial with coefficients in `\ZZ`:: @@ -10992,7 +10991,7 @@ cdef class Polynomial_generic_dense(Polynomial): Make sure we're testing the right method:: sage: type(f) - + """ return make_generic_polynomial, (self._parent, self.__coeffs) @@ -11300,7 +11299,7 @@ cdef class Polynomial_generic_dense(Polynomial): Check that :trac:`12552` is fixed:: sage: type(f.degree()) - + """ return smallInteger(len(self.__coeffs) - 1) @@ -11317,7 +11316,7 @@ cdef class Polynomial_generic_dense(Polynomial): sage: R. = PolynomialRing(PolynomialRing(QQ,'y'), 'x') sage: p = x^2 + 2*x + 4 sage: type(p) - + sage: p.shift(0) x^2 + 2*x + 4 sage: p.shift(-1) @@ -11474,7 +11473,7 @@ cdef class Polynomial_generic_dense(Polynomial): :: sage: type(f) - + """ l = len(self.__coeffs) if n > l: @@ -11779,7 +11778,7 @@ cdef class ConstantPolynomialSection(Map): From: Univariate Polynomial Ring in y_1 over Finite Field of size 3 To: Finite Field of size 3 sage: type(phi) - + sage: phi(P0.one()) 1 sage: phi(y_1) @@ -11971,7 +11970,7 @@ cdef class PolynomialBaseringInjection(Morphism): From: Univariate Polynomial Ring in x over Real Double Field To: Real Double Field sage: type(m.section()) - + """ return ConstantPolynomialSection(self._codomain, self.domain()) diff --git a/src/sage/rings/polynomial/polynomial_integer_dense_flint.pyx b/src/sage/rings/polynomial/polynomial_integer_dense_flint.pyx index 112b17e8d24..75f61f37a46 100644 --- a/src/sage/rings/polynomial/polynomial_integer_dense_flint.pyx +++ b/src/sage/rings/polynomial/polynomial_integer_dense_flint.pyx @@ -182,11 +182,11 @@ cdef class Polynomial_integer_dense_flint(Polynomial): sage: f = R([-1, 2, 5]); f 5*x^2 + 2*x - 1 sage: type(f) - + sage: type(pari(f)) - + sage: type(R(pari(f))) - + sage: R(pari(f)) 5*x^2 + 2*x - 1 @@ -205,7 +205,7 @@ cdef class Polynomial_integer_dense_flint(Polynomial): sage: f = (x^3 - 1) / (x - 1) sage: type(f) - + sage: g = R(f); g x^2 + x + 1 @@ -1389,7 +1389,7 @@ cdef class Polynomial_integer_dense_flint(Polynomial): TESTS:: sage: type(x.degree()) - + """ return smallInteger(fmpz_poly_degree(self.__poly)) diff --git a/src/sage/rings/polynomial/polynomial_integer_dense_ntl.pyx b/src/sage/rings/polynomial/polynomial_integer_dense_ntl.pyx index 75227af230f..160899b6d64 100644 --- a/src/sage/rings/polynomial/polynomial_integer_dense_ntl.pyx +++ b/src/sage/rings/polynomial/polynomial_integer_dense_ntl.pyx @@ -127,11 +127,11 @@ cdef class Polynomial_integer_dense_ntl(Polynomial): sage: f = R([-1, 2, 5]); f 5*x^2 + 2*x - 1 sage: type(f) - + sage: type(pari(f)) - + sage: type(R(pari(f))) - + sage: R(pari(f)) 5*x^2 + 2*x - 1 @@ -150,7 +150,7 @@ cdef class Polynomial_integer_dense_ntl(Polynomial): sage: f = (x^3 - 1) / (x - 1) sage: type(f) - + sage: g = R(f); g x^2 + x + 1 diff --git a/src/sage/rings/polynomial/polynomial_quotient_ring.py b/src/sage/rings/polynomial/polynomial_quotient_ring.py index 4c89ef22db1..b069cdd749c 100644 --- a/src/sage/rings/polynomial/polynomial_quotient_ring.py +++ b/src/sage/rings/polynomial/polynomial_quotient_ring.py @@ -1333,7 +1333,7 @@ def S_class_group(self, S, proof=True): sage: type(CG[0][0][1]) sage: type(CG[0][1]) - + TESTS: @@ -1493,7 +1493,7 @@ def class_group(self, proof=True): sage: type(CG[0][0][1]) sage: type(CG[0][1]) - + """ return self.S_class_group((), proof=proof) @@ -1559,7 +1559,7 @@ def S_units(self, S, proof=True): sage: type(U[0][0]) sage: type(U[0][1]) - + sage: type(U[1][1]) @@ -1645,7 +1645,7 @@ def units(self, proof=True): sage: type(U[0][0]) sage: type(U[0][1]) - + sage: type(U[1][1]) diff --git a/src/sage/rings/polynomial/polynomial_rational_flint.pyx b/src/sage/rings/polynomial/polynomial_rational_flint.pyx index 8fd36a34dd0..7c71af6fb75 100644 --- a/src/sage/rings/polynomial/polynomial_rational_flint.pyx +++ b/src/sage/rings/polynomial/polynomial_rational_flint.pyx @@ -392,7 +392,7 @@ cdef class Polynomial_rational_flint(Polynomial): TESTS:: sage: type(f.degree()) - + """ return smallInteger(fmpq_poly_degree(self.__poly)) diff --git a/src/sage/rings/polynomial/polynomial_real_mpfr_dense.pyx b/src/sage/rings/polynomial/polynomial_real_mpfr_dense.pyx index 10e852d52f3..e806ae2d228 100644 --- a/src/sage/rings/polynomial/polynomial_real_mpfr_dense.pyx +++ b/src/sage/rings/polynomial/polynomial_real_mpfr_dense.pyx @@ -248,7 +248,7 @@ cdef class PolynomialRealDense(Polynomial): TESTS:: sage: type(f.degree()) - + """ return smallInteger(self._degree) diff --git a/src/sage/rings/polynomial/polynomial_ring.py b/src/sage/rings/polynomial/polynomial_ring.py index 7cef097c1a8..82ff837a2b5 100644 --- a/src/sage/rings/polynomial/polynomial_ring.py +++ b/src/sage/rings/polynomial/polynomial_ring.py @@ -165,7 +165,7 @@ from sage.misc.cachefunc import cached_method from sage.misc.lazy_attribute import lazy_attribute -from sage.rings.real_mpfr import is_RealField +import sage.rings.abc from sage.rings.fraction_field_element import FractionFieldElement from sage.rings.finite_rings.element_base import FiniteRingElement @@ -219,7 +219,7 @@ def is_PolynomialRing(x): sage: is_PolynomialRing(R) False sage: type(R) - + """ return isinstance(x, PolynomialRing_general) @@ -1794,12 +1794,12 @@ def __init__(self, base_ring, name="x", sparse=False, implementation=None, sage: R = PRing(ZZ, 'x'); R Univariate Polynomial Ring in x over Integer Ring sage: type(R.gen()) - + sage: R = PRing(ZZ, 'x', implementation='NTL'); R Univariate Polynomial Ring in x over Integer Ring (using NTL) sage: type(R.gen()) - + """ self._implementation_repr = '' if element_class is None: @@ -1964,7 +1964,7 @@ def __init__(self, base_ring, name="x", sparse=False, element_class=None, catego sage: R = PRing(QQ, 'x'); R Univariate Polynomial Ring in x over Rational Field sage: type(R.gen()) - + sage: R = PRing(QQ, 'x', sparse=True); R Sparse Univariate Polynomial Ring in x over Rational Field sage: type(R.gen()) @@ -1995,7 +1995,7 @@ def __init__(self, base_ring, name="x", sparse=False, element_class=None, catego else: from sage.rings.polynomial.polynomial_number_field import Polynomial_relative_number_field_dense element_class = Polynomial_relative_number_field_dense - elif is_RealField(base_ring): + elif isinstance(base_ring, sage.rings.abc.RealField): element_class = PolynomialRealDense elif isinstance(base_ring, sage.rings.complex_arb.ComplexBallField): from sage.rings.polynomial.polynomial_complex_arb import Polynomial_complex_arb @@ -2384,7 +2384,7 @@ def __init__(self, base_ring, name="x", element_class=None, implementation=None) sage: S = PolynomialRing_dense_finite_field(GF(25, 'a'), implementation='NTL') sage: type(S(0)) - + sage: S = PolynomialRing_dense_finite_field(GF(64), implementation='superfast') Traceback (most recent call last): @@ -2976,17 +2976,17 @@ def __init__(self, base_ring, name=None, element_class=None, sage: R = PRing(Zmod(15), 'x'); R Univariate Polynomial Ring in x over Ring of integers modulo 15 sage: type(R.gen()) - + sage: R = PRing(Zmod(15), 'x', implementation='NTL'); R Univariate Polynomial Ring in x over Ring of integers modulo 15 (using NTL) sage: type(R.gen()) - + sage: R = PRing(Zmod(2**63*3), 'x', implementation='NTL'); R Univariate Polynomial Ring in x over Ring of integers modulo 27670116110564327424 (using NTL) sage: type(R.gen()) - + sage: R = PRing(Zmod(2**63*3), 'x', implementation='FLINT') Traceback (most recent call last): @@ -2996,7 +2996,7 @@ def __init__(self, base_ring, name=None, element_class=None, sage: R = PRing(Zmod(2**63*3), 'x'); R Univariate Polynomial Ring in x over Ring of integers modulo 27670116110564327424 (using NTL) sage: type(R.gen()) - + """ if element_class is None: implementation = self._implementation_names(implementation, base_ring)[0] @@ -3131,24 +3131,24 @@ def __init__(self, base_ring, name="x", implementation=None, category=None): sage: P = GF(2)['x']; P Univariate Polynomial Ring in x over Finite Field of size 2 (using GF2X) sage: type(P.gen()) - + sage: from sage.rings.polynomial.polynomial_ring import PolynomialRing_dense_mod_p sage: P = PolynomialRing_dense_mod_p(GF(5), 'x'); P Univariate Polynomial Ring in x over Finite Field of size 5 sage: type(P.gen()) - + sage: P = PolynomialRing_dense_mod_p(GF(5), 'x', implementation='NTL'); P Univariate Polynomial Ring in x over Finite Field of size 5 (using NTL) sage: type(P.gen()) - + sage: P = PolynomialRing_dense_mod_p(GF(9223372036854775837), 'x') sage: P Univariate Polynomial Ring in x over Finite Field of size 9223372036854775837 (using NTL) sage: type(P.gen()) - + This caching bug was fixed in :trac:`24264`:: diff --git a/src/sage/rings/polynomial/polynomial_ring_constructor.py b/src/sage/rings/polynomial/polynomial_ring_constructor.py index c88f6705ccd..289c80160c3 100644 --- a/src/sage/rings/polynomial/polynomial_ring_constructor.py +++ b/src/sage/rings/polynomial/polynomial_ring_constructor.py @@ -27,9 +27,9 @@ import sage.rings.ring as ring import sage.rings.padics.padic_base_leaves as padic_base_leaves +import sage.rings.abc from sage.rings.integer import Integer from sage.rings.finite_rings.finite_field_base import is_FiniteField -from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing from sage.misc.cachefunc import weak_cached_function @@ -426,7 +426,7 @@ def PolynomialRing(base_ring, *args, **kwds): sage: R = PolynomialRing(ZZ, 'x,y', implementation="generic"); type(R) sage: S = PolynomialRing(ZZ, 'x,y'); type(S) - + Sparse univariate polynomials only support a generic implementation:: @@ -694,7 +694,7 @@ def _single_variate(base_ring, name, sparse=None, implementation=None, order=Non # Specialized implementations specialized = None - if is_IntegerModRing(base_ring): + if isinstance(base_ring, sage.rings.abc.IntegerModRing): n = base_ring.order() if n.is_prime(): specialized = polynomial_ring.PolynomialRing_dense_mod_p diff --git a/src/sage/rings/polynomial/polynomial_singular_interface.py b/src/sage/rings/polynomial/polynomial_singular_interface.py index 61777d5556a..c122bfd438d 100644 --- a/src/sage/rings/polynomial/polynomial_singular_interface.py +++ b/src/sage/rings/polynomial/polynomial_singular_interface.py @@ -38,14 +38,10 @@ ###################################################################### import sage.rings.fraction_field +import sage.rings.abc import sage.rings.number_field as number_field from sage.interfaces.all import singular -from sage.rings.complex_mpfr import is_ComplexField -from sage.rings.real_mpfr import is_RealField -from sage.rings.complex_double import is_ComplexDoubleField -from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing -from sage.rings.real_double import is_RealDoubleField from sage.rings.rational_field import is_RationalField from sage.rings.function_field.function_field import RationalFunctionField from sage.rings.finite_rings.finite_field_base import is_FiniteField @@ -257,26 +253,26 @@ def _singular_init_(self, singular=singular): base_ring = self.base_ring() - if is_RealField(base_ring): + if isinstance(base_ring, sage.rings.abc.RealField): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); precision = base_ring.precision() digits = sage.arith.all.integer_ceil((2*precision - 2)/7.0) self.__singular = singular.ring("(real,%d,0)"%digits, _vars, order=order, check=False) - elif is_ComplexField(base_ring): + elif isinstance(base_ring, sage.rings.abc.ComplexField): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); precision = base_ring.precision() digits = sage.arith.all.integer_ceil((2*precision - 2)/7.0) self.__singular = singular.ring("(complex,%d,0,I)"%digits, _vars, order=order, check=False) - elif is_RealDoubleField(base_ring): + elif isinstance(base_ring, sage.rings.abc.RealDoubleField): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); self.__singular = singular.ring("(real,15,0)", _vars, order=order, check=False) - elif is_ComplexDoubleField(base_ring): + elif isinstance(base_ring, sage.rings.abc.ComplexDoubleField): # singular converts to bits from base_10 in mpr_complex.cc by: # size_t bits = 1 + (size_t) ((float)digits * 3.5); self.__singular = singular.ring("(complex,15,0,I)", _vars, order=order, check=False) @@ -336,7 +332,7 @@ def _singular_init_(self, singular=singular): gen = str(base_ring.gen()) self.__singular = singular.ring( "(%s,%s)"%(base_ring.characteristic(),gen), _vars, order=order, check=False) - elif is_IntegerModRing(base_ring): + elif isinstance(base_ring, sage.rings.abc.IntegerModRing): ch = base_ring.characteristic() if ch.is_power_of(2): exp = ch.nbits() -1 @@ -388,11 +384,9 @@ def can_convert_to_singular(R): if (base_ring is ZZ or sage.rings.finite_rings.finite_field_constructor.is_FiniteField(base_ring) or is_RationalField(base_ring) - or is_IntegerModRing(base_ring) - or is_RealField(base_ring) - or is_ComplexField(base_ring) - or is_RealDoubleField(base_ring) - or is_ComplexDoubleField(base_ring)): + or isinstance(base_ring, (sage.rings.abc.IntegerModRing, + sage.rings.abc.RealField, sage.rings.abc.ComplexField, + sage.rings.abc.RealDoubleField, sage.rings.abc.ComplexDoubleField))): return True elif base_ring.is_prime_field(): return base_ring.characteristic() <= 2147483647 diff --git a/src/sage/rings/polynomial/polynomial_zmod_flint.pyx b/src/sage/rings/polynomial/polynomial_zmod_flint.pyx index fc7898dde64..18d04f404d8 100644 --- a/src/sage/rings/polynomial/polynomial_zmod_flint.pyx +++ b/src/sage/rings/polynomial/polynomial_zmod_flint.pyx @@ -16,10 +16,10 @@ EXAMPLES:: sage: R. = PolynomialRing(Integers(100)) sage: type(a) - + sage: R. = PolynomialRing(Integers(5*2^64)) sage: type(a) - + sage: R. = PolynomialRing(Integers(5*2^64), implementation="FLINT") Traceback (most recent call last): ... diff --git a/src/sage/rings/polynomial/term_order.py b/src/sage/rings/polynomial/term_order.py index 6c411c2011e..51c4e6ef4c6 100644 --- a/src/sage/rings/polynomial/term_order.py +++ b/src/sage/rings/polynomial/term_order.py @@ -2216,7 +2216,7 @@ def termorder_from_singular(S): sage: PolynomialRing(QQ, 'x,y', order='degneglex')('x^2')._singular_().sage() x^2 """ - from sage.all import ZZ + from sage.rings.integer_ring import ZZ singular = S T = singular('ringlist(basering)[3]') order = [] diff --git a/src/sage/rings/power_series_pari.pyx b/src/sage/rings/power_series_pari.pyx index b4d32da0b98..038c66dd1b7 100644 --- a/src/sage/rings/power_series_pari.pyx +++ b/src/sage/rings/power_series_pari.pyx @@ -18,21 +18,21 @@ not the type of the parents:: sage: type(R) sage: type(q) - + sage: type(S) sage: type(t) - + If `k` is a finite field implemented using PARI, this is the default implementation for power series over `k`:: sage: k. = GF(5^12) sage: type(c) - + sage: A. = k[[]] sage: type(x) - + .. WARNING:: diff --git a/src/sage/rings/power_series_ring_element.pyx b/src/sage/rings/power_series_ring_element.pyx index a021390d012..71ff6407c18 100644 --- a/src/sage/rings/power_series_ring_element.pyx +++ b/src/sage/rings/power_series_ring_element.pyx @@ -1005,7 +1005,7 @@ cdef class PowerSeries(AlgebraElement): sage: t.inverse() t^-1 sage: type(_) - + sage: (1-t).inverse() 1 + t + t^2 + t^3 + t^4 + t^5 + t^6 + t^7 + t^8 + ... """ diff --git a/src/sage/rings/qqbar.py b/src/sage/rings/qqbar.py index e75d09d58f0..ae926cde625 100644 --- a/src/sage/rings/qqbar.py +++ b/src/sage/rings/qqbar.py @@ -566,7 +566,7 @@ from sage.rings.real_mpfr import RR from sage.rings.real_mpfi import RealIntervalField, RIF, is_RealIntervalFieldElement, RealIntervalField_class from sage.rings.complex_mpfr import ComplexField -from sage.rings.complex_interval_field import ComplexIntervalField, is_ComplexIntervalField +from sage.rings.complex_interval_field import ComplexIntervalField from sage.rings.complex_interval import is_ComplexIntervalFieldElement from sage.rings.polynomial.all import PolynomialRing from sage.rings.polynomial.polynomial_element import is_Polynomial @@ -5013,7 +5013,7 @@ def interval_exact(self, field): sage: (a - b).interval_exact(CIF) 0 """ - if not is_ComplexIntervalField(field): + if not isinstance(field, sage.rings.abc.ComplexIntervalField): raise ValueError("AlgebraicNumber interval_exact requires a ComplexIntervalField") rfld = field._real_field() re = self.real().interval_exact(rfld) @@ -5210,7 +5210,7 @@ def _ensure_real(self): sage: b._value 0.7071067811865475244? sage: type(b._value) - + """ if is_ComplexIntervalFieldElement(self._value): self._value = self._value.real() @@ -5910,7 +5910,7 @@ def _complex_mpfr_field_(self, field): sage: AA(golden_ratio)._complex_mpfr_field_(ComplexField(100)) 1.6180339887498948482045868344 """ - if is_ComplexIntervalField(field): + if isinstance(field, sage.rings.abc.ComplexIntervalField): return field(self.interval(field._real_field())) else: return field(self.real_number(field._real_field())) diff --git a/src/sage/rings/quotient_ring_element.py b/src/sage/rings/quotient_ring_element.py index af2b3d43bb4..8d09a28f6ba 100644 --- a/src/sage/rings/quotient_ring_element.py +++ b/src/sage/rings/quotient_ring_element.py @@ -506,7 +506,7 @@ def _rational_(self): TESTS:: sage: type(S(-2/3)._rational_()) - + """ from sage.rings.rational_field import QQ return QQ(self.lift()) diff --git a/src/sage/rings/rational.pyx b/src/sage/rings/rational.pyx index 2be63156923..6e02cf4387d 100644 --- a/src/sage/rings/rational.pyx +++ b/src/sage/rings/rational.pyx @@ -404,7 +404,7 @@ cdef class Rational(sage.structure.element.FieldElement): sage: a = -2/3 sage: type(a) - + sage: parent(a) Rational Field sage: Rational('1/0') @@ -2526,7 +2526,7 @@ cdef class Rational(sage.structure.element.FieldElement): sage: a = (0/1)^(0/1); a 1 sage: type(a) - + If the result is rational, it is returned as a rational:: @@ -2562,7 +2562,7 @@ cdef class Rational(sage.structure.element.FieldElement): sage: a = int(2)^(3/1); a 8 sage: type(a) - + The exponent must fit in a long unless the base is -1, 0, or 1:: @@ -3482,7 +3482,7 @@ cdef class Rational(sage.structure.element.FieldElement): sage: (0/1)._lcm(0/1) 0 sage: type((2/3)._lcm(3/5)) - + """ if mpz_cmp_si(mpq_numref(self.value), 0) == 0 and \ mpz_cmp_si(mpq_numref(other.value), 0) == 0: @@ -3773,7 +3773,7 @@ cdef class Rational(sage.structure.element.FieldElement): sage: m = n.__pari__(); m 9390823/17 sage: type(m) - + sage: m.type() 't_FRAC' """ @@ -4148,7 +4148,7 @@ cdef class Q_to_Z(Map): TESTS:: sage: type(ZZ.convert_map_from(QQ)) - + """ cpdef Element _call_(self, x): """ diff --git a/src/sage/rings/rational_field.py b/src/sage/rings/rational_field.py index 059593e3836..fbd0fd79d65 100644 --- a/src/sage/rings/rational_field.py +++ b/src/sage/rings/rational_field.py @@ -173,7 +173,7 @@ def __init__(self): sage: Q('49/7') 7 sage: type(Q('49/7')) - + sage: a = Q('19/374'); a 19/374 sage: b = Q('17/371'); b diff --git a/src/sage/rings/real_arb.pyx b/src/sage/rings/real_arb.pyx index 72164d0ec13..c616e9cd304 100644 --- a/src/sage/rings/real_arb.pyx +++ b/src/sage/rings/real_arb.pyx @@ -219,6 +219,7 @@ from sage.libs.mpfr cimport MPFR_RNDN, MPFR_RNDU, MPFR_RNDD, MPFR_RNDZ from sage.structure.element cimport Element, ModuleElement, RingElement from sage.rings.ring cimport Field +import sage.rings.abc from sage.rings.integer cimport Integer from sage.rings.rational cimport Rational from sage.rings.real_double cimport RealDoubleElement @@ -320,7 +321,7 @@ cdef int arb_to_mpfi(mpfi_t target, arb_t source, const long precision) except - mpfr_clear(right) -class RealBallField(UniqueRepresentation, Field): +class RealBallField(UniqueRepresentation, sage.rings.abc.RealBallField): r""" An approximation of the field of real numbers using mid-rad intervals, also known as balls. @@ -2548,7 +2549,7 @@ cdef class RealBall(RingElement): sage: RBF(sqrt(2)).contains_exact(sqrt(2)) Traceback (most recent call last): ... - TypeError: unsupported type: + TypeError: unsupported type: TESTS:: @@ -3605,11 +3606,13 @@ cdef class RealBall(RingElement): sage: RBF(1/2).zetaderiv(1) [-3.92264613920915...] + sage: RBF(2).zetaderiv(3) + [-6.0001458028430...] """ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing Pol = PolynomialRing(self._parent.complex_field(), 'x') ser = Pol([self, 1])._zeta_series(k + 1) - return ser[k].real() + return ser[k].real()*ZZ.coerce(k).factorial() def lambert_w(self): r""" diff --git a/src/sage/rings/real_double.pyx b/src/sage/rings/real_double.pyx index 7356600a482..405153db6b9 100644 --- a/src/sage/rings/real_double.pyx +++ b/src/sage/rings/real_double.pyx @@ -77,16 +77,26 @@ def is_RealDoubleField(x): """ Returns ``True`` if ``x`` is the field of real double precision numbers. + This function is deprecated. Use :func:`isinstance` with + :class:`~sage.rings.abc.RealDoubleField` instead. + EXAMPLES:: sage: from sage.rings.real_double import is_RealDoubleField sage: is_RealDoubleField(RDF) + doctest:warning... + DeprecationWarning: is_RealDoubleField is deprecated; + use isinstance(..., sage.rings.abc.RealDoubleField) instead + See https://trac.sagemath.org/32610 for details. True sage: is_RealDoubleField(RealField(53)) False """ + from sage.misc.superseded import deprecation + deprecation(32610, 'is_RealDoubleField is deprecated; use isinstance(..., sage.rings.abc.RealDoubleField) instead') return isinstance(x, RealDoubleField_class) + cdef class RealDoubleField_class(sage.rings.abc.RealDoubleField): """ An approximation to the field of real numbers using double @@ -1223,7 +1233,7 @@ cdef class RealDoubleElement(FieldElement): sage: a = r.integer_part(); a -1 sage: type(a) - + sage: r = RDF(0.0/0.0) sage: a = r.integer_part() Traceback (most recent call last): diff --git a/src/sage/rings/real_interval_absolute.pyx b/src/sage/rings/real_interval_absolute.pyx index 2b193145eb3..7b39d84b5fa 100644 --- a/src/sage/rings/real_interval_absolute.pyx +++ b/src/sage/rings/real_interval_absolute.pyx @@ -10,12 +10,13 @@ from sage.structure.factory import UniqueFactory from sage.structure.element cimport RingElement, ModuleElement, Element, FieldElement from sage.rings.ring cimport Field from sage.rings.integer cimport Integer +import sage.rings.abc from sage.structure.parent cimport Parent from sage.structure.element cimport parent from sage.rings.real_mpfr import RR_min_prec -from sage.rings.real_mpfi import RealIntervalField, RealIntervalFieldElement, is_RealIntervalField +from sage.rings.real_mpfi import RealIntervalField, RealIntervalFieldElement from sage.rings.rational_field import QQ cdef Integer zero = Integer(0) @@ -185,7 +186,7 @@ cdef class RealIntervalAbsoluteField_class(Field): """ if isinstance(R, RealIntervalAbsoluteField_class): return self._absprec < (R)._absprec - elif is_RealIntervalField(R): + elif isinstance(R, sage.rings.abc.RealIntervalField): return True else: return RR_min_prec.has_coerce_map_from(R) diff --git a/src/sage/rings/real_lazy.pyx b/src/sage/rings/real_lazy.pyx index 24b679f8935..1ac123cfdb3 100644 --- a/src/sage/rings/real_lazy.pyx +++ b/src/sage/rings/real_lazy.pyx @@ -1709,7 +1709,7 @@ cdef class LazyWrapperMorphism(Morphism): sage: a = f(3); a 3 sage: type(a) - + sage: a._value 3 sage: a._value.parent() @@ -1727,7 +1727,7 @@ cdef class LazyWrapperMorphism(Morphism): sage: a = f(1/3); a # indirect doctest 0.3333333333333334? sage: type(a) - + sage: Reals(100)(a) 0.33333333333333333333333333333 diff --git a/src/sage/rings/real_mpfi.pxd b/src/sage/rings/real_mpfi.pxd index c32dcc959d0..5466a5f575f 100644 --- a/src/sage/rings/real_mpfi.pxd +++ b/src/sage/rings/real_mpfi.pxd @@ -2,7 +2,7 @@ from sage.libs.mpfr.types cimport mpfr_prec_t from sage.libs.mpfi.types cimport mpfi_t from sage.rings.ring cimport Field - +cimport sage.rings.abc from sage.structure.element cimport RingElement from .rational cimport Rational @@ -10,7 +10,7 @@ from .real_mpfr cimport RealField_class cdef class RealIntervalFieldElement(RingElement) # forward decl -cdef class RealIntervalField_class(Field): +cdef class RealIntervalField_class(sage.rings.abc.RealIntervalField): cdef mpfr_prec_t __prec cdef bint sci_not # Cache RealField instances for the lower, upper, and middle bounds. diff --git a/src/sage/rings/real_mpfi.pyx b/src/sage/rings/real_mpfi.pyx index 2bfdc5f2512..ce83e1ddf4e 100644 --- a/src/sage/rings/real_mpfi.pyx +++ b/src/sage/rings/real_mpfi.pyx @@ -345,7 +345,7 @@ cpdef RealIntervalField_class RealIntervalField(prec=53, sci_not=False): return R -cdef class RealIntervalField_class(Field): +cdef class RealIntervalField_class(sage.rings.abc.RealIntervalField): """ Class of the real interval field. diff --git a/src/sage/rings/real_mpfr.pyx b/src/sage/rings/real_mpfr.pyx index 5d4557a6d37..774ab916659 100644 --- a/src/sage/rings/real_mpfr.pyx +++ b/src/sage/rings/real_mpfr.pyx @@ -5366,7 +5366,7 @@ cdef class RealNumber(sage.structure.element.RingElement): :: sage: type(z) - + sage: R(z) 1.64493406684823 """ @@ -5753,9 +5753,9 @@ cdef class RealLiteral(RealNumber): The result is a non-literal:: sage: type(1.3) - + sage: type(n(1.3)) - + """ if prec is None: prec = digits_to_bits(digits) @@ -5900,15 +5900,25 @@ def is_RealField(x): """ Returns ``True`` if ``x`` is technically of a Python real field type. + This function is deprecated. Use :func:`isinstance` with + :class:`~sage.rings.abc.RealField` instead. + EXAMPLES:: sage: sage.rings.real_mpfr.is_RealField(RR) + doctest:warning... + DeprecationWarning: is_RealField is deprecated; + use isinstance(..., sage.rings.abc.RealField) instead + See https://trac.sagemath.org/32610 for details. True sage: sage.rings.real_mpfr.is_RealField(CC) False """ + from sage.misc.superseded import deprecation + deprecation(32610, 'is_RealField is deprecated; use isinstance(..., sage.rings.abc.RealField) instead') return isinstance(x, RealField_class) + def is_RealNumber(x): """ Return ``True`` if ``x`` is of type :class:`RealNumber`, meaning that it diff --git a/src/sage/rings/ring.pyx b/src/sage/rings/ring.pyx index 7cc9c6d3f70..562dd5cd2ff 100644 --- a/src/sage/rings/ring.pyx +++ b/src/sage/rings/ring.pyx @@ -1406,9 +1406,9 @@ cdef class CommutativeRing(Ring): sage: ZZ.krull_dimension() 1 sage: type(R); type(QQ); type(ZZ) - + - + All orders in number fields have Krull dimension 1, including non-maximal orders:: @@ -2049,7 +2049,7 @@ cdef class PrincipalIdealDomain(IntegralDomain): sage: QQ.gcd(ZZ(42), ZZ(48)); type(QQ.gcd(ZZ(42), ZZ(48))) 6 - + sage: QQ.gcd(1/2, 1/3) 1/6 @@ -2091,7 +2091,7 @@ cdef class PrincipalIdealDomain(IntegralDomain): sage: QQ.content(ZZ(42), ZZ(48)); type(QQ.content(ZZ(42), ZZ(48))) 6 - + sage: QQ.content(1/2, 1/3) 1/6 sage: factor(1/2); factor(1/3); factor(1/6) diff --git a/src/sage/rings/ring_extension.pyx b/src/sage/rings/ring_extension.pyx index 754b8c2ca63..640971fb47e 100644 --- a/src/sage/rings/ring_extension.pyx +++ b/src/sage/rings/ring_extension.pyx @@ -507,7 +507,7 @@ cdef class RingExtension_generic(CommutativeAlgebra): Rational Field over its base sage: type(Q) - + sage: TestSuite(Q).run() @@ -705,7 +705,7 @@ cdef class RingExtension_generic(CommutativeAlgebra): sage: K = GF(7^3).over() sage: type(K) - + sage: loads(dumps(K)) is K True """ @@ -841,7 +841,7 @@ cdef class RingExtension_generic(CommutativeAlgebra): sage: E.print_options(over=ZZ) Traceback (most recent call last): ... - TypeError: unable to coerce to an integer + TypeError: unable to coerce to an integer """ if over is not None and over is not Infinity: over = ZZ(over) @@ -1900,7 +1900,7 @@ cdef class RingExtensionFractionField(RingExtension_generic): Fraction Field of Integer Ring over its base sage: type(Q) - + sage: TestSuite(Q).run() @@ -2457,7 +2457,7 @@ cdef class RingExtensionWithGen(RingExtensionWithBasis): sage: K = A.over() sage: type(K) - + sage: TestSuite(K).run() diff --git a/src/sage/rings/ring_extension_conversion.pyx b/src/sage/rings/ring_extension_conversion.pyx index f432faf8bb2..36e12b8fcac 100644 --- a/src/sage/rings/ring_extension_conversion.pyx +++ b/src/sage/rings/ring_extension_conversion.pyx @@ -198,7 +198,7 @@ cdef _backend_morphism(f): sage: K. = GF(7^3).over() sage: f = End(K)(Frob) sage: type(f) - + sage: backend_morphism(f) == Frob # indirect doctest True @@ -219,7 +219,7 @@ cdef _backend_morphism(f): sage: iota = End(K).identity() sage: type(iota) - + sage: backend_morphism(iota) Identity endomorphism of Finite Field in z3 of size 7^3 """ diff --git a/src/sage/rings/ring_extension_element.pyx b/src/sage/rings/ring_extension_element.pyx index 1f34ba48078..610291dc620 100644 --- a/src/sage/rings/ring_extension_element.pyx +++ b/src/sage/rings/ring_extension_element.pyx @@ -91,7 +91,7 @@ cdef class RingExtensionElement(CommutativeAlgebraElement): sage: K = GF(5^3).over() sage: x = K.random_element() sage: type(x) - + sage: loads(dumps(x)) == x True """ @@ -566,7 +566,7 @@ cdef class RingExtensionFractionFieldElement(RingExtensionElement): sage: Q = Z.fraction_field() sage: x = Q.random_element() sage: type(x) - + sage: TestSuite(x).run() """ def __hash__(self): @@ -733,7 +733,7 @@ cdef class RingExtensionWithBasisElement(RingExtensionElement): sage: K. = GF(5^3).over() sage: L. = GF(5^9).over(K) sage: type(b) - + sage: TestSuite(b).run() """ def __hash__(self): diff --git a/src/sage/rings/ring_extension_morphism.pyx b/src/sage/rings/ring_extension_morphism.pyx index 463a07276a6..c5e6b556e56 100644 --- a/src/sage/rings/ring_extension_morphism.pyx +++ b/src/sage/rings/ring_extension_morphism.pyx @@ -93,7 +93,7 @@ cdef class RingExtensionHomomorphism(RingMap): a |--> 1 - a sage: type(phi) - + sage: TestSuite(phi).run() @@ -546,7 +546,7 @@ cdef class RingExtensionBackendIsomorphism(RingExtensionHomomorphism): To: Field in z9 with defining polynomial x^3 + (9*z3^2 + 5*z3 + 1)*x^2 + (4*z3 + 3)*x + 10*z3 over its base sage: type(f) - + sage: TestSuite(f).run() """ @@ -637,7 +637,7 @@ cdef class RingExtensionBackendReverseIsomorphism(RingExtensionHomomorphism): To: Finite Field in z9 of size 11^9 sage: type(f) - + sage: TestSuite(f).run() @@ -723,7 +723,7 @@ cdef class MapFreeModuleToRelativeRing(Map): sage: K = GF(5^2).over() sage: V, i, j = K.free_module() sage: type(i) - + """ def __init__(self, E, K): @@ -810,7 +810,7 @@ cdef class MapRelativeRingToFreeModule(Map): sage: K = GF(5^2).over() sage: V, i, j = K.free_module() sage: type(j) - + """ def __init__(self, E, K): diff --git a/src/sage/rings/semirings/non_negative_integer_semiring.py b/src/sage/rings/semirings/non_negative_integer_semiring.py index 6f80d4749c9..ea3bce495d9 100644 --- a/src/sage/rings/semirings/non_negative_integer_semiring.py +++ b/src/sage/rings/semirings/non_negative_integer_semiring.py @@ -53,7 +53,7 @@ class NonNegativeIntegerSemiring(NonNegativeIntegers): Sage ``Integers`` with ``Integer Ring`` as parent:: sage: x = NN(15); type(x) - + sage: x.parent() Integer Ring sage: x+3 diff --git a/src/sage/rings/tests.py b/src/sage/rings/tests.py index 4fd37826771..9575ef5c6a8 100644 --- a/src/sage/rings/tests.py +++ b/src/sage/rings/tests.py @@ -29,7 +29,8 @@ def prime_finite_field(): sage: K.cardinality().is_prime() True """ - from sage.all import ZZ, GF + from sage.rings.integer_ring import ZZ + from sage.rings.finite_rings.finite_field_constructor import GF return GF(ZZ.random_element(x=2, y=10**20 - 12).next_prime()) @@ -49,7 +50,8 @@ def finite_field(): sage: while K.cardinality().is_prime(): ....: K = sage.rings.tests.finite_field() """ - from sage.all import ZZ, GF + from sage.rings.integer_ring import ZZ + from sage.rings.finite_rings.finite_field_constructor import GF p = ZZ.random_element(x=2, y=10**6 - 18).next_prime() d = ZZ.random_element(x=1, y=20) return GF(p**d, 'a') @@ -72,7 +74,8 @@ def small_finite_field(): sage: q <= 2^16 True """ - from sage.all import ZZ, GF + from sage.rings.integer_ring import ZZ + from sage.rings.finite_rings.finite_field_constructor import GF while True: q = ZZ.random_element(x=2, y=2**16) if q.is_prime_power(): @@ -182,7 +185,7 @@ def relative_number_field(n=2, maxdeg=2): sage: from sage.rings.tests import relative_number_field sage: _ = relative_number_field(3) """ - from sage.all import ZZ + from sage.rings.integer_ring import ZZ K = absolute_number_field(maxdeg) n -= 1 var = 'aa' diff --git a/src/sage/rings/universal_cyclotomic_field.py b/src/sage/rings/universal_cyclotomic_field.py index 9c7ed719378..61d21e1acb9 100644 --- a/src/sage/rings/universal_cyclotomic_field.py +++ b/src/sage/rings/universal_cyclotomic_field.py @@ -1477,7 +1477,7 @@ def _element_constructor_(self, elt): Traceback (most recent call last): ... TypeError: [ [ 0, 1 ], [ 0, 2 ] ] - of type not valid + of type not valid to initialize an element of the universal cyclotomic field Some conversions from symbolic functions are possible:: diff --git a/src/sage/rings/valuation/valuation_space.py b/src/sage/rings/valuation/valuation_space.py index a4ace6dbece..705e3831799 100644 --- a/src/sage/rings/valuation/valuation_space.py +++ b/src/sage/rings/valuation/valuation_space.py @@ -475,7 +475,8 @@ def element_with_valuation(self, s): 1024 """ - from sage.rings.all import QQ, ZZ + from sage.rings.integer_ring import ZZ + from sage.rings.rational_field import QQ s = QQ.coerce(s) if s not in self.value_semigroup(): raise ValueError("s must be in the value semigroup of this valuation but %r is not in %r"%(s, self.value_semigroup())) diff --git a/src/sage/schemes/affine/affine_rational_point.py b/src/sage/schemes/affine/affine_rational_point.py index 122103dacc4..513b5d67aa0 100644 --- a/src/sage/schemes/affine/affine_rational_point.py +++ b/src/sage/schemes/affine/affine_rational_point.py @@ -51,7 +51,8 @@ # http://www.gnu.org/licenses/ #***************************************************************************** -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.misc.all import cartesian_product_iterator from sage.schemes.generic.scheme import is_Scheme diff --git a/src/sage/schemes/berkovich/berkovich_cp_element.py b/src/sage/schemes/berkovich/berkovich_cp_element.py index 9c730a31626..ef419c0b50a 100644 --- a/src/sage/schemes/berkovich/berkovich_cp_element.py +++ b/src/sage/schemes/berkovich/berkovich_cp_element.py @@ -34,7 +34,7 @@ # ***************************************************************************** from sage.structure.element import Element -from sage.symbolic.expression import is_Expression +from sage.structure.element import Expression from sage.rings.real_mpfr import RR, is_RealNumber from sage.rings.padics.padic_generic_element import pAdicGenericElement from sage.rings.padics.padic_base_generic import pAdicBaseGeneric @@ -118,16 +118,16 @@ def __init__(self, parent, center, radius=None, power=None, prec=20, space_type= # check if the radius and the center are functions center_func_check = is_FunctionFieldElement(center) or is_Polynomial(center) or\ - isinstance(center, FractionFieldElement_1poly_field) or is_Expression(center) + isinstance(center, FractionFieldElement_1poly_field) or isinstance(center, Expression) radius_func_check = is_FunctionFieldElement(radius) or is_Polynomial(radius) or\ - isinstance(radius, FractionFieldElement_1poly_field) or is_Expression(radius) + isinstance(radius, FractionFieldElement_1poly_field) or isinstance(radius, Expression) if center_func_check: # check that both center and radii are supported univariate function center_expr_check = False radius_expr_check = False if error_check: - if is_Expression(center): + if isinstance(center, Expression): if len(center.variables()) != 1: raise ValueError("an expression with %s " % (len(center.variables())) + "variables cannot define the centers approximating a type IV point") @@ -136,16 +136,16 @@ def __init__(self, parent, center, radius=None, power=None, prec=20, space_type= center_expr_check = True if not radius_func_check: raise TypeError("center was passed a function but radius was not a function") - if is_Expression(radius): + if isinstance(radius, Expression): if len(radius.variables()) != 1: raise ValueError("an expression with %s " % (len(radius.variables())) + "variables cannot define the radii approximating a type IV point") else: radius_expr_check = True else: - if is_Expression(center): + if isinstance(center, Expression): center_expr_check = True - if is_Expression(radius): + if isinstance(radius, Expression): radius_expr_check = True self._type = 4 self._prec = prec @@ -216,7 +216,7 @@ def __init__(self, parent, center, radius=None, power=None, prec=20, space_type= center.normalize_coordinates() # make sure the radius coerces into the reals if not is_RealNumber(radius): - if is_Expression(radius): + if isinstance(radius, Expression): radius = RR(radius) elif RR.has_coerce_map_from(radius.parent()): radius = RR(radius) @@ -259,7 +259,7 @@ def __init__(self, parent, center, radius=None, power=None, prec=20, space_type= raise ValueError('could not convert %s to %s' % (center, self._base_space)) # make sure the radius coerces into the reals if not is_RealNumber(radius): - if is_Expression(radius): + if isinstance(radius, Expression): radius = RR(radius) elif RR.has_coerce_map_from(radius.parent()): radius = RR(radius) @@ -375,7 +375,7 @@ def __init__(self, parent, center, radius=None, power=None, prec=20, space_type= self._type = 2 return if radius is not None: - if is_Expression(radius): + if isinstance(radius, Expression): try: power = QQ(radius.log(self._p).expand_log()) except TypeError: @@ -659,7 +659,7 @@ def diameter(self, basepoint=Infinity): from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing R = PolynomialRing(QQ, names="x") x = R.gens()[0] - if is_Expression(self._radius_func): + if isinstance(self._radius_func, Expression): radius_func_variable = self._radius_func.variables()[0] radius_expr = self._radius_func.subs({radius_func_variable: x}) else: diff --git a/src/sage/schemes/elliptic_curves/constructor.py b/src/sage/schemes/elliptic_curves/constructor.py index e9320cc174b..90bc4519082 100644 --- a/src/sage/schemes/elliptic_curves/constructor.py +++ b/src/sage/schemes/elliptic_curves/constructor.py @@ -25,7 +25,7 @@ import sage.rings.all as rings -from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing +import sage.rings.abc from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing from sage.rings.finite_rings.finite_field_constructor import is_FiniteField from sage.rings.number_field.number_field import is_NumberField @@ -464,7 +464,7 @@ def create_object(self, version, key, **kwds): elif rings.is_pAdicField(R): from .ell_padic_field import EllipticCurve_padic_field return EllipticCurve_padic_field(R, x) - elif is_FiniteField(R) or (is_IntegerModRing(R) and R.characteristic().is_prime()): + elif is_FiniteField(R) or (isinstance(R, sage.rings.abc.IntegerModRing) and R.characteristic().is_prime()): from .ell_finite_field import EllipticCurve_finite_field return EllipticCurve_finite_field(R, x) elif R in _Fields: diff --git a/src/sage/schemes/elliptic_curves/ell_field.py b/src/sage/schemes/elliptic_curves/ell_field.py index d11395872c2..0013cf1938a 100644 --- a/src/sage/schemes/elliptic_curves/ell_field.py +++ b/src/sage/schemes/elliptic_curves/ell_field.py @@ -13,8 +13,7 @@ #***************************************************************************** import sage.rings.all as rings -from sage.rings.complex_mpfr import is_ComplexField -from sage.rings.real_mpfr import is_RealField +import sage.rings.abc from sage.schemes.elliptic_curves.ell_point import EllipticCurvePoint_field from sage.schemes.curves.projective_curve import ProjectivePlaneCurve_field @@ -1069,9 +1068,9 @@ def isogenies_prime_degree(self, l=None, max_l=31): ValueError: 4 is not prime. """ F = self.base_ring() - if is_RealField(F): + if isinstance(F, sage.rings.abc.RealField): raise NotImplementedError("This code could be implemented for general real fields, but has not been yet.") - if is_ComplexField(F): + if isinstance(F, sage.rings.abc.ComplexField): raise NotImplementedError("This code could be implemented for general complex fields, but has not been yet.") if F is rings.QQbar: raise NotImplementedError("This code could be implemented for QQbar, but has not been yet.") diff --git a/src/sage/schemes/elliptic_curves/ell_generic.py b/src/sage/schemes/elliptic_curves/ell_generic.py index 912496bca28..b5207f513f0 100644 --- a/src/sage/schemes/elliptic_curves/ell_generic.py +++ b/src/sage/schemes/elliptic_curves/ell_generic.py @@ -46,6 +46,7 @@ import math +import sage.rings.abc from sage.rings.all import PolynomialRing from sage.rings.polynomial.polynomial_ring import polygen, polygens import sage.groups.additive_abelian.additive_abelian_group as groups @@ -156,8 +157,7 @@ def __init__(self, K, ainvs): # EllipticCurvePoint_finite_field for finite rings, so that we # can do some arithmetic on points over Z/NZ, for teaching # purposes. - from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing - if is_IntegerModRing(K): + if isinstance(K, sage.rings.abc.IntegerModRing): self._point = ell_point.EllipticCurvePoint_finite_field _point = ell_point.EllipticCurvePoint diff --git a/src/sage/schemes/elliptic_curves/ell_number_field.py b/src/sage/schemes/elliptic_curves/ell_number_field.py index 76929fef275..576e670d0eb 100644 --- a/src/sage/schemes/elliptic_curves/ell_number_field.py +++ b/src/sage/schemes/elliptic_curves/ell_number_field.py @@ -85,6 +85,7 @@ # https://www.gnu.org/licenses/ # **************************************************************************** +import sage.rings.abc from .ell_field import EllipticCurve_field from .ell_generic import is_EllipticCurve from .ell_point import EllipticCurvePoint_number_field @@ -2612,11 +2613,10 @@ def real_components(self, embedding): ... ValueError: invalid embedding specified: should have domain ... """ - from sage.rings.real_mpfr import is_RealField try: if not embedding.domain() is self.base_field(): raise ValueError("invalid embedding specified: should have domain {}".format(self.base_field())) - if not is_RealField(embedding.codomain()): + if not isinstance(embedding.codomain(), sage.rings.abc.RealField): raise ValueError("invalid embedding specified: should be real") except AttributeError: raise ValueError("invalid embedding") diff --git a/src/sage/schemes/elliptic_curves/ell_point.py b/src/sage/schemes/elliptic_curves/ell_point.py index 7edafee118a..63b027eae62 100644 --- a/src/sage/schemes/elliptic_curves/ell_point.py +++ b/src/sage/schemes/elliptic_curves/ell_point.py @@ -125,7 +125,7 @@ from sage.rings.padics.precision_error import PrecisionError import sage.rings.all as rings -from sage.rings.real_mpfr import is_RealField +import sage.rings.abc from sage.rings.integer import Integer from sage.rings.integer_ring import ZZ import sage.groups.generic as generic @@ -2219,7 +2219,7 @@ def is_on_identity_component(self, embedding=None): e = embedding # It is also trivially true if we have a complex embedding if e is not None: - if not is_RealField(e.codomain()): + if not isinstance(e.codomain(), sage.rings.abc.RealField): return True # find a suitable embedding if none was supplied: @@ -2232,7 +2232,7 @@ def is_on_identity_component(self, embedding=None): e = K.embeddings(rings.ComplexField())[0] # If there is only one component, the result is True: - if not is_RealField(e.codomain()): # complex embedding + if not isinstance(e.codomain(), sage.rings.abc.RealField): # complex embedding return True if e(E.discriminant()) < 0: # only one component return True @@ -3237,7 +3237,7 @@ def elliptic_logarithm(self, embedding=None, precision=100, L = E.period_lattice(emb) - if algorithm == 'sage' or not is_RealField(emb.codomain): + if algorithm == 'sage' or not isinstance(emb.codomain, sage.rings.abc.RealField): return L.elliptic_logarithm(self, precision) if algorithm != 'pari': diff --git a/src/sage/schemes/elliptic_curves/ell_torsion.py b/src/sage/schemes/elliptic_curves/ell_torsion.py index 33265f11d7d..5e1795f088f 100644 --- a/src/sage/schemes/elliptic_curves/ell_torsion.py +++ b/src/sage/schemes/elliptic_curves/ell_torsion.py @@ -320,7 +320,8 @@ def torsion_bound(E, number_of_places=20): sage: E.torsion_subgroup().invariants() (4, 4) """ - from sage.rings.all import ZZ, GF + from sage.rings.integer_ring import ZZ + from sage.rings.finite_rings.finite_field_constructor import GF from sage.schemes.elliptic_curves.constructor import EllipticCurve K = E.base_field() diff --git a/src/sage/schemes/elliptic_curves/gp_simon.py b/src/sage/schemes/elliptic_curves/gp_simon.py index d1d45aa7c3d..fd68549b118 100644 --- a/src/sage/schemes/elliptic_curves/gp_simon.py +++ b/src/sage/schemes/elliptic_curves/gp_simon.py @@ -21,7 +21,8 @@ from sage.interfaces.gp import Gp from sage.misc.sage_eval import sage_eval from sage.misc.randstate import current_randstate -from sage.rings.all import QQ, ZZ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ gp = None diff --git a/src/sage/schemes/elliptic_curves/isogeny_class.py b/src/sage/schemes/elliptic_curves/isogeny_class.py index 94d99a82ec5..174359868b3 100644 --- a/src/sage/schemes/elliptic_curves/isogeny_class.py +++ b/src/sage/schemes/elliptic_curves/isogeny_class.py @@ -28,7 +28,8 @@ from sage.structure.sage_object import SageObject from sage.structure.richcmp import richcmp_method, richcmp import sage.databases.cremona -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.misc.all import flatten, cached_method from sage.schemes.elliptic_curves.ell_field import EllipticCurve_field from sage.schemes.elliptic_curves.ell_number_field import EllipticCurve_number_field diff --git a/src/sage/schemes/elliptic_curves/isogeny_small_degree.py b/src/sage/schemes/elliptic_curves/isogeny_small_degree.py index 6be7af72487..887f84bde65 100644 --- a/src/sage/schemes/elliptic_curves/isogeny_small_degree.py +++ b/src/sage/schemes/elliptic_curves/isogeny_small_degree.py @@ -32,7 +32,8 @@ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.rings.polynomial.polynomial_ring import polygen -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.schemes.elliptic_curves.all import EllipticCurve from sage.misc.cachefunc import cached_function diff --git a/src/sage/schemes/elliptic_curves/padic_lseries.py b/src/sage/schemes/elliptic_curves/padic_lseries.py index 3506a565459..d462d6c7151 100644 --- a/src/sage/schemes/elliptic_curves/padic_lseries.py +++ b/src/sage/schemes/elliptic_curves/padic_lseries.py @@ -841,6 +841,20 @@ def series(self, n=2, quadratic_twist=+1, prec=5, eta=0): sage: lp = E.padic_lseries(2) sage: lp.series(6) 2^2 + 2^6 + O(2^7) + (2 + O(2^4))*T + O(2^3)*T^2 + (2^2 + O(2^3))*T^3 + (2 + O(2^2))*T^4 + O(T^5) + + Check that twists by odd Teichmuller characters are ok (:trac:`32258`):: + + sage: E = EllipticCurve("443c1") + sage: lp = E.padic_lseries(17, implementation="num") + sage: l8 = lp.series(2,eta=8,prec=3) + sage: l8.list()[0] - 1/lp.alpha() + O(17^4) + sage: lp = E.padic_lseries(2, implementation="num") + sage: l1 = lp.series(8,eta=1,prec=3) + sage: l1.list()[0] - 4/lp.alpha()^2 + O(2^9) + + """ n = ZZ(n) if n < 1: @@ -851,7 +865,7 @@ def series(self, n=2, quadratic_twist=+1, prec=5, eta=0): raise ValueError("Insufficient precision (%s)" % prec) # check if the conditions on quadratic_twist are satisfied - eta = ZZ(eta) % (self._p - 1) + eta = ZZ(eta) % (self._p- 1) if self._p != 2 else ZZ(eta) % 2 D = ZZ(quadratic_twist) if D != 1: if eta != 0: @@ -870,6 +884,7 @@ def series(self, n=2, quadratic_twist=+1, prec=5, eta=0): if valuation(self._E.conductor(), ell) > valuation(D, ell): raise ValueError("cannot twist a curve of conductor (=%s) by the quadratic twist (=%s)."%(self._E.conductor(),D)) p = self._p + si = 1-2*(eta % 2) #verbose("computing L-series for p=%s, n=%s, and prec=%s"%(p,n,prec)) @@ -891,17 +906,9 @@ def series(self, n=2, quadratic_twist=+1, prec=5, eta=0): return L else: # here we need some sums anyway - if eta % 2 == 1: - si = ZZ(-1) - else: - si = ZZ(1) bounds = self._prec_bounds(n,prec,sign=si) padic_prec = 20 else: - if eta % 2 == 1: - si = ZZ(-1) - else: - si = ZZ(1) bounds = self._prec_bounds(n,prec,sign=si) padic_prec = max(bounds[1:]) + 5 @@ -926,7 +933,7 @@ def series(self, n=2, quadratic_twist=+1, prec=5, eta=0): gamma_power = K(1) teich = self.teichmuller(padic_prec) if p == 2: - teich = [0, 1,-1] + teich = [0, 1, -1] gamma = K(5) p_power = 2**(n-2) a_range = 3 @@ -935,7 +942,6 @@ def series(self, n=2, quadratic_twist=+1, prec=5, eta=0): gamma = K(1+ p) p_power = p**(n-1) a_range = p - si = 1-2*(eta % 2) verbose("Now iterating over %s summands"%((p-1)*p_power)) verbose_level = get_verbose() @@ -964,7 +970,9 @@ def series(self, n=2, quadratic_twist=+1, prec=5, eta=0): [aj[j].add_bigoh(bounds[j]) for j in range(1,len(aj))] L = R(aj,res_series_prec ) - L /= self._quotient_of_periods_to_twist(D)*self._E.real_components() + L /= self._quotient_of_periods_to_twist(D) + if si == +1: + L /= self._E.real_components() self._set_series_in_cache(n, res_series_prec, D, eta, L) @@ -1226,9 +1234,7 @@ def series(self, n=3, quadratic_twist=+1, prec=5, eta=0): raise ValueError("cannot twist a curve of conductor (=%s) by the quadratic twist (=%s)." % (self._E.conductor(), D)) p = self._p - eta = ZZ(eta) % (p - 1) - #if p == 2 and self._normalize: - #print('Warning : for p = 2 the normalization might not be correct !') + eta = ZZ(eta) % (p - 1) if p != 2 else ZZ(eta) % 2 if prec == 1: if eta == 0: @@ -1306,7 +1312,9 @@ def series(self, n=3, quadratic_twist=+1, prec=5, eta=0): bj.append( aj[j].add_bigoh(bounds[j]) ) j += 1 L = R(bj, prec) - L /= self._quotient_of_periods_to_twist(D)*self._E.real_components() + L /= self._quotient_of_periods_to_twist(D) + if si == +1: + L /= self._E.real_components() self._set_series_in_cache(n, prec, quadratic_twist, eta, L) return L diff --git a/src/sage/schemes/elliptic_curves/period_lattice.py b/src/sage/schemes/elliptic_curves/period_lattice.py index 1fcb6a3e1a4..8ecd30c848c 100644 --- a/src/sage/schemes/elliptic_curves/period_lattice.py +++ b/src/sage/schemes/elliptic_curves/period_lattice.py @@ -100,8 +100,8 @@ from sage.modules.free_module import FreeModule_generic_pid from sage.rings.all import ZZ, QQ, RealField, ComplexField, QQbar, AA -from sage.rings.real_mpfr import is_RealField -from sage.rings.complex_mpfr import ComplexNumber, is_ComplexField +import sage.rings.abc +from sage.rings.complex_mpfr import ComplexNumber from sage.rings.real_mpfr import RealNumber as RealNumber from sage.rings.number_field.number_field import refine_embedding from sage.rings.infinity import Infinity @@ -1169,11 +1169,11 @@ def coordinates(self, z, rounding=None): (12, 23) """ C = z.parent() - if is_RealField(C): + if isinstance(C, sage.rings.abc.RealField): C = ComplexField(C.precision()) z = C(z) else: - if is_ComplexField(C): + if isinstance(C, sage.rings.abc.ComplexField): pass else: try: @@ -1233,10 +1233,10 @@ def reduce(self, z): 0.958696500380444 """ C = z.parent() - if is_RealField(C): + if isinstance(C, sage.rings.abc.RealField): C = ComplexField(C.precision()) z = C(z) - elif is_ComplexField(C): + elif isinstance(C, sage.rings.abc.ComplexField): pass else: try: @@ -1789,12 +1789,12 @@ def elliptic_exponential(self, z, to_curve=True): """ C = z.parent() z_is_real = False - if is_RealField(C): + if isinstance(C, sage.rings.abc.RealField): z_is_real = True C = ComplexField(C.precision()) z = C(z) else: - if is_ComplexField(C): + if isinstance(C, sage.rings.abc.ComplexField): z_is_real = z.is_real() else: try: diff --git a/src/sage/schemes/plane_conics/con_field.py b/src/sage/schemes/plane_conics/con_field.py index 04ee419f880..0d5eb412034 100644 --- a/src/sage/schemes/plane_conics/con_field.py +++ b/src/sage/schemes/plane_conics/con_field.py @@ -26,8 +26,7 @@ from sage.rings.all import PolynomialRing -from sage.rings.complex_mpfr import is_ComplexField -from sage.rings.real_mpfr import is_RealField +import sage.rings.abc from sage.modules.free_module_element import vector from sage.structure.sequence import Sequence @@ -517,7 +516,7 @@ def has_rational_point(self, point = False, if algorithm != 'default': raise ValueError("Unknown algorithm: %s" % algorithm) - if is_ComplexField(B): + if isinstance(B, sage.rings.abc.ComplexField): if point: [_,_,_,d,e,f] = self._coefficients if d == 0: @@ -525,7 +524,7 @@ def has_rational_point(self, point = False, return True, self.point([0, ((e**2-4*d*f).sqrt()-e)/(2*d), 1], check = False) return True - if is_RealField(B): + if isinstance(B, sage.rings.abc.RealField): D, T = self.diagonal_matrix() [a, b, c] = [D[0,0], D[1,1], D[2,2]] if a == 0: diff --git a/src/sage/schemes/plane_conics/con_rational_field.py b/src/sage/schemes/plane_conics/con_rational_field.py index e8b1d824cbd..d24bd59898c 100644 --- a/src/sage/schemes/plane_conics/con_rational_field.py +++ b/src/sage/schemes/plane_conics/con_rational_field.py @@ -26,7 +26,7 @@ from sage.rings.all import (PolynomialRing, ZZ, QQ) -from sage.rings.real_mpfr import is_RealField +import sage.rings.abc from sage.structure.sequence import Sequence from sage.schemes.projective.projective_space import ProjectiveSpace @@ -230,11 +230,11 @@ def is_locally_solvable(self, p) -> bool: return True a = -abc[0] / abc[2] b = -abc[1] / abc[2] - if is_RealField(p) or isinstance(p, InfinityElement): + if isinstance(p, sage.rings.abc.RealField) or isinstance(p, InfinityElement): p = -1 elif isinstance(p, Map) and p.category_for().is_subcategory(Rings()): # p is a morphism of Rings - if p.domain() is QQ and is_RealField(p.codomain()): + if p.domain() is QQ and isinstance(p.codomain(), sage.rings.abc.RealField): p = -1 else: raise TypeError("p (=%s) needs to be a prime of base field " diff --git a/src/sage/schemes/projective/projective_space.py b/src/sage/schemes/projective/projective_space.py index 14bf23cac43..82763ef7344 100644 --- a/src/sage/schemes/projective/projective_space.py +++ b/src/sage/schemes/projective/projective_space.py @@ -106,6 +106,7 @@ from sage.combinat.permutation import Permutation from sage.combinat.tuple import Tuples from sage.combinat.tuple import UnorderedTuples +from sage.combinat.subset import Subsets from sage.matrix.constructor import matrix from sage.modules.free_module_element import prepare from sage.schemes.generic.ambient_space import AmbientSpace @@ -1531,7 +1532,7 @@ def hyperplane_transformation_matrix(self, plane_1, plane_2): Return a PGL element sending ``plane_1`` to ``plane_2``. ``plane_1`` and ``plane_2`` must be hyperplanes (subschemes of - codimension 1, each defined by a single linear homogenous equation). + codimension 1, each defined by a single linear homogeneous equation). INPUT: @@ -1706,6 +1707,101 @@ def hyperplane_transformation_matrix(self, plane_1, plane_2): points.append(source_points) return self.point_transformation_matrix(points[0], points[1]) + def is_linearly_independent(self, points, n=None): + r""" + Return whether the set of points is linearly independent. + + Alternatively, specify ``n`` to check if every subset of + size ``n`` is linearly independent. + + INPUT: + + - ``points`` -- a list of points in this projective space. + + - ``n`` -- (Optional) A positive integer less than or equal to the length + of ``points``. Specifies the size of the subsets to check for + linear independence. + + OUTPUT: + + - ``True`` if ``points`` is linearly independent, ``False`` otherwise. + + EXAMPLES:: + + sage: P. = ProjectiveSpace(QQ, 2) + sage: points = [P((1, 0, 1)), P((1, 2, 1)), P((1, 3, 4))] + sage: P.is_linearly_independent(points) + True + + :: + + sage: P. = ProjectiveSpace(GF(5), 2) + sage: points = [P((1, 0, 1)), P((1, 2, 1)), P((1, 3, 4)), P((0, 0 ,1))] + sage: P.is_linearly_independent(points, 2) + True + + :: + + sage: R. = QQ[] + sage: P. = ProjectiveSpace(R, 2) + sage: points = [P((c, 0, 1)), P((0, c, 1)), P((1, 0, 4)), P((0, 0 ,1))] + sage: P.is_linearly_independent(points, 3) + False + + :: + + sage: R. = QQ[] + sage: P. = ProjectiveSpace(FractionField(R), 2) + sage: points = [P((c, 0, 1)), P((0, c, 1)), P((1, 3, 4)), P((0, 0 ,1))] + sage: P.is_linearly_independent(points, 3) + True + + :: + + sage: K. = CyclotomicField(3) + sage: P. = ProjectiveSpace(K, 2) + sage: points = [P((k, k^2, 1)), P((0, k, 1)), P((1, 0, 4)), P((0, 0 ,1))] + sage: P.is_linearly_independent(points, 3) + True + + :: + + sage: P. = ProjectiveSpace(QQ, 1) + sage: points = [P((1, 0)), P((1, 1))] + sage: P.is_linearly_independent(points) + True + + TESTS:: + + sage: points = [P(1, 0), P(1, 1), P(2, 1)] + sage: P.is_linearly_independent(points, 5) + Traceback (most recent call last): + ... + ValueError: n must be a non negative integer not greater than the length of points + """ + if not isinstance(points, list): + raise TypeError("points must be a list") + if any(not isinstance(point, SchemeMorphism_point_projective_ring) for point in points): + raise TypeError("points must be a list of projective points") + if any(x.codomain() != self for x in points): + raise ValueError("points not in this projective space") + if n is None: + M = matrix([list(t) for t in points]) + return M.rank() == len(points) + n = Integer(n) + if n < 1 or n > len(points): + raise ValueError('n must be a non negative integer not greater than the length of points') + all_subsets = Subsets(range(len(points)), n) + linearly_independent = True + for subset in all_subsets: + point_list = [] + for index in subset: + point_list.append(list(points[index])) + M = matrix(point_list) + if M.rank() != n: + linearly_independent = False + break + return linearly_independent class ProjectiveSpace_field(ProjectiveSpace_ring): def _point_homset(self, *args, **kwds): diff --git a/src/sage/schemes/toric/chow_group.py b/src/sage/schemes/toric/chow_group.py index 84d32fe373e..34deb208d74 100644 --- a/src/sage/schemes/toric/chow_group.py +++ b/src/sage/schemes/toric/chow_group.py @@ -110,7 +110,6 @@ sage: sum( mixed.project_to_degree(i) for i in range(X.dimension()+1) ) == mixed True """ - # **************************************************************************** # Copyright (C) 2010 Volker Braun # @@ -118,6 +117,7 @@ # # https://www.gnu.org/licenses/ # **************************************************************************** +from __future__ import annotations from sage.misc.all import flatten from sage.misc.fast_methods import WithEqualityById @@ -133,9 +133,6 @@ from sage.schemes.toric.divisor import is_ToricDivisor - - -#******************************************************************* class ChowCycle(FGP_Element): """ The elements of the Chow group. @@ -158,7 +155,6 @@ class ChowCycle(FGP_Element): sage: A( Cone([(1,0)]) ) ( 0 | 1 | 0 ) """ - def __init__(self, parent, v, check=True): r""" Construct a :class:`ChowCycle`. @@ -184,7 +180,7 @@ def __init__(self, parent, v, check=True): """ FGP_Element.__init__(self, parent, v, check) - def _repr_(self): + def _repr_(self) -> str: r""" Return a string representation of the Chow cycle. @@ -230,7 +226,7 @@ def _repr_(self): s += ')' return s - def degree(self): + def degree(self) -> int: r""" The degree of the Chow cycle. @@ -253,14 +249,13 @@ def degree(self): ambient_dim = self.parent()._variety.dimension() cone_dim = None for i, cone in enumerate(self.parent()._cones): - if self.lift()[i]!=0: - if cone_dim not in [None,cone.dim()]: + if self.lift()[i] != 0: + if cone_dim not in [None, cone.dim()]: raise ValueError('Chow cycle is not of definite degree.') cone_dim = cone.dim() self._dim = ambient_dim - cone_dim return self._dim - def project_to_degree(self, degree): r""" Project a (mixed-degree) Chow cycle to the given ``degree``. @@ -287,13 +282,12 @@ def project_to_degree(self, degree): v = list(self.lift()) for i in range(len(v)): cone = self.parent()._cones[i] - if cone.dim() != ambient_dim-degree: + if cone.dim() != ambient_dim - degree: v[i] = 0 v = self.parent().cover()(v) P = self.parent() return P.element_class(P, v, check=False) - def count_points(self): r""" Return the number of points in the Chow cycle. @@ -340,9 +334,7 @@ def count_points(self): sage: P1xP1_Z2.integrate( Dt.cohomology_class() * Dy.cohomology_class() ) 1/2 """ - c0 = self.project_to_degree(0).lift() - return sum(c0) - + return sum(self.project_to_degree(0).lift()) def intersection_with_divisor(self, divisor): """ @@ -413,7 +405,7 @@ def intersection_with_divisor(self, divisor): (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)] """ - assert is_ToricDivisor(divisor), str(divisor)+' is not a toric divisor.' + assert is_ToricDivisor(divisor), f'{divisor} is not a toric divisor' A = self.parent() # the Chow group X = A._variety # the toric variety @@ -421,11 +413,11 @@ def intersection_with_divisor(self, divisor): coefficients = self.lift() for sigma_idx, sigma in enumerate(A._cones): - if sigma.dim()==X.dimension(): + if sigma.dim() == X.dimension(): # full-dimensional cone = degree-0 Chow cycle continue coefficient = coefficients[sigma_idx] - if coefficient==0: + if coefficient == 0: continue D = divisor.move_away_from(sigma) for gamma in sigma.facet_of(): @@ -436,13 +428,11 @@ def intersection_with_divisor(self, divisor): i = I_gamma.pop() # index of a ray in gamma but not sigma v_i = X.fan().ray(i) a_i = D.coefficient(i) - s_i = (v_i*perp)/(n*perp) - b_gamma = a_i/s_i - # print sigma._points_idx, "\t", i, D, a_i, s_i, b_gamma, gamma.A() - intersection += self.base_ring()(coefficient*b_gamma) * A(gamma) + s_i = (v_i * perp) / (n * perp) + b_gamma = a_i / s_i + intersection += self.base_ring()(coefficient * b_gamma) * A(gamma) return intersection - def cohomology_class(self): r""" Return the (Poincaré-dual) cohomology class. @@ -523,13 +513,13 @@ def cohomology_class(self): """ toric_variety = self.parent().scheme() if not toric_variety.is_orbifold(): - raise ValueError + raise ValueError('not an orbifold') HH = toric_variety.cohomology_ring() coeff = self.lift() - return sum([ HH(cone) * coeff[i] for i,cone in enumerate(self.parent()._cones) ]) + return sum([HH(cone) * coeff[i] + for i, cone in enumerate(self.parent()._cones)]) -#******************************************************************* class ChowGroupFactory(UniqueFactory): """ Factory for :class:`ChowGroup_class`. @@ -558,14 +548,13 @@ def create_key_and_extra_args(self, toric_variety, base_ring=ZZ, check=True): if not is_ToricVariety(toric_variety): raise ValueError('First argument must be a toric variety.') - if not base_ring in [ZZ,QQ]: + if base_ring not in [ZZ, QQ]: raise ValueError('Base ring must be either ZZ or QQ.') key = tuple([toric_variety, base_ring]) - extra = {'check':check} + extra = {'check': check} return key, extra - def create_object(self, version, key, **extra_args): """ Create a :class:`ChowGroup_class`. @@ -593,21 +582,19 @@ def create_object(self, version, key, **extra_args): ChowGroup = ChowGroupFactory('ChowGroup') -#******************************************************************* class ChowGroup_class(FGP_Module_class, WithEqualityById): r""" The Chow group of a toric variety. EXAMPLES:: - sage: P2=toric_varieties.P2() + sage: P2 = toric_varieties.P2() sage: from sage.schemes.toric.chow_group import ChowGroup_class sage: A = ChowGroup_class(P2,ZZ,True); A Chow group of 2-d CPR-Fano toric variety covered by 3 affine patches sage: A.an_element() ( 0 | 0 | 1 ) """ - Element = ChowCycle def __init__(self, toric_variety, base_ring, check): @@ -615,7 +602,7 @@ def __init__(self, toric_variety, base_ring, check): EXAMPLES:: sage: from sage.schemes.toric.chow_group import * - sage: P2=toric_varieties.P2() + sage: P2 = toric_varieties.P2() sage: A = ChowGroup_class(P2,ZZ,True); A Chow group of 2-d CPR-Fano toric variety covered by 3 affine patches sage: is_ChowGroup(A) @@ -639,7 +626,7 @@ def __init__(self, toric_variety, base_ring, check): sage: print(coercion_model.get_action(A_ZZ, QQ)) None - You can't multiply integer classes with fractional + You cannot multiply integer classes with fractional numbers. For that you need to go to the rational Chow group:: sage: A_QQ = P2.Chow_group(QQ) @@ -657,13 +644,12 @@ def __init__(self, toric_variety, base_ring, check): self._variety = toric_variety # cones are automatically sorted by dimension - self._cones = flatten( toric_variety.fan().cones() ) + self._cones = flatten(toric_variety.fan().cones()) V = FreeModule(base_ring, len(self._cones)) W = self._rational_equivalence_relations(V) - super(ChowGroup_class,self).__init__(V, W, check) - + super(ChowGroup_class, self).__init__(V, W, check) def scheme(self): r""" @@ -685,7 +671,6 @@ def scheme(self): """ return self._variety - def _element_constructor_(self, x, check=True): r""" Construct a :class:`ChowCycle`. @@ -716,15 +701,14 @@ def _element_constructor_(self, x, check=True): cone = fan.embed(x) return self.element_class(self, self._cone_to_V(cone), False) if is_ToricDivisor(x): - v = sum(x.coefficient(i)*self._cone_to_V(onecone) - for i,onecone in enumerate(fan(1))) + v = sum(x.coefficient(i) * self._cone_to_V(onecone) + for i, onecone in enumerate(fan(1))) return self.element_class(self, v, False) - return super(ChowGroup_class,self)._element_constructor_(x, check) - + return super(ChowGroup_class, self)._element_constructor_(x, check) def _coerce_map_from_(self, S): """ - Return true if S canonically coerces to self. + Return ``True`` if ``S`` canonically coerces to ``self``. EXAMPLES:: @@ -735,9 +719,8 @@ def _coerce_map_from_(self, S): False """ # We might want to coerce Cone_of_fans into ChowCycles - # but cones don't have parents at the moment. - return super(ChowGroup_class,self)._coerce_map_from_(S) - + # but cones do not have parents at the moment. + return super(ChowGroup_class, self)._coerce_map_from_(S) def _rational_equivalence_relations(self, V): r""" @@ -770,8 +753,8 @@ def _rational_equivalence_relations(self, V): for sigma in rho.facet_of(): sigma_idx = self._cones.index(sigma) Q = sigma.relative_quotient(rho) - for v in [n.lift() for n in Q.gens()]: - rel += (u * v) * V.gen(sigma_idx) + for n in Q.gens(): + rel += (u * n.lift()) * V.gen(sigma_idx) relations.append(rel) return V.span(relations) @@ -790,18 +773,17 @@ def __truediv__(self, other): sage: A/Asub Traceback (most recent call last): ... - NotImplementedError: Quotients of the Chow group are not implemented. + NotImplementedError: quotients of the Chow group are not implemented """ - raise NotImplementedError('Quotients of the Chow group are not implemented.') + raise NotImplementedError('quotients of the Chow group are not implemented') - - def _repr_(self): + def _repr_(self) -> str: """ Return a string representation. EXAMPLES:: - sage: P2=toric_varieties.P2() + sage: P2 = toric_varieties.P2() sage: from sage.schemes.toric.chow_group import ChowGroup sage: ChowGroup(P2,ZZ)._repr_() 'Chow group of 2-d CPR-Fano toric variety covered by 3 affine patches' @@ -840,7 +822,6 @@ def _cone_to_V(self, cone): x[self._cones.index(cone)] = 1 return self._V(x) - def degree(self, k=None): r""" Return the degree-`k` Chow group. @@ -939,11 +920,10 @@ def degree(self, k=None): except AttributeError: pass - self._degree = tuple(ChowGroup_degree_class(self,d) + self._degree = tuple(ChowGroup_degree_class(self, d) for d in range(self._variety.dimension() + 1)) return self._degree - def coordinate_vector(self, chow_cycle, degree=None, reduce=True): r""" Return the coordinate vector of the ``chow_cycle``. @@ -981,7 +961,6 @@ def coordinate_vector(self, chow_cycle, degree=None, reduce=True): a = chow_cycle.project_to_degree(degree) return self.degree(degree).module().coordinate_vector(a, reduce=reduce) - def gens(self, degree=None): r""" Return the generators of the Chow group. @@ -1012,7 +991,6 @@ def gens(self, degree=None): else: return self.degree(degree).gens() - def relation_gens(self): r""" Return the Chow cycles equivalent to zero. @@ -1044,7 +1022,6 @@ def relation_gens(self): A tuple of Chow cycles, each rationally equivalent to zero, that generates the rational equivalence. - EXAMPLES:: sage: P2 = toric_varieties.P2() @@ -1057,11 +1034,9 @@ def relation_gens(self): sage: first.lift() (0, 1, 0, -1, 0, 0, 0) """ - gens = self.W().gens() - return tuple( self(gen) for gen in gens ) + return tuple(self(gen) for gen in self.W().gens()) -#******************************************************************* class ChowGroup_degree_class(SageObject): r""" A fixed-degree subgroup of the Chow group of a toric variety. @@ -1119,11 +1094,10 @@ def __init__(self, A, d): # The minimal set of generators self._module = A.submodule(gens) - self._gens = tuple([ A.element_class(A, a.lift(), False) - for a in self._module.gens() ]) - + self._gens = tuple([A.element_class(A, a.lift(), False) + for a in self._module.gens()]) - def _repr_(self): + def _repr_(self) -> str: """ Return a string representation. @@ -1153,7 +1127,7 @@ def _repr_(self): elif self._Chow_group.base_ring() is QQ: ring = 'Q' else: - raise NotImplementedError('Base ring must be ZZ or QQ.') + raise NotImplementedError('base ring must be ZZ or QQ') s = ['C' + str(x) for x in tors] if len(free) == 1: @@ -1179,7 +1153,7 @@ def module(self): """ return self._module - def ngens(self): + def ngens(self) -> int: """ Return the number of generators. @@ -1238,8 +1212,7 @@ def gens(self): return self._gens -#******************************************************************* -def is_ChowGroup(x): +def is_ChowGroup(x) -> bool: r""" Return whether ``x`` is a :class:`ChowGroup_class` @@ -1261,11 +1234,10 @@ def is_ChowGroup(x): sage: is_ChowGroup('Victoria') False """ - return isinstance(x,ChowGroup_class) + return isinstance(x, ChowGroup_class) -#******************************************************************* -def is_ChowCycle(x): +def is_ChowCycle(x) -> bool: r""" Return whether ``x`` is a :class:`ChowGroup_class` @@ -1279,7 +1251,7 @@ def is_ChowCycle(x): EXAMPLES:: - sage: P2=toric_varieties.P2() + sage: P2 = toric_varieties.P2() sage: A = P2.Chow_group() sage: from sage.schemes.toric.chow_group import * sage: is_ChowCycle(A) @@ -1289,4 +1261,4 @@ def is_ChowCycle(x): sage: is_ChowCycle('Victoria') False """ - return isinstance(x,ChowCycle) + return isinstance(x, ChowCycle) diff --git a/src/sage/schemes/toric/divisor.py b/src/sage/schemes/toric/divisor.py index c9ba1d4edf9..0442d7999fd 100644 --- a/src/sage/schemes/toric/divisor.py +++ b/src/sage/schemes/toric/divisor.py @@ -176,7 +176,8 @@ from sage.modules.free_module_element import vector from sage.modules.free_module import (FreeModule_ambient_field, FreeModule_ambient_pid) -from sage.rings.all import QQ, ZZ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.schemes.generic.divisor import Divisor_generic from sage.schemes.generic.divisor_group import DivisorGroup_generic from sage.schemes.toric.divisor_class import ToricRationalDivisorClass diff --git a/src/sage/schemes/toric/ideal.py b/src/sage/schemes/toric/ideal.py index fc0c5ecde5c..20681b39896 100644 --- a/src/sage/schemes/toric/ideal.py +++ b/src/sage/schemes/toric/ideal.py @@ -135,7 +135,8 @@ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing from sage.misc.misc_c import prod from sage.matrix.constructor import matrix -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.rings.polynomial.multi_polynomial_ideal import MPolynomialIdeal diff --git a/src/sage/schemes/toric/library.py b/src/sage/schemes/toric/library.py index 7de2cd950bc..7b3509c2132 100644 --- a/src/sage/schemes/toric/library.py +++ b/src/sage/schemes/toric/library.py @@ -42,7 +42,8 @@ from sage.matrix.all import matrix, identity_matrix from sage.geometry.all import Fan, LatticePolytope, ToricLattice -from sage.rings.all import ZZ, QQ +from sage.rings.integer_ring import ZZ +from sage.rings.rational_field import QQ from sage.arith.all import gcd from sage.schemes.toric.variety import (DEFAULT_PREFIX, ToricVariety, diff --git a/src/sage/sets/condition_set.py b/src/sage/sets/condition_set.py index 757014ace6c..80ff63d2260 100644 --- a/src/sage/sets/condition_set.py +++ b/src/sage/sets/condition_set.py @@ -19,9 +19,12 @@ from sage.categories.enumerated_sets import EnumeratedSets from sage.misc.cachefunc import cached_method from sage.misc.misc import _stable_uniq -from sage.symbolic.expression import is_Expression -from sage.symbolic.callable import is_CallableSymbolicExpression -from sage.symbolic.ring import SR +from sage.structure.element import Expression + +try: + from sage.symbolic.callable import is_CallableSymbolicExpression +except ImportError: + is_CallableSymbolicExpression = lambda x: False from .set import Set, Set_base, Set_boolean_operators, Set_add_sub_operators @@ -165,10 +168,11 @@ def __classcall_private__(cls, universe, *predicates, vars=None, names=None, cat if vars is None: vars = predicate.args() callable_symbolic_predicates.append(predicate) - elif is_Expression(predicate): + elif isinstance(predicate, Expression): if names is None: raise TypeError('use callable symbolic expressions or provide variable names') if vars is None: + from sage.symbolic.ring import SR vars = tuple(SR.var(name) for name in names) callable_symbolic_predicates.append(predicate.function(*vars)) else: @@ -291,6 +295,7 @@ def arguments(self): sage: args[0].parent() Symbolic Ring """ + from sage.symbolic.ring import SR return SR.var(self.variable_names()) def _element_constructor_(self, *args, **kwds): diff --git a/src/sage/sets/disjoint_union_enumerated_sets.py b/src/sage/sets/disjoint_union_enumerated_sets.py index 7a6f604dc16..79e5954c561 100644 --- a/src/sage/sets/disjoint_union_enumerated_sets.py +++ b/src/sage/sets/disjoint_union_enumerated_sets.py @@ -21,7 +21,8 @@ from sage.categories.finite_enumerated_sets import FiniteEnumeratedSets from sage.categories.infinite_enumerated_sets import InfiniteEnumeratedSets from sage.rings.infinity import Infinity -from sage.misc.all import cached_method, lazy_attribute +from sage.misc.cachefunc import cached_method +from sage.misc.lazy_attribute import lazy_attribute from sage.structure.unique_representation import UniqueRepresentation class DisjointUnionEnumeratedSets(UniqueRepresentation, Parent): diff --git a/src/sage/stats/hmm/chmm.pyx b/src/sage/stats/hmm/chmm.pyx index 741f3a3efb1..e848ddee11a 100644 --- a/src/sage/stats/hmm/chmm.pyx +++ b/src/sage/stats/hmm/chmm.pyx @@ -903,7 +903,7 @@ cdef class GaussianHiddenMarkovModel(HiddenMarkovModel): sage: m = hmm.GaussianHiddenMarkovModel([[.1,.9],[.5,.5]], [(1,.5), (-1,3)], [.1,.9]) sage: v = m.sample(10) sage: l = stats.TimeSeries([m.baum_welch(v,max_iter=1)[0] for _ in range(len(v))]) - sage: all(l[i] <= l[i+1] for i in range(9)) + sage: all(l[i] <= l[i+1] + 0.0001 for i in range(9)) True sage: l # random [-20.1167, -17.7611, -16.9814, -16.9364, -16.9314, -16.9309, -16.9309, -16.9309, -16.9309, -16.9309] diff --git a/src/sage/stats/time_series.pyx b/src/sage/stats/time_series.pyx index 1f267685b69..234925fb478 100644 --- a/src/sage/stats/time_series.pyx +++ b/src/sage/stats/time_series.pyx @@ -2579,7 +2579,7 @@ def unpickle_time_series_v1(bytes v, Py_ssize_t n): sage: v = stats.TimeSeries([1,2,3]) sage: s = v.__reduce__()[1][0] sage: type(s) - + sage: sage.stats.time_series.unpickle_time_series_v1(s,3) [1.0000, 2.0000, 3.0000] sage: sage.stats.time_series.unpickle_time_series_v1(s+s,6) diff --git a/src/sage/structure/coerce_actions.pyx b/src/sage/structure/coerce_actions.pyx index 4f1c4cdf45b..82a5eaf356c 100644 --- a/src/sage/structure/coerce_actions.pyx +++ b/src/sage/structure/coerce_actions.pyx @@ -63,7 +63,7 @@ cdef class GenericAction(Action): sage: sage.structure.coerce_actions.GenericAction(QQ, Z6, True) Traceback (most recent call last): ... - NotImplementedError: action for not implemented + NotImplementedError: action for not implemented This will break if we tried to use it:: diff --git a/src/sage/structure/dynamic_class.py b/src/sage/structure/dynamic_class.py index 6ff4bc7990c..434c2968f8d 100644 --- a/src/sage/structure/dynamic_class.py +++ b/src/sage/structure/dynamic_class.py @@ -201,11 +201,11 @@ def dynamic_class(name, bases, cls=None, reduction=None, doccls=None, '__main__' sage: Foo.__bases__ - (,) + (,) sage: FooBar.__bases__ (,) sage: Foo.mro() - [, ] + [, ] sage: FooBar.mro() [, , ] @@ -238,7 +238,7 @@ class also has a zero ``__dictoffset__``. This means that the sage: BarFoo = dynamic_class("BarFoo", (Foo,), Bar, reduction = (str, (3,))) sage: type(BarFoo).__reduce__(BarFoo) - (, (3,)) + (, (3,)) sage: loads(dumps(BarFoo)) '3' @@ -280,7 +280,7 @@ class also has a zero ``__dictoffset__``. This means that the first class:: sage: dynamic_class("BarFoo", (Foo,), Bar, reduction = (str, (2,)), cache="ignore_reduction")._reduction - (, (3,)) + (, (3,)) .. WARNING:: @@ -502,7 +502,7 @@ def __reduce__(self): sage: C = sage.structure.dynamic_class.dynamic_class_internal("bla", (object,), Foo, doccls = DocClass) sage: type(C).__reduce__(C) (, - ('bla', (,), , None, )) + ('bla', (,), , None, )) sage: C = sage.structure.dynamic_class.dynamic_class_internal("bla", (object,), Foo, doccls = DocClass, reduction = "blah") sage: type(C).__reduce__(C) 'blah' diff --git a/src/sage/structure/element.pxd b/src/sage/structure/element.pxd index 3cc480aa18c..5c6e295a4b8 100644 --- a/src/sage/structure/element.pxd +++ b/src/sage/structure/element.pxd @@ -236,9 +236,11 @@ cdef class AlgebraElement(RingElement): cdef class CommutativeAlgebraElement(CommutativeRingElement): pass -cdef class InfinityElement(RingElement): +cdef class Expression(CommutativeRingElement): pass +cdef class InfinityElement(RingElement): + pass cdef class Vector(ModuleElementWithMutability): cdef Py_ssize_t _degree diff --git a/src/sage/structure/element.pyx b/src/sage/structure/element.pyx index 7cdddb22644..76df456113e 100644 --- a/src/sage/structure/element.pyx +++ b/src/sage/structure/element.pyx @@ -47,6 +47,7 @@ abstract base classes. EuclideanDomainElement FieldElement CommutativeAlgebraElement + Expression AlgebraElement Matrix InfinityElement @@ -2453,7 +2454,7 @@ cdef class ModuleElementWithMutability(ModuleElement): sage: v = sage.modules.free_module_element.FreeModuleElement(QQ^3) sage: type(v) - + """ self._parent = parent self._is_immutable = is_immutable @@ -3254,6 +3255,16 @@ cdef class CommutativeRingElement(RingElement): ############################################## +cdef class Expression(CommutativeRingElement): + + r""" + Abstract base class for :class:`~sage.symbolic.expression.Expression`. + """ + + pass + + ############################################## + cdef class Vector(ModuleElementWithMutability): cdef bint is_sparse_c(self): raise NotImplementedError diff --git a/src/sage/structure/parent.pyx b/src/sage/structure/parent.pyx index 4559972c94f..506946bf5f4 100644 --- a/src/sage/structure/parent.pyx +++ b/src/sage/structure/parent.pyx @@ -1169,8 +1169,8 @@ cdef class Parent(sage.structure.category_object.CategoryObject): elif EQ: return True else: - from sage.symbolic.expression import is_Expression - return is_Expression(EQ) + from sage.structure.element import Expression + return isinstance(EQ, Expression) # if comparing gives an Expression, then it must be an equation. # We return *true* here, even though the equation # EQ must have evaluated to False for us to get to @@ -2642,8 +2642,8 @@ cdef class Parent(sage.structure.category_object.CategoryObject): elif self_on_left and op is operator.pow: S_is_int = parent_is_integers(S) if not S_is_int: - from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing - if is_IntegerModRing(S): + from sage.rings.abc import IntegerModRing + if isinstance(S, IntegerModRing): # We allow powering by an IntegerMod by treating it # as an integer. # diff --git a/src/sage/structure/sage_object.pyx b/src/sage/structure/sage_object.pyx index 7ebf2734e9f..8c05c347491 100644 --- a/src/sage/structure/sage_object.pyx +++ b/src/sage/structure/sage_object.pyx @@ -645,7 +645,7 @@ cdef class SageObject: remote Sage session, and get it back. """ tester = self._tester(**options) - from sage.misc.all import loads, dumps + from sage.misc.persist import loads, dumps tester.assertEqual(loads(dumps(self)), self) ############################################################################# diff --git a/src/sage/structure/sequence.py b/src/sage/structure/sequence.py index 0c8440da8e0..49fa26c7490 100644 --- a/src/sage/structure/sequence.py +++ b/src/sage/structure/sequence.py @@ -116,7 +116,7 @@ def Sequence(x, universe=None, check=True, immutable=False, cr=False, cr_str=Non sage: v = Sequence(range(10)) sage: v.universe() - + sage: v [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] @@ -213,15 +213,19 @@ def Sequence(x, universe=None, check=True, immutable=False, cr=False, cr_str=Non ... TypeError: unable to convert a to an element of Integer Ring """ - from sage.rings.polynomial.multi_polynomial_ideal import MPolynomialIdeal - - if isinstance(x, Sequence_generic) and universe is None: - universe = x.universe() - x = list(x) - - if isinstance(x, MPolynomialIdeal) and universe is None: - universe = x.ring() - x = x.gens() + if universe is None: + if isinstance(x, Sequence_generic): + universe = x.universe() + x = list(x) + else: + try: + from sage.rings.polynomial.multi_polynomial_ideal import MPolynomialIdeal + except ImportError: + pass + else: + if isinstance(x, MPolynomialIdeal): + universe = x.ring() + x = x.gens() if universe is None: orig_x = x @@ -248,15 +252,18 @@ def Sequence(x, universe=None, check=True, immutable=False, cr=False, cr_str=Non if universe is None: # no type errors raised. universe = sage.structure.element.parent(x[len(x)-1]) - from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence - from sage.rings.polynomial.pbori.pbori import BooleanMonomialMonoid - from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing - from sage.rings.quotient_ring import is_QuotientRing - - if is_MPolynomialRing(universe) or isinstance(universe, BooleanMonomialMonoid) or (is_QuotientRing(universe) and is_MPolynomialRing(universe.cover_ring())): - return PolynomialSequence(x, universe, immutable=immutable, cr=cr, cr_str=cr_str) + try: + from sage.rings.polynomial.multi_polynomial_sequence import PolynomialSequence + from sage.rings.polynomial.pbori.pbori import BooleanMonomialMonoid + from sage.rings.polynomial.multi_polynomial_ring import is_MPolynomialRing + from sage.rings.quotient_ring import is_QuotientRing + except ImportError: + pass else: - return Sequence_generic(x, universe, check, immutable, cr, cr_str, use_sage_types) + if is_MPolynomialRing(universe) or isinstance(universe, BooleanMonomialMonoid) or (is_QuotientRing(universe) and is_MPolynomialRing(universe.cover_ring())): + return PolynomialSequence(x, universe, immutable=immutable, cr=cr, cr_str=cr_str) + + return Sequence_generic(x, universe, check, immutable, cr, cr_str, use_sage_types) class Sequence_generic(sage.structure.sage_object.SageObject, list): @@ -298,7 +305,7 @@ class Sequence_generic(sage.structure.sage_object.SageObject, list): sage: v = Sequence(range(10)) sage: v.universe() - + sage: v [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] @@ -485,7 +492,7 @@ def __setitem__(self, n, value): sage: v [1, 5, 3, 4] sage: type(v[2]) - + """ self._require_mutable() if isinstance(n, slice): @@ -539,7 +546,7 @@ def append(self, x): sage: v = Sequence([1/3,2,3,4]) sage: v.append(4) sage: type(v[4]) - + """ self._require_mutable() y = self.__universe(x) @@ -776,7 +783,7 @@ def is_mutable(self): True sage: a[0] = 100 sage: type(a[0]) - + sage: a.set_immutable() sage: a[0] = 50 Traceback (most recent call last): diff --git a/src/sage/symbolic/callable.py b/src/sage/symbolic/callable.py index 758fa7ff790..f1a45811db8 100644 --- a/src/sage/symbolic/callable.py +++ b/src/sage/symbolic/callable.py @@ -109,8 +109,8 @@ def is_CallableSymbolicExpression(x): sage: is_CallableSymbolicExpression(foo) False """ - from sage.symbolic.expression import is_Expression - return is_Expression(x) and isinstance(x.parent(), CallableSymbolicExpressionRing_class) + from sage.structure.element import Expression + return isinstance(x, Expression) and isinstance(x.parent(), CallableSymbolicExpressionRing_class) class CallableSymbolicExpressionFunctor(ConstructionFunctor): def __init__(self, arguments): diff --git a/src/sage/symbolic/comparison_impl.pxi b/src/sage/symbolic/comparison_impl.pxi index 9d73c7359fe..2b112b271cd 100644 --- a/src/sage/symbolic/comparison_impl.pxi +++ b/src/sage/symbolic/comparison_impl.pxi @@ -79,9 +79,9 @@ cpdef int print_order(lhs, rhs) except -2: sage: print_order(SR(oo), sqrt(2)) 1 """ - if not is_Expression(lhs): + if not isinstance(lhs, Expression): lhs = SR(lhs) - if not is_Expression(rhs): + if not isinstance(rhs, Expression): rhs = SR(rhs) return print_order_c(lhs, rhs) @@ -103,7 +103,7 @@ class _print_key(object): sage: _print_key(1) """ - self.ex = ex if is_Expression(ex) else SR(ex) + self.ex = ex if isinstance(ex, Expression) else SR(ex) def __lt__(self, other): """ @@ -171,7 +171,7 @@ class _math_key(object): sage: _math_key(1) """ - self.ex = ex if is_Expression(ex) else SR(ex) + self.ex = ex if isinstance(ex, Expression) else SR(ex) def __lt__(self, other): """ @@ -283,9 +283,9 @@ cpdef int mixed_order(lhs, rhs) except -2: """ if lhs is rhs: return 0 - if not is_Expression(lhs): + if not isinstance(lhs, Expression): lhs = SR(lhs) - if not is_Expression(rhs): + if not isinstance(rhs, Expression): rhs = SR(rhs) less_than = _mixed_key(lhs) < _mixed_key(rhs) if less_than: @@ -318,7 +318,7 @@ class _mixed_key(object): sage: _mixed_key(1) """ - self.ex = ex if is_Expression(ex) else SR(ex) + self.ex = ex if isinstance(ex, Expression) else SR(ex) def __lt__(self, other): """ diff --git a/src/sage/symbolic/constants.py b/src/sage/symbolic/constants.py index a4b43b2a9f3..29c43eb64c5 100644 --- a/src/sage/symbolic/constants.py +++ b/src/sage/symbolic/constants.py @@ -717,7 +717,7 @@ def _mpfr_(self,R): sage: NaN._mpfr_(RealField(53)) NaN sage: type(_) - + """ return R('NaN') #??? nan in mpfr: void mpfr_set_nan (mpfr_t x) diff --git a/src/sage/symbolic/expression.pyx b/src/sage/symbolic/expression.pyx index 34145c0fad4..9023bbf97c7 100644 --- a/src/sage/symbolic/expression.pyx +++ b/src/sage/symbolic/expression.pyx @@ -385,6 +385,7 @@ from cpython.object cimport Py_EQ, Py_NE, Py_LE, Py_GE, Py_LT, Py_GT from sage.cpython.string cimport str_to_bytes, char_to_str from sage.structure.element cimport RingElement, Element, Matrix +from sage.structure.element cimport Expression as Expression_abc from sage.symbolic.complexity_measures import string_length from sage.symbolic.function cimport SymbolicFunction from sage.rings.rational import Rational @@ -395,7 +396,7 @@ from sage.misc.latex import latex_variable_name from sage.rings.infinity import AnInfinity, infinity, minus_infinity, unsigned_infinity from sage.rings.integer_ring import ZZ from sage.rings.real_mpfr import RR -from sage.rings.complex_mpfr import is_ComplexField +import sage.rings.abc from sage.misc.decorators import rename_keyword from sage.structure.dynamic_class import dynamic_class from sage.structure.element cimport CommutativeRingElement @@ -407,18 +408,27 @@ include "pynac_impl.pxi" cpdef bint is_Expression(x): """ - Return True if *x* is a symbolic Expression. + Return True if ``x`` is a symbolic expression. + + This method is deprecated. Use :func:`isinstance` with + :class:`sage.structure.element.Expression` instead. EXAMPLES:: sage: from sage.symbolic.expression import is_Expression sage: is_Expression(x) + doctest:warning... + DeprecationWarning: is_Expression is deprecated; + use isinstance(..., sage.structure.element.Expression) instead + See https://trac.sagemath.org/32638 for details. True sage: is_Expression(2) False sage: is_Expression(SR(2)) True """ + from sage.misc.superseded import deprecation + deprecation(32638, 'is_Expression is deprecated; use isinstance(..., sage.structure.element.Expression) instead') return isinstance(x, Expression) @@ -472,7 +482,7 @@ cpdef bint _is_SymbolicVariable(x): sage: ZZ['x'] Univariate Polynomial Ring in x over Integer Ring """ - return is_Expression(x) and is_a_symbol((x)._gobj) + return isinstance(x, Expression) and is_a_symbol((x)._gobj) def _dict_update_check_duplicate(dict d1, dict d2): @@ -694,7 +704,7 @@ def _subs_fun_make_dict(s): raise TypeError(msg.format(s)) -cdef class Expression(CommutativeRingElement): +cdef class Expression(Expression_abc): cdef GEx _gobj @@ -1476,7 +1486,7 @@ cdef class Expression(CommutativeRingElement): sage: ZZ(f.coefficient(x,0)) -3 sage: type(ZZ(f.coefficient(x,0))) - + Coercion is done if necessary:: @@ -1484,7 +1494,7 @@ cdef class Expression(CommutativeRingElement): sage: ZZ(f.coefficient(x)) 17 sage: type(ZZ(f.coefficient(x))) - + If the symbolic expression is just a wrapper around an integer, that very same integer is not preserved, but a new one returned:: @@ -1549,7 +1559,7 @@ cdef class Expression(CommutativeRingElement): sage: a = QQ(f.coefficient(x)); a 17 sage: type(a) - + sage: QQ(f.coefficient(x,0)) -3/8 @@ -1679,7 +1689,7 @@ cdef class Expression(CommutativeRingElement): sage: SR(CBF(1+I))._convert({'parent':RDF}) 1.0 + 1.0*I sage: type(_.pyobject()) - + sage: SR(CBF(1+I))._convert({'parent':CDF}) 1.0 + 1.0*I sage: SR(RBF(1))._convert({'parent':RDF}) @@ -1687,7 +1697,7 @@ cdef class Expression(CommutativeRingElement): sage: SR(CBF(1))._convert({'parent':RDF}) 1.0 sage: type(_.pyobject()) - + """ cdef GEx res = self._gobj.evalf(0, kwds) return new_Expression_from_GEx(self._parent, res) @@ -3565,8 +3575,8 @@ cdef class Expression(CommutativeRingElement): else: domain = RIF else: - is_interval = (is_RealIntervalField(domain) - or is_ComplexIntervalField(domain) + is_interval = (isinstance(domain, (sage.rings.abc.RealIntervalField, + sage.rings.abc.ComplexIntervalField)) or is_AlgebraicField(domain) or is_AlgebraicRealField(domain)) zero = domain(0) @@ -3620,7 +3630,7 @@ cdef class Expression(CommutativeRingElement): eq_count += val.contains_zero() except (TypeError, ValueError, ArithmeticError, AttributeError) as ex: errors += 1 - if k == errors > 3 and is_ComplexIntervalField(domain): + if k == errors > 3 and isinstance(domain, sage.rings.abc.ComplexIntervalField): domain = RIF.to_prec(domain.prec()) # we are plugging in random values above, don't be surprised # if something goes wrong... @@ -6270,7 +6280,7 @@ cdef class Expression(CommutativeRingElement): sage: type(t._unpack_operands()) <... 'tuple'> sage: list(map(type, t._unpack_operands())) - [, , , , ] + [, , , , ] sage: u = SR._force_pyobject((t, x^2)) sage: u._unpack_operands() ((1, 2, x, x + 1, x + 2), x^2) @@ -8264,7 +8274,7 @@ cdef class Expression(CommutativeRingElement): sage: abs(SR(-5)) 5 sage: type(abs(SR(-5))) - + Because this overrides a Python builtin function, we do not currently support a ``hold`` parameter to prevent automatic @@ -10361,7 +10371,7 @@ cdef class Expression(CommutativeRingElement): sage: res = t.maxima_methods().logcontract(); res log((sqrt(2) + 1)*(sqrt(2) - 1)) sage: type(res) - + """ from sage.symbolic.maxima_wrapper import MaximaWrapper return MaximaWrapper(self) @@ -13559,7 +13569,7 @@ cpdef new_Expression(parent, x): sage: a = SR(-3/4); a -3/4 sage: type(a) - + sage: a.parent() Symbolic Ring sage: K. = QuadraticField(-3) @@ -13574,7 +13584,7 @@ cpdef new_Expression(parent, x): x + 1 """ cdef GEx exp - if is_Expression(x): + if isinstance(x, Expression): return new_Expression_from_GEx(parent, (x)._gobj) if hasattr(x, '_symbolic_'): return x._symbolic_(parent) @@ -13654,7 +13664,7 @@ cpdef new_Expression_from_pyobject(parent, x, bint force=True, bint recursive=Tr sage: t = SR._force_pyobject(QQ); t # indirect doctest Rational Field sage: type(t) - + sage: from sage.symbolic.expression import new_Expression_from_pyobject sage: t = new_Expression_from_pyobject(SR, 17); t @@ -13826,7 +13836,7 @@ cdef unsigned sage_domain_to_ginac_domain(object domain) except? 3474701533: return domain_real elif domain == 'positive': return domain_positive - elif is_ComplexField(domain) or domain == 'complex': + elif isinstance(domain, sage.rings.abc.ComplexField) or domain == 'complex': return domain_complex elif domain is ZZ or domain == 'integer': return domain_integer @@ -13840,7 +13850,7 @@ cdef void send_sage_domain_to_maxima(Expression v, object domain) except +: assume(v, 'real') elif domain == 'positive': assume(v>0) - elif is_ComplexField(domain) or domain == 'complex': + elif isinstance(domain, sage.rings.abc.ComplexField) or domain == 'complex': assume(v, 'complex') elif domain is ZZ or domain == 'integer': assume(v, 'integer') diff --git a/src/sage/symbolic/function.pyx b/src/sage/symbolic/function.pyx index d2c7d8e468f..91c66fc5eff 100644 --- a/src/sage/symbolic/function.pyx +++ b/src/sage/symbolic/function.pyx @@ -139,12 +139,11 @@ is attempted, and after that ``sin()`` which succeeds:: #***************************************************************************** from sage.structure.sage_object cimport SageObject -from sage.structure.element cimport Element, parent +from sage.structure.element cimport Element, parent, Expression from sage.misc.lazy_attribute import lazy_attribute from .expression import ( call_registered_function, find_registered_function, register_or_update_function, - get_sfunction_from_hash, - is_Expression + get_sfunction_from_hash ) from .expression import get_sfunction_from_serial as get_sfunction_from_serial @@ -333,7 +332,7 @@ cdef class Function(SageObject): try: evalf = self._evalf_ # catch AttributeError early if any(self._is_numerical(x) for x in args): - if not any(is_Expression(x) for x in args): + if not any(isinstance(x, Expression) for x in args): p = coercion_model.common_parent(*args) return evalf(*args, parent=p) except Exception: @@ -446,7 +445,7 @@ cdef class Function(SageObject): sage: arctan(float(1)) 0.7853981633974483 sage: type(lambert_w(SR(0))) - + Precision of the result depends on the precision of the input:: @@ -542,7 +541,7 @@ cdef class Function(SageObject): else: # coerce == False for a in args: - if not is_Expression(a): + if not isinstance(a, Expression): raise TypeError("arguments must be symbolic expressions") return call_registered_function(self._serial, self._nargs, args, hold, @@ -955,7 +954,7 @@ cdef class BuiltinFunction(Function): sage: sin(numpy.int32(0)) 0.0 sage: type(_) - + TESTS:: diff --git a/src/sage/symbolic/ginac/inifcns_comb.cpp b/src/sage/symbolic/ginac/inifcns_comb.cpp index 2f34fe76700..f31ea4f14e4 100644 --- a/src/sage/symbolic/ginac/inifcns_comb.cpp +++ b/src/sage/symbolic/ginac/inifcns_comb.cpp @@ -126,9 +126,9 @@ static ex binomial_imag_part(const ex & x, const ex & y) static void binomial_print_latex(const ex & x, const ex & y, const print_context & c) { - c.s<<"{"; + c.s<<"\\binom{"; x.print(c); - c.s<<" \\choose "; + c.s<<"}{"; y.print(c); c.s<<"}"; } diff --git a/src/sage/symbolic/pynac_impl.pxi b/src/sage/symbolic/pynac_impl.pxi index 01a51af2997..880a07faf17 100644 --- a/src/sage/symbolic/pynac_impl.pxi +++ b/src/sage/symbolic/pynac_impl.pxi @@ -101,9 +101,9 @@ cdef exprseq_to_PyTuple(GEx seq): sage: tfunc = TFunc() sage: u = SR._force_pyobject((1, x+1, 2)) sage: tfunc(u, x, SR._force_pyobject((3.0, 2^x))) - len(args): 3, types: [<... 'tuple'>, , <... 'tuple'>] - argument 0 is a tuple, with types [, , ] - argument 2 is a tuple, with types [, ] + len(args): 3, types: [<... 'tuple'>, , <... 'tuple'>] + argument 0 is a tuple, with types [, , ] + argument 2 is a tuple, with types [, ] tfunc((1, x + 1, 2), x, (3.00000000000000, 2^x)) """ from sage.symbolic.ring import SR @@ -128,7 +128,7 @@ def unpack_operands(Expression ex): sage: type(unpack_operands(t)) <... 'tuple'> sage: list(map(type, unpack_operands(t))) - [, , , , ] + [, , , , ] sage: u = SR._force_pyobject((t, x^2)) sage: unpack_operands(u) ((1, 2, x, x + 1, x + 2), x^2) @@ -159,7 +159,7 @@ cdef exvector_to_PyTuple(GExVector seq): sage: tfunc = TFunc() sage: u = SR._force_pyobject((1, x+1, 2)) sage: tfunc(u, x, 3.0, 5.0r) - len(args): 4, types: [<... 'tuple'>, , , <... 'float'>] + len(args): 4, types: [<... 'tuple'>, , , <... 'float'>] tfunc((1, x + 1, 2), x, 3.00000000000000, 5.0) TESTS: @@ -167,8 +167,8 @@ cdef exvector_to_PyTuple(GExVector seq): Check if symbolic functions in the arguments are preserved:: sage: tfunc(sin(x), tfunc(1, x^2)) - len(args): 2, types: [, ] - len(args): 2, types: [, ] + len(args): 2, types: [, ] + len(args): 2, types: [, ] tfunc(sin(x), tfunc(1, x^2)) """ @@ -1343,11 +1343,11 @@ cdef py_float(n, PyObject* kwds): sage: py_float(10, {'parent':CDF}) 10.0 sage: type(py_float(10, {'parent':CDF})) - + sage: py_float(1/2, {'parent':CC}) 0.500000000000000 sage: type(py_float(1/2, {'parent':CC})) - + """ if kwds is not NULL: p = (kwds)['parent'] @@ -2420,9 +2420,9 @@ def init_pynac_I(): sage: sage.symbolic.expression.init_pynac_I() sage: type(sage.symbolic.expression.I) - + sage: type(sage.symbolic.expression.I.pyobject()) - + Check that :trac:`10064` is fixed:: diff --git a/src/sage/symbolic/relation.py b/src/sage/symbolic/relation.py index da9dcc0a8b1..e07e50feea1 100644 --- a/src/sage/symbolic/relation.py +++ b/src/sage/symbolic/relation.py @@ -1029,7 +1029,7 @@ def solve(f, *args, **kwds): or a list of symbolic expressions. """ from sage.symbolic.ring import is_SymbolicVariable - from sage.symbolic.expression import Expression, is_Expression + from sage.structure.element import Expression explicit_solutions = kwds.get('explicit_solutions', None) multiplicities = kwds.get('multiplicities', None) to_poly_solve = kwds.get('to_poly_solve', None) @@ -1058,14 +1058,14 @@ def solve(f, *args, **kwds): if isinstance(f, (list, tuple)) and len(f) == 1: # f is a list with a single element - if is_Expression(f[0]): + if isinstance(f[0], Expression): f = f[0] else: raise TypeError("The first argument to solve() should be a " "symbolic expression or a list of symbolic " "expressions.") - if is_Expression(f): # f is a single expression + if isinstance(f, Expression): # f is a single expression return _solve_expression(f, x, explicit_solutions, multiplicities, to_poly_solve, solution_dict, algorithm, domain) if not isinstance(f, (list, tuple)): @@ -1095,7 +1095,7 @@ def solve(f, *args, **kwds): if algorithm == 'sympy': from sympy import solve as ssolve from sage.interfaces.sympy import sympy_set_to_list - if is_Expression(f): # f is a single expression + if isinstance(f, Expression): # f is a single expression sympy_f = f._sympy_() else: sympy_f = [s._sympy_() for s in f] @@ -1103,7 +1103,7 @@ def solve(f, *args, **kwds): sympy_vars = (x._sympy_(),) else: sympy_vars = tuple([v._sympy_() for v in x]) - if len(sympy_vars) > 1 or not is_Expression(f): + if len(sympy_vars) > 1 or not isinstance(f, Expression): ret = ssolve(sympy_f, sympy_vars, dict=True) if isinstance(ret, dict): if solution_dict: @@ -1569,14 +1569,14 @@ def solve_mod(eqns, modulus, solution_dict=False): """ from sage.rings.all import Integer, Integers, crt_basis - from sage.symbolic.expression import is_Expression + from sage.structure.element import Expression from sage.misc.all import cartesian_product_iterator from sage.modules.free_module_element import vector from sage.matrix.constructor import matrix if not isinstance(eqns, (list, tuple)): eqns = [eqns] - eqns = [eq if is_Expression(eq) else (eq.lhs() - eq.rhs()) for eq in eqns] + eqns = [eq if isinstance(eq, Expression) else (eq.lhs() - eq.rhs()) for eq in eqns] modulus = Integer(modulus) if modulus < 1: raise ValueError("the modulus must be a positive integer") diff --git a/src/sage/symbolic/ring.pyx b/src/sage/symbolic/ring.pyx index a07d43d2aec..0bd5749b2b4 100644 --- a/src/sage/symbolic/ring.pyx +++ b/src/sage/symbolic/ring.pyx @@ -32,9 +32,9 @@ The symbolic ring # **************************************************************************** from sage.rings.integer cimport Integer +import sage.rings.abc from sage.symbolic.expression cimport ( - is_Expression, _latex_Expression, _repr_Expression, new_Expression, @@ -43,10 +43,11 @@ from sage.symbolic.expression cimport ( new_Expression_symbol, ) -from sage.structure.element cimport Element +from sage.structure.element cimport Element, Expression from sage.categories.morphism cimport Morphism from sage.structure.coerce cimport is_numpy_type +import sage.rings.abc from sage.rings.integer_ring import ZZ # is_SymbolicVariable used to be defined here; re-export it @@ -205,9 +206,7 @@ cdef class SymbolicRing(CommutativeRing): from sage.rings.real_mpfr import mpfr_prec_min from sage.rings.fraction_field import is_FractionField - from sage.rings.finite_rings.integer_mod_ring import is_IntegerModRing from sage.rings.real_mpfi import is_RealIntervalField - from sage.rings.complex_interval_field import is_ComplexIntervalField from sage.rings.real_arb import RealBallField from sage.rings.complex_arb import ComplexBallField from sage.rings.polynomial.polynomial_ring import is_PolynomialRing @@ -231,10 +230,12 @@ cdef class SymbolicRing(CommutativeRing): base = R.base_ring() return base is not self and self.has_coerce_map_from(base) elif (R is InfinityRing or R is UnsignedInfinityRing - or is_RealIntervalField(R) or is_ComplexIntervalField(R) - or isinstance(R, RealBallField) - or isinstance(R, ComplexBallField) - or is_IntegerModRing(R) or is_FiniteField(R)): + or isinstance(R, (sage.rings.abc.RealIntervalField, + sage.rings.abc.ComplexIntervalField, + sage.rings.abc.RealBallField, + sage.rings.abc.ComplexBallField, + sage.rings.abc.IntegerModRing)) + or is_FiniteField(R)): return True elif isinstance(R, GenericSymbolicSubring): return True @@ -248,7 +249,7 @@ cdef class SymbolicRing(CommutativeRing): sage: a = SR(-3/4); a -3/4 sage: type(a) - + sage: a.parent() Symbolic Ring sage: K. = QuadraticField(-3) @@ -402,7 +403,7 @@ cdef class SymbolicRing(CommutativeRing): sage: t = SR._force_pyobject(QQ); t Rational Field sage: type(t) - + Testing tuples:: @@ -525,7 +526,7 @@ cdef class SymbolicRing(CommutativeRing): sage: c = SR.characteristic(); c 0 sage: type(c) - + """ return Integer(0) @@ -795,7 +796,7 @@ cdef class SymbolicRing(CommutativeRing): The return type is a symbolic expression:: sage: type(zz) - + We can specify the domain as well:: @@ -870,7 +871,7 @@ cdef class SymbolicRing(CommutativeRing): ... ValueError: cannot specify n for multiple symbol names """ - if is_Expression(name): + if isinstance(name, Expression): return name if not isinstance(name, (basestring, list, tuple)): name = repr(name) @@ -1177,7 +1178,7 @@ cdef class NumpyToSRMorphism(Morphism): sage: a = f(numpy.int8('2')).pyobject() sage: type(a) - + This behavior also applies to standard functions:: diff --git a/src/sage/symbolic/subring.py b/src/sage/symbolic/subring.py index 060ad32a5ed..c1eb48e16ae 100644 --- a/src/sage/symbolic/subring.py +++ b/src/sage/symbolic/subring.py @@ -97,6 +97,7 @@ # http://www.gnu.org/licenses/ #***************************************************************************** +import sage.rings.abc from .ring import SymbolicRing, SR from sage.categories.pushout import ConstructionFunctor from sage.structure.factory import UniqueFactory @@ -412,8 +413,6 @@ def _coerce_map_from_(self, P): return False from sage.rings.all import RLF, CLF, AA, QQbar, InfinityRing - from sage.rings.real_mpfi import is_RealIntervalField - from sage.rings.complex_interval_field import is_ComplexIntervalField if isinstance(P, type): return SR._coerce_map_from_(P) @@ -425,7 +424,8 @@ def _coerce_map_from_(self, P): return True elif (P is InfinityRing or - is_RealIntervalField(P) or is_ComplexIntervalField(P)): + isinstance(P, (sage.rings.abc.RealIntervalField, + sage.rings.abc.ComplexIntervalField))): return True elif P._is_numerical(): diff --git a/src/sage/tests/book_stein_ent.py b/src/sage/tests/book_stein_ent.py index cd6d4f7f179..5041f7ea4cf 100644 --- a/src/sage/tests/book_stein_ent.py +++ b/src/sage/tests/book_stein_ent.py @@ -267,8 +267,9 @@ ....: if g != 1 and g != n: ....: return g sage: n=32295194023343; e=29468811804857; d=11127763319273 -sage: crack_given_decrypt(n, e*d - 1) -737531 +sage: p = crack_given_decrypt(n, e*d - 1) +sage: p in (737531, n/737531) # could be other prime divisor +True sage: factor(n) 737531 * 43788253 sage: e = 22601762315966221465875845336488389513 diff --git a/src/sage/tests/book_stein_modform.py b/src/sage/tests/book_stein_modform.py index 14bcacf8888..b0e909c0017 100644 --- a/src/sage/tests/book_stein_modform.py +++ b/src/sage/tests/book_stein_modform.py @@ -444,6 +444,7 @@ (Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -zeta6, Dirichlet character modulo 13 of conductor 1 mapping 2 |--> 1, 1) (Dirichlet character modulo 13 of conductor 1 mapping 2 |--> 1, Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -zeta6 + 1, 1) (Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -zeta6 + 1, Dirichlet character modulo 13 of conductor 1 mapping 2 |--> 1, 1) +sage: from sage.modular.dims import * sage: dimension_cusp_forms(Gamma0(2007),2) 221 sage: dimension_eis(Gamma0(2007),2) diff --git a/src/sage/tests/books/computational-mathematics-with-sagemath/linalg_doctest.py b/src/sage/tests/books/computational-mathematics-with-sagemath/linalg_doctest.py index e3c78e66202..902b3c1aec2 100644 --- a/src/sage/tests/books/computational-mathematics-with-sagemath/linalg_doctest.py +++ b/src/sage/tests/books/computational-mathematics-with-sagemath/linalg_doctest.py @@ -269,6 +269,8 @@ sage: A = random_matrix(R,2,3); A # random [ 3*x^2 + x x^2 + 2*x 2*x^2 + 2] [ x^2 + x + 2 2*x^2 + 4*x + 3 x^2 + 4*x + 3] + sage: while A.rank() < 2: + ....: A = random_matrix(R,2,3) Sage example in ./linalg.tex, line 1830:: diff --git a/src/sage/tests/books/computational-mathematics-with-sagemath/sol/graphique_doctest.py b/src/sage/tests/books/computational-mathematics-with-sagemath/sol/graphique_doctest.py index 95e7f328255..549f48e1b77 100644 --- a/src/sage/tests/books/computational-mathematics-with-sagemath/sol/graphique_doctest.py +++ b/src/sage/tests/books/computational-mathematics-with-sagemath/sol/graphique_doctest.py @@ -42,7 +42,7 @@ sage: g = plot([c*e^(-1/x) for c in srange(-8, 8, 0.4)], (x, -3, 3)) sage: y = var('y') sage: g += plot_vector_field((x^2, y), (x,-3,3), (y,-5,5)) - sage: g.show() + sage: g.show() # not tested, known bug, see :trac:`32657` Sage example in ./sol/graphique.tex, line 124:: diff --git a/src/sage/version.py b/src/sage/version.py index e9950f06043..0cd77c29e31 100644 --- a/src/sage/version.py +++ b/src/sage/version.py @@ -1,5 +1,5 @@ # Sage version information for Python scripts # This file is auto-generated by the sage-update-version script, do not edit! -version = '9.5.beta3' -date = '2021-10-11' -banner = 'SageMath version 9.5.beta3, Release Date: 2021-10-11' +version = '9.5.beta4' +date = '2021-10-19' +banner = 'SageMath version 9.5.beta4, Release Date: 2021-10-19' diff --git a/src/setup.py b/src/setup.py index 686f25aec36..81ee8babd19 100755 --- a/src/setup.py +++ b/src/setup.py @@ -52,7 +52,7 @@ # ## Configuration # ######################################################## -if len(sys.argv) > 1 and sys.argv[1] == "sdist": +if len(sys.argv) > 1 and (sys.argv[1] == "sdist" or sys.argv[1] == "egg_info"): sdist = True else: sdist = False @@ -69,52 +69,55 @@ # ######################################################## # ## Discovering Sources # ######################################################## - -log.info("Discovering Python/Cython source code....") -t = time.time() - -# Exclude a few files if the corresponding distribution is not loaded -optional_packages = ['mcqd', 'bliss', 'tdlib', 'primecount', - 'coxeter3', 'fes', 'sirocco', 'meataxe'] -not_installed_packages = [package for package in optional_packages - if not is_package_installed_and_updated(package)] - -distributions_to_exclude = [f"sagemath-{pkg}" - for pkg in not_installed_packages] -files_to_exclude = filter_cython_sources(SAGE_SRC, distributions_to_exclude) - -log.debug(f"files_to_exclude = {files_to_exclude}") - -python_packages = find_namespace_packages(where=SAGE_SRC, include=['sage', 'sage.*']) -log.debug(f"python_packages = {python_packages}") - -log.info(f"Discovered Python/Cython sources, time: {(time.time() - t):.2f} seconds.") - -# from sage_build_cython: -import Cython.Compiler.Options -Cython.Compiler.Options.embed_pos_in_docstring = True -gdb_debug = os.environ.get('SAGE_DEBUG', None) != 'no' - -try: +if sdist: + extensions = [] + python_packages = [] +else: log.info("Generating auto-generated sources") from sage_setup.autogen import autogen_all autogen_all() - from Cython.Build import cythonize - from sage.env import cython_aliases, sage_include_directories - extensions = cythonize( - ["**/*.pyx"], - exclude=files_to_exclude, - include_path=sage_include_directories(use_sources=True) + ['.'], - compile_time_env=compile_time_env_variables(), - compiler_directives=compiler_directives(False), - aliases=cython_aliases(), - create_extension=create_extension, - gdb_debug=gdb_debug, - nthreads=4) -except Exception as exception: - log.warn(f"Exception while generating and cythonizing source files: {exception}") - raise + log.info("Discovering Python/Cython source code....") + t = time.time() + + # Exclude a few files if the corresponding distribution is not loaded + optional_packages = ['mcqd', 'bliss', 'tdlib', 'primecount', + 'coxeter3', 'fes', 'sirocco', 'meataxe'] + not_installed_packages = [package for package in optional_packages + if not is_package_installed_and_updated(package)] + + distributions_to_exclude = [f"sagemath-{pkg}" + for pkg in not_installed_packages] + files_to_exclude = filter_cython_sources(SAGE_SRC, distributions_to_exclude) + + log.debug(f"files_to_exclude = {files_to_exclude}") + + python_packages = find_namespace_packages(where=SAGE_SRC, include=['sage', 'sage.*']) + log.debug(f"python_packages = {python_packages}") + + log.info(f"Discovered Python/Cython sources, time: {(time.time() - t):.2f} seconds.") + + # from sage_build_cython: + import Cython.Compiler.Options + Cython.Compiler.Options.embed_pos_in_docstring = True + gdb_debug = os.environ.get('SAGE_DEBUG', None) != 'no' + + try: + from Cython.Build import cythonize + from sage.env import cython_aliases, sage_include_directories + extensions = cythonize( + ["sage/**/*.pyx"], + exclude=files_to_exclude, + include_path=sage_include_directories(use_sources=True) + ['.'], + compile_time_env=compile_time_env_variables(), + compiler_directives=compiler_directives(False), + aliases=cython_aliases(), + create_extension=create_extension, + gdb_debug=gdb_debug, + nthreads=4) + except Exception as exception: + log.warn(f"Exception while cythonizing source files: {repr(exception)}") + raise # ######################################################## # ## Distutils diff --git a/tox.ini b/tox.ini index 88bcc65c4e6..8c5301eb28e 100644 --- a/tox.ini +++ b/tox.ini @@ -577,8 +577,8 @@ commands = local: config*) ;; \ local: *) make -k V=0 base-toolchain ;; \ local: esac && \ - local: make -k V=0 SAGE_CHECK=warn SAGE_CHECK_PACKAGES="!cython,!r,!python3,!nose,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!rpy2,!symengine_py,!sage_sws2rst" {env:TARGETS_PRE:} {posargs:build} && \ - local: ( [ -z "{env:TARGETS_OPTIONAL:}" ] || make -k V=0 SAGE_CHECK=warn SAGE_CHECK_PACKAGES="!cython,!r,!python3,!nose,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!networkx,!rpy2,!symengine_py,!sage_sws2rst" {env:TARGETS_OPTIONAL:} || echo "(error ignored)" ) ' + local: make -k V=0 SAGE_CHECK=warn SAGE_CHECK_PACKAGES="!cython,!r,!python3,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!rpy2,!sage_sws2rst" {env:TARGETS_PRE:} {posargs:build} && \ + local: ( [ -z "{env:TARGETS_OPTIONAL:}" ] || make -k V=0 SAGE_CHECK=warn SAGE_CHECK_PACKAGES="!cython,!r,!python3,!gap,!cysignals,!linbox,!git,!ppl,!cmake,!rpy2,!sage_sws2rst" {env:TARGETS_OPTIONAL:} || echo "(error ignored)" ) ' [testenv:check_configure] ## Test that configure behaves properly