diff --git a/.github/workflows/pyright.yml b/.github/workflows/pyright.yml index eb84117cb3a..eef1aad5976 100644 --- a/.github/workflows/pyright.yml +++ b/.github/workflows/pyright.yml @@ -32,7 +32,7 @@ jobs: eval $(sage-print-system-package-command auto --spkg --yes --no-install-recommends install git) - name: Install GH CLI - uses: dev-hanz-ops/install-gh-cli-action@v0.2.0 + uses: dev-hanz-ops/install-gh-cli-action@v0.2.1 with: gh-cli-version: 2.32.0 diff --git a/CITATION.cff b/CITATION.cff index 1a4f50ce0c0..b4e3a375a3a 100644 --- a/CITATION.cff +++ b/CITATION.cff @@ -4,8 +4,8 @@ title: SageMath abstract: SageMath is a free open-source mathematics software system. authors: - name: "The SageMath Developers" -version: 10.6.beta4 +version: 10.6.beta5 doi: 10.5281/zenodo.8042260 -date-released: 2025-01-18 +date-released: 2025-01-26 repository-code: "https://github.com/sagemath/sage" url: "https://www.sagemath.org/" diff --git a/VERSION.txt b/VERSION.txt index c6b18bd1ad9..5c3eb78337a 100644 --- a/VERSION.txt +++ b/VERSION.txt @@ -1 +1 @@ -SageMath version 10.6.beta4, Release Date: 2025-01-18 +SageMath version 10.6.beta5, Release Date: 2025-01-26 diff --git a/build/bin/sage-spkg b/build/bin/sage-spkg index 6af5214c27f..1ea8ad70b93 100755 --- a/build/bin/sage-spkg +++ b/build/bin/sage-spkg @@ -603,14 +603,14 @@ case "$PKG_SRC" in esac # Poison the proxy variable to forbid downloads in spkg-install -# for normal packages -case $PKG_SRC_TYPE in - normal|wheel) - export http_proxy=http://192.0.2.0:5187/ - export https_proxy=$http_proxy - export ftp_proxy=$http_proxy - export rsync_proxy=$http_proxy - ;; +# for normal/wheel standard packages +case "$PKG_TYPE:$PKG_SRC_TYPE" in + standard:normal|standard:wheel) + export http_proxy=http://192.0.2.0:5187/ + export https_proxy=$http_proxy + export ftp_proxy=$http_proxy + export rsync_proxy=$http_proxy + ;; esac # Make sage-logger show the full logs diff --git a/build/pkgs/ccache/spkg-install.in b/build/pkgs/ccache/spkg-install.in index 6e7bcf1fc55..4408cd0ef0f 100644 --- a/build/pkgs/ccache/spkg-install.in +++ b/build/pkgs/ccache/spkg-install.in @@ -4,7 +4,6 @@ mkdir build cd build sdh_cmake -DCMAKE_BUILD_TYPE=Release \ -DENABLE_TESTING=OFF \ - -DREDIS_STORAGE_BACKEND=OFF \ .. sdh_make sdh_make_install diff --git a/build/pkgs/configure/checksums.ini b/build/pkgs/configure/checksums.ini index 8adc17b1426..ada82676b33 100644 --- a/build/pkgs/configure/checksums.ini +++ b/build/pkgs/configure/checksums.ini @@ -1,3 +1,3 @@ tarball=configure-VERSION.tar.gz -sha1=f9c1bea6113a6a09430ee1f1aca16c75ed427d48 -sha256=c1e0826fb54dd60e78f19e6fcad0b0ef90b33e1771fbbc2165a54c9297a89557 +sha1=86711d4cbef2cd4e7bb4afcde36965e5dea908e0 +sha256=9793cf92ebdceb09050a585294de93c242c033745a0012cae1bd301d307a45df diff --git a/build/pkgs/configure/package-version.txt b/build/pkgs/configure/package-version.txt index 0597496b77d..d1c6cb2da71 100644 --- a/build/pkgs/configure/package-version.txt +++ b/build/pkgs/configure/package-version.txt @@ -1 +1 @@ -5eb37241946a9ef9130ce36eff7e4f135d980eaf +efc0914cd8d72a9bdfdcca4511b55e290b9b6674 diff --git a/build/pkgs/igraph/checksums.ini b/build/pkgs/igraph/checksums.ini index 62eafa1aec9..d82c4789be7 100644 --- a/build/pkgs/igraph/checksums.ini +++ b/build/pkgs/igraph/checksums.ini @@ -1,4 +1,4 @@ tarball=igraph-VERSION.tar.gz -sha1=3789f61beac1f1231f8c3832102dcb2720f2a0c9 -sha256=b011f7f9f38a3e59924cc9ff652e6d33105fa03fcaf3792f47d752626a0a4625 +sha1=af74e361167bd790ed2fcc248acd21ec946ddb2a +sha256=03ba01db0544c4e32e51ab66f2356a034394533f61b4e14d769b9bbf5ad5e52c upstream_url=https://github.com/igraph/igraph/releases/download/VERSION/igraph-VERSION.tar.gz diff --git a/build/pkgs/igraph/package-version.txt b/build/pkgs/igraph/package-version.txt index 70016a7c6ad..ba788384c38 100644 --- a/build/pkgs/igraph/package-version.txt +++ b/build/pkgs/igraph/package-version.txt @@ -1 +1 @@ -0.10.12 +0.10.15 diff --git a/build/pkgs/igraph/spkg-configure.m4 b/build/pkgs/igraph/spkg-configure.m4 index 0072f6ea6bc..ee220dd39fd 100644 --- a/build/pkgs/igraph/spkg-configure.m4 +++ b/build/pkgs/igraph/spkg-configure.m4 @@ -3,7 +3,7 @@ SAGE_SPKG_CONFIGURE([igraph], [ dnl check for igraph with pkg-config dnl Per upstream in https://github.com/sagemath/sage/pull/36750#issuecomment-1826998762: dnl each python-igraph release is only guaranteed to be compatible with the same C/igraph that it bundles - PKG_CHECK_MODULES([IGRAPH], [igraph >= 0.10.12 igraph < 0.10.13], [], [ + PKG_CHECK_MODULES([IGRAPH], [igraph >= 0.10.14 igraph < 0.10.16], [], [ sage_spkg_install_igraph=yes]) ]) ]) diff --git a/build/pkgs/python_igraph/checksums.ini b/build/pkgs/python_igraph/checksums.ini index f7e3d8bff22..74b1d04cb5b 100644 --- a/build/pkgs/python_igraph/checksums.ini +++ b/build/pkgs/python_igraph/checksums.ini @@ -1,4 +1,4 @@ tarball=python-igraph-VERSION.tar.gz -sha1=da963213ab22c60938d4e77ffab811875ee43a8a -sha256=2d71d645a4c3344c5910543fabbae10d3163f46a3e824ba7753c14b9036b8233 +sha1=19b52531169f200ff60f2cb8245eaa9e277c6c13 +sha256=d7dc1404567ba3b0ea1bf8b5fa6e101617915c8ad11ea5a9f925a40bf4adad7d upstream_url=https://files.pythonhosted.org/packages/source/i/igraph/igraph-VERSION.tar.gz diff --git a/build/pkgs/python_igraph/package-version.txt b/build/pkgs/python_igraph/package-version.txt index 62d5dbdf3c7..1ee43fc53c1 100644 --- a/build/pkgs/python_igraph/package-version.txt +++ b/build/pkgs/python_igraph/package-version.txt @@ -1 +1 @@ -0.11.5 +0.11.8 diff --git a/build/pkgs/sage_conf/version_requirements.txt b/build/pkgs/sage_conf/version_requirements.txt index 0a47bcf1281..040b5f2631a 100644 --- a/build/pkgs/sage_conf/version_requirements.txt +++ b/build/pkgs/sage_conf/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-conf ~= 10.6b4 +sage-conf ~= 10.6b5 diff --git a/build/pkgs/sage_docbuild/version_requirements.txt b/build/pkgs/sage_docbuild/version_requirements.txt index 2986652773e..c0283b9405a 100644 --- a/build/pkgs/sage_docbuild/version_requirements.txt +++ b/build/pkgs/sage_docbuild/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-docbuild ~= 10.6b4 +sage-docbuild ~= 10.6b5 diff --git a/build/pkgs/sage_setup/version_requirements.txt b/build/pkgs/sage_setup/version_requirements.txt index 3d739f2c183..bd4234f31a6 100644 --- a/build/pkgs/sage_setup/version_requirements.txt +++ b/build/pkgs/sage_setup/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-setup ~= 10.6b4 +sage-setup ~= 10.6b5 diff --git a/build/pkgs/sage_sws2rst/version_requirements.txt b/build/pkgs/sage_sws2rst/version_requirements.txt index a1c57461d38..e856ed4cc63 100644 --- a/build/pkgs/sage_sws2rst/version_requirements.txt +++ b/build/pkgs/sage_sws2rst/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sage-sws2rst ~= 10.6b4 +sage-sws2rst ~= 10.6b5 diff --git a/build/pkgs/sagelib/version_requirements.txt b/build/pkgs/sagelib/version_requirements.txt index 09e6e070dbf..c6e36270655 100644 --- a/build/pkgs/sagelib/version_requirements.txt +++ b/build/pkgs/sagelib/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-standard ~= 10.6b4 +sagemath-standard ~= 10.6b5 diff --git a/build/pkgs/sagemath_bliss/version_requirements.txt b/build/pkgs/sagemath_bliss/version_requirements.txt index 370e9dc8d11..bf5262fa6eb 100644 --- a/build/pkgs/sagemath_bliss/version_requirements.txt +++ b/build/pkgs/sagemath_bliss/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-bliss ~= 10.6b4 +sagemath-bliss ~= 10.6b5 diff --git a/build/pkgs/sagemath_categories/version_requirements.txt b/build/pkgs/sagemath_categories/version_requirements.txt index 6e0f464e560..39c5c3b7890 100644 --- a/build/pkgs/sagemath_categories/version_requirements.txt +++ b/build/pkgs/sagemath_categories/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-categories ~= 10.6b4 +sagemath-categories ~= 10.6b5 diff --git a/build/pkgs/sagemath_coxeter3/version_requirements.txt b/build/pkgs/sagemath_coxeter3/version_requirements.txt index 825ad688d44..d1ebc2d30a9 100644 --- a/build/pkgs/sagemath_coxeter3/version_requirements.txt +++ b/build/pkgs/sagemath_coxeter3/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-coxeter3 ~= 10.6b4 +sagemath-coxeter3 ~= 10.6b5 diff --git a/build/pkgs/sagemath_environment/version_requirements.txt b/build/pkgs/sagemath_environment/version_requirements.txt index 27e9c97c883..c88968f714c 100644 --- a/build/pkgs/sagemath_environment/version_requirements.txt +++ b/build/pkgs/sagemath_environment/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-environment ~= 10.6b4 +sagemath-environment ~= 10.6b5 diff --git a/build/pkgs/sagemath_mcqd/version_requirements.txt b/build/pkgs/sagemath_mcqd/version_requirements.txt index 32529957f70..ef5a7f503b7 100644 --- a/build/pkgs/sagemath_mcqd/version_requirements.txt +++ b/build/pkgs/sagemath_mcqd/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-mcqd ~= 10.6b4 +sagemath-mcqd ~= 10.6b5 diff --git a/build/pkgs/sagemath_meataxe/version_requirements.txt b/build/pkgs/sagemath_meataxe/version_requirements.txt index f579dd099c5..569e25992ab 100644 --- a/build/pkgs/sagemath_meataxe/version_requirements.txt +++ b/build/pkgs/sagemath_meataxe/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-meataxe ~= 10.6b4 +sagemath-meataxe ~= 10.6b5 diff --git a/build/pkgs/sagemath_objects/version_requirements.txt b/build/pkgs/sagemath_objects/version_requirements.txt index 92754c524f1..2e920aa86d6 100644 --- a/build/pkgs/sagemath_objects/version_requirements.txt +++ b/build/pkgs/sagemath_objects/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-objects ~= 10.6b4 +sagemath-objects ~= 10.6b5 diff --git a/build/pkgs/sagemath_repl/version_requirements.txt b/build/pkgs/sagemath_repl/version_requirements.txt index ca8348f0f76..cfff7dea4c2 100644 --- a/build/pkgs/sagemath_repl/version_requirements.txt +++ b/build/pkgs/sagemath_repl/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-repl ~= 10.6b4 +sagemath-repl ~= 10.6b5 diff --git a/build/pkgs/sagemath_sirocco/version_requirements.txt b/build/pkgs/sagemath_sirocco/version_requirements.txt index 881707ea9d5..b0d92f0ad87 100644 --- a/build/pkgs/sagemath_sirocco/version_requirements.txt +++ b/build/pkgs/sagemath_sirocco/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-sirocco ~= 10.6b4 +sagemath-sirocco ~= 10.6b5 diff --git a/build/pkgs/sagemath_tdlib/version_requirements.txt b/build/pkgs/sagemath_tdlib/version_requirements.txt index 8110525f3b7..0d1d8e4eaaa 100644 --- a/build/pkgs/sagemath_tdlib/version_requirements.txt +++ b/build/pkgs/sagemath_tdlib/version_requirements.txt @@ -1,2 +1,2 @@ # This file is updated on every release by the sage-update-version script -sagemath-tdlib ~= 10.6b4 +sagemath-tdlib ~= 10.6b5 diff --git a/build/sage_bootstrap/download/mirror_list.py b/build/sage_bootstrap/download/mirror_list.py index f464d87ffbd..dc9cb9575ba 100644 --- a/build/sage_bootstrap/download/mirror_list.py +++ b/build/sage_bootstrap/download/mirror_list.py @@ -170,7 +170,8 @@ def _rank_mirrors(self): This method is used by the YUM fastestmirror plugin """ timed_mirrors = [] - import time, socket + import time + import socket log.info('Searching fastest mirror') timeout = 1 for mirror in self.mirrors: diff --git a/pkgs/sage-conf/VERSION.txt b/pkgs/sage-conf/VERSION.txt index 8595985e4bf..d201bc08e28 100644 --- a/pkgs/sage-conf/VERSION.txt +++ b/pkgs/sage-conf/VERSION.txt @@ -1 +1 @@ -10.6.beta4 +10.6.beta5 diff --git a/pkgs/sage-conf_conda/VERSION.txt b/pkgs/sage-conf_conda/VERSION.txt index 8595985e4bf..d201bc08e28 100644 --- a/pkgs/sage-conf_conda/VERSION.txt +++ b/pkgs/sage-conf_conda/VERSION.txt @@ -1 +1 @@ -10.6.beta4 +10.6.beta5 diff --git a/pkgs/sage-conf_conda/setup.py b/pkgs/sage-conf_conda/setup.py index 96f163dfe5a..d3c8a8df3bd 100644 --- a/pkgs/sage-conf_conda/setup.py +++ b/pkgs/sage-conf_conda/setup.py @@ -38,7 +38,7 @@ def run(self): print("Warning: A configuration has been written, but the configure script has exited with an error. " "Carefully check any messages above before continuing.") else: - print(f"Error: The configure script has failed; this may be caused by missing build prerequisites.") + print("Error: The configure script has failed; this may be caused by missing build prerequisites.") sys.stdout.flush() PREREQ_SPKG = "_prereq bzip2 xz libffi" # includes python3 SPKG_DEPCHECK packages os.system(f'cd {SAGE_ROOT} && export PACKAGES="$(build/bin/sage-get-system-packages conda {PREREQ_SPKG})" && [ -n "$PACKAGES" ] && echo "You can install the required build prerequisites using the following shell command" && echo "" && build/bin/sage-print-system-package-command conda --verbose --sudo install $PACKAGES && echo ""') @@ -73,7 +73,7 @@ def _create_writable_sage_root(self): def ignore(path, names): # exclude all embedded src trees - if fnmatch.fnmatch(path, f'*/build/pkgs/*'): + if fnmatch.fnmatch(path, '*/build/pkgs/*'): return ['src'] ### ignore more stuff --- .tox etc. return [name for name in names diff --git a/pkgs/sage-conf_pypi/VERSION.txt b/pkgs/sage-conf_pypi/VERSION.txt index 8595985e4bf..d201bc08e28 100644 --- a/pkgs/sage-conf_pypi/VERSION.txt +++ b/pkgs/sage-conf_pypi/VERSION.txt @@ -1 +1 @@ -10.6.beta4 +10.6.beta5 diff --git a/pkgs/sage-conf_pypi/setup.py b/pkgs/sage-conf_pypi/setup.py index 5a8240b6e9d..54dcecf7e17 100644 --- a/pkgs/sage-conf_pypi/setup.py +++ b/pkgs/sage-conf_pypi/setup.py @@ -47,7 +47,7 @@ def run(self): print(f"Running {cmd}") sys.stdout.flush() if os.system(cmd) != 0: - print(f"configure failed; this may be caused by missing build prerequisites.") + print("configure failed; this may be caused by missing build prerequisites.") sys.stdout.flush() PREREQ_SPKG = "_prereq bzip2 xz libffi" # includes python3 SPKG_DEPCHECK packages os.system(f'cd {SAGE_ROOT} && export SYSTEM=$(build/bin/sage-guess-package-system 2>/dev/null) && export PACKAGES="$(build/bin/sage-get-system-packages $SYSTEM {PREREQ_SPKG})" && [ -n "$PACKAGES" ] && echo "You can install the required build prerequisites using the following shell command" && echo "" && build/bin/sage-print-system-package-command $SYSTEM --verbose --sudo install $PACKAGES && echo ""') @@ -95,7 +95,7 @@ def _create_writable_sage_root(self): def ignore(path, names): # exclude all embedded src trees - if fnmatch.fnmatch(path, f'*/build/pkgs/*'): + if fnmatch.fnmatch(path, '*/build/pkgs/*'): return ['src'] ### ignore more stuff --- .tox etc. return [name for name in names diff --git a/pkgs/sage-docbuild/VERSION.txt b/pkgs/sage-docbuild/VERSION.txt index 8595985e4bf..d201bc08e28 100644 --- a/pkgs/sage-docbuild/VERSION.txt +++ b/pkgs/sage-docbuild/VERSION.txt @@ -1 +1 @@ -10.6.beta4 +10.6.beta5 diff --git a/pkgs/sage-setup/VERSION.txt b/pkgs/sage-setup/VERSION.txt index 8595985e4bf..d201bc08e28 100644 --- a/pkgs/sage-setup/VERSION.txt +++ b/pkgs/sage-setup/VERSION.txt @@ -1 +1 @@ -10.6.beta4 +10.6.beta5 diff --git a/pkgs/sage-sws2rst/VERSION.txt b/pkgs/sage-sws2rst/VERSION.txt index 8595985e4bf..d201bc08e28 100644 --- a/pkgs/sage-sws2rst/VERSION.txt +++ b/pkgs/sage-sws2rst/VERSION.txt @@ -1 +1 @@ -10.6.beta4 +10.6.beta5 diff --git a/pkgs/sage-sws2rst/sage_sws2rst/worksheet2rst.py b/pkgs/sage-sws2rst/sage_sws2rst/worksheet2rst.py index 8053cf0b5f6..4ed315ca393 100644 --- a/pkgs/sage-sws2rst/sage_sws2rst/worksheet2rst.py +++ b/pkgs/sage-sws2rst/sage_sws2rst/worksheet2rst.py @@ -111,7 +111,8 @@ def code_parser(text): lines = ['::', ''] for s in text.splitlines(): l = s[6:] if s.startswith('sage: ') else s - if not l: continue + if not l: + continue prefix = ' ....: ' if l[0] == ' ' else ' sage: ' lines.append(prefix + l) return '\n'.join(lines) diff --git a/pkgs/sagemath-bliss/VERSION.txt b/pkgs/sagemath-bliss/VERSION.txt index 8595985e4bf..d201bc08e28 100644 --- a/pkgs/sagemath-bliss/VERSION.txt +++ b/pkgs/sagemath-bliss/VERSION.txt @@ -1 +1 @@ -10.6.beta4 +10.6.beta5 diff --git a/pkgs/sagemath-categories/VERSION.txt b/pkgs/sagemath-categories/VERSION.txt index 8595985e4bf..d201bc08e28 100644 --- a/pkgs/sagemath-categories/VERSION.txt +++ b/pkgs/sagemath-categories/VERSION.txt @@ -1 +1 @@ -10.6.beta4 +10.6.beta5 diff --git a/pkgs/sagemath-coxeter3/VERSION.txt b/pkgs/sagemath-coxeter3/VERSION.txt index 8595985e4bf..d201bc08e28 100644 --- a/pkgs/sagemath-coxeter3/VERSION.txt +++ b/pkgs/sagemath-coxeter3/VERSION.txt @@ -1 +1 @@ -10.6.beta4 +10.6.beta5 diff --git a/pkgs/sagemath-environment/VERSION.txt b/pkgs/sagemath-environment/VERSION.txt index 8595985e4bf..d201bc08e28 100644 --- a/pkgs/sagemath-environment/VERSION.txt +++ b/pkgs/sagemath-environment/VERSION.txt @@ -1 +1 @@ -10.6.beta4 +10.6.beta5 diff --git a/pkgs/sagemath-mcqd/VERSION.txt b/pkgs/sagemath-mcqd/VERSION.txt index 8595985e4bf..d201bc08e28 100644 --- a/pkgs/sagemath-mcqd/VERSION.txt +++ b/pkgs/sagemath-mcqd/VERSION.txt @@ -1 +1 @@ -10.6.beta4 +10.6.beta5 diff --git a/pkgs/sagemath-meataxe/VERSION.txt b/pkgs/sagemath-meataxe/VERSION.txt index 8595985e4bf..d201bc08e28 100644 --- a/pkgs/sagemath-meataxe/VERSION.txt +++ b/pkgs/sagemath-meataxe/VERSION.txt @@ -1 +1 @@ -10.6.beta4 +10.6.beta5 diff --git a/pkgs/sagemath-objects/VERSION.txt b/pkgs/sagemath-objects/VERSION.txt index 8595985e4bf..d201bc08e28 100644 --- a/pkgs/sagemath-objects/VERSION.txt +++ b/pkgs/sagemath-objects/VERSION.txt @@ -1 +1 @@ -10.6.beta4 +10.6.beta5 diff --git a/pkgs/sagemath-repl/VERSION.txt b/pkgs/sagemath-repl/VERSION.txt index 8595985e4bf..d201bc08e28 100644 --- a/pkgs/sagemath-repl/VERSION.txt +++ b/pkgs/sagemath-repl/VERSION.txt @@ -1 +1 @@ -10.6.beta4 +10.6.beta5 diff --git a/pkgs/sagemath-sirocco/VERSION.txt b/pkgs/sagemath-sirocco/VERSION.txt index 8595985e4bf..d201bc08e28 100644 --- a/pkgs/sagemath-sirocco/VERSION.txt +++ b/pkgs/sagemath-sirocco/VERSION.txt @@ -1 +1 @@ -10.6.beta4 +10.6.beta5 diff --git a/pkgs/sagemath-tdlib/VERSION.txt b/pkgs/sagemath-tdlib/VERSION.txt index 8595985e4bf..d201bc08e28 100644 --- a/pkgs/sagemath-tdlib/VERSION.txt +++ b/pkgs/sagemath-tdlib/VERSION.txt @@ -1 +1 @@ -10.6.beta4 +10.6.beta5 diff --git a/src/VERSION.txt b/src/VERSION.txt index 8595985e4bf..d201bc08e28 100644 --- a/src/VERSION.txt +++ b/src/VERSION.txt @@ -1 +1 @@ -10.6.beta4 +10.6.beta5 diff --git a/src/bin/sage-version.sh b/src/bin/sage-version.sh index ddaee05e046..a4df2cecd2c 100644 --- a/src/bin/sage-version.sh +++ b/src/bin/sage-version.sh @@ -4,6 +4,6 @@ # which stops "setup.py develop" from rewriting it as a Python file. : # This file is auto-generated by the sage-update-version script, do not edit! -SAGE_VERSION='10.6.beta4' -SAGE_RELEASE_DATE='2025-01-18' -SAGE_VERSION_BANNER='SageMath version 10.6.beta4, Release Date: 2025-01-18' +SAGE_VERSION='10.6.beta5' +SAGE_RELEASE_DATE='2025-01-26' +SAGE_VERSION_BANNER='SageMath version 10.6.beta5, Release Date: 2025-01-26' diff --git a/src/doc/de/tutorial/interfaces.rst b/src/doc/de/tutorial/interfaces.rst index e02578af380..c1ce7d14df9 100644 --- a/src/doc/de/tutorial/interfaces.rst +++ b/src/doc/de/tutorial/interfaces.rst @@ -198,8 +198,8 @@ Sages Singular-Schnittstelle (ohne die ``....:``): sage: R1 = singular.ring(0, '(x,y)', 'dp') sage: R1 polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 2 + // coefficients: QQ... + // number of vars : 2 // block 1 : ordering dp // : names x y // block 2 : ordering C diff --git a/src/doc/de/tutorial/tour_advanced.rst b/src/doc/de/tutorial/tour_advanced.rst index 56523ae5650..59d9661c040 100644 --- a/src/doc/de/tutorial/tour_advanced.rst +++ b/src/doc/de/tutorial/tour_advanced.rst @@ -35,11 +35,11 @@ wir diese schneiden und dann die irreduziblen Komponenten berechnen. sage: V = C2.intersection(C3) sage: V.irreducible_components() [Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: - y, - x - 1, - Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: y - 1, x, + Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: + y, + x - 1, Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: x + y + 2, 2*y^2 + 4*y + 3] diff --git a/src/doc/el/a_tour_of_sage/conf.py b/src/doc/el/a_tour_of_sage/conf.py index ff4e9436313..5494e6c429c 100644 --- a/src/doc/el/a_tour_of_sage/conf.py +++ b/src/doc/el/a_tour_of_sage/conf.py @@ -27,8 +27,8 @@ # Add small view/edit buttons. html_theme_options.update({ - 'source_view_link': os.path.join(source_repository, f'blob/develop/src/doc/el/a_tour_of_sage', '{filename}'), - 'source_edit_link': os.path.join(source_repository, f'edit/develop/src/doc/el/a_tour_of_sage', '{filename}'), + 'source_view_link': os.path.join(source_repository, 'blob/develop/src/doc/el/a_tour_of_sage', '{filename}'), + 'source_edit_link': os.path.join(source_repository, 'edit/develop/src/doc/el/a_tour_of_sage', '{filename}'), }) # General information about the project. diff --git a/src/doc/en/a_tour_of_sage/conf.py b/src/doc/en/a_tour_of_sage/conf.py index 689eed59af3..440a70f5d5b 100644 --- a/src/doc/en/a_tour_of_sage/conf.py +++ b/src/doc/en/a_tour_of_sage/conf.py @@ -27,8 +27,8 @@ # Add small view/edit buttons. html_theme_options.update({ - 'source_view_link': os.path.join(source_repository, f'blob/develop/src/doc/en/a_tour_of_sage', '{filename}'), - 'source_edit_link': os.path.join(source_repository, f'edit/develop/src/doc/en/a_tour_of_sage', '{filename}'), + 'source_view_link': os.path.join(source_repository, 'blob/develop/src/doc/en/a_tour_of_sage', '{filename}'), + 'source_edit_link': os.path.join(source_repository, 'edit/develop/src/doc/en/a_tour_of_sage', '{filename}'), }) # General information about the project. diff --git a/src/doc/en/constructions/algebraic_geometry.rst b/src/doc/en/constructions/algebraic_geometry.rst index 76b173d80a5..fea75431fbf 100644 --- a/src/doc/en/constructions/algebraic_geometry.rst +++ b/src/doc/en/constructions/algebraic_geometry.rst @@ -162,14 +162,12 @@ Other methods sage: singular.LIB("brnoeth.lib") sage: s = singular.ring(2,'(x,y)','lp') - ... sage: f = singular.poly('x3y+y3+x') - ... sage: klein1 = f.Adj_div(); print(klein1) [1]: [1]: - // coefficients: ZZ/2 - // number of vars : 2 + // coefficients: ZZ/2... + // number of vars : 2 // block 1 : ordering lp // : names x y // block 2 : ordering C @@ -191,14 +189,14 @@ Other methods sage: print(klein1) [1]: [1]: - // coefficients: ZZ/2 - // number of vars : 2 + // coefficients: ZZ/2... + // number of vars : 2 // block 1 : ordering lp // : names x y // block 2 : ordering C [2]: - // coefficients: ZZ/2 - // number of vars : 3 + // coefficients: ZZ/2... + // number of vars : 3 // block 1 : ordering lp // : names x y z // block 2 : ordering C @@ -214,8 +212,8 @@ Other methods [5]: [1]: [1]: - // coefficients: ZZ/2 - // number of vars : 3 + // coefficients: ZZ/2... + // number of vars : 3 // block 1 : ordering ls // : names x y t // block 2 : ordering C diff --git a/src/doc/en/constructions/rings.rst b/src/doc/en/constructions/rings.rst index 65557b229e1..d31684ccc77 100644 --- a/src/doc/en/constructions/rings.rst +++ b/src/doc/en/constructions/rings.rst @@ -57,8 +57,8 @@ Here's an example using the Singular interface: sage: I = singular.ideal(['a+b+c+d', 'ab+ad+bc+cd', 'abc+abd+acd+bcd', 'abcd-1']) sage: R polynomial ring, over a field, global ordering - // coefficients: ZZ/97 - // number of vars : 4 + // coefficients: ZZ/97... + // number of vars : 4 // block 1 : ordering lp // : names a b c d // block 2 : ordering C diff --git a/src/doc/en/developer/coding_in_other.rst b/src/doc/en/developer/coding_in_other.rst index 3410c9e6edc..d59886b5391 100644 --- a/src/doc/en/developer/coding_in_other.rst +++ b/src/doc/en/developer/coding_in_other.rst @@ -403,8 +403,8 @@ interface to Singular:: sage: singular.LIB("brnoeth.lib") sage: singular.ring(5,'(x,y)','lp') polynomial ring, over a field, global ordering - // coefficients: ZZ/5 - // number of vars : 2 + // coefficients: ZZ/5... + // number of vars : 2 // block 1 : ordering lp // : names x y // block 2 : ordering C diff --git a/src/doc/en/reference/matroids/index.rst b/src/doc/en/reference/matroids/index.rst index 284caabe8d0..9a9fa4991ed 100644 --- a/src/doc/en/reference/matroids/index.rst +++ b/src/doc/en/reference/matroids/index.rst @@ -27,12 +27,14 @@ Concrete implementations :maxdepth: 1 sage/matroids/basis_matroid - sage/matroids/circuits_matroid sage/matroids/circuit_closures_matroid + sage/matroids/circuits_matroid sage/matroids/flats_matroid + sage/matroids/gammoid + sage/matroids/graphic_matroid sage/matroids/linear_matroid sage/matroids/rank_matroid - sage/matroids/graphic_matroid + sage/matroids/transversal_matroid Chow rings of matroids ---------------------- @@ -49,9 +51,9 @@ Abstract matroid classes .. toctree:: :maxdepth: 1 + sage/matroids/basis_exchange_matroid sage/matroids/dual_matroid sage/matroids/minor_matroid - sage/matroids/basis_exchange_matroid Advanced functionality ---------------------- @@ -60,8 +62,8 @@ Advanced functionality :maxdepth: 1 sage/matroids/advanced - sage/matroids/utilities sage/matroids/extension + sage/matroids/utilities Internals --------- diff --git a/src/doc/en/reference/references/index.rst b/src/doc/en/reference/references/index.rst index ca81cda3f75..31cb3ec8074 100644 --- a/src/doc/en/reference/references/index.rst +++ b/src/doc/en/reference/references/index.rst @@ -490,6 +490,11 @@ REFERENCES: "Spook: Sponge-Based Leakage-Resilient AuthenticatedEncryption with a Masked Tweakable Block Cipher" https://csrc.nist.gov/CSRC/media/Projects/Lightweight-Cryptography/documents/round-1/spec-doc/Spook-spec.pdf +.. [BBC2000] Anne Berry, Jean-Paul Bordat, Olivier Cogis. *Generating all the + minimal separators of a graph*. International Journal of + Foundations of Computer Science, 11(3):397-403, 2000. + :doi:`10.1142/S0129054100000211` + .. [BCDM2019] \T. Beyne, Y. L. Chen, C. Dobraunig, B. Mennink. *Elephant v1* (2019) https://csrc.nist.gov/CSRC/media/Projects/Lightweight-Cryptography/documents/round-1/spec-doc/elephant-spec.pdf @@ -872,7 +877,7 @@ REFERENCES: .. [BrHu2019] Petter Brändén, June Huh. *Lorentzian polynomials*. Ann. Math. (2) 192, No. 3, 821-891 (2020). :arxiv:`1902.03719`, :doi:`10.4007/annals.2020.192.3.4`. - + .. [Bru2014] Erwan Brugalle and Kristin Shaw. *A bit of tropical geometry*. Amer. Math. Monthly, 121(7):563-589, 2014. @@ -1153,6 +1158,10 @@ REFERENCES: .. [Bo2009] Bosch, S., Algebra, Springer 2009 +.. [Bon2017] Joseph E. Bonin, *Lattices Related to Extensions of + Presentations of Transversal Matroids*. + Electronic Journal of Combinatorics (2017), #P1.49. + .. [Bor1993] Lev A. Borisov, "Towards the mirror symmetry for Calabi-Yau complete intersections in Gorenstein Fano toric varieties", 1993. @@ -5243,7 +5252,7 @@ REFERENCES: .. [NT2007] Serguei Norine and Robin Thomas. *Minimally Non-Pfaffian Graphs*. Combinatorica, vol. 27, no. 5, pages: 587 -- 600, Springer. 2007. :doi:`10.1016/j.jctb.2007.12.005`. - + .. [Nur2004] K. Nurmela. *Upper bounds for covering arrays by tabu search*. Discrete Applied Math., 138 (2004), 143-152. @@ -6193,7 +6202,7 @@ REFERENCES: of the chromatic polynomial of a graph*, Adv. Math., ***111*** no.1 (1995), 166-194. :doi:`10.1006/aima.1995.1020`. -.. [Sta1998] \R. P. Stanley, *Graph colorings and related symmetric functions: +.. [Sta1998] \R. P. Stanley, *Graph colorings and related symmetric functions: ideas and applications A description of results, interesting applications, & notable open problems*, Discrete Mathematics, 193, no.1-3, (1998), 267-286. :doi:`10.1016/S0012-365X(98)00146-0`. diff --git a/src/doc/en/thematic_tutorials/coercion_and_categories.rst b/src/doc/en/thematic_tutorials/coercion_and_categories.rst index 9494f8c43ee..12a5cebe3aa 100644 --- a/src/doc/en/thematic_tutorials/coercion_and_categories.rst +++ b/src/doc/en/thematic_tutorials/coercion_and_categories.rst @@ -131,7 +131,6 @@ This base class provides a lot more methods than a general parent:: 'gens', 'integral_closure', 'is_field', - 'krull_dimension', 'ngens', 'one', 'order', diff --git a/src/doc/en/tutorial/interfaces.rst b/src/doc/en/tutorial/interfaces.rst index 543a74b7af7..16019427a34 100644 --- a/src/doc/en/tutorial/interfaces.rst +++ b/src/doc/en/tutorial/interfaces.rst @@ -195,8 +195,8 @@ Singular (do not type the ``....:``): sage: R1 = singular.ring(0, '(x,y)', 'dp') sage: R1 polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 2 + // coefficients: QQ... + // number of vars : 2 // block 1 : ordering dp // : names x y // block 2 : ordering C diff --git a/src/doc/en/tutorial/tour_advanced.rst b/src/doc/en/tutorial/tour_advanced.rst index da3dd7fc4c5..9a93145e972 100644 --- a/src/doc/en/tutorial/tour_advanced.rst +++ b/src/doc/en/tutorial/tour_advanced.rst @@ -35,11 +35,11 @@ intersecting them and computing the irreducible components. sage: V = C2.intersection(C3) sage: V.irreducible_components() [Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: - y, - x - 1, - Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: y - 1, x, + Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: + y, + x - 1, Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: x + y + 2, 2*y^2 + 4*y + 3] diff --git a/src/doc/fr/a_tour_of_sage/conf.py b/src/doc/fr/a_tour_of_sage/conf.py index 9cca4b7d1f8..0fcc6f5cc4b 100644 --- a/src/doc/fr/a_tour_of_sage/conf.py +++ b/src/doc/fr/a_tour_of_sage/conf.py @@ -49,7 +49,3 @@ ('index', name + '.tex', 'A Tour Of Sage', 'The Sage Development Team', 'manual'), ] - -# the definition of \\at in the standard preamble of the sphinx doc -# conflicts with that in babel/french[b] -latex_elements['preamble'] += '\\let\\at\\undefined' diff --git a/src/doc/fr/tutorial/conf.py b/src/doc/fr/tutorial/conf.py index 38e0160f3ba..ef795861bf9 100644 --- a/src/doc/fr/tutorial/conf.py +++ b/src/doc/fr/tutorial/conf.py @@ -49,7 +49,3 @@ ('index', name + '.tex', project, 'The Sage Group', 'manual'), ] - -# the definition of \\at in the standard preamble of the sphinx doc -# conflicts with that in babel/french[b] -latex_elements['preamble'] += '\\let\\at\\undefined' diff --git a/src/doc/fr/tutorial/interfaces.rst b/src/doc/fr/tutorial/interfaces.rst index 9b9da93519c..9f314601bf8 100644 --- a/src/doc/fr/tutorial/interfaces.rst +++ b/src/doc/fr/tutorial/interfaces.rst @@ -199,8 +199,8 @@ fournie par Sage (n'entrez pas les ``....:``) : sage: R1 = singular.ring(0, '(x,y)', 'dp') sage: R1 polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 2 + // coefficients: QQ... + // number of vars : 2 // block 1 : ordering dp // : names x y // block 2 : ordering C diff --git a/src/doc/fr/tutorial/tour_advanced.rst b/src/doc/fr/tutorial/tour_advanced.rst index 70ece3bc944..add83373629 100644 --- a/src/doc/fr/tutorial/tour_advanced.rst +++ b/src/doc/fr/tutorial/tour_advanced.rst @@ -36,11 +36,11 @@ irréductibles. sage: V = C2.intersection(C3) sage: V.irreducible_components() [Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: - y, - x - 1, - Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: y - 1, x, + Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: + y, + x - 1, Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: x + y + 2, 2*y^2 + 4*y + 3] diff --git a/src/doc/ja/tutorial/interfaces.rst b/src/doc/ja/tutorial/interfaces.rst index 222eca889a1..4a93efa92f5 100644 --- a/src/doc/ja/tutorial/interfaces.rst +++ b/src/doc/ja/tutorial/interfaces.rst @@ -171,8 +171,8 @@ Singularは,グレブナー基底,多変数多項式のgcd,平面曲線の sage: R1 = singular.ring(0, '(x,y)', 'dp') sage: R1 polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 2 + // coefficients: QQ... + // number of vars : 2 // block 1 : ordering dp // : names x y // block 2 : ordering C diff --git a/src/doc/ja/tutorial/tour_advanced.rst b/src/doc/ja/tutorial/tour_advanced.rst index 6b8ed96904a..f8681a86f93 100644 --- a/src/doc/ja/tutorial/tour_advanced.rst +++ b/src/doc/ja/tutorial/tour_advanced.rst @@ -35,11 +35,11 @@ Sageでは,任意の代数多様体を定義することができるが,そ sage: V = C2.intersection(C3) sage: V.irreducible_components() [Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: - y, - x - 1, - Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: y - 1, x, + Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: + y, + x - 1, Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: x + y + 2, 2*y^2 + 4*y + 3] diff --git a/src/doc/pt/tutorial/interfaces.rst b/src/doc/pt/tutorial/interfaces.rst index 0e3cac7b9d2..79388ef9d43 100644 --- a/src/doc/pt/tutorial/interfaces.rst +++ b/src/doc/pt/tutorial/interfaces.rst @@ -197,8 +197,8 @@ digite ``...``): sage: R1 = singular.ring(0, '(x,y)', 'dp') sage: R1 polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 2 + // coefficients: QQ... + // number of vars : 2 // block 1 : ordering dp // : names x y // block 2 : ordering C diff --git a/src/doc/pt/tutorial/tour_advanced.rst b/src/doc/pt/tutorial/tour_advanced.rst index 5a8fdd04de9..96eb07f0a4c 100644 --- a/src/doc/pt/tutorial/tour_advanced.rst +++ b/src/doc/pt/tutorial/tour_advanced.rst @@ -36,11 +36,11 @@ irredutíveis. sage: V = C2.intersection(C3) sage: V.irreducible_components() [Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: - y, - x - 1, - Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: y - 1, x, + Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: + y, + x - 1, Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: x + y + 2, 2*y^2 + 4*y + 3] diff --git a/src/doc/ru/tutorial/interfaces.rst b/src/doc/ru/tutorial/interfaces.rst index 0bd8cf703aa..ab4850ca119 100644 --- a/src/doc/ru/tutorial/interfaces.rst +++ b/src/doc/ru/tutorial/interfaces.rst @@ -190,8 +190,8 @@ Singular предоставляет массивную и продуманную sage: R1 = singular.ring(0, '(x,y)', 'dp') sage: R1 polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 2 + // coefficients: QQ... + // number of vars : 2 // block 1 : ordering dp // : names x y // block 2 : ordering C diff --git a/src/doc/ru/tutorial/tour_advanced.rst b/src/doc/ru/tutorial/tour_advanced.rst index 1420053e93b..f09db1d2d3f 100644 --- a/src/doc/ru/tutorial/tour_advanced.rst +++ b/src/doc/ru/tutorial/tour_advanced.rst @@ -33,11 +33,11 @@ Sage позволяет создавать любые алгебраически sage: V = C2.intersection(C3) sage: V.irreducible_components() [Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: - y, - x - 1, - Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: y - 1, x, + Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: + y, + x - 1, Closed subscheme of Affine Space of dimension 2 over Rational Field defined by: x + y + 2, 2*y^2 + 4*y + 3] diff --git a/src/doc/tr/a_tour_of_sage/conf.py b/src/doc/tr/a_tour_of_sage/conf.py index 9d2a503d78d..04d20c565a9 100644 --- a/src/doc/tr/a_tour_of_sage/conf.py +++ b/src/doc/tr/a_tour_of_sage/conf.py @@ -27,8 +27,8 @@ # Add small view/edit buttons. html_theme_options.update({ - 'source_view_link': os.path.join(source_repository, f'blob/develop/src/doc/tr/a_tour_of_sage', '{filename}'), - 'source_edit_link': os.path.join(source_repository, f'edit/develop/src/doc/tr/a_tour_of_sage', '{filename}'), + 'source_view_link': os.path.join(source_repository, 'blob/develop/src/doc/tr/a_tour_of_sage', '{filename}'), + 'source_edit_link': os.path.join(source_repository, 'edit/develop/src/doc/tr/a_tour_of_sage', '{filename}'), }) # General information about the project. diff --git a/src/sage/algebras/hecke_algebras/ariki_koike_algebra.py b/src/sage/algebras/hecke_algebras/ariki_koike_algebra.py index e6368ea8389..2e6cba1e965 100644 --- a/src/sage/algebras/hecke_algebras/ariki_koike_algebra.py +++ b/src/sage/algebras/hecke_algebras/ariki_koike_algebra.py @@ -212,14 +212,14 @@ class ArikiKoikeAlgebra(Parent, UniqueRepresentation): sage: T1 * L1 * T2 * L3 * T1 * T2 -(q-q^2)*L2*L3*T[2] + q*L1*L2*T[2,1] - (1-q)*L1*L2*T[2,1,2] sage: L1^3 - u0*u1*u2 + ((-u0*u1-u0*u2-u1*u2))*L1 + ((u0+u1+u2))*L1^2 + u0*u1*u2 - ((u0*u1+u0*u2+u1*u2))*L1 + ((u0+u1+u2))*L1^2 sage: L3 * L2 * L1 L1*L2*L3 sage: u = LT.u() sage: q = LT.q() sage: (q + 2*u[0]) * (T1 * T2) * L3 - (-2*u0+(2*u0-1)*q+q^2)*L3*T[1] + (-2*u0+(2*u0-1)*q+q^2)*L2*T[2] - + (2*u0+q)*L1*T[1,2] + -(2*u0+(-2*u0+1)*q-q^2)*L3*T[1] - (2*u0+(-2*u0+1)*q-q^2)*L2*T[2] + + (2*u0+q)*L1*T[1,2] We check the defining relations:: @@ -789,11 +789,11 @@ def L(self, i=None): sage: LT = algebras.ArikiKoike(1, 3).LT() sage: LT.L(2) - u + (-u*q^-1+u)*T[1] + u - (u*q^-1-u)*T[1] sage: LT.L() [u, - u + (-u*q^-1+u)*T[1], - u + (-u*q^-1+u)*T[2] + (-u*q^-2+u*q^-1)*T[2,1,2]] + u - (u*q^-1-u)*T[1], + u - (u*q^-1-u)*T[2] - (u*q^-2-u*q^-1)*T[2,1,2]] """ G = self.algebra_generators() if i is None: @@ -824,18 +824,18 @@ def product_on_basis(self, m1, m2): sage: L1^2 * T1 * L1^2 * T1 q*L1^2*L2^2 + (1-q)*L1^3*L2*T[1] sage: L1^3 * T1 * L1^2 * T1 - (-u0*u1*u2*u3+u0*u1*u2*u3*q)*L2*T[1] - + ((u0*u1*u2+u0*u1*u3+u0*u2*u3+u1*u2*u3)+(-u0*u1*u2-u0*u1*u3-u0*u2*u3-u1*u2*u3)*q)*L1*L2*T[1] - + ((-u0*u1-u0*u2-u1*u2-u0*u3-u1*u3-u2*u3)+(u0*u1+u0*u2+u1*u2+u0*u3+u1*u3+u2*u3)*q)*L1^2*L2*T[1] - + ((u0+u1+u2+u3)+(-u0-u1-u2-u3)*q)*L1^3*L2*T[1] + q*L1^3*L2^2 + -(u0*u1*u2*u3-u0*u1*u2*u3*q)*L2*T[1] + + ((u0*u1*u2+u0*u1*u3+u0*u2*u3+u1*u2*u3)+(-u0*u1*u2-u0*u1*u3-u0*u2*u3-u1*u2*u3)*q)*L1*L2*T[1] + - ((u0*u1+u0*u2+u1*u2+u0*u3+u1*u3+u2*u3)+(-u0*u1-u0*u2-u1*u2-u0*u3-u1*u3-u2*u3)*q)*L1^2*L2*T[1] + + ((u0+u1+u2+u3)+(-u0-u1-u2-u3)*q)*L1^3*L2*T[1] + q*L1^3*L2^2 sage: L1^2 * T1 * L1^3 * T1 - (-u0*u1*u2*u3+u0*u1*u2*u3*q)*L2*T[1] - + ((u0*u1*u2+u0*u1*u3+u0*u2*u3+u1*u2*u3)+(-u0*u1*u2-u0*u1*u3-u0*u2*u3-u1*u2*u3)*q)*L1*L2*T[1] - + ((-u0*u1-u0*u2-u1*u2-u0*u3-u1*u3-u2*u3)+(u0*u1+u0*u2+u1*u2+u0*u3+u1*u3+u2*u3)*q)*L1^2*L2*T[1] - + q*L1^2*L2^3 - + ((u0+u1+u2+u3)+(-u0-u1-u2-u3)*q)*L1^3*L2*T[1] - + (1-q)*L1^3*L2^2*T[1] + -(u0*u1*u2*u3-u0*u1*u2*u3*q)*L2*T[1] + + ((u0*u1*u2+u0*u1*u3+u0*u2*u3+u1*u2*u3)+(-u0*u1*u2-u0*u1*u3-u0*u2*u3-u1*u2*u3)*q)*L1*L2*T[1] + - ((u0*u1+u0*u2+u1*u2+u0*u3+u1*u3+u2*u3)+(-u0*u1-u0*u2-u1*u2-u0*u3-u1*u3-u2*u3)*q)*L1^2*L2*T[1] + + q*L1^2*L2^3 + + ((u0+u1+u2+u3)+(-u0-u1-u2-u3)*q)*L1^3*L2*T[1] + + (1-q)*L1^3*L2^2*T[1] sage: L1^2 * T1*T2*T1 * L2 * L3 * T2 (q-2*q^2+q^3)*L1^2*L2*L3 - (1-2*q+2*q^2-q^3)*L1^2*L2*L3*T[2] @@ -1061,7 +1061,7 @@ def _Li_power(self, i, m): sage: H = algebras.ArikiKoike(3, 2).LT() sage: L2 = H.L(2) sage: H._Li_power(2, 4) - ((u0^2*u1*u2+u0*u1^2*u2+u0*u1*u2^2)) + ... + ((u0^2*u1*u2+u0*u1^2*u2+u0*u1*u2^2)) ... - (q^-1-1)*L1*L2^3*T[1] ... - (q^-1-1)*L1^3*L2*T[1] sage: H._Li_power(2, 4) == L2^4 @@ -1078,20 +1078,20 @@ def _Li_power(self, i, m): L_1^0 = 1 L_1^1 = L1 L_1^2 = L1^2 - L_1^3 = u0*u1*u2 + ((-u0*u1-u0*u2-u1*u2))*L1 + ((u0+u1+u2))*L1^2 + L_1^3 = u0*u1*u2 - ((u0*u1+u0*u2+u1*u2))*L1 + ((u0+u1+u2))*L1^2 L_2^0 = 1 L_2^1 = L2 L_2^2 = L2^2 - L_2^3 = u0*u1*u2 + (-u0*u1*u2*q^-1+u0*u1*u2)*T[1] - + ((-u0*u1-u0*u2-u1*u2))*L2 + ((u0+u1+u2))*L2^2 + L_2^3 = u0*u1*u2 - (u0*u1*u2*q^-1-u0*u1*u2)*T[1] + - ((u0*u1+u0*u2+u1*u2))*L2 + ((u0+u1+u2))*L2^2 + ((u0+u1+u2)*q^-1+(-u0-u1-u2))*L1*L2*T[1] - (q^-1-1)*L1*L2^2*T[1] - (q^-1-1)*L1^2*L2*T[1] L_3^0 = 1 L_3^1 = L3 L_3^2 = L3^2 - L_3^3 = u0*u1*u2 + (-u0*u1*u2*q^-1+u0*u1*u2)*T[2] - + (-u0*u1*u2*q^-2+u0*u1*u2*q^-1)*T[2,1,2] - + ((-u0*u1-u0*u2-u1*u2))*L3 + ((u0+u1+u2))*L3^2 + L_3^3 = u0*u1*u2 - (u0*u1*u2*q^-1-u0*u1*u2)*T[2] + - (u0*u1*u2*q^-2-u0*u1*u2*q^-1)*T[2,1,2] + - ((u0*u1+u0*u2+u1*u2))*L3 + ((u0+u1+u2))*L3^2 + ((u0+u1+u2)*q^-1+(-u0-u1-u2))*L2*L3*T[2] - (q^-1-1)*L2*L3^2*T[2] - (q^-1-1)*L2^2*L3*T[2] + ((u0+u1+u2)*q^-2+(-2*u0-2*u1-2*u2)*q^-1+(u0+u1+u2))*L1*L3*T[1,2] @@ -1376,11 +1376,11 @@ def L(self, i=None): sage: T = algebras.ArikiKoike(1, 3).T() sage: T.L(2) - u + (-u*q^-1+u)*T[1] + u - (u*q^-1-u)*T[1] sage: T.L() [u, - u + (-u*q^-1+u)*T[1], - u + (-u*q^-1+u)*T[2] + (-u*q^-2+u*q^-1)*T[2,1,2]] + u - (u*q^-1-u)*T[1], + u - (u*q^-1-u)*T[2] - (u*q^-2-u*q^-1)*T[2,1,2]] TESTS: @@ -1432,10 +1432,10 @@ def product_on_basis(self, m1, m2): sage: T2 * (T2 * T1 * T0) -(1-q)*T[2,1,0] + q*T[1,0] sage: (T1 * T0 * T1 * T0) * T0 - (-u0*u1)*T[1,0,1] + ((u0+u1))*T[0,1,0,1] + -u0*u1*T[1,0,1] + ((u0+u1))*T[0,1,0,1] sage: (T0 * T1 * T0 * T1) * (T0 * T1) - (-u0*u1*q)*T[1,0] + (u0*u1-u0*u1*q)*T[1,0,1] - + ((u0+u1)*q)*T[0,1,0] + ((-u0-u1)+(u0+u1)*q)*T[0,1,0,1] + -u0*u1*q*T[1,0] + (u0*u1-u0*u1*q)*T[1,0,1] + + ((u0+u1)*q)*T[0,1,0] - ((u0+u1)+(-u0-u1)*q)*T[0,1,0,1] sage: T1 * (T0 * T2 * T1 * T0) T[1,0,2,1,0] sage: (T1 * T2) * (T2 * T1 * T0) @@ -1462,7 +1462,7 @@ def product_on_basis(self, m1, m2): sage: T = algebras.ArikiKoike(2, 3).T() sage: T0, T1, T2 = T.T() sage: (T1 * T0 * T1) * (T0 * T0) - (-u0*u1)*T[1,0,1] + ((u0+u1))*T[0,1,0,1] + -u0*u1*T[1,0,1] + ((u0+u1))*T[0,1,0,1] sage: T1 * T.L(3) * T2 * T1 * T0 - T1 * (T.L(3) * T2 * T1 * T0) 0 @@ -1674,19 +1674,19 @@ def _product_TT(self, kp, a, k, b): sage: T._product_TT(1, 2, 0, 1) T[1,0,0,0] sage: T._product_TT(1, 3, 0, 1) - (-u0*u1*u2*u3)*T[1] + -u0*u1*u2*u3*T[1] + ((u0*u1*u2+u0*u1*u3+u0*u2*u3+u1*u2*u3))*T[1,0] - + ((-u0*u1-u0*u2-u1*u2-u0*u3-u1*u3-u2*u3))*T[1,0,0] + - ((u0*u1+u0*u2+u1*u2+u0*u3+u1*u3+u2*u3))*T[1,0,0] + ((u0+u1+u2+u3))*T[1,0,0,0] sage: T._product_TT(1, 2, 0, 2) - (-u0*u1*u2*u3)*T[1] + -u0*u1*u2*u3*T[1] + ((u0*u1*u2+u0*u1*u3+u0*u2*u3+u1*u2*u3))*T[1,0] - + ((-u0*u1-u0*u2-u1*u2-u0*u3-u1*u3-u2*u3))*T[1,0,0] + - ((u0*u1+u0*u2+u1*u2+u0*u3+u1*u3+u2*u3))*T[1,0,0] + ((u0+u1+u2+u3))*T[1,0,0,0] sage: T._product_TT(2, 1, 0, 3) - (-u0*u1*u2*u3)*T[2,1] + -u0*u1*u2*u3*T[2,1] + ((u0*u1*u2+u0*u1*u3+u0*u2*u3+u1*u2*u3))*T[2,1,0] - + ((-u0*u1-u0*u2-u1*u2-u0*u3-u1*u3-u2*u3))*T[2,1,0,0] + - ((u0*u1+u0*u2+u1*u2+u0*u3+u1*u3+u2*u3))*T[2,1,0,0] + ((u0+u1+u2+u3))*T[2,1,0,0,0] TESTS:: @@ -1694,22 +1694,19 @@ def _product_TT(self, kp, a, k, b): sage: H = algebras.ArikiKoike(3, 4) sage: T = H.T() sage: T._product_TT(1, 2, 1, 2) - (-u0*u1*u2+u0*u1*u2*q)*T[1,0] - + (u0*u1*u2-u0*u1*u2*q)*T[0,1] + -(u0*u1*u2-u0*u1*u2*q)*T[1,0] + (u0*u1*u2-u0*u1*u2*q)*T[0,1] + ((u0+u1+u2)+(-u0-u1-u2)*q)*T[0,1,0,0] - + ((-u0-u1-u2)+(u0+u1+u2)*q)*T[0,0,1,0] - + T[0,0,1,0,0,1] + - ((u0+u1+u2)+(-u0-u1-u2)*q)*T[0,0,1,0] + T[0,0,1,0,0,1] sage: T._product_TT(2,2,2,2) - (-u0*u1*u2+u0*u1*u2*q)*T[2,1,0,2] + -(u0*u1*u2-u0*u1*u2*q)*T[2,1,0,2] + (u0*u1*u2-u0*u1*u2*q)*T[1,0,2,1] + ((u0+u1+u2)+(-u0-u1-u2)*q)*T[1,0,2,1,0,0] - + ((-u0-u1-u2)+(u0+u1+u2)*q)*T[1,0,0,2,1,0] - + T[1,0,0,2,1,0,0,1] + - ((u0+u1+u2)+(-u0-u1-u2)*q)*T[1,0,0,2,1,0] + T[1,0,0,2,1,0,0,1] sage: T._product_TT(3,2,3,2) - (-u0*u1*u2+u0*u1*u2*q)*T[3,2,1,0,3,2] + -(u0*u1*u2-u0*u1*u2*q)*T[3,2,1,0,3,2] + (u0*u1*u2-u0*u1*u2*q)*T[2,1,0,3,2,1] + ((u0+u1+u2)+(-u0-u1-u2)*q)*T[2,1,0,3,2,1,0,0] - + ((-u0-u1-u2)+(u0+u1+u2)*q)*T[2,1,0,0,3,2,1,0] + - ((u0+u1+u2)+(-u0-u1-u2)*q)*T[2,1,0,0,3,2,1,0] + T[2,1,0,0,3,2,1,0,0,1] """ # Quadratic relation: S_i^2 - (q - 1) S_i - q == 0 diff --git a/src/sage/algebras/hecke_algebras/cubic_hecke_algebra.py b/src/sage/algebras/hecke_algebras/cubic_hecke_algebra.py index 514d9b035d7..ac5d9b945f7 100644 --- a/src/sage/algebras/hecke_algebras/cubic_hecke_algebra.py +++ b/src/sage/algebras/hecke_algebras/cubic_hecke_algebra.py @@ -30,9 +30,9 @@ sage: braid = BG3((1,2,-1,2,2,-1)); braid c0*c1*c0^-1*c1^2*c0^-1 sage: braid_image = CHA3(braid); braid_image - u*c1*c0^-1*c1 + u*v*c0*c1^-1*c0^-1 + (-u^2)*c0^-1*c1 + u*c1*c0^-1*c1 + u*v*c0*c1^-1*c0^-1 - u^2*c0^-1*c1 + ((u^2*v-v^2)/w)*c0*c1*c0^-1 + ((u^2-v)/w)*c0*c1*c0 - + ((-u^3+u*v)/w)*c0*c1 + (-u*v+w)*c1^-1 + - ((u^3-u*v)/w)*c0*c1 - (u*v-w)*c1^-1 If the ring elements `u, v, w` (which will be called the *cubic equation parameters* in the sequel) are taken to be `u = v = 0, w = 1` the cubic Hecke @@ -73,7 +73,7 @@ sage: CHA3 = algebras.CubicHecke(3) sage: c1, c2 = CHA3.gens() sage: b = c1^2*c2 - c2*c1^2 - c1*c2^2 + c2^2*c1; b - w*c0^-1*c1 + (-w)*c0*c1^-1 + (-w)*c1*c0^-1 + w*c1^-1*c0 + w*c0^-1*c1 - w*c0*c1^-1 - w*c1*c0^-1 + w*c1^-1*c0 sage: b2 = b*b sage: b3 = b2*b sage: BR = CHA3.base_ring() @@ -151,10 +151,10 @@ class CubicHeckeElement(CombinatorialFreeModule.Element): EXAMPLES:: sage: CHA3s = algebras.CubicHecke('s1, s2'); CHA3s.an_element() - (-w)*s1*s2^-1 + v*s1 + u*s2 + ((-v*w+u)/w) + -w*s1*s2^-1 + v*s1 + u*s2 - ((v*w-u)/w) sage: CHA3. = algebras.CubicHecke(3) sage: c1**3*~c2 - u*w*c1^-1*c2^-1 + (u^2-v)*c1*c2^-1 + (-u*v+w)*c2^-1 + u*w*c1^-1*c2^-1 + (u^2-v)*c1*c2^-1 - (u*v-w)*c2^-1 """ # -------------------------------------------------------------------------- # Overloading inherited methods @@ -173,11 +173,11 @@ def __invert__(self): sage: CHA2 = algebras.CubicHecke(2) sage: x = CHA2.an_element(); x - v*c + ((-v*w+u)/w) + v*c - ((v*w-u)/w) sage: ~x Traceback (most recent call last): ... - ValueError: cannot invert self (= v*c + ((-v*w+u)/w)) + ValueError: cannot invert self (= v*c - ((v*w-u)/w)) """ self_Tietze = self.Tietze() @@ -206,7 +206,7 @@ def Tietze(self): sage: CHA3 = algebras.CubicHecke(3) sage: ele = CHA3.an_element(); ele - (-w)*c0*c1^-1 + v*c0 + u*c1 + ((-v*w+u)/w) + -w*c0*c1^-1 + v*c0 + u*c1 - ((v*w-u)/w) sage: ele.Tietze() is None True sage: [CHA3(sp).Tietze() for sp in ele.support()] @@ -228,7 +228,7 @@ def max_len(self): sage: CHA3 = algebras.CubicHecke(3) sage: ele = CHA3.an_element(); ele - (-w)*c0*c1^-1 + v*c0 + u*c1 + ((-v*w+u)/w) + -w*c0*c1^-1 + v*c0 + u*c1 - ((v*w-u)/w) sage: ele.max_len() 2 """ @@ -248,9 +248,9 @@ def braid_group_algebra_pre_image(self): sage: CHA3 = algebras.CubicHecke(3) sage: ele = CHA3.an_element(); ele - (-w)*c0*c1^-1 + v*c0 + u*c1 + ((-v*w+u)/w) + -w*c0*c1^-1 + v*c0 + u*c1 - ((v*w-u)/w) sage: b_ele = ele.braid_group_algebra_pre_image(); b_ele - ((-v*w+u)/w) + v*c0 + u*c1 + (-w)*c0*c1^-1 + -((v*w-u)/w) + v*c0 + u*c1 - w*c0*c1^-1 sage: ele in CHA3 True sage: b_ele in CHA3 @@ -281,9 +281,9 @@ def cubic_braid_group_algebra_pre_image(self): sage: CHA3 = algebras.CubicHecke(3) sage: ele = CHA3.an_element(); ele - (-w)*c0*c1^-1 + v*c0 + u*c1 + ((-v*w+u)/w) + -w*c0*c1^-1 + v*c0 + u*c1 - ((v*w-u)/w) sage: cb_ele = ele.cubic_braid_group_algebra_pre_image(); cb_ele - (-w)*c0*c1^-1 + v*c0 + u*c1 + ((-v*w+u)/w) + -w*c0*c1^-1 + v*c0 + u*c1 - ((v*w-u)/w) sage: ele in CHA3 True sage: cb_ele in CHA3 @@ -455,7 +455,7 @@ def revert_orientation(self): sage: CHA3. = algebras.CubicHecke(3) sage: e = CHA3.an_element() sage: e.revert_orientation() - (-w)*c2^-1*c1 + v*c1 + u*c2 + ((-v*w+u)/w) + -w*c2^-1*c1 + v*c1 + u*c2 - ((v*w-u)/w) sage: _.revert_orientation() == e True """ @@ -518,7 +518,7 @@ def formal_markov_trace(self, extended=False, field_embedding=False): sage: K3_1 = KnotInfo.K3_1 sage: b3_1 = CHA2(K3_1.braid()) sage: mt3_1 = b3_1.formal_markov_trace(); mt3_1 - ((u^2*s^2-v*s^2+u*w)/s)*B[U1] + (-u*v+w)*B[U2] + ((u^2*s^2-v*s^2+u*w)/s)*B[U1] - (u*v-w)*B[U2] sage: mt3_1.parent() Free module generated by {U1, U2} over Multivariate Polynomial Ring in u, v, w, s @@ -534,7 +534,7 @@ def formal_markov_trace(self, extended=False, field_embedding=False): sage: f = b3_1.formal_markov_trace(extended=True, field_embedding=True); f ((a^2*b*c+a*b^2*c+a*b*c^2+a^2*s^2+a*b*s^2+b^2*s^2+a*c*s^2+b*c*s^2+c^2*s^2)/s)*B[U1] - + (-a^2*b-a*b^2-a^2*c-2*a*b*c-b^2*c-a*c^2-b*c^2)*B[U2] + - (a^2*b+a*b^2+a^2*c+2*a*b*c+b^2*c+a*c^2+b*c^2)*B[U2] sage: f.parent().base_ring() Fraction Field of Multivariate Polynomial Ring in a, b, c, s over Cyclotomic Field of order 3 and degree 2 @@ -699,19 +699,19 @@ class CubicHeckeAlgebra(CombinatorialFreeModule): Element construction:: sage: ele = CHA3.an_element(); ele - (-w)*s1*s2^-1 + v*s1 + u*s2 + ((-v*w+u)/w) + -w*s1*s2^-1 + v*s1 + u*s2 - ((v*w-u)/w) sage: ele2 = ele**2; ele2 - w^2*(s1^-1*s2)^2 + (-u*w^2)*s1^-1*s2*s1^-1 + (-v*w)*s2*s1^-1*s2 - + (-v*w^2)*s1^-1*s2^-1 + u*w*s1*s2*s1^-1*s2 + (-u*w)*s1^-1*s2*s1 - + (-u*v*w+2*v*w-2*u)*s1*s2^-1 + u*v*w*s2*s1^-1 + u*v*s2*s1 + v^2*w*s1^-1 - + (-u^2*w)*s1*s2*s1^-1 + ((u*v^2*w-2*v^2*w-u*w^2+2*u*v)/w)*s1 - + u*v*s1*s2 + (u^2*w+v^2*w)*s2^-1 + ((u^3*w-2*u*v*w+2*u^2)/w)*s2 - + ((-u^2*v*w^2-v^3*w^2+v^2*w^2-2*u*v*w+u^2)/w^2) + w^2*(s1^-1*s2)^2 - u*w^2*s1^-1*s2*s1^-1 - v*w*s2*s1^-1*s2 + - v*w^2*s1^-1*s2^-1 + u*w*s1*s2*s1^-1*s2 - u*w*s1^-1*s2*s1 + - (u*v*w-2*v*w+2*u)*s1*s2^-1 + u*v*w*s2*s1^-1 + u*v*s2*s1 + v^2*w*s1^-1 + - u^2*w*s1*s2*s1^-1 + ((u*v^2*w-2*v^2*w-u*w^2+2*u*v)/w)*s1 + u*v*s1*s2 + + (u^2*w+v^2*w)*s2^-1 + ((u^3*w-2*u*v*w+2*u^2)/w)*s2 + - ((u^2*v*w^2+v^3*w^2-v^2*w^2+2*u*v*w-u^2)/w^2) sage: B3 = CHA3.braid_group() sage: braid = B3((2,-1, 2, 1)); braid s2*s1^-1*s2*s1 sage: ele3 = CHA3(braid); ele3 - s1*s2*s1^-1*s2 + u*s1^-1*s2*s1 + (-v)*s1*s2^-1 + v*s2^-1*s1 + (-u)*s1*s2*s1^-1 + s1*s2*s1^-1*s2 + u*s1^-1*s2*s1 - v*s1*s2^-1 + v*s2^-1*s1 - u*s1*s2*s1^-1 sage: ele3t = CHA3((2,-1, 2, 1)) sage: ele3 == ele3t True @@ -1185,7 +1185,7 @@ def _element_constructor_(self, x): sage: cb2 = cb**2 sage: CHA2 = algebras.CubicHecke(2) sage: CHA2(b2) - w*c^-1 + u*c + (-v) + w*c^-1 + u*c - v sage: CHA2(cb2) c^-1 sage: CHA3 = algebras.CubicHecke(3) @@ -1195,10 +1195,10 @@ def _element_constructor_(self, x): sage: braid = B3((1,2,2,-1,2,1,1,-1)); braid c0*c1^2*c0^-1*c1*c0 sage: img_braid = CHA3(braid); img_braid - u*w*(c0^-1*c1)^2 + u*v*c0*c1^-1*c0 + (-u^2*w)*c0^-1*c1*c0^-1 - + (-u*v)*c1*c0^-1*c1 + (-u*v*w+w^2)*c0^-1*c1^-1 + u^2*c0*c1*c0^-1*c1 - + (-u^2*v+u*w)*c0*c1^-1 + u^2*v*c1*c0^-1 + (u^2-v)*c1*c0 - + (-u^3)*c0*c1*c0^-1 + (u*v^2-v*w)*c1^-1 + u*w*(c0^-1*c1)^2 + u*v*c0*c1^-1*c0 - u^2*w*c0^-1*c1*c0^-1 + - u*v*c1*c0^-1*c1 - (u*v*w-w^2)*c0^-1*c1^-1 + u^2*c0*c1*c0^-1*c1 + - (u^2*v-u*w)*c0*c1^-1 + u^2*v*c1*c0^-1 + (u^2-v)*c1*c0 + - u^3*c0*c1*c0^-1 + (u*v^2-v*w)*c1^-1 sage: cbraid = CB3(braid); cbraid c0*c1^2*c0^-1*c1*c0 sage: img_cbraid = CHA3(cbraid); img_cbraid @@ -1461,7 +1461,7 @@ def _an_element_(self): sage: CHA2 = algebras.CubicHecke(2) sage: CHA2.an_element() # indirect doctest - v*c + ((-v*w+u)/w) + v*c - ((v*w-u)/w) """ n = self.ngens() + 1 base_ring = self.base_ring() @@ -1535,7 +1535,7 @@ def product_on_basis(self, g1, g2): sage: CHA3.product_on_basis(g, ~g) 1 sage: CHA3.product_on_basis(g, g) - w*c0^-1*c1*c0 + (-v)*c1*c0 + u*c0*c1*c0 + w*c0^-1*c1*c0 - v*c1*c0 + u*c0*c1*c0 """ # ---------------------------------------------------------------------- # short way for multiplications with one @@ -1912,12 +1912,12 @@ def _braid_image_from_filecache(self, braid): sage: CHA3 = algebras.CubicHecke(3) sage: b1, b2 = CHA3.braid_group().gens(); br = ~b2*b1*~b2 sage: CHA3._braid_image_from_filecache(br) - 1/w*c0*c1*c0^-1*c1 + v/w*c1^-1*c0 + ((-u)/w)*c0*c1*c0^-1 + 1/w*c0*c1*c0^-1*c1 + v/w*c1^-1*c0 - u/w*c0*c1*c0^-1 sage: F = CHA3.base_ring().fraction_field() sage: par = tuple([F(p) for p in CHA3.cubic_equation_parameters()]) sage: CHA3F = algebras.CubicHecke(3, cubic_equation_parameters=par) sage: CHA3F._braid_image_from_filecache(br) - 1/w*c0*c1*c0^-1*c1 + v/w*c1^-1*c0 + ((-u)/w)*c0*c1*c0^-1 + 1/w*c0*c1*c0^-1*c1 + v/w*c1^-1*c0 - u/w*c0*c1*c0^-1 sage: section = CHA3.filecache_section().braid_images sage: CHA3.reset_filecache(section) sage: CHA3._braid_image_from_filecache(br) @@ -1954,7 +1954,7 @@ def _braid_image_to_filecache(self, braid_tietze, braid_image_vect): True sage: CHA2._braid_image_to_filecache(br2.Tietze(), CHA2(br2).to_vector()) sage: CHA2._braid_image_from_filecache(br2) - w*c^-1 + u*c + (-v) + w*c^-1 + u*c - v sage: CHA2.reset_filecache(CHA2.filecache_section().braid_images) sage: CHA2._braid_image_from_filecache(br2) == None True @@ -1986,7 +1986,7 @@ def _braid_image(self, braid): sage: CHA2 = algebras.CubicHecke(2) sage: br, = CHA2.braid_group().gens(); br2 = br**2 sage: CHA2._braid_image(br2) - w*c^-1 + u*c + (-v) + w*c^-1 + u*c - v """ # ---------------------------------------------------------------------- # first use the cubic equation to express the braid as a linear @@ -2029,7 +2029,7 @@ def _braid_image_from_reduced_powers(self, braid_tietze): sage: CHA3._braid_image_from_reduced_powers((1, -2, 1)) c0*c1^-1*c0 sage: CHA3._braid_image_from_reduced_powers((1, -2, 1, 2)) - w*c0^-1*c1*c0^-1 + (-v)*c1*c0^-1 + u*c0*c1*c0^-1 + w*c0^-1*c1*c0^-1 - v*c1*c0^-1 + u*c0*c1*c0^-1 """ n = self.ngens() braid_list = list(braid_tietze) @@ -2853,7 +2853,7 @@ def garside_involution(self, element): sage: CHA3 = algebras.CubicHecke(3) sage: ele = CHA3.an_element() sage: ele_gar = CHA3.garside_involution(ele); ele_gar - (-w)*c1*c0^-1 + u*c0 + v*c1 + ((-v*w+u)/w) + -w*c1*c0^-1 + u*c0 + v*c1 - ((v*w-u)/w) sage: ele == CHA3.garside_involution(ele_gar) True """ @@ -2891,7 +2891,7 @@ def orientation_antiinvolution(self, element): sage: CHA3 = algebras.CubicHecke(3) sage: ele = CHA3.an_element() sage: ele_ori = CHA3.orientation_antiinvolution(ele); ele_ori - (-w)*c1^-1*c0 + v*c0 + u*c1 + ((-v*w+u)/w) + -w*c1^-1*c0 + v*c0 + u*c1 - ((v*w-u)/w) sage: ele == CHA3.orientation_antiinvolution(ele_ori) True """ diff --git a/src/sage/algebras/hecke_algebras/cubic_hecke_base_ring.py b/src/sage/algebras/hecke_algebras/cubic_hecke_base_ring.py index 1b011c68c61..ff997d29cde 100644 --- a/src/sage/algebras/hecke_algebras/cubic_hecke_base_ring.py +++ b/src/sage/algebras/hecke_algebras/cubic_hecke_base_ring.py @@ -1334,7 +1334,7 @@ def specialize_homfly(self): From: Multivariate Polynomial Ring in u, v, w, s over Integer Ring localized at (s, w, v, u) To: Multivariate Polynomial Ring in L, M - over Integer Ring localized at (M, M - 1, L) + over Integer Ring localized at (M - 1, M, L) Defn: u |--> -M + 1 v |--> -M + 1 w |--> 1 @@ -1342,7 +1342,7 @@ def specialize_homfly(self): then Conversion map: From: Multivariate Polynomial Ring in L, M - over Integer Ring localized at (M, M - 1, L) + over Integer Ring localized at (M - 1, M, L) To: Multivariate Laurent Polynomial Ring in L, M over Integer Ring sage: sup = mt.support() diff --git a/src/sage/algebras/iwahori_hecke_algebra.py b/src/sage/algebras/iwahori_hecke_algebra.py index ecc6788979b..8162873a651 100644 --- a/src/sage/algebras/iwahori_hecke_algebra.py +++ b/src/sage/algebras/iwahori_hecke_algebra.py @@ -1703,12 +1703,12 @@ class Element(CombinatorialFreeModule.Element): sage: R. = QQ[] sage: H = IwahoriHeckeAlgebra("A2", q1, q2=q2).T(prefix='x') sage: sum(H.algebra_generators())^2 - x[2,1] + x[1,2] + (q1+q2)*x[1] + (q1+q2)*x[2] + (-2*q1*q2) + x[2,1] + x[1,2] + (q1+q2)*x[1] + (q1+q2)*x[2] - 2*q1*q2 sage: H = IwahoriHeckeAlgebra("A2", q1, q2=q2).T(prefix='t') sage: t1,t2 = H.algebra_generators() sage: (t1-t2)^3 - (q1^2-q1*q2+q2^2)*t[1] + (-q1^2+q1*q2-q2^2)*t[2] + (q1^2-q1*q2+q2^2)*t[1] - (q1^2-q1*q2+q2^2)*t[2] sage: R. = QQ[] sage: H = IwahoriHeckeAlgebra("G2", q).T() diff --git a/src/sage/algebras/lie_algebras/examples.py b/src/sage/algebras/lie_algebras/examples.py index f2db23d445b..dc9c76ce605 100644 --- a/src/sage/algebras/lie_algebras/examples.py +++ b/src/sage/algebras/lie_algebras/examples.py @@ -85,7 +85,7 @@ def three_dimensional(R, a, b, c, d, names=['X', 'Y', 'Z']): sage: Q. = PolynomialRing(QQ) sage: L = lie_algebras.three_dimensional(Q, a, b, c, d) sage: L.structure_coefficients() - Finite family {('X', 'Y'): d*Y + a*Z, ('X', 'Z'): (-c)*Y + (-d)*Z, ('Y', 'Z'): b*X} + Finite family {('X', 'Y'): d*Y + a*Z, ('X', 'Z'): -c*Y - d*Z, ('Y', 'Z'): b*X} sage: TestSuite(L).run() """ if isinstance(names, str): diff --git a/src/sage/algebras/quantum_groups/q_numbers.py b/src/sage/algebras/quantum_groups/q_numbers.py index 19ee17df5ca..cdde70cd4b8 100644 --- a/src/sage/algebras/quantum_groups/q_numbers.py +++ b/src/sage/algebras/quantum_groups/q_numbers.py @@ -7,15 +7,15 @@ typically used in combinatorics (see :mod:`sage.combinat.q_analogues`). """ -#***************************************************************************** +# *************************************************************************** # Copyright (C) 2013-2017 Travis Scrimshaw # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# *************************************************************************** from sage.misc.misc_c import prod from sage.rings.integer_ring import ZZ @@ -181,7 +181,8 @@ def q_binomial(n, k, q=None): TESTS:: sage: from sage.algebras.quantum_groups.q_numbers import q_binomial - sage: all(q_binomial(n, k, 1) == binomial(n, k) for n in range(7) for k in range(n+1)) + sage: all(q_binomial(n, k, 1) == binomial(n, k) + ....: for n in range(6) for k in range(n+1)) True sage: q_binomial(-2, 1) Traceback (most recent call last): @@ -190,13 +191,13 @@ def q_binomial(n, k, q=None): """ # sanity checks if not (n in ZZ and k in ZZ): - raise ValueError("arguments ({}, {}) must be integers".format(n, k)) + raise ValueError(f"arguments ({n}, {k}) must be integers") if n < 0: raise ValueError('n must be nonnegative') - if not (0 <= k and k <= n): + if not (0 <= k <= n): return 0 - k = min(n - k, k) # Pick the smallest k + k = min(n - k, k) # Pick the smallest k denomin = q_factorial(n - k, q) * q_factorial(k, q) numerat = q_factorial(n, q) try: diff --git a/src/sage/arith/misc.py b/src/sage/arith/misc.py index 637ed9192bd..5525fae666c 100644 --- a/src/sage/arith/misc.py +++ b/src/sage/arith/misc.py @@ -1457,11 +1457,11 @@ def random_prime(n, proof=None, lbound=2): lbound = max(2, lbound) if lbound > 2: if lbound == 3 or n <= 2*lbound - 2: - # check for Betrand's postulate (proved by Chebyshev) + # check for Betrand's postulate (proved by Chebyshev) if lbound < 25 or n <= 6*lbound/5: - # see J. Nagura, Proc. Japan Acad. 28, (1952). 177-181. + # see J. Nagura, Proc. Japan Acad. 28, (1952). 177-181 if lbound < 2010760 or n <= 16598*lbound/16597: - # see L. Schoenfeld, Math. Comp. 30 (1976), no. 134, 337-360. + # see L. Schoenfeld, Math. Comp. 30 (1976), no 134, 337-360 if proof: smallest_prime = ZZ(lbound-1).next_prime() else: @@ -2060,7 +2060,7 @@ def xgcd(a, b=None): sage: h = R.base_ring().gen() sage: S. = R.fraction_field()[] sage: xgcd(y^2, a*h*y + b) - (1, 7*a^2/b^2, (((-h)*a)/b^2)*y + 1/b) + (1, 7*a^2/b^2, (((-7)*a)/(h*b^2))*y + 7/(7*b)) Tests with randomly generated integers:: diff --git a/src/sage/calculus/interpolators.pyx b/src/sage/calculus/interpolators.pyx index c13fcff8f93..6ad950c28d7 100644 --- a/src/sage/calculus/interpolators.pyx +++ b/src/sage/calculus/interpolators.pyx @@ -223,7 +223,7 @@ cdef class CCSpline: cdef int N cdef np.ndarray avec, bvec, cvec, dvec - #standard cubic interpolation method + # standard cubic interpolation method def __init__(self, pts): """ TESTS:: diff --git a/src/sage/calculus/riemann.pyx b/src/sage/calculus/riemann.pyx index 455567371eb..b52997530b8 100644 --- a/src/sage/calculus/riemann.pyx +++ b/src/sage/calculus/riemann.pyx @@ -267,7 +267,7 @@ cdef class Riemann_Map: ymax = cps.imag.max() ymin = cps.imag.min() space = 0.1 * max(xmax - xmin, ymax - ymin) - #The default plotting window for this map. + # The default plotting window for this map. self.cps = cps self.dps = dps self.x_range = (xmin - space, xmax + space) @@ -1134,10 +1134,10 @@ cpdef get_derivatives(np.ndarray[COMPLEX_T, ndim=2] z_values, FLOAT_T xstep, cdef np.ndarray[FLOAT_T, ndim = 2] dr, dtheta, zabs imax = len(z_values)-2 jmax = len(z_values[0])-2 - #(f(x+delta)-f(x-delta))/2delta + # (f(x+delta)-f(x-delta))/2delta xderiv = (z_values[1:-1,2:]-z_values[1:-1,:-2])/(2*xstep) - #b/c the function is analytic, we know the magnitude of its - #derivative is equal in all directions + # b/c the function is analytic, we know the magnitude of its + # derivative is equal in all directions dr = np.abs(xderiv) # the abs(derivative) scaled by distance from origin zabs = np.abs(z_values[1:-1,1:-1]) @@ -1242,15 +1242,15 @@ cpdef complex_to_spiderweb(np.ndarray[COMPLEX_T, ndim = 2] z_values, spoke_angles = srange(-PI,PI+TWOPI/spokes,TWOPI/spokes) else: spoke_angles = [] - for i in range(imax-2): # the d arrays are 1 smaller on each side + for i in range(imax-2): # the d arrays are 1 smaller on each side for j in range(jmax-2): z = z_values[i+1,j+1] mag = abs(z) arg = phase(z) dmag = dr[i,j] darg = dtheta[i,j] - #points that change too rapidly are presumed to be borders - #points that are too small are presumed to be outside + # points that change too rapidly are presumed to be borders + # points that are too small are presumed to be outside if darg < DMAX and mag > min_mag: for target in circ_radii: if abs(mag - target)/dmag < precision: diff --git a/src/sage/calculus/wester.py b/src/sage/calculus/wester.py index 21c6865d0cb..65c270da5a3 100644 --- a/src/sage/calculus/wester.py +++ b/src/sage/calculus/wester.py @@ -477,7 +477,7 @@ sage: d a^3*b^2*c - a^2*b^3*c - a^3*b*c^2 + a*b^3*c^2 + a^2*b*c^3 - a*b^2*c^3 - a^3*b^2*d + a^2*b^3*d + a^3*c^2*d - b^3*c^2*d - a^2*c^3*d + b^2*c^3*d + a^3*b*d^2 - a*b^3*d^2 - a^3*c*d^2 + b^3*c*d^2 + a*c^3*d^2 - b*c^3*d^2 - a^2*b*d^3 + a*b^2*d^3 + a^2*c*d^3 - b^2*c*d^3 - a*c^2*d^3 + b*c^2*d^3 sage: d.factor() - (-1) * (c - d) * (-b + c) * (b - d) * (-a + c) * (-a + b) * (a - d) + (-1) * (-a + c) * (-a + b) * (-b + c) * (c - d) * (b - d) * (a - d) :: diff --git a/src/sage/categories/commutative_rings.py b/src/sage/categories/commutative_rings.py index f67990df978..59da67d1e46 100644 --- a/src/sage/categories/commutative_rings.py +++ b/src/sage/categories/commutative_rings.py @@ -59,6 +59,67 @@ class CommutativeRings(CategoryWithAxiom): False """ class ParentMethods: + def krull_dimension(self): + """ + Return the Krull dimension of this commutative ring. + + The Krull dimension is the length of the longest ascending chain + of prime ideals. + + This raises :exc:`NotImplementedError` by default + for generic commutative rings. + + Fields and PIDs, with Krull dimension equal to 0 and 1, + respectively, have naive implementations of ``krull_dimension``. + Orders in number fields also have Krull dimension 1. + + EXAMPLES: + + Some polynomial rings:: + + sage: T. = PolynomialRing(QQ,2); T + Multivariate Polynomial Ring in x, y over Rational Field + sage: T.krull_dimension() + 2 + sage: U. = PolynomialRing(ZZ,3); U + Multivariate Polynomial Ring in x, y, z over Integer Ring + sage: U.krull_dimension() + 4 + + All orders in number fields have Krull dimension 1, including + non-maximal orders:: + + sage: # needs sage.rings.number_field + sage: K. = QuadraticField(-1) + sage: R = K.order(2*i); R + Order of conductor 2 generated by 2*i + in Number Field in i with defining polynomial x^2 + 1 with i = 1*I + sage: R.is_maximal() + False + sage: R.krull_dimension() + 1 + sage: R = K.maximal_order(); R + Gaussian Integers generated by i in Number Field in i + with defining polynomial x^2 + 1 with i = 1*I + sage: R.krull_dimension() + 1 + + TESTS:: + + sage: R = CommutativeRing(ZZ) + sage: R.krull_dimension() + Traceback (most recent call last): + ... + NotImplementedError + + sage: R = GF(9).galois_group().algebra(QQ) + sage: R.krull_dimension() + Traceback (most recent call last): + ... + NotImplementedError + """ + raise NotImplementedError + def is_commutative(self) -> bool: """ Return whether the ring is commutative. diff --git a/src/sage/categories/coxeter_group_algebras.py b/src/sage/categories/coxeter_group_algebras.py index 32fe0292bb5..312dfd564c6 100644 --- a/src/sage/categories/coxeter_group_algebras.py +++ b/src/sage/categories/coxeter_group_algebras.py @@ -36,13 +36,13 @@ def demazure_lusztig_operator_on_basis(self, w, i, q1, q2, sage: KW = W.algebra(K) sage: w = W.an_element() sage: KW.demazure_lusztig_operator_on_basis(w, 0, q1, q2) - (-q2)*323123 + (q1+q2)*123 + -q2*323123 + (q1+q2)*123 sage: KW.demazure_lusztig_operator_on_basis(w, 1, q1, q2) q1*1231 sage: KW.demazure_lusztig_operator_on_basis(w, 2, q1, q2) q1*1232 sage: KW.demazure_lusztig_operator_on_basis(w, 3, q1, q2) - (q1+q2)*123 + (-q2)*12 + (q1+q2)*123 - q2*12 At `q_1=1` and `q_2=0` we recover the action of the isobaric divided differences `\pi_i`:: @@ -112,13 +112,13 @@ def demazure_lusztig_operators(self, q1, q2, side='right', affine=True): sage: x = KW.monomial(W.an_element()); x 123 sage: T[0](x) - (-q2)*323123 + (q1+q2)*123 + -q2*323123 + (q1+q2)*123 sage: T[1](x) q1*1231 sage: T[2](x) q1*1232 sage: T[3](x) - (q1+q2)*123 + (-q2)*12 + (q1+q2)*123 - q2*12 sage: T._test_relations() @@ -174,7 +174,7 @@ def demazure_lusztig_eigenvectors(self, q1, q2): Weyl Group of type ['B', 2] (as a matrix group acting on the ambient space) sage: w = W.an_element() sage: E[w] # needs sage.rings.number_field - (q2/(-q1+q2))*2121 + ((-q2)/(-q1+q2))*121 - 212 + 12 + (q2/(-q1+q2))*2121 - (q2/(-q1+q2))*121 - 212 + 12 """ W = self.basis().keys() if not W.cartan_type().is_finite(): diff --git a/src/sage/categories/dedekind_domains.py b/src/sage/categories/dedekind_domains.py index ae4a198423b..3be25caea61 100644 --- a/src/sage/categories/dedekind_domains.py +++ b/src/sage/categories/dedekind_domains.py @@ -53,30 +53,6 @@ def krull_dimension(self): sage: OK = K.ring_of_integers() # needs sage.rings.number_field sage: OK.krull_dimension() # needs sage.rings.number_field 1 - - The following are not Dedekind domains but have - a ``krull_dimension`` function:: - - sage: QQ.krull_dimension() - 0 - sage: T. = PolynomialRing(QQ,2); T - Multivariate Polynomial Ring in x, y over Rational Field - sage: T.krull_dimension() - 2 - sage: U. = PolynomialRing(ZZ,3); U - Multivariate Polynomial Ring in x, y, z over Integer Ring - sage: U.krull_dimension() - 4 - - sage: # needs sage.rings.number_field - sage: K. = QuadraticField(-1) - sage: R = K.order(2*i); R - Order of conductor 2 generated by 2*i - in Number Field in i with defining polynomial x^2 + 1 with i = 1*I - sage: R.is_maximal() - False - sage: R.krull_dimension() - 1 """ from sage.rings.integer_ring import ZZ return ZZ.one() diff --git a/src/sage/categories/fields.py b/src/sage/categories/fields.py index 98251904607..2868cd29d3e 100644 --- a/src/sage/categories/fields.py +++ b/src/sage/categories/fields.py @@ -192,6 +192,18 @@ def _call_(self, x): Finite = LazyImport('sage.categories.finite_fields', 'FiniteFields', at_startup=True) class ParentMethods: + def krull_dimension(self): + """ + Return the Krull dimension of this field, which is 0. + + EXAMPLES:: + + sage: QQ.krull_dimension() + 0 + sage: Frac(QQ['x,y']).krull_dimension() + 0 + """ + return 0 def is_field(self, proof=True): r""" @@ -673,6 +685,11 @@ def gcd(self, other): sage: gcd(0.0, 0.0) # needs sage.rings.real_mpfr 0.000000000000000 + TESTS:: + + sage: QQbar(0).gcd(QQbar.zeta(3)) + 1 + AUTHOR: - Simon King (2011-02) -- :issue:`10771` @@ -687,7 +704,7 @@ def gcd(self, other): from sage.rings.integer_ring import ZZ try: return P(ZZ(self).gcd(ZZ(other))) - except TypeError: + except (TypeError, ValueError): pass if self == P.zero() and other == P.zero(): diff --git a/src/sage/categories/finite_complex_reflection_groups.py b/src/sage/categories/finite_complex_reflection_groups.py index c834ccbef21..7bb9fda5a81 100644 --- a/src/sage/categories/finite_complex_reflection_groups.py +++ b/src/sage/categories/finite_complex_reflection_groups.py @@ -1227,8 +1227,8 @@ def milnor_fiber_complex(self): to_test.extend((hp, j) for j in Ip) cosets[Ip].append(frozenset(H)) verts = {} - for Ip in cosets: - for C in cosets[Ip]: + for Ip, cosetsIp in cosets.items(): + for C in cosetsIp: verts[C, Ip] = len(verts) facets = [[verts[k] for k in verts if g in k[0]] for g in self] from sage.topology.simplicial_complex import SimplicialComplex diff --git a/src/sage/categories/homset.py b/src/sage/categories/homset.py index 1b05cca4a52..5fd49d46ec9 100644 --- a/src/sage/categories/homset.py +++ b/src/sage/categories/homset.py @@ -663,10 +663,10 @@ def __init__(self, X, Y, category=None, base=None, check=True): if check: if not isinstance(category, Category): raise TypeError("category (=%s) must be a category" % category) - #if not X in category: - # raise TypeError, "X (=%s) must be in category (=%s)"%(X, category) - #if not Y in category: - # raise TypeError, "Y (=%s) must be in category (=%s)"%(Y, category) + # if not X in category: + # raise TypeError("X (=%s) must be in category (=%s)" % (X, category)) + # if not Y in category: + # raise TypeError("Y (=%s) must be in category (=%s)" % (Y, category)) if base is None and hasattr(category, "WithBasis"): # The above is a lame but fast check that category is a diff --git a/src/sage/categories/loop_crystals.py b/src/sage/categories/loop_crystals.py index e6bf9126876..a13925b8f6e 100644 --- a/src/sage/categories/loop_crystals.py +++ b/src/sage/categories/loop_crystals.py @@ -547,7 +547,7 @@ def is_perfect(self, ell=None): from sage.rings.integer_ring import ZZ if ell is None: if (self.cartan_type().dual().type() == 'BC' - and self.cartan_type().rank() - 1 == self.r()): + and self.cartan_type().rank() - 1 == self.r()): return True ell = self.s() / self.cartan_type().c()[self.r()] if ell not in ZZ: @@ -557,9 +557,9 @@ def is_perfect(self, ell=None): raise ValueError("perfectness not defined for non-integral levels") # [FOS2010]_ check - if self.cartan_type().classical().type() not in ['E','F','G']: + if self.cartan_type().classical().type() not in ['E', 'F', 'G']: if (self.cartan_type().dual().type() == 'BC' - and self.cartan_type().rank() - 1 == self.r()): + and self.cartan_type().rank() - 1 == self.r()): return ell == self.s() return ell == self.s() / self.cartan_type().c()[self.r()] @@ -580,9 +580,9 @@ def is_perfect(self, ell=None): rank = len(I) La = self.weight_lattice_realization().basis() from sage.combinat.integer_vector import IntegerVectors - for n in range(1, ell+1): + for n in range(1, ell + 1): for c in IntegerVectors(n, rank): - w = sum(c[i]*La[i] for i in I) + w = sum(c[i] * La[i] for i in I) if w.level() == ell: weights.append(w) return sorted(b.Phi() for b in MPhi) == sorted(weights) @@ -629,7 +629,7 @@ def level(self): if not self.is_perfect(): raise ValueError("this crystal is not perfect") if (self.cartan_type().dual().type() == 'BC' - and self.cartan_type().rank() - 1 == self.r()): + and self.cartan_type().rank() - 1 == self.r()): return self.s() return self.s() / self.cartan_type().c()[self.r()] @@ -764,7 +764,7 @@ def classically_highest_weight_vectors(self): """ n = len(self.crystals) I0 = self.cartan_type().classical().index_set() - it = [ iter(self.crystals[-1].classically_highest_weight_vectors()) ] + it = [iter(self.crystals[-1].classically_highest_weight_vectors())] path = [] ret = [] while it: @@ -784,7 +784,7 @@ def classically_highest_weight_vectors(self): ret.append(b) path.pop(0) else: - it.append( iter(self.crystals[-len(path)-1]) ) + it.append(iter(self.crystals[-len(path) - 1])) return tuple(ret) # TODO: This is duplicated in KR crystals category @@ -873,9 +873,10 @@ def one_dimensional_configuration_sum(self, q=None, group_components=True): if group_components: G = self.digraph(index_set=self.cartan_type().classical().index_set()) C = G.connected_components(sort=False) - return B.sum(q**(c[0].energy_function())*B.sum(B(P0(b.weight())) for b in c) + return B.sum(q**(c[0].energy_function()) * B.sum(B(P0(b.weight())) + for b in c) for c in C) - return B.sum(q**(b.energy_function())*B(P0(b.weight())) for b in self) + return B.sum(q**(b.energy_function()) * B(P0(b.weight())) for b in self) class ElementMethods: def energy_function(self, algorithm=None): @@ -975,8 +976,8 @@ def energy_function(self, algorithm=None): from sage.arith.misc import integer_ceil as ceil C = self.parent().crystals[0] - ell = ceil(C.s()/C.cartan_type().c()[C.r()]) - is_perfect = all(ell == K.s()/K.cartan_type().c()[K.r()] + ell = ceil(C.s() / C.cartan_type().c()[C.r()]) + is_perfect = all(ell == K.s() / K.cartan_type().c()[K.r()] for K in self.parent().crystals) if algorithm is None: if is_perfect: @@ -995,12 +996,12 @@ def energy_function(self, algorithm=None): from sage.rings.integer_ring import ZZ energy = ZZ.zero() R_mats = [[K.R_matrix(Kp) for Kp in self.parent().crystals[i+1:]] - for i,K in enumerate(self.parent().crystals)] + for i, K in enumerate(self.parent().crystals)] H_funcs = [[K.local_energy_function(Kp) for Kp in self.parent().crystals[i+1:]] - for i,K in enumerate(self.parent().crystals)] + for i, K in enumerate(self.parent().crystals)] - for i,b in enumerate(self): - for j,R in enumerate(R_mats[i]): + for i, b in enumerate(self): + for j, R in enumerate(R_mats[i]): H = H_funcs[i][j] bp = self[i+j+1] T = R.domain() @@ -1128,7 +1129,7 @@ def e_string_to_ground_state(self): ##################################################################### -## Local energy function +# Local energy function class LocalEnergyFunction(Map): r""" @@ -1246,9 +1247,9 @@ def to_classical_hw(cur): for i in self._I0: b = cur.e(i) if b is not None and b not in visited: - visited[b] = visited[cur] # No change + visited[b] = visited[cur] # No change return b - return None # is classically HW or all have been visited + return None # is classically HW or all have been visited cur = x # Get the affine node (it might not be 0 if the type @@ -1270,19 +1271,19 @@ def to_classical_hw(cur): bp = self._R_matrix(b) cp = bp.e(i0) - if b[1] == c[1] and bp[1] == cp[1]: # LL case + if b[1] == c[1] and bp[1] == cp[1]: # LL case visited[c] = visited[b] + 1 - elif b[0] == c[0] and bp[0] == cp[0]: # RR case + elif b[0] == c[0] and bp[0] == cp[0]: # RR case visited[c] = visited[b] - 1 else: - visited[c] = visited[b] # Otherwise no change + visited[c] = visited[b] # Otherwise no change b = c cur = b check0.append(b) baseline = self._known_values[cur] - visited[cur] - for y in visited: - self._known_values[y] = baseline + visited[y] + for y, vy in visited.items(): + self._known_values[y] = baseline + vy return self._known_values[x] diff --git a/src/sage/categories/modules_with_basis.py b/src/sage/categories/modules_with_basis.py index cda4ecdca68..8993d020e37 100644 --- a/src/sage/categories/modules_with_basis.py +++ b/src/sage/categories/modules_with_basis.py @@ -1419,12 +1419,12 @@ class ElementMethods: # subclasses). These methods should be consistent with those on # polynomials. -# def _neg_(self): -# """ -# Default implementation of negation by trying to multiply by -1. -# TODO: doctest -# """ -# return self._lmul_(-self.parent().base_ring().one(), self) + # def _neg_(self): + # """ + # Default implementation of negation by trying to multiply by -1. + # TODO: doctest + # """ + # return self._lmul_(-self.parent().base_ring().one(), self) @abstract_method def monomial_coefficients(self, copy=True): diff --git a/src/sage/categories/pushout.py b/src/sage/categories/pushout.py index a2b5e910257..17f059f967f 100644 --- a/src/sage/categories/pushout.py +++ b/src/sage/categories/pushout.py @@ -3925,8 +3925,8 @@ class BlackBoxConstructionFunctor(ConstructionFunctor): sage: FS = BlackBoxConstructionFunctor(singular) sage: FS(QQ['t']) # needs sage.libs.singular polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 1 + // coefficients: QQ... + // number of vars : 1 // block 1 : ordering lp // : names t // block 2 : ordering C diff --git a/src/sage/categories/simplicial_sets.py b/src/sage/categories/simplicial_sets.py index f30ed0ffeb2..9bdfcfd7081 100644 --- a/src/sage/categories/simplicial_sets.py +++ b/src/sage/categories/simplicial_sets.py @@ -723,7 +723,7 @@ def twist(s): if s in twop: return twop[s] if s.dimension() > 1: - return twist(self.face(s,s.dimension())) + return twist(self.face(s, s.dimension())) return 1 base_ring = cm.common_parent(*twop.values()) @@ -815,9 +815,8 @@ def twist(s): differentials[d] = matrix(base_ring, old_rank, rank, sparse=False) if cochain: - new_diffs = {} - for d in differentials: - new_diffs[d-1] = differentials[d].transpose() + new_diffs = {d - 1: diff_d.transpose() + for d, diff_d in differentials.items()} return ChainComplex(new_diffs, degree_of_differential=1, check=check) return ChainComplex(differentials, degree_of_differential=-1, @@ -961,7 +960,7 @@ def lift_to_submodule(S, M): res = M for g in GB: res = res.stack(g*identity_matrix(M.ncols())) - singres = matrix(singlift(res.T, S.T,ring=res.base_ring())) + singres = matrix(singlift(res.T, S.T, ring=res.base_ring())) return singres.submatrix(0, 0, M.nrows(), S.nrows()) def mgb(M): @@ -973,7 +972,7 @@ def mgb(M): sres = matrix(singstd(res.T, ring=RP)) to_delete = [i for i, r in enumerate(sres.apply_map(reduce_laurent)) if not r] return sres.delete_rows(to_delete) - M2 = border_matrix(n+1) + if M1.nrows() == 0: opt_verb.reset_default() return (RP**0).quotient_module([]) diff --git a/src/sage/categories/unique_factorization_domains.py b/src/sage/categories/unique_factorization_domains.py index 0189898f6d0..19f90a5ff92 100644 --- a/src/sage/categories/unique_factorization_domains.py +++ b/src/sage/categories/unique_factorization_domains.py @@ -152,7 +152,7 @@ def _gcd_univariate_polynomial(self, f, g): sage: S. = R[] sage: p = (-3*x^2 - x)*T^3 - 3*x*T^2 + (x^2 - x)*T + 2*x^2 + 3*x - 2 sage: q = (-x^2 - 4*x - 5)*T^2 + (6*x^2 + x + 1)*T + 2*x^2 - x - sage: quo,rem=p.pseudo_quo_rem(q); quo,rem + sage: quo, rem = p.pseudo_quo_rem(q); quo, rem ((3*x^4 + 13*x^3 + 19*x^2 + 5*x)*T + 18*x^4 + 12*x^3 + 16*x^2 + 16*x, (-113*x^6 - 106*x^5 - 133*x^4 - 101*x^3 - 42*x^2 - 41*x)*T - 34*x^6 + 13*x^5 + 54*x^4 + 126*x^3 + 134*x^2 - 5*x - 50) @@ -167,50 +167,71 @@ def _gcd_univariate_polynomial(self, f, g): sage: g = 4*x + 2 sage: f.gcd(g).parent() is R True + + A slightly more exotic base ring:: + + sage: P = PolynomialRing(QQbar, 4, "x") + sage: p = sum(QQbar.zeta(i + 1) * P.gen(i) for i in range(4)) + sage: ((p^4 - 1).gcd(p^3 + 1) / (p + 1)).is_unit() + True """ + def content(X): + """ + Return the content of ``X`` up to a unit. + """ + # heuristically, polynomials tend to be monic + X_it = reversed(X.coefficients()) + x = next(X_it) + # TODO: currently, there is no member of + # `UniqueFactorizationDomains` with `is_unit` + # significantly slower than `is_one`, see + # :issue:`38924` - when such a domain is eventually + # implemented, check whether this is a bottleneck + if x.is_unit(): + return None + for c in X_it: + x = x.gcd(c) + if x.is_unit(): + return None + return x + if f.degree() < g.degree(): - A,B = g, f + A, B = g, f else: - A,B = f, g + A, B = f, g if B.is_zero(): return A - a = b = self.zero() - for c in A.coefficients(): - a = a.gcd(c) - if a.is_one(): - break - for c in B.coefficients(): - b = b.gcd(c) - if b.is_one(): - break - - d = a.gcd(b) - A = A // a - B = B // b - g = h = 1 - - delta = A.degree()-B.degree() - _,R = A.pseudo_quo_rem(B) + a = content(A) + if a is not None: + A //= a + b = content(B) + if b is not None: + B //= b + one = A.base_ring().one() + if a is not None and b is not None: + d = a.gcd(b) + else: + d = one + g = h = one + delta = A.degree() - B.degree() + _, R = A.pseudo_quo_rem(B) while R.degree() > 0: A = B - B = R // (g*h**delta) + h_delta = h**delta + B = R // (g * h_delta) g = A.leading_coefficient() - h = h*g**delta // h**delta + h = h * g**delta // h_delta delta = A.degree() - B.degree() _, R = A.pseudo_quo_rem(B) if R.is_zero(): - b = self.zero() - for c in B.coefficients(): - b = b.gcd(c) - if b.is_one(): - break - - return d*B // b - + b = content(B) + if b is None: + return d * B + return d * B // b return f.parent()(d) class ElementMethods: diff --git a/src/sage/coding/binary_code.pyx b/src/sage/coding/binary_code.pyx index f2eb22c046a..83dbefdfaf3 100644 --- a/src/sage/coding/binary_code.pyx +++ b/src/sage/coding/binary_code.pyx @@ -2140,7 +2140,7 @@ cdef class PartitionStack: # location now points to the beginning of the first, smallest, # nontrivial cell j = location - #zero out this level of W: + # zero out this level of W: ell = 1 + nwords/radix if nwords%radix: ell += 1 @@ -4035,7 +4035,7 @@ cdef class BinaryCodeClassifier: bingo2 = 0 for coset_rep in rt_transversal: hwp = create_word_perm(coset_rep) - #dealloc_word_perm(gwp) + # dealloc_word_perm(gwp) bingo2 = 1 for j from 0 <= j < B.nrows: temp = permute_word_by_wp(hwp, temp_basis[j]) diff --git a/src/sage/coding/self_dual_codes.py b/src/sage/coding/self_dual_codes.py index 10565d9e1a0..53d892a640d 100644 --- a/src/sage/coding/self_dual_codes.py +++ b/src/sage/coding/self_dual_codes.py @@ -612,19 +612,19 @@ def self_dual_binary_codes(n): return self_dual_codes if n == 20: - # all of these of these are Type I; 2 of these codes - # are formally equivalent but with different automorphism groups; - # one of these has a unique codeword of lowest weight - A10 = MatrixSpace(_F,10,10)([[1, 1, 1, 1, 1, 1, 1, 1, 1, 0], - [1, 1, 1, 0, 1, 0, 1, 0, 1, 1], - [1, 0, 0, 1, 0, 1, 0, 1, 0, 1], - [0, 0, 0, 1, 1, 1, 0, 1, 0, 1], - [0, 0, 1, 1, 0, 1, 0, 1, 0, 1], - [0, 0, 0, 1, 0, 1, 1, 1, 0, 1], - [0, 1, 0, 1, 0, 1, 0, 1, 0, 1], - [0, 0, 0, 1, 0, 0, 0, 0, 1, 1], - [0, 0, 0, 0, 0, 1, 0, 0, 1, 1], - [0, 0, 0, 0, 0, 0, 0, 1, 1, 1]]) + # all of these of these are Type I; 2 of these codes + # are formally equivalent but with different automorphism groups; + # one of these has a unique codeword of lowest weight + A10 = MatrixSpace(_F, 10, 10)([[1, 1, 1, 1, 1, 1, 1, 1, 1, 0], + [1, 1, 1, 0, 1, 0, 1, 0, 1, 1], + [1, 0, 0, 1, 0, 1, 0, 1, 0, 1], + [0, 0, 0, 1, 1, 1, 0, 1, 0, 1], + [0, 0, 1, 1, 0, 1, 0, 1, 0, 1], + [0, 0, 0, 1, 0, 1, 1, 1, 0, 1], + [0, 1, 0, 1, 0, 1, 0, 1, 0, 1], + [0, 0, 0, 1, 0, 0, 0, 0, 1, 1], + [0, 0, 0, 0, 0, 1, 0, 0, 1, 1], + [0, 0, 0, 0, 0, 0, 0, 1, 1, 1]]) # [20,0]: genmat = _I2(n).augment(_I2(n)) # G = PermutationGroup( ["(10,20)", "(9,10)(19,20)", "(8,9)(18,19)", "(7,8)(17,18)", "(6,7)(16,17)",\ diff --git a/src/sage/combinat/bijectionist.py b/src/sage/combinat/bijectionist.py index 2020b729917..0e70847728e 100644 --- a/src/sage/combinat/bijectionist.py +++ b/src/sage/combinat/bijectionist.py @@ -357,6 +357,7 @@ sage: A = B = [permutation for n in range(4) for permutation in Permutations(n)] sage: tau = Permutation.longest_increasing_subsequence_length sage: bij = Bijectionist(A, B, tau, value_restrictions=((Permutation([1, 2]), [4, 5]),)) + sage: next(bij.solutions_iterator()) Traceback (most recent call last): ... ValueError: no possible values found for singleton block [[1, 2]] @@ -494,7 +495,7 @@ def __init__(self, A, B, tau=None, alpha_beta=tuple(), P=None, Check that large input sets are handled well:: sage: A = B = range(20000) - sage: bij = Bijectionist(A, B) # long time + sage: bij = Bijectionist(A, B) """ # glossary of standard letters: # A, B, Z, W ... finite sets @@ -612,7 +613,7 @@ def set_constant_blocks(self, P): for a in p: self._P.union(p[0], a) - self._compute_possible_block_values() + self._possible_block_values = None def constant_blocks(self, singletons=False, optimal=False): r""" @@ -1093,8 +1094,7 @@ def _compute_possible_block_values(self): if not self._possible_block_values[p]: if len(block) == 1: raise ValueError(f"no possible values found for singleton block {block}") - else: - raise ValueError(f"no possible values found for block {block}") + raise ValueError(f"no possible values found for block {block}") def set_distributions(self, *elements_distributions): r""" @@ -1789,13 +1789,18 @@ def possible_values(self, p=None, optimal=False): # veto new value and try again tmp_constraints.append(bmilp._x[p, solution[p]] == 0) - # create dictionary to return - possible_values = {} - for p in blocks: - for a in self._P.root_to_elements_dict()[p]: - if optimal: + # create dictionary to return + possible_values = {} + for p in blocks: + for a in self._P.root_to_elements_dict()[p]: possible_values[a] = solutions[p] - else: + else: + # create dictionary to return + if self._possible_block_values is None: + self._compute_possible_block_values() + possible_values = {} + for p in blocks: + for a in self._P.root_to_elements_dict()[p]: possible_values[a] = self._possible_block_values[p] return possible_values @@ -2124,11 +2129,6 @@ def _preprocess_intertwining_relations(self): In particular, if `P` consists only if singletons, this method has no effect. - .. TODO:: - - create one test with one and one test with two - intertwining relations - .. TODO:: it is not clear whether this method makes sense @@ -2144,6 +2144,17 @@ def _preprocess_intertwining_relations(self): sage: bij._P {{'a'}, {'b'}, {'c'}, {'d'}} + However, adding that ``'a'`` and ``'c'`` are in the same block, + we can infer that also ``'b'`` and ``'d'`` are in the same + block:: + + sage: bij.set_constant_blocks([['a', 'c']]) + sage: bij._P + {{'a', 'c'}, {'b'}, {'d'}} + sage: bij._preprocess_intertwining_relations() + sage: bij._P + {{'a', 'c'}, {'b', 'd'}} + Let a group act on permutations:: sage: A = B = Permutations(3) @@ -2152,6 +2163,11 @@ def _preprocess_intertwining_relations(self): sage: bij._preprocess_intertwining_relations() sage: bij._P {{[1, 2, 3]}, {[1, 3, 2]}, {[2, 1, 3]}, {[2, 3, 1]}, {[3, 1, 2]}, {[3, 2, 1]}} + + Thus, in this case we do not detect the constant blocks:: + + sage: bij.constant_blocks(optimal=True) + {{[1, 2, 3], [3, 2, 1]}, {[1, 3, 2], [2, 3, 1]}, {[2, 1, 3], [3, 1, 2]}} """ A = self._A P = self._P diff --git a/src/sage/combinat/composition_tableau.py b/src/sage/combinat/composition_tableau.py index 1e05da84c4e..4649251552d 100644 --- a/src/sage/combinat/composition_tableau.py +++ b/src/sage/combinat/composition_tableau.py @@ -823,7 +823,7 @@ def _rec(self, obj, state): # We check to make sure that k does not violate the Triple Rule if j != 0 and i != 0 and any(k == obj_copy[m][j] for m in range(i)): continue - if j != 0 and i != 0 and any(obj_copy[m][j] < k and k <= obj_copy[m][j - 1] + if j != 0 and i != 0 and any(obj_copy[m][j] < k <= obj_copy[m][j - 1] for m in range(i)): continue diff --git a/src/sage/combinat/crystals/pbw_datum.pyx b/src/sage/combinat/crystals/pbw_datum.pyx index fa3be1ca72e..7144feca9c6 100644 --- a/src/sage/combinat/crystals/pbw_datum.pyx +++ b/src/sage/combinat/crystals/pbw_datum.pyx @@ -22,7 +22,7 @@ AUTHORS: # https://www.gnu.org/licenses/ # **************************************************************************** -#from sage.misc.lazy_attribute import lazy_attribute +# from sage.misc.lazy_attribute import lazy_attribute from sage.misc.cachefunc import cached_method from sage.combinat.root_system.cartan_type import CartanType from sage.combinat.root_system.root_system import RootSystem diff --git a/src/sage/combinat/crystals/spins.pyx b/src/sage/combinat/crystals/spins.pyx index 28729fc93c0..a4f5229f92c 100644 --- a/src/sage/combinat/crystals/spins.pyx +++ b/src/sage/combinat/crystals/spins.pyx @@ -11,9 +11,9 @@ We follow Kashiwara and Nakashima (Journal of Algebra 165, 1994) in representing the elements of the spin crystal by sequences of signs `\pm`. """ -#TODO: Do we want the following two representations? +# TODO: Do we want the following two representations? # -#Two other representations are available as attributes +# Two other representations are available as attributes #:meth:`Spin.internal_repn` and :meth:`Spin.signature` of the crystal element. # #- A numerical internal representation, an integer `n` such that if `n-1` @@ -24,7 +24,7 @@ representing the elements of the spin crystal by sequences of signs # ``-`` by `-1`. -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2007 Anne Schilling # Nicolas Thiery # Daniel Bump @@ -39,8 +39,8 @@ representing the elements of the spin crystal by sequences of signs # # The full text of the GPL is available at: # -# http://www.gnu.org/licenses/ -#**************************************************************************** +# https://www.gnu.org/licenses/ +# *************************************************************************** from cpython.object cimport Py_EQ, Py_NE, Py_LE, Py_GE, Py_LT, Py_GT from cysignals.memory cimport sig_malloc, sig_free diff --git a/src/sage/combinat/designs/bibd.py b/src/sage/combinat/designs/bibd.py index 02391553032..db0a5feaaa1 100644 --- a/src/sage/combinat/designs/bibd.py +++ b/src/sage/combinat/designs/bibd.py @@ -613,7 +613,7 @@ def BIBD_from_TD(v, k, existence=False): BIBD = TDkv._blocks for i in range(k): - BIBD.extend([[x+i*v for x in B] for B in BIBDvk]) + BIBD.extend([x+i*v for x in B] for B in BIBDvk) # Second construction elif ((v-1) % k == 0 and @@ -630,7 +630,7 @@ def BIBD_from_TD(v, k, existence=False): inf = v*k BIBD = TDkv for i in range(k): - BIBD.extend([[inf if x == v else x+i*v for x in B] for B in BIBDv1k]) + BIBD.extend([inf if x == v else x+i*v for x in B] for B in BIBDv1k) # Third construction elif ((v-k) % k == 0 and @@ -650,7 +650,8 @@ def BIBD_from_TD(v, k, existence=False): BIBDvpkk = [B for B in BIBDvpkk if min(B) < v] for i in range(k): - BIBD.extend([[(x-v)+inf if x >= v else x+i*v for x in B] for B in BIBDvpkk]) + BIBD.extend([(x-v)+inf if x >= v else x+i*v for x in B] + for B in BIBDvpkk) BIBD.append(list(range(k * v, v * k + k))) diff --git a/src/sage/combinat/designs/database.py b/src/sage/combinat/designs/database.py index ad86c612e86..e56467cfcd8 100644 --- a/src/sage/combinat/designs/database.py +++ b/src/sage/combinat/designs/database.py @@ -1058,8 +1058,8 @@ def OA_11_185(): assert all(len(B) in (11,13) or set(B) == set(special_set) for B in PBD) OA = OA_from_PBD(11,185,[B for B in PBD if len(B) < 17],check=False)[:-185] - OA.extend([[i]*11 for i in range(185) if i not in special_set]) - OA.extend([[special_set[x] for x in B] for B in orthogonal_array(11,17)]) + OA.extend([i]*11 for i in range(185) if i not in special_set) + OA.extend([special_set[x] for x in B] for B in orthogonal_array(11,17)) return OA @@ -1126,7 +1126,7 @@ def OA_10_205(): GDD = [[relabel[xx] for xx in B if xx in relabel] for B in pplane if p not in B] # We turn the GDD into a PBD by extending the groups with a new point 204. - GDD.extend([[relabel[xx] for xx in G]+[204] for G in groups]) + GDD.extend([relabel[xx] for xx in G]+[204] for G in groups) # We build the OA, knowing that the blocks of size 9 are disjoint blocks_of_size_9 = [B for B in GDD if len(B) == 9] @@ -1134,13 +1134,13 @@ def OA_10_205(): OA = OA_from_PBD(10,205,[B for B in GDD if len(B) != 9],check=False)[:-205] - OA.extend([[B[xx] for xx in R] - for R in orthogonal_array(10,9) - for B in blocks_of_size_9]) + OA.extend([B[xx] for xx in R] + for R in orthogonal_array(10,9) + for B in blocks_of_size_9) # The missing [i,i,...] blocks - OA.extend([[i]*10 - for i in set(range(205)).difference(blocks_of_size_9_union)]) + OA.extend([i]*10 + for i in set(range(205)).difference(blocks_of_size_9_union)) return OA @@ -1627,7 +1627,8 @@ def OA_10_796(): OA = OA_relabel(OA,17,47,blocks=[OA[0]]) # making sure [46]*17 is a block PBD = [[i*47+x for i,x in enumerate(B) if (x < 46 or i < 13)] for B in OA] extra_point = 10000 - PBD.extend([list(range(i*47,(i+1)*47-int(i >= 13)))+[extra_point] for i in range(17)]) # Adding the columns + PBD.extend(list(range(i*47,(i+1)*47-int(i >= 13)))+[extra_point] + for i in range(17)) # Adding the columns rel = {v:i for i,v in enumerate(set(range(17*47)).difference([(i+1)*47-1 for i in range(13,17)]))} rel[extra_point] = len(rel) @@ -1645,7 +1646,7 @@ def OA_10_796(): for B in PBD: if len(B) >= 47: B.sort(key=lambda x:int(x == extra_point)) - OA.extend([[B[i] for i in BB] for BB in iOA[len(B)]]) + OA.extend([B[i] for i in BB] for BB in iOA[len(B)]) span.update(B[:-1]) else: others.append(B) diff --git a/src/sage/combinat/designs/orthogonal_arrays_build_recursive.py b/src/sage/combinat/designs/orthogonal_arrays_build_recursive.py index 2bfd385492c..08ea78b8ea3 100644 --- a/src/sage/combinat/designs/orthogonal_arrays_build_recursive.py +++ b/src/sage/combinat/designs/orthogonal_arrays_build_recursive.py @@ -256,7 +256,7 @@ def construction_3_5(k, n, m, r, s, t, explain_construction=False): group_k_3 = [B[-1] for B in master_design if B[-3] not in group_k_1 and B[-2] not in group_k_2] group_k_3 = list(set(group_k_3)) assert len(group_k_3) <= t - group_k_3.extend([x for x in range(q) if x not in group_k_3]) + group_k_3.extend(x for x in range(q) if x not in group_k_3) group_k_3 = group_k_3[:t] # Relabelling the OA @@ -545,7 +545,7 @@ def construction_q_x(k, q, x, check=True, explain_construction=False): # delete points. # # TD.extend([range(i*q,(i+1)*q) for i in range(x)]) - TD.extend([list(range(i*q,(i+1)*q))+[p2] for i in range(x,q)]) + TD.extend(list(range(i*q,(i+1)*q))+[p2] for i in range(x,q)) points_to_delete = set([i*q+j for i in range(x) for j in range(1,q)]+[i*q for i in range(x,q)]) points_to_keep = set(range(q**2+2))-points_to_delete @@ -1002,7 +1002,7 @@ def three_factor_product(k, n1, n2, n3, check=False, explain_construction=False) Rolf S. Rees, Journal of Combinatorial Designs 1.1 (1993): 15-26. """ - assert n1 <= n2 and n2 <= n3 + assert n1 <= n2 <= n3 if explain_construction: return ("Three-factor product with n={}.{}.{} from:\n" + @@ -1567,7 +1567,8 @@ def brouwer_separable_design(k, t, q, x, check=False, verbose=False, explain_con blocks_of_size_q_plus_t = _reorder_matrix(blocks_of_size_q_plus_t) for i,classs in enumerate(OA_tq1_classes): - OA.extend([R[xx] if xx < t+q else N-i-1 for xx in B] for R in blocks_of_size_q_plus_t for B in classs) + OA.extend([R[xx] if xx < t+q else N-i-1 for xx in B] + for R in blocks_of_size_q_plus_t for B in classs) # The set of size x OA.extend([N-1-xx for xx in R] for R in orthogonal_array(k,x)) diff --git a/src/sage/combinat/gray_codes.py b/src/sage/combinat/gray_codes.py index db1539d2376..be1fd5fdf98 100644 --- a/src/sage/combinat/gray_codes.py +++ b/src/sage/combinat/gray_codes.py @@ -200,13 +200,12 @@ def combinations(n, t): n = int(n) else: n = Infinity - assert 0 <= t and t <= n, "t(={}) must be >=0 and <=n(={})".format(t,n) + assert 0 <= t <= n, "t(={}) must be >=0 and <=n(={})".format(t, n) if t == 0 or t == n: return iter([]) if t % 2: - return _revolving_door_odd(n,t) - else: - return _revolving_door_even(n,t) + return _revolving_door_odd(n, t) + return _revolving_door_even(n, t) def _revolving_door_odd(n, t): diff --git a/src/sage/combinat/interval_posets.py b/src/sage/combinat/interval_posets.py index 046d2ba3a7f..afdae758dfc 100644 --- a/src/sage/combinat/interval_posets.py +++ b/src/sage/combinat/interval_posets.py @@ -592,8 +592,8 @@ def _mul_(self, other: TIP) -> TIP: n = self._size m = other.size() relations = self._poset.cover_relations() - relations.extend([(i + n, j + n) - for i, j in other._poset.cover_relations_iterator()]) + relations.extend((i + n, j + n) + for i, j in other._poset.cover_relations_iterator()) P = FinitePoset(DiGraph([list(range(1, n + m + 1)), relations], format='vertices_and_edges')) # type:ignore return TamariIntervalPoset(P, check=False) # type:ignore @@ -1980,9 +1980,9 @@ def subposet(self, start, end) -> TIP: relations = [(i - start + 1, j - start + 1) for (i, j) in self.increasing_cover_relations() if i >= start and j < end] - relations.extend([(j - start + 1, i - start + 1) - for (j, i) in self.decreasing_cover_relations() - if i >= start and j < end]) + relations.extend((j - start + 1, i - start + 1) + for (j, i) in self.decreasing_cover_relations() + if i >= start and j < end) return TamariIntervalPoset(end - start, relations, check=False) sub_poset = subposet @@ -3110,7 +3110,7 @@ def get_relations(bt, start=1): rroots, rrelations, rindex = get_relations(bt[1], start=index + 1) roots.append(index) relations.extend(rrelations) - relations.extend([(j, index) for j in rroots]) + relations.extend((j, index) for j in rroots) return roots, relations, rindex _, relations, index = get_relations(binary_tree) @@ -3224,7 +3224,7 @@ def get_relations(bt, start=1): roots, relations, rindex = get_relations(bt[1], start=index + 1) roots.append(index) relations.extend(lrelations) - relations.extend([(j, index) for j in lroots]) + relations.extend((j, index) for j in lroots) return roots, relations, rindex _, relations, index = get_relations(binary_tree) diff --git a/src/sage/combinat/ncsf_qsym/combinatorics.py b/src/sage/combinat/ncsf_qsym/combinatorics.py index 605ad56aa12..c44b0607339 100644 --- a/src/sage/combinat/ncsf_qsym/combinatorics.py +++ b/src/sage/combinat/ncsf_qsym/combinatorics.py @@ -293,11 +293,11 @@ def number_of_SSRCT(content_comp, shape_comp): else: return ZZ.zero() s = ZZ.zero() - cond = lambda al,be: all(al[j] <= be_val - and not any(al[i] <= k and k <= be[i] - for k in range(al[j], be_val) - for i in range(j)) - for j, be_val in enumerate(be)) + cond = lambda al, be: all(al[j] <= be_val + and not any(al[i] <= k <= be[i] + for k in range(al[j], be_val) + for i in range(j)) + for j, be_val in enumerate(be)) C = Compositions(content_comp.size()-content_comp[0], inner=[1]*len(shape_comp), outer=list(shape_comp)) diff --git a/src/sage/combinat/partition.py b/src/sage/combinat/partition.py index 927f1da8ec5..abc84654166 100644 --- a/src/sage/combinat/partition.py +++ b/src/sage/combinat/partition.py @@ -2720,7 +2720,7 @@ def suter_diagonal_slide(self, n, exp=1): exp += 1 continue res = [n - leng - 1] - res.extend([i - 1 for i in ret._list if i > 1]) + res.extend(i - 1 for i in ret._list if i > 1) ret = Partition(res) exp += 1 return ret @@ -3066,7 +3066,7 @@ def young_subgroup(self): gens = [] m = 0 for row in self: - gens.extend([(c, c+1) for c in range(m+1, m+row)]) + gens.extend((c, c + 1) for c in range(m + 1, m + row)) m += row gens.append(list(range(1, self.size() + 1))) # to ensure we get a subgroup of Sym_n return PermutationGroup(gens) diff --git a/src/sage/combinat/partition_tuple.py b/src/sage/combinat/partition_tuple.py index 527df5a2728..fa12e689039 100644 --- a/src/sage/combinat/partition_tuple.py +++ b/src/sage/combinat/partition_tuple.py @@ -1485,7 +1485,7 @@ def young_subgroup(self): m = 0 for comp in self: for row in comp: - gens.extend([(c, c+1) for c in range(m+1, m+row)]) + gens.extend((c, c + 1) for c in range(m + 1, m + row)) m += row gens.append(list(range(1, self.size()+1))) # to ensure we get a subgroup of Sym_n return PermutationGroup(gens) @@ -1504,7 +1504,7 @@ def young_subgroup_generators(self): m = 0 for comp in self: for row in comp: - gens.extend(list(range(m + 1, m + row))) + gens.extend(range(m + 1, m + row)) m += row return gens diff --git a/src/sage/combinat/permutation.py b/src/sage/combinat/permutation.py index 53901bb3c17..a1043f59646 100644 --- a/src/sage/combinat/permutation.py +++ b/src/sage/combinat/permutation.py @@ -2121,13 +2121,13 @@ def _icondition(self, i): pos_ip1 = self.index(i + 1) pos_im1 = self.index(i - 1) - if pos_i < pos_im1 and pos_im1 < pos_ip1: + if pos_i < pos_im1 < pos_ip1: state = '213' - elif pos_im1 < pos_ip1 and pos_ip1 < pos_i: + elif pos_im1 < pos_ip1 < pos_i: state = '132' - elif pos_i < pos_ip1 and pos_ip1 < pos_im1: + elif pos_i < pos_ip1 < pos_im1: state = '231' - elif pos_ip1 < pos_im1 and pos_im1 < pos_i: + elif pos_ip1 < pos_im1 < pos_i: state = '312' else: state = None diff --git a/src/sage/combinat/permutation_cython.pyx b/src/sage/combinat/permutation_cython.pyx index db58f15f51e..62866bf2210 100644 --- a/src/sage/combinat/permutation_cython.pyx +++ b/src/sage/combinat/permutation_cython.pyx @@ -81,31 +81,30 @@ cdef int next_swap(int n, int *c, int *o) noexcept: Returns the index i such that the next permutation can be obtained by swapping P[i] <-> P[i+1] """ + cdef int j, s, q, offset - cdef int j,s,q,offset - - #state 3 + # state 3 j = n-1 if j <= 0: return -1 s = -1 while True: - #state 4 + # state 4 q = c[j] + o[j] if q == j: - #state 6 + # state 6 if j == 1: return -1 s = s+1 elif q >= -1: break - #state 7 + # state 7 o[j] = -o[j] j = j-1 - #state 5 + # state 5 offset = c[j] if q > offset: offset = q @@ -227,18 +226,18 @@ cpdef bint next_perm(array l) noexcept: if two == 0: return False - #starting from the end, find the first j such that - #l[j] > l[one] + # starting from the end, find the first j such that + # l[j] > l[one] while l.data.as_uints[j] <= l.data.as_uints[one]: j -= 1 - #Swap positions one and j + # Swap positions one and j t = l.data.as_uints[one] l.data.as_uints[one] = l.data.as_uints[j] l.data.as_uints[j] = t - #Reverse the list between two and last - #mset_list = mset_list[:two] + [x for x in reversed(mset_list[two:])] + # Reverse the list between two and last + # mset_list = mset_list[:two] + [x for x in reversed(mset_list[two:])] n -= 1 # In the loop, we only need n-1, so just do it once here cdef Py_ssize_t i for i in range((n + 1 - two) // 2 - 1, -1, -1): diff --git a/src/sage/combinat/posets/poset_examples.py b/src/sage/combinat/posets/poset_examples.py index 468ad8d9a01..f5c129c6255 100644 --- a/src/sage/combinat/posets/poset_examples.py +++ b/src/sage/combinat/posets/poset_examples.py @@ -1590,7 +1590,7 @@ def DoubleTailedDiamond(n): edges = [(i, i + 1) for i in range(1, n)] edges.extend([(n, n + 1), (n, n + 2), (n + 1, n + 3), (n + 2, n + 3)]) - edges.extend([(i, i + 1) for i in range(n + 3, 2 * n + 2)]) + edges.extend((i, i + 1) for i in range(n + 3, 2 * n + 2)) p = DiGraph([list(range(1, 2 * n + 3)), edges]) return DCompletePoset(p) diff --git a/src/sage/combinat/posets/posets.py b/src/sage/combinat/posets/posets.py index 6d319084295..a2039494ce4 100644 --- a/src/sage/combinat/posets/posets.py +++ b/src/sage/combinat/posets/posets.py @@ -2584,10 +2584,10 @@ def intervals_poset(self): covers = [] for a, b in ints: - covers.extend([[(a, b), (a, bb)] for bb in self.upper_covers(b)]) + covers.extend([(a, b), (a, bb)] for bb in self.upper_covers(b)) if a != b: - covers.extend([[(a, b), (aa, b)] for aa in self.upper_covers(a) - if self.le(aa, b)]) + covers.extend([(a, b), (aa, b)] for aa in self.upper_covers(a) + if self.le(aa, b)) dg = DiGraph([ints, covers], format='vertices_and_edges') return constructor(dg, cover_relations=True) diff --git a/src/sage/combinat/rigged_configurations/kr_tableaux.py b/src/sage/combinat/rigged_configurations/kr_tableaux.py index fb6f223e62c..ec0c1face46 100644 --- a/src/sage/combinat/rigged_configurations/kr_tableaux.py +++ b/src/sage/combinat/rigged_configurations/kr_tableaux.py @@ -800,17 +800,17 @@ def _fill(self, shape): shape_list.append(0) lst = [] - for col in range(1, self._s+1): + for col in range(1, self._s + 1): if (self._s - col) % 2 == 0: - lst.extend( [self.letters(self._r - x) for x in range(self._r)] ) + lst.extend(self.letters(self._r - x) for x in range(self._r)) else: m = self._r for j, val in enumerate(shape_list): if col >= val: m = j break - lst.extend([self.letters(-x) for x in range(m+1, self._r+1)]) - lst.extend([self.letters(m - x) for x in range(m)]) + lst.extend(self.letters(-x) for x in range(m + 1, self._r + 1)) + lst.extend(self.letters(m - x) for x in range(m)) return self.element_class(self, lst) diff --git a/src/sage/combinat/root_system/branching_rules.py b/src/sage/combinat/root_system/branching_rules.py index cf6b0012c85..718c4eb624a 100644 --- a/src/sage/combinat/root_system/branching_rules.py +++ b/src/sage/combinat/root_system/branching_rules.py @@ -1774,7 +1774,8 @@ def rule(x): if all(t[0] == 'A' for t in stypes): def rule(x): ret = [sum(x[i*ns[1]:(i+1)*ns[1]]) for i in range(ns[0])] - ret.extend([sum(x[ns[1]*j+i] for j in range(ns[0])) for i in range(ns[1])]) + ret.extend(sum(x[ns[1]*j+i] for j in range(ns[0])) + for i in range(ns[1])) return ret return BranchingRule(Rtype, Stype, rule, "tensor") else: diff --git a/src/sage/combinat/root_system/hecke_algebra_representation.py b/src/sage/combinat/root_system/hecke_algebra_representation.py index a2a5d4421dc..5d87a3dfa8d 100644 --- a/src/sage/combinat/root_system/hecke_algebra_representation.py +++ b/src/sage/combinat/root_system/hecke_algebra_representation.py @@ -378,7 +378,7 @@ def Tw(self, word, signs=None, scalar=None): sage: phi = T.Tw((1,2), (-1,1), 3) sage: phi(KW.one()) - ((-3*q1)/q2)*12 + ((3*q1+3*q2)/q2)*2 + -3*q1/q2*12 + ((3*q1+3*q2)/q2)*2 sage: phi(T[1](x)) == 3*T[2](x) True @@ -429,8 +429,8 @@ def Tw_inverse(self, word): sage: x = KW.monomial(W.an_element()); x 123 sage: rho.Tw_inverse(word)(x) - 1/q2^2*12321 + ((-q1-q2)/(q1*q2^2))*1231 + ((-q1-q2)/(q1*q2^2))*1232 - + ((q1^2+2*q1*q2+q2^2)/(q1^2*q2^2))*123 + 1/q2^2*12321 - ((q1+q2)/(q1*q2^2))*1231 - ((q1+q2)/(q1*q2^2))*1232 + + ((q1^2+2*q1*q2+q2^2)/(q1^2*q2^2))*123 sage: rho.Tw(word)(_) 123 """ @@ -549,16 +549,17 @@ def Y_lambdacheck(self, lambdacheck): sage: x = KW.monomial(W.an_element()); x 12 sage: Y1(x) - ((-q1^2-2*q1*q2-q2^2)/(-q2^2))*2121 - + ((q1^3+q1^2*q2+q1*q2^2+q2^3)/(-q1*q2^2))*121 - + ((q1^2+q1*q2)/(-q2^2))*212 + ((-q1^2)/(-q2^2))*12 + -((q1^2+2*q1*q2+q2^2)/(-q2^2))*2121 + + ((q1^3+q1^2*q2+q1*q2^2+q2^3)/(-q1*q2^2))*121 + + ((q1^2+q1*q2)/(-q2^2))*212 - (q1^2/(-q2^2))*12 sage: Y2(x) - ((-q1^4-q1^3*q2-q1*q2^3-q2^4)/(-q1^3*q2))*2121 - + ((q1^3+q1^2*q2+q1*q2^2+q2^3)/(-q1^2*q2))*121 + (q2^3/(-q1^3))*12 + -((q1^4+q1^3*q2+q1*q2^3+q2^4)/(-q1^3*q2))*2121 + + ((q1^3+q1^2*q2+q1*q2^2+q2^3)/(-q1^2*q2))*121 + + (q2^3/(-q1^3))*12 sage: Y1(Y2(x)) - ((q1*q2+q2^2)/q1^2)*212 + ((-q2)/q1)*12 + ((q1*q2+q2^2)/q1^2)*212 - q2/q1*12 sage: Y2(Y1(x)) - ((q1*q2+q2^2)/q1^2)*212 + ((-q2)/q1)*12 + ((q1*q2+q2^2)/q1^2)*212 - q2/q1*12 The `Y` operators commute:: @@ -754,13 +755,12 @@ def Y_eigenvectors(self): sage: [E[w] for w in W] [2121 - 121 - 212 + 12 + 21 - 1 - 2 + , -2121 + 212, - (q2/(q1-q2))*2121 + (q2/(-q1+q2))*121 - + (q2/(-q1+q2))*212 - 12 + ((-q2)/(-q1+q2))*21 + 2, - ((-q2^2)/(-q1^2+q1*q2-q2^2))*2121 - 121 + (q2^2/(-q1^2+q1*q2-q2^2))*212 + 21, - ((-q1^2-q2^2)/(q1^2-q1*q2+q2^2))*2121 + ((-q1^2-q2^2)/(-q1^2+q1*q2-q2^2))*121 - + ((-q2^2)/(-q1^2+q1*q2-q2^2))*212 + (q2^2/(-q1^2+q1*q2-q2^2))*12 - 21 + 1, + (q2/(q1-q2))*2121 + (q2/(-q1+q2))*121 + (q2/(-q1+q2))*212 - 12 - (q2/(-q1+q2))*21 + 2, + -(q2^2/(-q1^2+q1*q2-q2^2))*2121 - 121 + (q2^2/(-q1^2+q1*q2-q2^2))*212 + 21, + -((q1^2+q2^2)/(q1^2-q1*q2+q2^2))*2121 - ((q1^2+q2^2)/(-q1^2+q1*q2-q2^2))*121 + - (q2^2/(-q1^2+q1*q2-q2^2))*212 + (q2^2/(-q1^2+q1*q2-q2^2))*12 - 21 + 1, 2121, - (q2/(-q1+q2))*2121 + ((-q2)/(-q1+q2))*121 - 212 + 12, + (q2/(-q1+q2))*2121 - (q2/(-q1+q2))*121 - 212 + 12, -2121 + 121] """ if not self.cartan_type().is_affine(): diff --git a/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py b/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py index 90482002c92..62ab2116e12 100644 --- a/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py +++ b/src/sage/combinat/root_system/non_symmetric_macdonald_polynomials.py @@ -74,8 +74,8 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): `[2,0,1]`:: sage: E[L0([2,0,1])] # needs sage.libs.gap - ((-q*q1-q*q2)/(-q*q1-q2))*B[(1, 1, 1)] - + ((-q1-q2)/(-q*q1-q2))*B[(2, 1, 0)] + B[(2, 0, 1)] + -((q*q1+q*q2)/(-q*q1-q2))*B[(1, 1, 1)] + - ((q1+q2)/(-q*q1-q2))*B[(2, 1, 0)] + B[(2, 0, 1)] It can be seen as a polynomial (or in general a Laurent polynomial) by interpreting each term as an exponent vector. The @@ -106,8 +106,8 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: L0 = E.keys() sage: omega = L0.fundamental_weights() sage: E[omega[2] - omega[1]] - ((-q*q1^3*q2-q*q1^2*q2^2)/(q*q1^4-q2^4))*B[(0, 0, 0)] - + B[(1, -1, 0)] + ((-q1*q2^3-q2^4)/(q*q1^4-q2^4))*B[(1, 0, -1)] + -((q*q1^3*q2+q*q1^2*q2^2)/(q*q1^4-q2^4))*B[(0, 0, 0)] + B[(1, -1, 0)] + - ((q1*q2^3+q2^4)/(q*q1^4-q2^4))*B[(1, 0, -1)] Many more examples are given after the background section. @@ -228,11 +228,11 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: Y1 = Y[alphacheck[1]] sage: Y1(x) ((q1^2+2*q1*q2+q2^2)/(-q1*q2))*B[e[0] + e['deltacheck']] - + ((-q1^2-2*q1*q2-q2^2)/(-q2^2))*B[-e[1] + e['deltacheck']] - + ((-q1^2-q1*q2)/(-q2^2))*B[2*e[0] - e[1] - e['delta'] - + e['deltacheck']] + ((q1^3+q1^2*q2)/(-q2^3))*B[e[0] - e['delta'] - + e['deltacheck']] + ((q1^3+q1^2*q2)/(-q2^3))*B[e[0] - 2*e[1] - e['delta'] - + e['deltacheck']] + ((q1+q2)/(-q2))*B[e[1] + e['deltacheck']] + - ((q1^2+2*q1*q2+q2^2)/(-q2^2))*B[-e[1] + e['deltacheck']] + - ((q1^2+q1*q2)/(-q2^2))*B[2*e[0] - e[1] - e['delta'] + e['deltacheck']] + + ((q1^3+q1^2*q2)/(-q2^3))*B[e[0] - e['delta'] + e['deltacheck']] + + ((q1^3+q1^2*q2)/(-q2^3))*B[e[0] - 2*e[1] - e['delta'] + e['deltacheck']] + + ((q1+q2)/(-q2))*B[e[1] + e['deltacheck']] + ((q1^3+2*q1^2*q2+q1*q2^2)/(-q2^3))*B[-e[1] - e['delta'] + e['deltacheck']] + ((q1^3+q1^2*q2)/(-q2^3))*B[2*e[0] - e[1] - 2*e['delta'] + e['deltacheck']] + ((q1^3+2*q1^2*q2+q1*q2^2)/(-q2^3))*B[-e[0] - e['delta'] + e['deltacheck']] @@ -273,7 +273,7 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: omega = L0.fundamental_weights() sage: x = KL0.monomial(omega[1]) sage: T[0](x) - (-q*q2)*B[(-1, 0)] + -q*q2*B[(-1, 0)] For classical nodes these are the usual Demazure-Lusztig operators:: @@ -377,16 +377,16 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: E = NonSymmetricMacdonaldPolynomials(['D',3,1], q, u, -1/u) sage: omega = E.keys().fundamental_weights() sage: E[omega[1]+omega[3]] - ((-q*u^2+q)/(-q*u^4+1))*B[(1/2, -1/2, 1/2)] - + ((-q*u^2+q)/(-q*u^4+1))*B[(1/2, 1/2, -1/2)] + B[(3/2, 1/2, 1/2)] + -((q*u^2-q)/(-q*u^4+1))*B[(1/2, -1/2, 1/2)] + - ((q*u^2-q)/(-q*u^4+1))*B[(1/2, 1/2, -1/2)] + B[(3/2, 1/2, 1/2)] sage: KL = RootSystem(["D",3,1]).ambient_space().algebra(K) sage: P = NonSymmetricMacdonaldPolynomials(KL, q, u, -1/u) sage: E[omega[1]+omega[3]] == P[omega[1]+omega[3]] True sage: E[E.keys()((0,1,-1))] - ((-q*u^2+q)/(-q*u^2+1))*B[(0, 0, 0)] + ((-u^2+1)/(-q*u^2+1))*B[(1, 1, 0)] - + ((-u^2+1)/(-q*u^2+1))*B[(1, 0, -1)] + B[(0, 1, -1)] + -((q*u^2-q)/(-q*u^2+1))*B[(0, 0, 0)] - ((u^2-1)/(-q*u^2+1))*B[(1, 1, 0)] + - ((u^2-1)/(-q*u^2+1))*B[(1, 0, -1)] + B[(0, 1, -1)] In type `A`, there is also a combinatorial implementation of the nonsymmetric Macdonald polynomials in terms of augmented diagram @@ -457,11 +457,11 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): The same, directly in the ambient lattice with several shifts:: sage: E[L0([2,0])] # needs sage.combinat - ((-q*t+q)/(-q*t+1))*B[(1, 1)] + B[(2, 0)] + -((q*t-q)/(-q*t+1))*B[(1, 1)] + B[(2, 0)] sage: E[L0([1,-1])] # needs sage.combinat - ((-q*t+q)/(-q*t+1))*B[(0, 0)] + B[(1, -1)] + -((q*t-q)/(-q*t+1))*B[(0, 0)] + B[(1, -1)] sage: E[L0([0,-2])] # needs sage.combinat - ((-q*t+q)/(-q*t+1))*B[(-1, -1)] + B[(0, -2)] + -((q*t-q)/(-q*t+1))*B[(-1, -1)] + B[(0, -2)] Systematic checks with Sage's implementation of [HHL06]_:: @@ -478,31 +478,29 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: L0 = E.keys() sage: E[L0.fundamental_weight(1).weyl_action([2,4,3,2,1])] - ((-u^2+1)/(-q*u^16+1))*B[-Lambda[1] + Lambda[3]] - + ((-u^2+1)/(-q*u^16+1))*B[Lambda[1]] - + B[-Lambda[2] + Lambda[5]] - + ((-u^2+1)/(-q*u^16+1))*B[Lambda[2] - Lambda[4] + Lambda[5]] - + ((-u^2+1)/(-q*u^16+1))*B[-Lambda[3] + Lambda[4]] + -((u^2-1)/(-q*u^16+1))*B[-Lambda[1] + Lambda[3]] + - ((u^2-1)/(-q*u^16+1))*B[Lambda[1]] + B[-Lambda[2] + Lambda[5]] + - ((u^2-1)/(-q*u^16+1))*B[Lambda[2] + - Lambda[4] + Lambda[5]] - ((u^2-1)/(-q*u^16+1))*B[-Lambda[3] + Lambda[4]] sage: E[L0.fundamental_weight(2).weyl_action([2,5,3,4,2])] # long time (6s) - ((-q^2*u^20+q^2*u^18+q*u^2-q)/(-q^2*u^32+2*q*u^16-1))*B[0] + -((q^2*u^20-q^2*u^18-q*u^2+q)/(-q^2*u^32+2*q*u^16-1))*B[0] + B[Lambda[1] - Lambda[3] + Lambda[4] - Lambda[5] + Lambda[6]] - + ((-u^2+1)/(-q*u^16+1))*B[Lambda[1] - Lambda[3] + Lambda[5]] - + ((-q*u^20+q*u^18+u^2-1)/(-q^2*u^32+2*q*u^16-1))*B[-Lambda[2] + Lambda[4]] - + ((-q*u^20+q*u^18+u^2-1)/(-q^2*u^32+2*q*u^16-1))*B[Lambda[2]] + - ((u^2-1)/(-q*u^16+1))*B[Lambda[1] - Lambda[3] + Lambda[5]] + - ((q*u^20-q*u^18-u^2+1)/(-q^2*u^32+2*q*u^16-1))*B[-Lambda[2] + Lambda[4]] + - ((q*u^20-q*u^18-u^2+1)/(-q^2*u^32+2*q*u^16-1))*B[Lambda[2]] + ((u^4-2*u^2+1)/(q^2*u^32-2*q*u^16+1))*B[Lambda[3] - Lambda[4] + Lambda[5]] - + ((-u^2+1)/(-q*u^16+1))*B[Lambda[3] - Lambda[5] + Lambda[6]] + - ((u^2-1)/(-q*u^16+1))*B[Lambda[3] - Lambda[5] + Lambda[6]] sage: E[L0.fundamental_weight(1)+L0.fundamental_weight(6)] # long time (13s) ((q^2*u^10-q^2*u^8-q^2*u^2+q^2)/(q^2*u^26-q*u^16-q*u^10+1))*B[0] - + ((-q*u^2+q)/(-q*u^10+1))*B[Lambda[1] - Lambda[2] + Lambda[6]] - + ((-q*u^2+q)/(-q*u^10+1))*B[Lambda[1] + Lambda[2] - Lambda[4] + Lambda[6]] - + ((-q*u^2+q)/(-q*u^10+1))*B[Lambda[1] - Lambda[3] + Lambda[4] - Lambda[5] + Lambda[6]] - + ((-q*u^2+q)/(-q*u^10+1))*B[Lambda[1] - Lambda[3] + Lambda[5]] - + B[Lambda[1] + Lambda[6]] - + ((-q*u^2+q)/(-q*u^10+1))*B[-Lambda[2] + Lambda[4]] - + ((-q*u^2+q)/(-q*u^10+1))*B[Lambda[2]] - + ((-q*u^2+q)/(-q*u^10+1))*B[Lambda[3] - Lambda[4] + Lambda[5]] - + ((-q*u^2+q)/(-q*u^10+1))*B[Lambda[3] - Lambda[5] + Lambda[6]] + - ((q*u^2-q)/(-q*u^10+1))*B[Lambda[1] - Lambda[2] + Lambda[6]] + - ((q*u^2-q)/(-q*u^10+1))*B[Lambda[1] + Lambda[2] - Lambda[4] + Lambda[6]] + - ((q*u^2-q)/(-q*u^10+1))*B[Lambda[1] - Lambda[3] + Lambda[4] - Lambda[5] + Lambda[6]] + - ((q*u^2-q)/(-q*u^10+1))*B[Lambda[1] - Lambda[3] + Lambda[5]] + B[Lambda[1] + Lambda[6]] + - ((q*u^2-q)/(-q*u^10+1))*B[-Lambda[2] + Lambda[4]] + - ((q*u^2-q)/(-q*u^10+1))*B[Lambda[2]] + - ((q*u^2-q)/(-q*u^10+1))*B[Lambda[3] - Lambda[4] + Lambda[5]] + - ((q*u^2-q)/(-q*u^10+1))*B[Lambda[3] - Lambda[5] + Lambda[6]] We test various other types:: @@ -512,51 +510,50 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: E = NonSymmetricMacdonaldPolynomials(KL, q, u, -1/u) sage: L0 = E.keys() sage: E[L0.fundamental_weight(2)] - ((-q*u^2+q)/(-q*u^8+1))*B[(0, 0, 0)] + B[(1, 1, 0)] + -((q*u^2-q)/(-q*u^8+1))*B[(0, 0, 0)] + B[(1, 1, 0)] sage: E[L0((0,-1,1))] # long time (1.5s) - ((-q^2*u^10+q^2*u^8-q*u^6+q*u^4+q*u^2+u^2-q-1)/(-q^3*u^12+q^2*u^8+q*u^4-1))*B[(0, 0, 0)] - + ((-u^2+1)/(-q*u^4+1))*B[(1, -1, 0)] + -((q^2*u^10-q^2*u^8+q*u^6-q*u^4-q*u^2-u^2+q+1)/(-q^3*u^12+q^2*u^8+q*u^4-1))*B[(0, 0, 0)] + - ((u^2-1)/(-q*u^4+1))*B[(1, -1, 0)] + ((u^6-u^4-u^2+1)/(q^3*u^12-q^2*u^8-q*u^4+1))*B[(1, 1, 0)] + ((u^4-2*u^2+1)/(q^3*u^12-q^2*u^8-q*u^4+1))*B[(1, 0, -1)] + ((q^2*u^12-q^2*u^10-u^2+1)/(q^3*u^12-q^2*u^8-q*u^4+1))*B[(1, 0, 1)] + B[(0, -1, 1)] - + ((-u^2+1)/(-q^2*u^8+1))*B[(0, 1, -1)] + ((-u^2+1)/(-q^2*u^8+1))*B[(0, 1, 1)] + - ((u^2-1)/(-q^2*u^8+1))*B[(0, 1, -1)] - ((u^2-1)/(-q^2*u^8+1))*B[(0, 1, 1)] sage: K = QQ['q,u'].fraction_field() sage: q, u = K.gens() sage: KL = RootSystem(["E",6,2]).ambient_space().algebra(K) sage: E = NonSymmetricMacdonaldPolynomials(KL,q,u,-1/u) sage: L0 = E.keys() sage: E[L0.fundamental_weight(4)] # long time (5s) - ((-q^3*u^20+q^3*u^18+q^2*u^2-q^2)/(-q^3*u^28+q^2*u^22+q*u^6-1))*B[(0, 0, 0, 0)] - + ((-q*u^2+q)/(-q*u^6+1))*B[(1/2, 1/2, -1/2, -1/2)] - + ((-q*u^2+q)/(-q*u^6+1))*B[(1/2, 1/2, -1/2, 1/2)] - + ((-q*u^2+q)/(-q*u^6+1))*B[(1/2, 1/2, 1/2, -1/2)] - + ((-q*u^2+q)/(-q*u^6+1))*B[(1/2, 1/2, 1/2, 1/2)] - + ((q*u^2-q)/(q*u^6-1))*B[(1, 0, 0, 0)] - + B[(1, 1, 0, 0)] - + ((-q*u^2+q)/(-q*u^6+1))*B[(0, 1, 0, 0)] + -((q^3*u^20-q^3*u^18-q^2*u^2+q^2)/(-q^3*u^28+q^2*u^22+q*u^6-1))*B[(0, 0, 0, 0)] + - ((q*u^2-q)/(-q*u^6+1))*B[(1/2, 1/2, -1/2, -1/2)] + - ((q*u^2-q)/(-q*u^6+1))*B[(1/2, 1/2, -1/2, 1/2)] + - ((q*u^2-q)/(-q*u^6+1))*B[(1/2, 1/2, 1/2, -1/2)] + - ((q*u^2-q)/(-q*u^6+1))*B[(1/2, 1/2, 1/2, 1/2)] + + ((q*u^2-q)/(q*u^6-1))*B[(1, 0, 0, 0)] + B[(1, 1, 0, 0)] + - ((q*u^2-q)/(-q*u^6+1))*B[(0, 1, 0, 0)] sage: E[L0((1,-1,0,0))] # long time (23s) ((q^3*u^18-q^3*u^16+q*u^4-q^2*u^2-2*q*u^2+q^2+q)/(q^3*u^18-q^2*u^12-q*u^6+1))*B[(0, 0, 0, 0)] - + ((-q^3*u^18+q^3*u^16+q*u^2-q)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(1/2, -1/2, -1/2, -1/2)] - + ((-q^3*u^18+q^3*u^16+q*u^2-q)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(1/2, -1/2, -1/2, 1/2)] + - ((q^3*u^18-q^3*u^16-q*u^2+q)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(1/2, -1/2, -1/2, -1/2)] + - ((q^3*u^18-q^3*u^16-q*u^2+q)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(1/2, -1/2, -1/2, 1/2)] + ((q^3*u^18-q^3*u^16-q*u^2+q)/(q^3*u^18-q^2*u^12-q*u^6+1))*B[(1/2, -1/2, 1/2, -1/2)] + ((q^3*u^18-q^3*u^16-q*u^2+q)/(q^3*u^18-q^2*u^12-q*u^6+1))*B[(1/2, -1/2, 1/2, 1/2)] + ((q*u^8-q*u^6-q*u^2+q)/(q^3*u^18-q^2*u^12-q*u^6+1))*B[(1/2, 1/2, -1/2, -1/2)] + ((q*u^8-q*u^6-q*u^2+q)/(q^3*u^18-q^2*u^12-q*u^6+1))*B[(1/2, 1/2, -1/2, 1/2)] - + ((-q*u^8+q*u^6+q*u^2-q)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(1/2, 1/2, 1/2, -1/2)] - + ((-q*u^8+q*u^6+q*u^2-q)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(1/2, 1/2, 1/2, 1/2)] - + ((-q^2*u^18+q^2*u^16-q*u^8+q*u^6+q*u^2+u^2-q-1)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(1, 0, 0, 0)] - + B[(1, -1, 0, 0)] + ((-u^2+1)/(-q^2*u^12+1))*B[(1, 1, 0, 0)] - + ((-u^2+1)/(-q^2*u^12+1))*B[(1, 0, -1, 0)] + - ((q*u^8-q*u^6-q*u^2+q)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(1/2, 1/2, 1/2, -1/2)] + - ((q*u^8-q*u^6-q*u^2+q)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(1/2, 1/2, 1/2, 1/2)] + - ((q^2*u^18-q^2*u^16+q*u^8-q*u^6-q*u^2-u^2+q+1)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(1, 0, 0, 0)] + + B[(1, -1, 0, 0)] - ((u^2-1)/(-q^2*u^12+1))*B[(1, 1, 0, 0)] + - ((u^2-1)/(-q^2*u^12+1))*B[(1, 0, -1, 0)] + ((u^2-1)/(q^2*u^12-1))*B[(1, 0, 1, 0)] - + ((-u^2+1)/(-q^2*u^12+1))*B[(1, 0, 0, -1)] - + ((-u^2+1)/(-q^2*u^12+1))*B[(1, 0, 0, 1)] - + ((-q*u^2+q)/(-q*u^6+1))*B[(0, -1, 0, 0)] - + ((-q*u^4+2*q*u^2-q)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(0, 1, 0, 0)] - + ((-q*u^4+2*q*u^2-q)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(0, 0, -1, 0)] - + ((-q*u^4+2*q*u^2-q)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(0, 0, 1, 0)] - + ((-q*u^4+2*q*u^2-q)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(0, 0, 0, -1)] - + ((-q*u^4+2*q*u^2-q)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(0, 0, 0, 1)] + - ((u^2-1)/(-q^2*u^12+1))*B[(1, 0, 0, -1)] + - ((u^2-1)/(-q^2*u^12+1))*B[(1, 0, 0, 1)] + - ((q*u^2-q)/(-q*u^6+1))*B[(0, -1, 0, 0)] + - ((q*u^4-2*q*u^2+q)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(0, 1, 0, 0)] + - ((q*u^4-2*q*u^2+q)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(0, 0, -1, 0)] + - ((q*u^4-2*q*u^2+q)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(0, 0, 1, 0)] + - ((q*u^4-2*q*u^2+q)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(0, 0, 0, -1)] + - ((q*u^4-2*q*u^2+q)/(-q^3*u^18+q^2*u^12+q*u^6-1))*B[(0, 0, 0, 1)] Next we test a twisted type (checked against Maple computation by Bogdan Ion for `q_1=t^2` and `q_2=-1`):: @@ -574,13 +571,13 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): + ((q1+q2)/(q*q1+q2))*B[(0, 0, -1)] + ((q1+q2)/(q*q1+q2))*B[(0, 0, 1)] sage: E[omega[2]] - ((-q1*q2^3-q2^4)/(q*q1^4-q2^4))*B[(1, 0, 0)] + B[(0, 1, 0)] + -((q1*q2^3+q2^4)/(q*q1^4-q2^4))*B[(1, 0, 0)] + B[(0, 1, 0)] sage: E[-omega[2]] ((q^2*q1^7+q^2*q1^6*q2-q1*q2^6-q2^7)/(q^3*q1^7-q^2*q1^5*q2^2+q*q1^2*q2^5-q2^7))*B[(1, 0, 0)] + B[(0, -1, 0)] + ((q*q1^5*q2^2+q*q1^4*q2^3-q1*q2^6-q2^7)/(q^3*q1^7-q^2*q1^5*q2^2+q*q1^2*q2^5-q2^7))*B[(0, 1, 0)] - + ((-q1*q2-q2^2)/(q*q1^2-q2^2))*B[(0, 0, -1)] + - ((q1*q2+q2^2)/(q*q1^2-q2^2))*B[(0, 0, -1)] + ((q1*q2+q2^2)/(-q*q1^2+q2^2))*B[(0, 0, 1)] sage: E[-omega[1]-omega[2]] @@ -588,7 +585,7 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): + B[(-1, -1, 0)] + ((q*q1^4+q*q1^3*q2+q1*q2^3+q2^4)/(q^3*q1^4+q^2*q1^3*q2+q*q1*q2^3+q2^4))*B[(-1, 1, 0)] + ((q1+q2)/(q*q1+q2))*B[(-1, 0, -1)] - + ((-q1-q2)/(-q*q1-q2))*B[(-1, 0, 1)] + - ((q1+q2)/(-q*q1-q2))*B[(-1, 0, 1)] + ((q*q1^4+q*q1^3*q2+q1*q2^3+q2^4)/(q^3*q1^4+q^2*q1^3*q2+q*q1*q2^3+q2^4))*B[(1, -1, 0)] + ((q^2*q1^6+q^2*q1^5*q2+q*q1^5*q2-q*q1^3*q2^3-q1^5*q2-q1^4*q2^2+q1^3*q2^3+q1^2*q2^4-q1*q2^5-q2^6)/(q^4*q1^6+q^3*q1^5*q2-q^3*q1^4*q2^2+q*q1^2*q2^4-q*q1*q2^5-q2^6))*B[(1, 1, 0)] + ((q*q1^4+2*q*q1^3*q2+q*q1^2*q2^2-q1^3*q2-q1^2*q2^2+q1*q2^3+q2^4)/(q^3*q1^4+q^2*q1^3*q2+q*q1*q2^3+q2^4))*B[(1, 0, -1)] @@ -602,17 +599,17 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): ((q^3*q1^7+q^3*q1^6*q2-q*q1*q2^6-q*q2^7)/(q^3*q1^7-q^2*q1^5*q2^2+q*q1^2*q2^5-q2^7))*B[(0, 0, 0)] + B[(1, -1, 0)] + ((q*q1^5*q2^2+q*q1^4*q2^3-q1*q2^6-q2^7)/(q^3*q1^7-q^2*q1^5*q2^2+q*q1^2*q2^5-q2^7))*B[(1, 1, 0)] - + ((-q1*q2-q2^2)/(q*q1^2-q2^2))*B[(1, 0, -1)] + - ((q1*q2+q2^2)/(q*q1^2-q2^2))*B[(1, 0, -1)] + ((q1*q2+q2^2)/(-q*q1^2+q2^2))*B[(1, 0, 1)] sage: E[omega[3]] - ((-q1*q2^2-q2^3)/(-q*q1^3-q2^3))*B[(1, 0, 0)] - + ((-q1*q2^2-q2^3)/(-q*q1^3-q2^3))*B[(0, 1, 0)] + B[(0, 0, 1)] + -((q1*q2^2+q2^3)/(-q*q1^3-q2^3))*B[(1, 0, 0)] + - ((q1*q2^2+q2^3)/(-q*q1^3-q2^3))*B[(0, 1, 0)] + B[(0, 0, 1)] sage: E[-omega[3]] ((q*q1^4*q2+q*q1^3*q2^2-q1*q2^4-q2^5)/(-q^2*q1^5-q2^5))*B[(1, 0, 0)] + ((q*q1^4*q2+q*q1^3*q2^2-q1*q2^4-q2^5)/(-q^2*q1^5-q2^5))*B[(0, 1, 0)] - + B[(0, 0, -1)] + ((-q1*q2^4-q2^5)/(-q^2*q1^5-q2^5))*B[(0, 0, 1)] + + B[(0, 0, -1)] - ((q1*q2^4+q2^5)/(-q^2*q1^5-q2^5))*B[(0, 0, 1)] .. RUBRIC:: Comparison with the energy function of crystals @@ -776,18 +773,18 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: omega = L0.fundamental_weights() sage: E[omega[1]] - ((-q*t^4+q*t^2)/(-q*t^6+1))*B[(0, 0)] + B[(1, 0)] + -((q*t^4-q*t^2)/(-q*t^6+1))*B[(0, 0)] + B[(1, 0)] sage: E[omega[2]] B[(1/2, 1/2)] sage: E[-omega[1]] - ((-q^2*t^8+q^2*t^6-q*t^6+2*q*t^4-q*t^2+t^2-1)/(-q^3*t^8+q^2*t^6+q*t^2-1))*B[(0, 0)] - + B[(-1, 0)] + ((-q*t^8+q*t^6+t^2-1)/(-q^3*t^8+q^2*t^6+q*t^2-1))*B[(1, 0)] - + ((-t^2+1)/(-q*t^2+1))*B[(0, -1)] + ((t^2-1)/(q*t^2-1))*B[(0, 1)] + -((q^2*t^8-q^2*t^6+q*t^6-2*q*t^4+q*t^2-t^2+1)/(-q^3*t^8+q^2*t^6+q*t^2-1))*B[(0, 0)] + + B[(-1, 0)] - ((q*t^8-q*t^6-t^2+1)/(-q^3*t^8+q^2*t^6+q*t^2-1))*B[(1, 0)] + - ((t^2-1)/(-q*t^2+1))*B[(0, -1)] + ((t^2-1)/(q*t^2-1))*B[(0, 1)] sage: E[L0([0,1])] - ((-q*t^4+q*t^2)/(-q*t^4+1))*B[(0, 0)] + ((-t^2+1)/(-q*t^4+1))*B[(1, 0)] + B[(0, 1)] + -((q*t^4-q*t^2)/(-q*t^4+1))*B[(0, 0)] - ((t^2-1)/(-q*t^4+1))*B[(1, 0)] + B[(0, 1)] sage: E[L0([1,1])] - ((q*t^2-q)/(q*t^2-1))*B[(0, 0)] + ((-q*t^2+q)/(-q*t^2+1))*B[(1, 0)] - + B[(1, 1)] + ((-q*t^2+q)/(-q*t^2+1))*B[(0, 1)] + ((q*t^2-q)/(q*t^2-1))*B[(0, 0)] - ((q*t^2-q)/(-q*t^2+1))*B[(1, 0)] + + B[(1, 1)] - ((q*t^2-q)/(-q*t^2+1))*B[(0, 1)] sage: E = NonSymmetricMacdonaldPolynomials(["A",2,1], q=q,q1=t,q2=-1/t) sage: L0 = E.keys() @@ -809,7 +806,7 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: E._T_Y[0] ( KL0.monomial(L0.zero()) ) t*B[(0)] sage: E._T_Y[0] ( KL0.monomial(-e[0])) - ((-t^2+1)/(q*t))*B[(0)] + 1/(q^2*t)*B[(1)] + -((t^2-1)/(q*t))*B[(0)] + 1/(q^2*t)*B[(1)] sage: Y = E.Y() sage: alphacheck = Y.keys().simple_roots() @@ -856,20 +853,21 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: E[0*omega[1]] B[(0, 0)] sage: E[omega[1]] - ((-q*q1*q2^3-q*q2^4)/(q^2*q1^4-q2^4))*B[(0, 0)] + B[(1, 0)] + -((q*q1*q2^3+q*q2^4)/(q^2*q1^4-q2^4))*B[(0, 0)] + B[(1, 0)] sage: E[2*omega[2]] # not checked against Bogdan's notes, but a good self-consistency test # long time - ((-q^12*q1^6-q^12*q1^5*q2+2*q^10*q1^5*q2+5*q^10*q1^4*q2^2+3*q^10*q1^3*q2^3+2*q^8*q1^5*q2+4*q^8*q1^4*q2^2+q^8*q1^3*q2^3-q^8*q1^2*q2^4+q^8*q1*q2^5+q^8*q2^6-q^6*q1^3*q2^3+q^6*q1^2*q2^4+4*q^6*q1*q2^5+2*q^6*q2^6+q^4*q1^3*q2^3+3*q^4*q1^2*q2^4+4*q^4*q1*q2^5+2*q^4*q2^6)/(-q^12*q1^6-q^10*q1^5*q2-q^8*q1^3*q2^3+q^6*q1^4*q2^2-q^6*q1^2*q2^4+q^4*q1^3*q2^3+q^2*q1*q2^5+q2^6))*B[(0, 0)] + -((q^12*q1^6+q^12*q1^5*q2-2*q^10*q1^5*q2-5*q^10*q1^4*q2^2-3*q^10*q1^3*q2^3-2*q^8*q1^5*q2-4*q^8*q1^4*q2^2-q^8*q1^3*q2^3+q^8*q1^2*q2^4-q^8*q1*q2^5-q^8*q2^6+q^6*q1^3*q2^3-q^6*q1^2*q2^4-4*q^6*q1*q2^5-2*q^6*q2^6-q^4*q1^3*q2^3-3*q^4*q1^2*q2^4-4*q^4*q1*q2^5-2*q^4*q2^6)/(-q^12*q1^6-q^10*q1^5*q2-q^8*q1^3*q2^3+q^6*q1^4*q2^2-q^6*q1^2*q2^4+q^4*q1^3*q2^3+q^2*q1*q2^5+q2^6))*B[(0, 0)] + ((q^7*q1^2*q2+2*q^7*q1*q2^2+q^7*q2^3+q^5*q1^2*q2+2*q^5*q1*q2^2+q^5*q2^3)/(-q^8*q1^3-q^6*q1^2*q2+q^2*q1*q2^2+q2^3))*B[(-1, 0)] - + ((-q^6*q1*q2-q^6*q2^2)/(q^6*q1^2-q2^2))*B[(-1, -1)] + - ((q^6*q1*q2+q^6*q2^2)/(q^6*q1^2-q2^2))*B[(-1, -1)] + ((q^6*q1^2*q2+2*q^6*q1*q2^2+q^6*q2^3+q^4*q1^2*q2+2*q^4*q1*q2^2+q^4*q2^3)/(-q^8*q1^3-q^6*q1^2*q2+q^2*q1*q2^2+q2^3))*B[(-1, 1)] - + ((-q^3*q1*q2-q^3*q2^2)/(q^6*q1^2-q2^2))*B[(-1, 2)] - + ((q^7*q1^3+q^7*q1^2*q2-q^7*q1*q2^2-q^7*q2^3-2*q^5*q1^2*q2-4*q^5*q1*q2^2-2*q^5*q2^3-2*q^3*q1^2*q2-4*q^3*q1*q2^2-2*q^3*q2^3)/(q^8*q1^3+q^6*q1^2*q2-q^2*q1*q2^2-q2^3))*B[(1, 0)] + ((q^6*q1^2*q2+2*q^6*q1*q2^2+q^6*q2^3+q^4*q1^2*q2+2*q^4*q1*q2^2+q^4*q2^3)/(-q^8*q1^3-q^6*q1^2*q2+q^2*q1*q2^2+q2^3))*B[(1, -1)] + - ((q^3*q1*q2+q^3*q2^2)/(q^6*q1^2-q2^2))*B[(-1, 2)] + + ((q^7*q1^3+q^7*q1^2*q2-q^7*q1*q2^2-q^7*q2^3-2*q^5*q1^2*q2-4*q^5*q1*q2^2-2*q^5*q2^3-2*q^3*q1^2*q2-4*q^3*q1*q2^2-2*q^3*q2^3)/(q^8*q1^3+q^6*q1^2*q2-q^2*q1*q2^2-q2^3))*B[(1, 0)] + + ((q^6*q1^2*q2+2*q^6*q1*q2^2+q^6*q2^3+q^4*q1^2*q2+2*q^4*q1*q2^2+q^4*q2^3)/(-q^8*q1^3-q^6*q1^2*q2+q^2*q1*q2^2+q2^3))*B[(1, -1)] + ((q^8*q1^3+q^8*q1^2*q2+q^6*q1^3+q^6*q1^2*q2-q^6*q1*q2^2-q^6*q2^3-2*q^4*q1^2*q2-4*q^4*q1*q2^2-2*q^4*q2^3-q^2*q1^2*q2-3*q^2*q1*q2^2-2*q^2*q2^3)/(q^8*q1^3+q^6*q1^2*q2-q^2*q1*q2^2-q2^3))*B[(1, 1)] + ((q^5*q1^2+q^5*q1*q2-q^3*q1*q2-q^3*q2^2-q*q1*q2-q*q2^2)/(q^6*q1^2-q2^2))*B[(1, 2)] - + ((-q^6*q1^2-q^6*q1*q2+q^4*q1*q2+q^4*q2^2+q^2*q1*q2+q^2*q2^2)/(-q^6*q1^2+q2^2))*B[(2, 0)] - + ((-q^3*q1*q2-q^3*q2^2)/(q^6*q1^2-q2^2))*B[(2, -1)] - + ((-q^5*q1^2-q^5*q1*q2+q^3*q1*q2+q^3*q2^2+q*q1*q2+q*q2^2)/(-q^6*q1^2+q2^2))*B[(2, 1)] + - ((q^6*q1^2+q^6*q1*q2-q^4*q1*q2-q^4*q2^2-q^2*q1*q2-q^2*q2^2)/(-q^6*q1^2+q2^2))*B[(2, 0)] + - ((q^3*q1*q2+q^3*q2^2)/(q^6*q1^2-q2^2))*B[(2, -1)] + - ((q^5*q1^2+q^5*q1*q2-q^3*q1*q2-q^3*q2^2-q*q1*q2-q*q2^2)/(-q^6*q1^2+q2^2))*B[(2, 1)] + B[(2, 2)] + ((q^7*q1^2*q2+2*q^7*q1*q2^2+q^7*q2^3+q^5*q1^2*q2+2*q^5*q1*q2^2+q^5*q2^3)/(-q^8*q1^3-q^6*q1^2*q2+q^2*q1*q2^2+q2^3))*B[(0, -1)] + ((q^7*q1^3+q^7*q1^2*q2-q^7*q1*q2^2-q^7*q2^3-2*q^5*q1^2*q2-4*q^5*q1*q2^2-2*q^5*q2^3-2*q^3*q1^2*q2-4*q^3*q1*q2^2-2*q^3*q2^3)/(q^8*q1^3+q^6*q1^2*q2-q^2*q1*q2^2-q2^3))*B[(0, 1)] @@ -891,11 +889,11 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: Ye1(KL0.one()) q1^2/q2^2*B[(0, 0)] sage: Ye2(KL0.one()) - ((-q1)/q2)*B[(0, 0)] + -q1/q2*B[(0, 0)] sage: Yalpha0(KL0.one()) q2^2/(q*q1^2)*B[(0, 0)] sage: Yalpha1(KL0.one()) - ((-q1)/q2)*B[(0, 0)] + -q1/q2*B[(0, 0)] sage: Yalpha2(KL0.one()) q1^2/q2^2*B[(0, 0)] @@ -952,11 +950,11 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: T0check_on_basis.j # what to match it with? 2 sage: T0check_on_basis(KL0.basis().keys().zero()) - ((-q1^2)/q2)*B[(1, 0)] + -q1^2/q2*B[(1, 0)] sage: T0check = E._T[0] sage: T0check(KL0.one()) - ((-q1^2)/q2)*B[(1, 0)] + -q1^2/q2*B[(1, 0)] Systematic tests of nonsymmetric Macdonald polynomials in type @@ -983,24 +981,24 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: E.eigenvalues(_) [t, 1/(q*t)] sage: E[2*omega[1]] - ((-q*t+q)/(-q*t+1))*B[0] + B[2*Lambda[1]] + -((q*t-q)/(-q*t+1))*B[0] + B[2*Lambda[1]] sage: E.eigenvalues(_) [q*t, 1/(q^2*t)] sage: E[3*omega[1]] - ((-q^2*t+q^2)/(-q^2*t+1))*B[-Lambda[1]] - + ((-q^2*t+q^2-q*t+q)/(-q^2*t+1))*B[Lambda[1]] + B[3*Lambda[1]] + -((q^2*t-q^2)/(-q^2*t+1))*B[-Lambda[1]] + - ((q^2*t-q^2+q*t-q)/(-q^2*t+1))*B[Lambda[1]] + B[3*Lambda[1]] sage: E.eigenvalues(_) [q^2*t, 1/(q^3*t)] sage: E[4*omega[1]] ((q^5*t^2-q^5*t+q^4*t^2-2*q^4*t+q^3*t^2+q^4-2*q^3*t+q^3-q^2*t+q^2)/(q^5*t^2-q^3*t-q^2*t+1))*B[0] - + ((-q^3*t+q^3)/(-q^3*t+1))*B[-2*Lambda[1]] - + ((-q^3*t+q^3-q^2*t+q^2-q*t+q)/(-q^3*t+1))*B[2*Lambda[1]] + - ((q^3*t-q^3)/(-q^3*t+1))*B[-2*Lambda[1]] + - ((q^3*t-q^3+q^2*t-q^2+q*t-q)/(-q^3*t+1))*B[2*Lambda[1]] + B[4*Lambda[1]] sage: E.eigenvalues(_) [q^3*t, 1/(q^4*t)] sage: E[6*omega[1]] - ((-q^12*t^3+q^12*t^2-q^11*t^3+2*q^11*t^2-2*q^10*t^3-q^11*t+4*q^10*t^2-2*q^9*t^3-2*q^10*t+5*q^9*t^2-2*q^8*t^3-4*q^9*t+6*q^8*t^2-q^7*t^3+q^9-5*q^8*t+5*q^7*t^2-q^6*t^3+q^8-6*q^7*t+4*q^6*t^2+2*q^7-5*q^6*t+2*q^5*t^2+2*q^6-4*q^5*t+q^4*t^2+2*q^5-2*q^4*t+q^4-q^3*t+q^3)/(-q^12*t^3+q^9*t^2+q^8*t^2+q^7*t^2-q^5*t-q^4*t-q^3*t+1))*B[0] - + ((-q^5*t+q^5)/(-q^5*t+1))*B[-4*Lambda[1]] + -((q^12*t^3-q^12*t^2+q^11*t^3-2*q^11*t^2+2*q^10*t^3+q^11*t-4*q^10*t^2+2*q^9*t^3+2*q^10*t-5*q^9*t^2+2*q^8*t^3+4*q^9*t-6*q^8*t^2+q^7*t^3-q^9+5*q^8*t-5*q^7*t^2+q^6*t^3-q^8+6*q^7*t-4*q^6*t^2-2*q^7+5*q^6*t-2*q^5*t^2-2*q^6+4*q^5*t-q^4*t^2-2*q^5+2*q^4*t-q^4+q^3*t-q^3)/(-q^12*t^3+q^9*t^2+q^8*t^2+q^7*t^2-q^5*t-q^4*t-q^3*t+1))*B[0] + - ((q^5*t-q^5)/(-q^5*t+1))*B[-4*Lambda[1]] + ((q^9*t^2-q^9*t+q^8*t^2-2*q^8*t+q^7*t^2+q^8-2*q^7*t+q^6*t^2+q^7-2*q^6*t+q^5*t^2+q^6-2*q^5*t+q^5-q^4*t+q^4)/(q^9*t^2-q^5*t-q^4*t+1))*B[-2*Lambda[1]] + ((q^9*t^2-q^9*t+q^8*t^2-2*q^8*t+2*q^7*t^2+q^8-3*q^7*t+2*q^6*t^2+q^7-4*q^6*t+2*q^5*t^2+2*q^6-4*q^5*t+q^4*t^2+2*q^5-3*q^4*t+q^3*t^2+2*q^4-2*q^3*t+q^3-q^2*t+q^2)/(q^9*t^2-q^5*t-q^4*t+1))*B[2*Lambda[1]] + ((q^5*t-q^5+q^4*t-q^4+q^3*t-q^3+q^2*t-q^2+q*t-q)/(q^5*t-1))*B[4*Lambda[1]] @@ -1008,7 +1006,7 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: E.eigenvalues(_) [q^5*t, 1/(q^6*t)] sage: E[-omega[1]] - B[-Lambda[1]] + ((-t+1)/(-q*t+1))*B[Lambda[1]] + B[-Lambda[1]] - ((t-1)/(-q*t+1))*B[Lambda[1]] sage: E.eigenvalues(_) [(-1)/(-q^2*t), q*t] @@ -1070,7 +1068,7 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: L0 = E.keys() sage: omega = L0.fundamental_weights() sage: E[2*omega[2]] - ((-q*q1-q*q2)/(-q*q1-q2))*B[(1, 2, 1)] + ((-q*q1-q*q2)/(-q*q1-q2))*B[(2, 1, 1)] + B[(2, 2, 0)] + -((q*q1+q*q2)/(-q*q1-q2))*B[(1, 2, 1)] - ((q*q1+q*q2)/(-q*q1-q2))*B[(2, 1, 1)] + B[(2, 2, 0)] sage: for d in range(4): # long time (9s) ....: for weight in IntegerVectors(d,3).map(list).map(L0): ....: eigenvalues = E.eigenvalues(E[L0(weight)]) @@ -1093,35 +1091,35 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): [t, 1/(q*t^3), t] sage: E[-omega[1]] # consistent with before refactoring - B[(-1, 0)] + ((-t+1)/(-q*t+1))*B[(1, 0)] - + ((-t+1)/(-q*t+1))*B[(0, -1)] + ((t-1)/(q*t-1))*B[(0, 1)] + B[(-1, 0)] - ((t-1)/(-q*t+1))*B[(1, 0)] - ((t-1)/(-q*t+1))*B[(0, -1)] + + ((t-1)/(q*t-1))*B[(0, 1)] sage: E.eigenvalues(_) # not checked [(-1)/(-q^2*t^3), q*t, t] sage: E[-omega[1]+omega[2]] # consistent with before refactoring - ((-t+1)/(-q*t^3+1))*B[(1, 0)] + B[(0, 1)] + -((t-1)/(-q*t^3+1))*B[(1, 0)] + B[(0, 1)] sage: E.eigenvalues(_) # not checked [t, q*t^3, (-1)/(-q*t^2)] sage: E[omega[1]-omega[2]] # consistent with before refactoring - ((-t+1)/(-q*t^2+1))*B[(1, 0)] + B[(0, -1)] + ((-t+1)/(-q*t^2+1))*B[(0, 1)] + -((t-1)/(-q*t^2+1))*B[(1, 0)] + B[(0, -1)] - ((t-1)/(-q*t^2+1))*B[(0, 1)] sage: E.eigenvalues(_) # not checked [1/(q^2*t^3), 1/(q*t), q*t^2] sage: E[-omega[2]] - ((-q^2*t^4+q^2*t^3-q*t^3+2*q*t^2-q*t+t-1)/(-q^3*t^4+q^2*t^3+q*t-1))*B[(0, 0)] - + B[(-1, -1)] + ((-t+1)/(-q*t+1))*B[(-1, 1)] + ((t-1)/(q*t-1))*B[(1, -1)] - + ((-q*t^4+q*t^3+t-1)/(-q^3*t^4+q^2*t^3+q*t-1))*B[(1, 1)] + -((q^2*t^4-q^2*t^3+q*t^3-2*q*t^2+q*t-t+1)/(-q^3*t^4+q^2*t^3+q*t-1))*B[(0, 0)] + + B[(-1, -1)] - ((t-1)/(-q*t+1))*B[(-1, 1)] + ((t-1)/(q*t-1))*B[(1, -1)] + - ((q*t^4-q*t^3-t+1)/(-q^3*t^4+q^2*t^3+q*t-1))*B[(1, 1)] sage: E.eigenvalues(_) # not checked # long time (1s) [1/(q^3*t^3), t, q*t] sage: E[-omega[2]].map_coefficients(lambda c: c.subs(t=0)) # checking against crystals B[(0, 0)] + B[(-1, -1)] + B[(-1, 1)] + B[(1, -1)] + B[(1, 1)] sage: E[2*omega[2]] - ((-q^6*t^7+q^6*t^6-q^5*t^6+2*q^5*t^5-q^4*t^5-q^5*t^3+3*q^4*t^4-3*q^4*t^3+q^3*t^4+q^4*t^2-2*q^3*t^2+q^3*t-q^2*t+q^2)/(-q^6*t^7+q^5*t^6+q^4*t^4+q^3*t^4-q^3*t^3-q^2*t^3-q*t+1))*B[(0, 0)] - + ((-q^3*t^2+q^3*t)/(-q^3*t^3+1))*B[(-1, -1)] - + ((-q^3*t^3+2*q^3*t^2-q^3*t)/(-q^4*t^4+q^3*t^3+q*t-1))*B[(-1, 1)] - + ((-q^3*t^3+2*q^3*t^2-q^3*t)/(-q^4*t^4+q^3*t^3+q*t-1))*B[(1, -1)] - + ((-q^4*t^4+q^4*t^3-q^3*t^3+2*q^3*t^2-q^2*t^3-q^3*t+2*q^2*t^2-q^2*t+q*t-q)/(-q^4*t^4+q^3*t^3+q*t-1))*B[(1, 1)] - + ((q*t-q)/(q*t-1))*B[(2, 0)] + B[(2, 2)] + ((-q*t+q)/(-q*t+1))*B[(0, 2)] + -((q^6*t^7-q^6*t^6+q^5*t^6-2*q^5*t^5+q^4*t^5+q^5*t^3-3*q^4*t^4+3*q^4*t^3-q^3*t^4-q^4*t^2+2*q^3*t^2-q^3*t+q^2*t-q^2)/(-q^6*t^7+q^5*t^6+q^4*t^4+q^3*t^4-q^3*t^3-q^2*t^3-q*t+1))*B[(0, 0)] + - ((q^3*t^2-q^3*t)/(-q^3*t^3+1))*B[(-1, -1)] + - ((q^3*t^3-2*q^3*t^2+q^3*t)/(-q^4*t^4+q^3*t^3+q*t-1))*B[(-1, 1)] + - ((q^3*t^3-2*q^3*t^2+q^3*t)/(-q^4*t^4+q^3*t^3+q*t-1))*B[(1, -1)] + - ((q^4*t^4-q^4*t^3+q^3*t^3-2*q^3*t^2+q^2*t^3+q^3*t-2*q^2*t^2+q^2*t-q*t+q)/(-q^4*t^4+q^3*t^3+q*t-1))*B[(1, 1)] + + ((q*t-q)/(q*t-1))*B[(2, 0)] + B[(2, 2)] - ((q*t-q)/(-q*t+1))*B[(0, 2)] sage: E.eigenvalues(_) # not checked [q^3*t^3, t, (-1)/(-q^2*t^2)] @@ -1154,22 +1152,22 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: E.eigenvalues(_) [1/(q*t^2), t, t] sage: E[omega[1]] - ((-q*t+q)/(-q*t^2+1))*B[(0, 0)] + B[(1, 0)] + -((q*t-q)/(-q*t^2+1))*B[(0, 0)] + B[(1, 0)] sage: E.eigenvalues(_) [q*t^2, 1/(q^2*t^3), t] sage: E[-omega[1]] - ((-q*t+q-t+1)/(-q^2*t+1))*B[(0, 0)] + B[(-1, 0)] + ((-t+1)/(-q^2*t+1))*B[(1, 0)] - + ((-t+1)/(-q^2*t+1))*B[(0, -1)] + ((t-1)/(q^2*t-1))*B[(0, 1)] + -((q*t-q+t-1)/(-q^2*t+1))*B[(0, 0)] + B[(-1, 0)] - ((t-1)/(-q^2*t+1))*B[(1, 0)] + - ((t-1)/(-q^2*t+1))*B[(0, -1)] + ((t-1)/(q^2*t-1))*B[(0, 1)] sage: E.eigenvalues(_) [(-1)/(-q^3*t^2), q^2*t, t] sage: E[-omega[1]+omega[2]] - B[(-1/2, 1/2)] + ((-t+1)/(-q^2*t^3+1))*B[(1/2, -1/2)] - + ((-q*t^3+q*t^2-t+1)/(-q^2*t^3+1))*B[(1/2, 1/2)] + B[(-1/2, 1/2)] - ((t-1)/(-q^2*t^3+1))*B[(1/2, -1/2)] + - ((q*t^3-q*t^2+t-1)/(-q^2*t^3+1))*B[(1/2, 1/2)] sage: E.eigenvalues(_) [(-1)/(-q^2*t^2), q^2*t^3, (-1)/(-q*t)] sage: E[omega[1]-omega[2]] - B[(1/2, -1/2)] + ((-t+1)/(-q*t^2+1))*B[(1/2, 1/2)] + B[(1/2, -1/2)] - ((t-1)/(-q*t^2+1))*B[(1/2, 1/2)] sage: E.eigenvalues(_) [t, 1/(q^2*t^3), q*t^2] @@ -1234,7 +1232,7 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): sage: E[0*omega[1]] B[(0, 0)] sage: E[omega[1]] - ((-q^2*q1^3*q2-q^2*q1^2*q2^2)/(q^2*q1^4-q2^4))*B[(0, 0)] + B[(1, 0)] + -((q^2*q1^3*q2+q^2*q1^2*q2^2)/(q^2*q1^4-q2^4))*B[(0, 0)] + B[(1, 0)] sage: Eomega1 = (KL.one() * (q^2*(-q1/q2)^2*(1-(-q1/q2))) / (1-q^2*(-q1/q2)^4) ....: + KL.monomial(omega[1])) sage: E[omega[1]] == Eomega1 @@ -1272,7 +1270,7 @@ class NonSymmetricMacdonaldPolynomials(CherednikOperatorsEigenvectors): ....: assert Tinv2(T[2](x)) == x and T[2](Tinv2(x)) == x sage: start = E[omega[1]]; start - ((-q^2*q1^3*q2-q^2*q1^2*q2^2)/(q^2*q1^4-q2^4))*B[(0, 0)] + B[(1, 0)] + -((q^2*q1^3*q2+q^2*q1^2*q2^2)/(q^2*q1^4-q2^4))*B[(0, 0)] + B[(1, 0)] sage: Tinv1(Tinv2(Tinv1(Tinv0(Tinv1(Tinv2(Tinv1(Tinv0(start)))))))) * (q1*q2)^4/q^2 == Y0(start) True sage: Y0(start) == q^2*q1^4/q2^4 * start @@ -1684,8 +1682,8 @@ def __getitem__(self, mu): of the affine weight lattice sage: E[2*omega[2]] # needs sage.libs.gap ((q^2*q1^2+q^2*q1*q2)/(q^2*q1^2-q2^2))*B[(0, 0)] - + ((-q^2*q1^2-q^2*q1*q2)/(-q^2*q1^2+q2^2))*B[(1, 0)] + B[(1, 1)] - + ((-q^2*q1^2-q^2*q1*q2)/(-q^2*q1^2+q2^2))*B[(0, 1)] + - ((q^2*q1^2+q^2*q1*q2)/(-q^2*q1^2+q2^2))*B[(1, 0)] + B[(1, 1)] + - ((q^2*q1^2+q^2*q1*q2)/(-q^2*q1^2+q2^2))*B[(0, 1)] """ muaff = self._L.embed_at_level(mu, 0) if not all(muaff.scalar(coroot) in ZZ for coroot in self._L.simple_coroots()): @@ -1908,14 +1906,44 @@ def symmetric_macdonald_polynomial(self, mu): sage: E = NonSymmetricMacdonaldPolynomials(['C',3,1], q, v, -1/v) sage: om = E.L0().fundamental_weights() sage: E.symmetric_macdonald_polynomial(om[1]+om[2]) - B[(-2, -1, 0)] + B[(-2, 1, 0)] + B[(-2, 0, -1)] + B[(-2, 0, 1)] + ((4*q^3*v^14+2*q^2*v^14-2*q^3*v^12+2*q^2*v^12-2*q^3*v^10+q*v^12-5*q^2*v^10-5*q*v^4+q^2*v^2-2*v^4+2*q*v^2-2*v^2+2*q+4)/(q^3*v^14-q^2*v^10-q*v^4+1))*B[(-1, 0, 0)] + B[(-1, -2, 0)] + ((2*q*v^4+v^4-q*v^2+v^2-q-2)/(q*v^4-1))*B[(-1, -1, -1)] + ((2*q*v^4+v^4-q*v^2+v^2-q-2)/(q*v^4-1))*B[(-1, -1, 1)] + ((2*q*v^4+v^4-q*v^2+v^2-q-2)/(q*v^4-1))*B[(-1, 1, -1)] + ((2*q*v^4+v^4-q*v^2+v^2-q-2)/(q*v^4-1))*B[(-1, 1, 1)] + B[(-1, 2, 0)] + B[(-1, 0, -2)] + B[(-1, 0, 2)] + ((4*q^3*v^14+2*q^2*v^14-2*q^3*v^12+2*q^2*v^12-2*q^3*v^10+q*v^12-5*q^2*v^10-5*q*v^4+q^2*v^2-2*v^4+2*q*v^2-2*v^2+2*q+4)/(q^3*v^14-q^2*v^10-q*v^4+1))*B[(1, 0, 0)] + B[(1, -2, 0)] + ((2*q*v^4+v^4-q*v^2+v^2-q-2)/(q*v^4-1))*B[(1, -1, -1)] + ((2*q*v^4+v^4-q*v^2+v^2-q-2)/(q*v^4-1))*B[(1, -1, 1)] + ((2*q*v^4+v^4-q*v^2+v^2-q-2)/(q*v^4-1))*B[(1, 1, -1)] + ((2*q*v^4+v^4-q*v^2+v^2-q-2)/(q*v^4-1))*B[(1, 1, 1)] + B[(1, 2, 0)] + B[(1, 0, -2)] + B[(1, 0, 2)] + B[(2, -1, 0)] + B[(2, 1, 0)] + B[(2, 0, -1)] + B[(2, 0, 1)] + B[(0, -2, -1)] + B[(0, -2, 1)] + ((-4*q^3*v^14-2*q^2*v^14+2*q^3*v^12-2*q^2*v^12+2*q^3*v^10-q*v^12+5*q^2*v^10+5*q*v^4-q^2*v^2+2*v^4-2*q*v^2+2*v^2-2*q-4)/(-q^3*v^14+q^2*v^10+q*v^4-1))*B[(0, -1, 0)] + B[(0, -1, -2)] + B[(0, -1, 2)] + ((-4*q^3*v^14-2*q^2*v^14+2*q^3*v^12-2*q^2*v^12+2*q^3*v^10-q*v^12+5*q^2*v^10+5*q*v^4-q^2*v^2+2*v^4-2*q*v^2+2*v^2-2*q-4)/(-q^3*v^14+q^2*v^10+q*v^4-1))*B[(0, 1, 0)] + B[(0, 1, -2)] + B[(0, 1, 2)] + B[(0, 2, -1)] + B[(0, 2, 1)] + ((4*q^3*v^14+2*q^2*v^14-2*q^3*v^12+2*q^2*v^12-2*q^3*v^10+q*v^12-5*q^2*v^10-5*q*v^4+q^2*v^2-2*v^4+2*q*v^2-2*v^2+2*q+4)/(q^3*v^14-q^2*v^10-q*v^4+1))*B[(0, 0, -1)] + ((4*q^3*v^14+2*q^2*v^14-2*q^3*v^12+2*q^2*v^12-2*q^3*v^10+q*v^12-5*q^2*v^10-5*q*v^4+q^2*v^2-2*v^4+2*q*v^2-2*v^2+2*q+4)/(q^3*v^14-q^2*v^10-q*v^4+1))*B[(0, 0, 1)] + B[(-2, -1, 0)] + B[(-2, 1, 0)] + B[(-2, 0, -1)] + B[(-2, 0, 1)] + + ((4*q^3*v^14+2*q^2*v^14-2*q^3*v^12+2*q^2*v^12-2*q^3*v^10+q*v^12-5*q^2*v^10-5*q*v^4+q^2*v^2-2*v^4+2*q*v^2-2*v^2+2*q+4)/(q^3*v^14-q^2*v^10-q*v^4+1))*B[(-1, 0, 0)] + + B[(-1, -2, 0)] + ((2*q*v^4+v^4-q*v^2+v^2-q-2)/(q*v^4-1))*B[(-1, -1, -1)] + + ((2*q*v^4+v^4-q*v^2+v^2-q-2)/(q*v^4-1))*B[(-1, -1, 1)] + ((2*q*v^4+v^4-q*v^2+v^2-q-2)/(q*v^4-1))*B[(-1, 1, -1)] + + ((2*q*v^4+v^4-q*v^2+v^2-q-2)/(q*v^4-1))*B[(-1, 1, 1)] + B[(-1, 2, 0)] + B[(-1, 0, -2)] + B[(-1, 0, 2)] + + ((4*q^3*v^14+2*q^2*v^14-2*q^3*v^12+2*q^2*v^12-2*q^3*v^10+q*v^12-5*q^2*v^10-5*q*v^4+q^2*v^2-2*v^4+2*q*v^2-2*v^2+2*q+4)/(q^3*v^14-q^2*v^10-q*v^4+1))*B[(1, 0, 0)] + B[(1, -2, 0)] + + ((2*q*v^4+v^4-q*v^2+v^2-q-2)/(q*v^4-1))*B[(1, -1, -1)] + + ((2*q*v^4+v^4-q*v^2+v^2-q-2)/(q*v^4-1))*B[(1, -1, 1)] + + ((2*q*v^4+v^4-q*v^2+v^2-q-2)/(q*v^4-1))*B[(1, 1, -1)] + + ((2*q*v^4+v^4-q*v^2+v^2-q-2)/(q*v^4-1))*B[(1, 1, 1)] + B[(1, 2, 0)] + B[(1, 0, -2)] + B[(1, 0, 2)] + + B[(2, -1, 0)] + B[(2, 1, 0)] + B[(2, 0, -1)] + B[(2, 0, 1)] + B[(0, -2, -1)] + B[(0, -2, 1)] + - ((4*q^3*v^14+2*q^2*v^14-2*q^3*v^12+2*q^2*v^12-2*q^3*v^10+q*v^12-5*q^2*v^10-5*q*v^4+q^2*v^2-2*v^4+2*q*v^2-2*v^2+2*q+4)/(-q^3*v^14+q^2*v^10+q*v^4-1))*B[(0, -1, 0)] + + B[(0, -1, -2)] + + B[(0, -1, 2)] + - ((4*q^3*v^14+2*q^2*v^14-2*q^3*v^12+2*q^2*v^12-2*q^3*v^10+q*v^12-5*q^2*v^10-5*q*v^4+q^2*v^2-2*v^4+2*q*v^2-2*v^2+2*q+4)/(-q^3*v^14+q^2*v^10+q*v^4-1))*B[(0, 1, 0)] + + B[(0, 1, -2)] + B[(0, 1, 2)] + B[(0, 2, -1)] + B[(0, 2, 1)] + + ((4*q^3*v^14+2*q^2*v^14-2*q^3*v^12+2*q^2*v^12-2*q^3*v^10+q*v^12-5*q^2*v^10-5*q*v^4+q^2*v^2-2*v^4+2*q*v^2-2*v^2+2*q+4)/(q^3*v^14-q^2*v^10-q*v^4+1))*B[(0, 0, -1)] + + ((4*q^3*v^14+2*q^2*v^14-2*q^3*v^12+2*q^2*v^12-2*q^3*v^10+q*v^12-5*q^2*v^10-5*q*v^4+q^2*v^2-2*v^4+2*q*v^2-2*v^2+2*q+4)/(q^3*v^14-q^2*v^10-q*v^4+1))*B[(0, 0, 1)] An example for type `G`:: sage: E = NonSymmetricMacdonaldPolynomials(['G',2,1], q, v, -1/v) sage: om = E.L0().fundamental_weights() sage: E.symmetric_macdonald_polynomial(2*om[1]) - ((3*q^6*v^22+3*q^5*v^22-3*q^6*v^20+q^4*v^22-4*q^5*v^20+q^4*v^18-q^5*v^16+q^3*v^18-2*q^4*v^16+q^5*v^14-q^3*v^16+q^4*v^14-4*q^4*v^12+q^2*v^14+q^5*v^10-8*q^3*v^12+4*q^4*v^10-4*q^2*v^12+8*q^3*v^10-q*v^12-q^4*v^8+4*q^2*v^10-q^2*v^8+q^3*v^6-q*v^8+2*q^2*v^6-q^3*v^4+q*v^6-q^2*v^4+4*q*v^2-q^2+3*v^2-3*q-3)/(q^6*v^22-q^5*v^20-q^4*v^12-q^3*v^12+q^3*v^10+q^2*v^10+q*v^2-1))*B[(0, 0, 0)] + ((q*v^2+v^2-q-1)/(q*v^2-1))*B[(-2, 1, 1)] + B[(-2, 2, 0)] + B[(-2, 0, 2)] + ((-q*v^2-v^2+q+1)/(-q*v^2+1))*B[(-1, -1, 2)] + ((2*q^4*v^12+2*q^3*v^12-2*q^4*v^10-2*q^3*v^10+q^2*v^8-q^3*v^6+q*v^8-2*q^2*v^6+q^3*v^4-q*v^6+q^2*v^4-2*q*v^2-2*v^2+2*q+2)/(q^4*v^12-q^3*v^10-q*v^2+1))*B[(-1, 1, 0)] + ((-q*v^2-v^2+q+1)/(-q*v^2+1))*B[(-1, 2, -1)] + ((2*q^4*v^12+2*q^3*v^12-2*q^4*v^10-2*q^3*v^10+q^2*v^8-q^3*v^6+q*v^8-2*q^2*v^6+q^3*v^4-q*v^6+q^2*v^4-2*q*v^2-2*v^2+2*q+2)/(q^4*v^12-q^3*v^10-q*v^2+1))*B[(-1, 0, 1)] + ((-q*v^2-v^2+q+1)/(-q*v^2+1))*B[(1, -2, 1)] + ((-2*q^4*v^12-2*q^3*v^12+2*q^4*v^10+2*q^3*v^10-q^2*v^8+q^3*v^6-q*v^8+2*q^2*v^6-q^3*v^4+q*v^6-q^2*v^4+2*q*v^2+2*v^2-2*q-2)/(-q^4*v^12+q^3*v^10+q*v^2-1))*B[(1, -1, 0)] + ((-q*v^2-v^2+q+1)/(-q*v^2+1))*B[(1, 1, -2)] + ((-2*q^4*v^12-2*q^3*v^12+2*q^4*v^10+2*q^3*v^10-q^2*v^8+q^3*v^6-q*v^8+2*q^2*v^6-q^3*v^4+q*v^6-q^2*v^4+2*q*v^2+2*v^2-2*q-2)/(-q^4*v^12+q^3*v^10+q*v^2-1))*B[(1, 0, -1)] + B[(2, -2, 0)] + ((q*v^2+v^2-q-1)/(q*v^2-1))*B[(2, -1, -1)] + B[(2, 0, -2)] + B[(0, -2, 2)] + ((-2*q^4*v^12-2*q^3*v^12+2*q^4*v^10+2*q^3*v^10-q^2*v^8+q^3*v^6-q*v^8+2*q^2*v^6-q^3*v^4+q*v^6-q^2*v^4+2*q*v^2+2*v^2-2*q-2)/(-q^4*v^12+q^3*v^10+q*v^2-1))*B[(0, -1, 1)] + ((2*q^4*v^12+2*q^3*v^12-2*q^4*v^10-2*q^3*v^10+q^2*v^8-q^3*v^6+q*v^8-2*q^2*v^6+q^3*v^4-q*v^6+q^2*v^4-2*q*v^2-2*v^2+2*q+2)/(q^4*v^12-q^3*v^10-q*v^2+1))*B[(0, 1, -1)] + B[(0, 2, -2)] + ((3*q^6*v^22+3*q^5*v^22-3*q^6*v^20+q^4*v^22-4*q^5*v^20+q^4*v^18-q^5*v^16+q^3*v^18-2*q^4*v^16+q^5*v^14-q^3*v^16+q^4*v^14-4*q^4*v^12+q^2*v^14+q^5*v^10-8*q^3*v^12+4*q^4*v^10-4*q^2*v^12+8*q^3*v^10-q*v^12-q^4*v^8+4*q^2*v^10-q^2*v^8+q^3*v^6-q*v^8+2*q^2*v^6-q^3*v^4+q*v^6-q^2*v^4+4*q*v^2-q^2+3*v^2-3*q-3)/(q^6*v^22-q^5*v^20-q^4*v^12-q^3*v^12+q^3*v^10+q^2*v^10+q*v^2-1))*B[(0, 0, 0)] + + ((q*v^2+v^2-q-1)/(q*v^2-1))*B[(-2, 1, 1)] + B[(-2, 2, 0)] + B[(-2, 0, 2)] + - ((q*v^2+v^2-q-1)/(-q*v^2+1))*B[(-1, -1, 2)] + + ((2*q^4*v^12+2*q^3*v^12-2*q^4*v^10-2*q^3*v^10+q^2*v^8-q^3*v^6+q*v^8-2*q^2*v^6+q^3*v^4-q*v^6+q^2*v^4-2*q*v^2-2*v^2+2*q+2)/(q^4*v^12-q^3*v^10-q*v^2+1))*B[(-1, 1, 0)] + - ((q*v^2+v^2-q-1)/(-q*v^2+1))*B[(-1, 2, -1)] + + ((2*q^4*v^12+2*q^3*v^12-2*q^4*v^10-2*q^3*v^10+q^2*v^8-q^3*v^6+q*v^8-2*q^2*v^6+q^3*v^4-q*v^6+q^2*v^4-2*q*v^2-2*v^2+2*q+2)/(q^4*v^12-q^3*v^10-q*v^2+1))*B[(-1, 0, 1)] + - ((q*v^2+v^2-q-1)/(-q*v^2+1))*B[(1, -2, 1)] + - ((2*q^4*v^12+2*q^3*v^12-2*q^4*v^10-2*q^3*v^10+q^2*v^8-q^3*v^6+q*v^8-2*q^2*v^6+q^3*v^4-q*v^6+q^2*v^4-2*q*v^2-2*v^2+2*q+2)/(-q^4*v^12+q^3*v^10+q*v^2-1))*B[(1, -1, 0)] + - ((q*v^2+v^2-q-1)/(-q*v^2+1))*B[(1, 1, -2)] + - ((2*q^4*v^12+2*q^3*v^12-2*q^4*v^10-2*q^3*v^10+q^2*v^8-q^3*v^6+q*v^8-2*q^2*v^6+q^3*v^4-q*v^6+q^2*v^4-2*q*v^2-2*v^2+2*q+2)/(-q^4*v^12+q^3*v^10+q*v^2-1))*B[(1, 0, -1)] + + B[(2, -2, 0)] + ((q*v^2+v^2-q-1)/(q*v^2-1))*B[(2, -1, -1)] + B[(2, 0, -2)] + B[(0, -2, 2)] + - ((2*q^4*v^12+2*q^3*v^12-2*q^4*v^10-2*q^3*v^10+q^2*v^8-q^3*v^6+q*v^8-2*q^2*v^6+q^3*v^4-q*v^6+q^2*v^4-2*q*v^2-2*v^2+2*q+2)/(-q^4*v^12+q^3*v^10+q*v^2-1))*B[(0, -1, 1)] + + ((2*q^4*v^12+2*q^3*v^12-2*q^4*v^10-2*q^3*v^10+q^2*v^8-q^3*v^6+q*v^8-2*q^2*v^6+q^3*v^4-q*v^6+q^2*v^4-2*q*v^2-2*v^2+2*q+2)/(q^4*v^12-q^3*v^10-q*v^2+1))*B[(0, 1, -1)] + + B[(0, 2, -2)] """ if self.cartan_type().classical() != mu.parent().cartan_type() or not mu.is_dominant(): raise ValueError("%s must be a dominant weight for the classical subrootsystem of %s" % (mu, self.cartan_type())) diff --git a/src/sage/combinat/root_system/reflection_group_real.py b/src/sage/combinat/root_system/reflection_group_real.py index c9c06a74906..257bf15d0ef 100644 --- a/src/sage/combinat/root_system/reflection_group_real.py +++ b/src/sage/combinat/root_system/reflection_group_real.py @@ -140,24 +140,24 @@ def ReflectionGroup(*args, **kwds): X = arg # precheck for valid input data - if not (isinstance(X, (CartanType_abstract,tuple)) or (X in ZZ and 4 <= X <= 37)): + if not (isinstance(X, (CartanType_abstract, tuple)) or (X in ZZ and 4 <= X <= 37)): raise ValueError(error_msg % X) # transforming two reducible types and an irreducible type if isinstance(X, CartanType_abstract): if not X.is_finite(): raise ValueError(error_msg % X) - if hasattr(X,"cartan_type"): + if hasattr(X, "cartan_type"): X = X.cartan_type() if X.is_irreducible(): W_types.extend([(X.letter, X.n)]) else: - W_types.extend([(x.letter, x.n) for x in X.component_types()]) + W_types.extend((x.letter, x.n) for x in X.component_types()) - elif X == (2,2,2) or X == ('I',2): - W_types.extend([('A',1), ('A',1)]) + elif X == (2, 2, 2) or X == ('I', 2): + W_types.extend([('A', 1), ('A', 1)]) - elif X == (2,2,3): + elif X == (2, 2, 3): W_types.extend([('A', 3)]) else: diff --git a/src/sage/combinat/root_system/root_lattice_realization_algebras.py b/src/sage/combinat/root_system/root_lattice_realization_algebras.py index 970f134ba90..b93504cf82e 100644 --- a/src/sage/combinat/root_system/root_lattice_realization_algebras.py +++ b/src/sage/combinat/root_system/root_lattice_realization_algebras.py @@ -349,7 +349,7 @@ def demazure_lusztig_operator_on_basis(self, weight, i, q1, q2, convention='anti sage: KL.demazure_lusztig_operator_on_basis(L((3,0)), 1, q1, q2) (q1+q2)*B[(1, 2)] + (q1+q2)*B[(2, 1)] + (q1+q2)*B[(3, 0)] + q1*B[(0, 3)] sage: KL.demazure_lusztig_operator_on_basis(L((0,3)), 1, q1, q2) - (-q1-q2)*B[(1, 2)] + (-q1-q2)*B[(2, 1)] + (-q2)*B[(3, 0)] + -(q1+q2)*B[(1, 2)] - (q1+q2)*B[(2, 1)] - q2*B[(3, 0)] At `q_1=1` and `q_2=0` we recover the action of the isobaric divided differences `\pi_i`:: @@ -455,14 +455,14 @@ def demazure_lusztig_operators(self, q1, q2, convention='antidominant'): sage: T[1](x) (q1+q2)*B[(1, 2)] + (q1+q2)*B[(2, 1)] + (q1+q2)*B[(3, 0)] + q1*B[(0, 3)] sage: Tbar[1](x) - (-q1-q2)*B[(1, 2)] + (-q1-q2)*B[(2, 1)] + (-q1-2*q2)*B[(0, 3)] + -(q1+q2)*B[(1, 2)] - (q1+q2)*B[(2, 1)] - (q1+2*q2)*B[(0, 3)] sage: Tbar[1](x) + T[1](x) - (q1+q2)*B[(3, 0)] + (-2*q2)*B[(0, 3)] + (q1+q2)*B[(3, 0)] - 2*q2*B[(0, 3)] sage: Tdominant[1](x) - (-q1-q2)*B[(1, 2)] + (-q1-q2)*B[(2, 1)] + (-q2)*B[(0, 3)] + -(q1+q2)*B[(1, 2)] - (q1+q2)*B[(2, 1)] - q2*B[(0, 3)] sage: Tdominant.Tw_inverse(1)(KL.monomial(-L.simple_root(1))) - ((-q1-q2)/(q1*q2))*B[(0, 0)] - 1/q2*B[(1, -1)] + -((q1+q2)/(q1*q2))*B[(0, 0)] - 1/q2*B[(1, -1)] We repeat similar computation in the affine setting:: @@ -480,14 +480,13 @@ def demazure_lusztig_operators(self, q1, q2, convention='antidominant'): (q1+q2)*B[e[0] + 2*e[1]] + (q1+q2)*B[2*e[0] + e[1]] + (q1+q2)*B[3*e[0]] + q1*B[3*e[1]] sage: Tbar[1](x) - (-q1-q2)*B[e[0] + 2*e[1]] + (-q1-q2)*B[2*e[0] + e[1]] - + (-q1-2*q2)*B[3*e[1]] + -(q1+q2)*B[e[0] + 2*e[1]] - (q1+q2)*B[2*e[0] + e[1]] - (q1+2*q2)*B[3*e[1]] sage: Tbar[1](x) + T[1](x) - (q1+q2)*B[3*e[0]] + (-2*q2)*B[3*e[1]] + (q1+q2)*B[3*e[0]] - 2*q2*B[3*e[1]] sage: Tdominant[1](x) - (-q1-q2)*B[e[0] + 2*e[1]] + (-q1-q2)*B[2*e[0] + e[1]] + (-q2)*B[3*e[1]] + -(q1+q2)*B[e[0] + 2*e[1]] - (q1+q2)*B[2*e[0] + e[1]] - q2*B[3*e[1]] sage: Tdominant.Tw_inverse(1)(KL.monomial(-L.simple_root(1))) - ((-q1-q2)/(q1*q2))*B[0] - 1/q2*B[e[0] - e[1]] + -((q1+q2)/(q1*q2))*B[0] - 1/q2*B[e[0] - e[1]] One can obtain iterated operators by passing a reduced word or an element of the Weyl group:: @@ -544,19 +543,19 @@ def demazure_lusztig_operators(self, q1, q2, convention='antidominant'): sage: Y[alphacheck[0]](KL.one()) q2^2/q1^2*B[0] sage: Y[alphacheck[1]](x) - ((-q2^2)/(-q1^2))*B[e[0] - e['delta']] + -(q2^2/(-q1^2))*B[e[0] - e['delta']] sage: Y[alphacheck[2]](x) (q1/(-q2))*B[e[0]] sage: KL.q_project(Y[alphacheck[1]](x),q) - ((-q2^2)/(-q*q1^2))*B[(1, 0, 0)] + -(q2^2/(-q*q1^2))*B[(1, 0, 0)] sage: # needs sage.graphs sage: KL.q_project(x, q) B[(1, 0, 0)] sage: KL.q_project(Y[alphacheck[0]](x),q) - ((-q*q1)/q2)*B[(1, 0, 0)] + -q*q1/q2*B[(1, 0, 0)] sage: KL.q_project(Y[alphacheck[1]](x),q) - ((-q2^2)/(-q*q1^2))*B[(1, 0, 0)] + -(q2^2/(-q*q1^2))*B[(1, 0, 0)] sage: KL.q_project(Y[alphacheck[2]](x),q) (q1/(-q2))*B[(1, 0, 0)] @@ -646,7 +645,7 @@ def demazure_lusztig_operator_on_classical_on_basis(self, weight, i, q, q1, q2, q1*B[(2, 2)] sage: KL.demazure_lusztig_operator_on_classical_on_basis(L0((3,0)), # needs sage.graphs ....: 0, q, q1, q2) - (-q^2*q1-q^2*q2)*B[(1, 2)] + (-q*q1-q*q2)*B[(2, 1)] + (-q^3*q2)*B[(0, 3)] + -(q^2*q1+q^2*q2)*B[(1, 2)] - (q*q1+q*q2)*B[(2, 1)] - q^3*q2*B[(0, 3)] """ L = self.basis().keys() weight = L.embed_at_level(weight, 0) @@ -695,7 +694,7 @@ def demazure_lusztig_operators_on_classical(self, q, q1, q2, convention='antidom is mapped to `q`:: sage: T[0](x) # needs sage.graphs - (-q^2*q1-q^2*q2)*B[(1, 2)] + (-q*q1-q*q2)*B[(2, 1)] + (-q^3*q2)*B[(0, 3)] + -(q^2*q1+q^2*q2)*B[(1, 2)] - (q*q1+q*q2)*B[(2, 1)] - q^3*q2*B[(0, 3)] Note that there is no translation part, and in particular 1 is an eigenvector for all `T_i`'s:: @@ -708,7 +707,7 @@ def demazure_lusztig_operators_on_classical(self, q, q1, q2, convention='antidom sage: Y = T.Y() sage: alphacheck = Y.keys().simple_roots() sage: Y[alphacheck[0]](KL0.one()) - ((-q2)/(q*q1))*B[(0, 0)] + -q2/(q*q1)*B[(0, 0)] Matching with Ion Bogdan's hand calculations from 3/15/2013:: @@ -746,7 +745,7 @@ def demazure_lusztig_operators_on_classical(self, q, q1, q2, convention='antidom sage: T0(KL0.monomial(-omega[1])) 1/(q*u)*B[Lambda[1]] sage: T0(KL0.monomial(-2*omega[1])) - ((-u^2+1)/(q*u))*B[0] + 1/(q^2*u)*B[2*Lambda[1]] + -((u^2-1)/(q*u))*B[0] + 1/(q^2*u)*B[2*Lambda[1]] """ # In type BC dual we used q^2 and q elsewhere # Not sure this is the right thing to do or just a workaround ... @@ -992,10 +991,10 @@ def twisted_demazure_lusztig_operator_on_basis(self, weight, i, q1, q2, conventi sage: Lambda = L.classical().fundamental_weights() sage: KL.twisted_demazure_lusztig_operator_on_basis( ....: Lambda[1] + 2*Lambda[2], 1, q1, q2, convention='dominant') - (-q2)*B[(2, 3, 0, 0)] + -q2*B[(2, 3, 0, 0)] sage: KL.twisted_demazure_lusztig_operator_on_basis( ....: Lambda[1] + 2*Lambda[2], 2, q1, q2, convention='dominant') - (-q1-q2)*B[(3, 1, 1, 0)] + (-q2)*B[(3, 0, 2, 0)] + -(q1+q2)*B[(3, 1, 1, 0)] - q2*B[(3, 0, 2, 0)] sage: KL.twisted_demazure_lusztig_operator_on_basis( ....: Lambda[1] + 2*Lambda[2], 3, q1, q2, convention='dominant') q1*B[(3, 2, 0, 0)] @@ -1060,7 +1059,7 @@ def twisted_demazure_lusztig_operators(self, q1, q2, convention='antidominant'): sage: T.Ti_inverse_on_basis(L0.zero(), 1) 1/q1*B[(0, 0)] sage: T.Ti_on_basis(alpha[1], 1) - (-q1-q2)*B[(0, 0)] + (-q2)*B[(-1, 1)] + -(q1+q2)*B[(0, 0)] - q2*B[(-1, 1)] sage: T.Ti_inverse_on_basis(alpha[1], 1) ((q1+q2)/(q1*q2))*B[(0, 0)] + 1/q1*B[(-1, 1)] + ((q1+q2)/(q1*q2))*B[(1, -1)] sage: T.Ti_on_basis(L0.zero(), 0) # needs sage.graphs @@ -1141,7 +1140,7 @@ def twisted_demazure_lusztig_operators(self, q1, q2, convention='antidominant'): sage: def T0c(*l0): return T0_check_on_basis(L0(l0)) sage: T0(0,0,1) # not double checked # needs sage.graphs - ((-t+1)/q)*B[(1, 0, 0)] + 1/q^2*B[(2, 0, -1)] + -((t-1)/q)*B[(1, 0, 0)] + 1/q^2*B[(2, 0, -1)] sage: T0c(0,0,1) # needs sage.graphs (t^2-t)*B[(1, 0, 0)] + (t^2-t)*B[(1, 1, -1)] + t^2*B[(2, 0, -1)] + (t-1)*B[(0, 0, 1)] """ diff --git a/src/sage/combinat/root_system/type_C.py b/src/sage/combinat/root_system/type_C.py index d7c6b67194f..7117eea0da2 100644 --- a/src/sage/combinat/root_system/type_C.py +++ b/src/sage/combinat/root_system/type_C.py @@ -83,10 +83,10 @@ def positive_roots(self): (0, 0, 2)] """ res = [] - for p in [0,1]: + for p in [0, 1]: for j in range(self.n): - res.extend([self.root(i,j,0,p) for i in range(j)]) - res.extend([self.root(i,i,0,0) for i in range(self.n)]) + res.extend(self.root(i, j, 0, p) for i in range(j)) + res.extend(self.root(i, i, 0, 0) for i in range(self.n)) return res def negative_roots(self): @@ -105,10 +105,10 @@ def negative_roots(self): (0, 0, -2)] """ res = [] - for p in [0,1]: + for p in [0, 1]: for j in range(self.n): - res.extend( [self.root(i,j,1,p) for i in range(j) ] ) - res.extend( [ self.root(i,i,1,1) for i in range(self.n) ] ) + res.extend(self.root(i, j, 1, p) for i in range(j)) + res.extend(self.root(i, i, 1, 1) for i in range(self.n)) return res def fundamental_weight(self, i): diff --git a/src/sage/combinat/root_system/type_D.py b/src/sage/combinat/root_system/type_D.py index 49e9d952a2f..83248451b5d 100644 --- a/src/sage/combinat/root_system/type_D.py +++ b/src/sage/combinat/root_system/type_D.py @@ -72,7 +72,7 @@ def positive_roots(self): res = [] for p in [0, 1]: for j in range(self.n): - res.extend([self.root(i, j, 0, p) for i in range(j)]) + res.extend(self.root(i, j, 0, p) for i in range(j)) return res def negative_roots(self): @@ -96,7 +96,7 @@ def negative_roots(self): res = [] for p in [0, 1]: for j in range(self.n): - res.extend([self.root(i, j, 1, p) for i in range(j)]) + res.extend(self.root(i, j, 1, p) for i in range(j)) return res def fundamental_weight(self, i): diff --git a/src/sage/combinat/rooted_tree.py b/src/sage/combinat/rooted_tree.py index 0ced874b74d..b82e0186029 100644 --- a/src/sage/combinat/rooted_tree.py +++ b/src/sage/combinat/rooted_tree.py @@ -192,8 +192,8 @@ def __init__(self, parent=None, children=[], check=True): children = list(children) except TypeError: raise TypeError(f"input ({children}) is not a valid tree") - #if not (children.__class__ is self.__class__ - # and children.parent() == parent): + # if not (children.__class__ is self.__class__ + # and children.parent() == parent): children = [self.__class__(parent, x) for x in children] NormalizedClonableList.__init__(self, parent, children, check=check) diff --git a/src/sage/combinat/sf/hall_littlewood.py b/src/sage/combinat/sf/hall_littlewood.py index c725d478749..cca78b8dce0 100644 --- a/src/sage/combinat/sf/hall_littlewood.py +++ b/src/sage/combinat/sf/hall_littlewood.py @@ -251,7 +251,7 @@ def P(self): sage: Pz(Qz[2,1]) (z^2-2*z+1)*HLP[2, 1] sage: Qz(Py[2]) - ((-y+z)/(z^3-z^2-z+1))*HLQ[1, 1] + (1/(-z+1))*HLQ[2] + -((y-z)/(z^3-z^2-z+1))*HLQ[1, 1] + (1/(-z+1))*HLQ[2] sage: Qy(Pz[2]) ((y-z)/(y^3-y^2-y+1))*HLQ[1, 1] + (1/(-y+1))*HLQ[2] sage: Qy.hall_littlewood_family() == HLy diff --git a/src/sage/combinat/sf/llt.py b/src/sage/combinat/sf/llt.py index d0a0a040672..5a3c2a0bf15 100644 --- a/src/sage/combinat/sf/llt.py +++ b/src/sage/combinat/sf/llt.py @@ -83,13 +83,13 @@ class LLT_class(UniqueRepresentation): sage: s(HS3t[2,1]) s[2, 1] + t*s[3] sage: HS3x(HS3t[2,1]) - HSp3[2, 1] + (-x+t)*HSp3[3] + HSp3[2, 1] - (x-t)*HSp3[3] sage: s(HS3x(HS3t[2,1])) s[2, 1] + t*s[3] sage: LLT3t2 = Symxt.llt(3,t=2) sage: HC3t2 = LLT3t2.hcospin() sage: HS3x(HC3t2[3,1]) - 2*HSp3[3, 1] + (-2*x+1)*HSp3[4] + 2*HSp3[3, 1] - (2*x-1)*HSp3[4] """ @staticmethod def __classcall__(cls, Sym, k, t='t'): diff --git a/src/sage/combinat/sf/macdonald.py b/src/sage/combinat/sf/macdonald.py index 395906bada4..cd6576cca85 100644 --- a/src/sage/combinat/sf/macdonald.py +++ b/src/sage/combinat/sf/macdonald.py @@ -251,14 +251,14 @@ def P(self): sage: P(Q([2])) ((q*t^2-q*t-t+1)/(q^3-q^2-q+1))*McdP[2] sage: P(Q([2,1])) - ((-q*t^4+2*q*t^3-q*t^2+t^2-2*t+1)/(-q^4*t+2*q^3*t-q^2*t+q^2-2*q+1))*McdP[2, 1] + -((q*t^4-2*q*t^3+q*t^2-t^2+2*t-1)/(-q^4*t+2*q^3*t-q^2*t+q^2-2*q+1))*McdP[2, 1] :: sage: P(J([2])) (q*t^2-q*t-t+1)*McdP[2] sage: P(J([2,1])) - (-q*t^4+2*q*t^3-q*t^2+t^2-2*t+1)*McdP[2, 1] + -(q*t^4-2*q*t^3+q*t^2-t^2+2*t-1)*McdP[2, 1] By transitivity, one get coercions from the classical bases:: @@ -278,13 +278,13 @@ def P(self): sage: P2 = Macyz.P() sage: P3 = Maczx.P() sage: m(P1[2,1]) - ((-2*x*y^2+x*y-y^2+x-y+2)/(-x*y^2+1))*m[1, 1, 1] + m[2, 1] + -((2*x*y^2-x*y+y^2-x+y-2)/(-x*y^2+1))*m[1, 1, 1] + m[2, 1] sage: m(P2[2,1]) - ((-2*y*z^2+y*z-z^2+y-z+2)/(-y*z^2+1))*m[1, 1, 1] + m[2, 1] + -((2*y*z^2-y*z+z^2-y+z-2)/(-y*z^2+1))*m[1, 1, 1] + m[2, 1] sage: m(P1(P2(P3[2,1]))) - ((-2*x^2*z-x^2+x*z-x+z+2)/(-x^2*z+1))*m[1, 1, 1] + m[2, 1] + -((2*x^2*z+x^2-x*z+x-z-2)/(-x^2*z+1))*m[1, 1, 1] + m[2, 1] sage: P1(P2[2]) - ((-x*y^2+2*x*y*z-y^2*z-x+2*y-z)/(x*y^2*z-x*y-y*z+1))*McdP[1, 1] + McdP[2] + -((x*y^2-2*x*y*z+y^2*z+x-2*y+z)/(x*y^2*z-x*y-y*z+1))*McdP[1, 1] + McdP[2] sage: m(z*P1[2]+x*P2[2]) ((x^2*y^2*z+x*y^2*z^2-x^2*y^2+x^2*y*z-x*y*z^2+y^2*z^2-x^2*y-2*x*y*z-y*z^2+x*y-y*z+x+z)/(x*y^2*z-x*y-y*z+1))*m[1, 1] + (x+z)*m[2] """ @@ -405,7 +405,7 @@ def J(self): :: sage: s(J([2])) - (-q*t+t^2+q-t)*s[1, 1] + (q*t^2-q*t-t+1)*s[2] + -(q*t-t^2-q+t)*s[1, 1] + (q*t^2-q*t-t+1)*s[2] sage: J(s([2])) ((q-t)/(q*t^4-q*t^3-q*t^2-t^3+q*t+t^2+t-1))*McdJ[1, 1] + (1/(q*t^2-q*t-t+1))*McdJ[2] """ @@ -483,9 +483,10 @@ def Ht(self): sage: Ht = Sym.macdonald().Ht() sage: s = Sym.schur() sage: Ht(s([2,1])) - (q/(q*t^2-t^3-q^2+q*t))*McdHt[1, 1, 1] + ((-q^2-q*t-t^2)/(q^2*t^2-q^3-t^3+q*t))*McdHt[2, 1] + (t/(-q^3+q^2*t+q*t-t^2))*McdHt[3] + (q/(q*t^2-t^3-q^2+q*t))*McdHt[1, 1, 1] - ((q^2+q*t+t^2)/(q^2*t^2-q^3-t^3+q*t))*McdHt[2, 1] + + (t/(-q^3+q^2*t+q*t-t^2))*McdHt[3] sage: Ht(s([2])) - ((-q)/(-q+t))*McdHt[1, 1] + (t/(-q+t))*McdHt[2] + -(q/(-q+t))*McdHt[1, 1] + (t/(-q+t))*McdHt[2] """ return MacdonaldPolynomials_ht(self) @@ -506,10 +507,11 @@ def S(self): sage: Sym = SymmetricFunctions(FractionField(QQ['q','t'])) sage: S = Sym.macdonald().S(); S - Symmetric Functions over Fraction Field of Multivariate Polynomial Ring in q, t over Rational Field in the Macdonald S basis + Symmetric Functions over Fraction Field of Multivariate Polynomial Ring in q, t + over Rational Field in the Macdonald S basis sage: p = Sym.power() sage: p(S[2,1]) - ((1/3*t^3-t^2+t-1/3)/(q^3-3*q^2+3*q-1))*p[1, 1, 1] + ((-1/3*t^3+1/3)/(q^3-1))*p[3] + ((1/3*t^3-t^2+t-1/3)/(q^3-3*q^2+3*q-1))*p[1, 1, 1] - ((1/3*t^3-1/3)/(q^3-1))*p[3] sage: J = Sym.macdonald().J() sage: S(J([2])) (q^3-q^2-q+1)*McdS[2] @@ -521,7 +523,7 @@ def S(self): sage: S(J[2]) q*McdS[1, 1] + McdS[2] sage: p(S[2,1]) - (-1/3*t^3+t^2-t+1/3)*p[1, 1, 1] + (1/3*t^3-1/3)*p[3] + -(1/3*t^3-t^2+t-1/3)*p[1, 1, 1] + (1/3*t^3-1/3)*p[3] sage: from sage.combinat.sf.macdonald import qt_kostka sage: qt_kostka([2],[1,1]) @@ -534,9 +536,9 @@ def S(self): sage: S = Sym.macdonald().S() sage: s = Sym.schur() sage: S(s([2])) - ((q^2-q*t-q+t)/(t^3-t^2-t+1))*McdS[1, 1] + ((-q^2*t+q*t+q-1)/(-t^3+t^2+t-1))*McdS[2] + ((q^2-q*t-q+t)/(t^3-t^2-t+1))*McdS[1, 1] - ((q^2*t-q*t-q+1)/(-t^3+t^2+t-1))*McdS[2] sage: s(S([1,1])) - ((-q*t^2+q*t+t-1)/(-q^3+q^2+q-1))*s[1, 1] + ((q*t-t^2-q+t)/(-q^3+q^2+q-1))*s[2] + -((q*t^2-q*t-t+1)/(-q^3+q^2+q-1))*s[1, 1] + ((q*t-t^2-q+t)/(-q^3+q^2+q-1))*s[2] """ return MacdonaldPolynomials_s(self) @@ -903,11 +905,11 @@ def product(self, left, right): sage: J([1])^2 #indirect doctest ((q-1)/(q*t-1))*McdJ[1, 1] + ((t-1)/(q*t-1))*McdJ[2] sage: J.product( J[1], J[2] ) - ((-q^2+1)/(-q^2*t+1))*McdJ[2, 1] + ((-t+1)/(-q^2*t+1))*McdJ[3] + -((q^2-1)/(-q^2*t+1))*McdJ[2, 1] - ((t-1)/(-q^2*t+1))*McdJ[3] sage: H.product( H[1], H[2] ) - ((q^2-1)/(q^2*t-1))*McdH[2, 1] + ((-t+1)/(-q^2*t+1))*McdH[3] + ((q^2-1)/(q^2*t-1))*McdH[2, 1] - ((t-1)/(-q^2*t+1))*McdH[3] sage: P.product( P[1], P[2] ) - ((-q^3*t^2+q*t^2+q^2-1)/(-q^3*t^2+q^2*t+q*t-1))*McdP[2, 1] + McdP[3] + -((q^3*t^2-q*t^2-q^2+1)/(-q^3*t^2+q^2*t+q*t-1))*McdP[2, 1] + McdP[3] sage: Q.product(Q[1],Q[2]) McdQ[2, 1] + ((q^2*t-q^2+q*t-q+t-1)/(q^2*t-1))*McdQ[3] sage: Ht.product(Ht[1],Ht[2]) @@ -970,15 +972,15 @@ def nabla(self, q=None, t=None, power=1): ((q^2*t+q*t-t-1)/(q*t-1))*McdP[1, 1] + McdP[2] sage: H = Sym.macdonald().H() sage: H([1,1]).nabla() - t*McdH[1, 1] + (-t^2+1)*McdH[2] + t*McdH[1, 1] - (t^2-1)*McdH[2] sage: H([1,1]).nabla(q=1) - ((t^2+q-t-1)/(q*t-1))*McdH[1, 1] + ((-t^3+t^2+t-1)/(q*t-1))*McdH[2] + ((t^2+q-t-1)/(q*t-1))*McdH[1, 1] - ((t^3-t^2-t+1)/(q*t-1))*McdH[2] sage: H(0).nabla() 0 sage: H([2,2,1]).nabla(t=1/H.t) - ((-q^2)/(-t^4))*McdH[2, 2, 1] + -(q^2/(-t^4))*McdH[2, 2, 1] sage: H([2,2,1]).nabla(t=1/H.t,power=-1) - ((-t^4)/(-q^2))*McdH[2, 2, 1] + -(t^4/(-q^2))*McdH[2, 2, 1] """ parent = self.parent() if (q is None and t is None): @@ -1179,7 +1181,7 @@ def _to_s(self, part): -q*t^4 + 2*q*t^3 - q*t^2 + t^2 - 2*t + 1, q*t^3 - t^4 - q*t^2 + t^3 - q*t + t^2 + q - t] sage: Sym.schur()( J[2,1] ) - (q*t^3-t^4-q*t^2+t^3-q*t+t^2+q-t)*s[1, 1, 1] + (-q*t^4+2*q*t^3-q*t^2+t^2-2*t+1)*s[2, 1] + (q*t^3-t^4-q*t^2+t^3-q*t+t^2+q-t)*s[1, 1, 1] - (q*t^4-2*q*t^3+q*t^2-t^2+2*t-1)*s[2, 1] """ q, t = QQqt.gens() S = self._macdonald.S() @@ -1292,7 +1294,7 @@ def _s_to_self(self, x): McdH[2, 1] sage: H2 = Sym.macdonald(t=0).H() sage: H2(q*s[1, 1, 1] + (q*t+1)*s[2, 1] + t*s[3]) - (-q^2*t+1)*McdH[2, 1] + t*McdH[3] + -(q^2*t-1)*McdH[2, 1] + t*McdH[3] sage: Sym = SymmetricFunctions(FractionField(QQ['x'])) sage: x = Sym.base_ring().gen() @@ -1478,7 +1480,7 @@ def _s_to_self( self, x ): sage: s = SymmetricFunctions(FractionField(QQ['q','t'])).s() sage: Ht = s.symmetric_function_ring().macdonald().Ht() sage: Ht._s_to_self(s[2]) - ((-q)/(-q+t))*McdHt[1, 1] + (t/(-q+t))*McdHt[2] + -(q/(-q+t))*McdHt[1, 1] + (t/(-q+t))*McdHt[2] """ return self._m_to_self(self._m(x)) @@ -1877,7 +1879,7 @@ def _creation_by_determinant(self, k): sage: S = Sym.macdonald().S() sage: a = S(1) sage: a = a._creation_by_determinant(1); a - (-q+1)*McdS[1] + -(q-1)*McdS[1] sage: a = a._creation_by_determinant(3) sage: Sym.macdonald().J()(a) McdJ[2, 1, 1] @@ -1905,7 +1907,7 @@ def creation(self, k): sage: S = Sym.macdonald().S() sage: a = S(1) sage: a.creation(1) - (-q+1)*McdS[1] + -(q-1)*McdS[1] sage: a.creation(2) (q^2*t-q*t-q+1)*McdS[1, 1] + (q^2-q*t-q+t)*McdS[2] """ diff --git a/src/sage/combinat/sf/sfa.py b/src/sage/combinat/sf/sfa.py index 60fc4b65c53..92a913a71ec 100644 --- a/src/sage/combinat/sf/sfa.py +++ b/src/sage/combinat/sf/sfa.py @@ -3145,7 +3145,7 @@ def factor(self): sage: R. = QQ[] sage: s = SymmetricFunctions(R.fraction_field()).s() sage: factor((s[3] + x*s[2,1] + 1)*(3*y*s[2] + s[4,1] + x*y)) - (-s[] + (-x)*s[2, 1] - s[3]) * ((-x*y)*s[] + (-3*y)*s[2] - s[4, 1]) + (-s[] - x*s[2, 1] - s[3]) * (-x*y*s[] - 3*y*s[2] - s[4, 1]) TESTS:: @@ -3833,7 +3833,7 @@ def theta_qt(self, q=None, t=None): sage: q,t = QQqt.gens() sage: p = SymmetricFunctions(QQqt).p() sage: p([2]).theta_qt(q,t) - ((-q^2+1)/(-t^2+1))*p[2] + -((q^2-1)/(-t^2+1))*p[2] sage: p([2,1]).theta_qt(q,t) ((q^3-q^2-q+1)/(t^3-t^2-t+1))*p[2, 1] sage: p(0).theta_qt(q=1,t=3) @@ -3892,13 +3892,13 @@ def omega_qt(self, q=None, t=None): sage: q,t = QQqt.gens() sage: p = SymmetricFunctions(QQqt).p() sage: p[5].omega_qt() - ((-q^5+1)/(-t^5+1))*p[5] + -((q^5-1)/(-t^5+1))*p[5] sage: p[5].omega_qt(q,t) - ((-q^5+1)/(-t^5+1))*p[5] + -((q^5-1)/(-t^5+1))*p[5] sage: p([2]).omega_qt(q,t) ((q^2-1)/(-t^2+1))*p[2] sage: p([2,1]).omega_qt(q,t) - ((-q^3+q^2+q-1)/(t^3-t^2-t+1))*p[2, 1] + -((q^3-q^2-q+1)/(t^3-t^2-t+1))*p[2, 1] sage: p([3,2]).omega_qt(5,q) -(2976/(q^5-q^3-q^2+1))*p[3, 2] sage: p(0).omega_qt() @@ -3911,11 +3911,11 @@ def omega_qt(self, q=None, t=None): sage: H([1,1]).omega_qt(q,t) ((2*q^2-2*q*t-2*q+2*t)/(t^3-t^2-t+1))*McdH[1, 1] + ((q-1)/(t-1))*McdH[2] sage: H([1,1]).omega_qt(t,q) - ((-t^3+t^2+t-1)/(-q^3+q^2+q-1))*McdH[2] + -((t^3-t^2-t+1)/(-q^3+q^2+q-1))*McdH[2] sage: Sym = SymmetricFunctions(FractionField(QQ['q','t'])) sage: S = Sym.macdonald().S() sage: S([1,1]).omega_qt() - ((q^2-q*t-q+t)/(t^3-t^2-t+1))*McdS[1, 1] + ((-q^2*t+q*t+q-1)/(-t^3+t^2+t-1))*McdS[2] + ((q^2-q*t-q+t)/(t^3-t^2-t+1))*McdS[1, 1] - ((q^2*t-q*t-q+1)/(-t^3+t^2+t-1))*McdS[2] sage: s = Sym.schur() sage: s(S([1,1]).omega_qt()) s[2] @@ -4859,14 +4859,14 @@ def nabla(self, q=None, t=None, power=1): sage: Sym = SymmetricFunctions(FractionField(QQ['q','t'])) sage: p = Sym.power() sage: p([1,1]).nabla() - (-1/2*q*t+1/2*q+1/2*t+1/2)*p[1, 1] + (1/2*q*t-1/2*q-1/2*t+1/2)*p[2] + -(1/2*q*t-1/2*q-1/2*t-1/2)*p[1, 1] + (1/2*q*t-1/2*q-1/2*t+1/2)*p[2] sage: p([2,1]).nabla(q=1) - (-t-1)*p[1, 1, 1] + t*p[2, 1] + -(t+1)*p[1, 1, 1] + t*p[2, 1] sage: p([2]).nabla(q=1)*p([1]).nabla(q=1) - (-t-1)*p[1, 1, 1] + t*p[2, 1] + -(t+1)*p[1, 1, 1] + t*p[2, 1] sage: s = Sym.schur() sage: s([2,1]).nabla() - (-q^3*t-q^2*t^2-q*t^3)*s[1, 1, 1] + (-q^2*t-q*t^2)*s[2, 1] + -(q^3*t+q^2*t^2+q*t^3)*s[1, 1, 1] - (q^2*t+q*t^2)*s[2, 1] sage: s([1,1,1]).nabla() (q^3+q^2*t+q*t^2+t^3+q*t)*s[1, 1, 1] + (q^2+q*t+t^2+q+t)*s[2, 1] + s[3] sage: s([1,1,1]).nabla(t=1) @@ -4876,9 +4876,9 @@ def nabla(self, q=None, t=None, power=1): sage: s(1).nabla() s[] sage: s([2,1]).nabla(power=-1) - ((-q-t)/(q^2*t^2))*s[2, 1] + ((q^2+q*t+t^2)/(-q^3*t^3))*s[3] + -((q+t)/(q^2*t^2))*s[2, 1] + ((q^2+q*t+t^2)/(-q^3*t^3))*s[3] sage: (s([2])+s([3])).nabla() - (-q*t)*s[1, 1] + (q^3*t^2+q^2*t^3)*s[1, 1, 1] + q^2*t^2*s[2, 1] + -q*t*s[1, 1] + (q^3*t^2+q^2*t^3)*s[1, 1, 1] + q^2*t^2*s[2, 1] """ parent = self.parent() BR = parent.base_ring() diff --git a/src/sage/combinat/skew_partition.py b/src/sage/combinat/skew_partition.py index aad38f9afbf..7285c4944e2 100644 --- a/src/sage/combinat/skew_partition.py +++ b/src/sage/combinat/skew_partition.py @@ -1009,12 +1009,9 @@ def frobenius_rank(self): """ N = len(self[0]) mu_betas = [x - j for j, x in enumerate(self[1])] - mu_betas.extend([- j for j in range(len(self[1]), N)]) - res = 0 - for i, x in enumerate(self[0]): - if (x - i) not in mu_betas: - res += 1 - return res + mu_betas.extend(- j for j in range(len(self[1]), N)) + return sum(1 for i, x in enumerate(self[0]) + if (x - i) not in mu_betas) def cells(self): """ diff --git a/src/sage/databases/cubic_hecke_db.py b/src/sage/databases/cubic_hecke_db.py index 3c75faf88ca..2614b4720bc 100644 --- a/src/sage/databases/cubic_hecke_db.py +++ b/src/sage/databases/cubic_hecke_db.py @@ -1067,7 +1067,7 @@ def read_braid_image(self, braid_tietze, ring_of_definition): sage: cha_fc.is_empty(CubicHeckeFileCache.section.braid_images) True sage: b2_img = CHA2(b2); b2_img - w*c^-1 + u*c + (-v) + w*c^-1 + u*c - v sage: cha_fc.write_braid_image(b2.Tietze(), b2_img.to_vector()) sage: cha_fc.read_braid_image(b2.Tietze(), ring_of_definition) (-v, u, w) @@ -1102,7 +1102,7 @@ def write_braid_image(self, braid_tietze, braid_image_vect): sage: B2 = BraidGroup(2) sage: b, = B2.gens(); b3 = b**3 sage: b3_img = CHA2(b3); b3_img - u*w*c^-1 + (u^2-v)*c + (-u*v+w) + u*w*c^-1 + (u^2-v)*c - (u*v-w) sage: cha_fc.write_braid_image(b3.Tietze(), b3_img.to_vector()) sage: cha_fc.read_braid_image(b3.Tietze(), ring_of_definition) (-u*v + w, u^2 - v, u*w) diff --git a/src/sage/dynamics/arithmetic_dynamics/berkovich_ds.py b/src/sage/dynamics/arithmetic_dynamics/berkovich_ds.py index 9734b3767ac..d32ce5c9435 100644 --- a/src/sage/dynamics/arithmetic_dynamics/berkovich_ds.py +++ b/src/sage/dynamics/arithmetic_dynamics/berkovich_ds.py @@ -613,7 +613,8 @@ def normalize_coordinates(self): sage: f.normalize_coordinates(); f Dynamical system of Projective Berkovich line over Cp(3) of precision 20 induced by the map - Defn: Defined on coordinates by sending (x : y) to (x^2 : y^2) + Defn: Defined on coordinates by sending (x : y) + to ((2 + O(3^20))*x^2 : (2 + O(3^20))*y^2) Normalize_coordinates may sometimes fail over `p`-adic fields:: diff --git a/src/sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx b/src/sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx index 1da1efc2bd7..453e0bc0b97 100644 --- a/src/sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx +++ b/src/sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx @@ -70,10 +70,10 @@ cpdef _fast_possible_periods(self, return_points=False): - More space efficient hash/point-table. """ - cdef int i, k, N + cdef int i, N cdef int hash_p, hash_q cdef int index, startindex - cdef list pointslist, points_periods + cdef list points_periods cdef list P, Q cdef set periods, lorders, rvalues @@ -88,7 +88,7 @@ cpdef _fast_possible_periods(self, return_points=False): p = PS.base_ring().order() N = int(PS.dimension_relative()) - point_table = [[0,0] for i in range(p**(N + 1))] + point_table = [[0, 0] for i in range(p**(N + 1))] index = 1 periods = set() points_periods = [] diff --git a/src/sage/dynamics/complex_dynamics/mandel_julia_helper.pyx b/src/sage/dynamics/complex_dynamics/mandel_julia_helper.pyx index 2fd00e9b07a..8ed94e11d5c 100644 --- a/src/sage/dynamics/complex_dynamics/mandel_julia_helper.pyx +++ b/src/sage/dynamics/complex_dynamics/mandel_julia_helper.pyx @@ -60,10 +60,11 @@ def _color_to_RGB(color): cpdef fast_mandelbrot_plot(double x_center, double y_center, - double image_width, long max_iteration, long pixel_count, - long level_sep, long color_num, base_color): + double image_width, long max_iteration, + long pixel_count, + long level_sep, long color_num, base_color): r""" - Plots the Mandelbrot set in the complex plane for the map `Q_c(z) = z^2 + c`. + Plot the Mandelbrot set in the complex plane for the map `Q_c(z) = z^2 + c`. ALGORITHM: @@ -115,14 +116,14 @@ cpdef fast_mandelbrot_plot(double x_center, double y_center, cdef: M, pixel, color_list - long i, j, col, row, level, color_value, iteration - double k, x_corner, y_corner, step_size, x_coor, y_coor, new_x, new_y + long i, j, col, row, level, iteration + double x_corner, y_corner, step_size, x_coor, y_coor, new_x, new_y # Make sure image_width is positive image_width = abs(image_width) # Initialize an image to the color black and access the pixels - M = Image("RGB", (pixel_count,pixel_count), 'black') + M = Image("RGB", (pixel_count, pixel_count), 'black') pixel = M.pixels() # Take the given base color and create a list of evenly spaced @@ -156,7 +157,7 @@ cpdef fast_mandelbrot_plot(double x_center, double y_center, while (new_x**2 + new_y**2 <= 4.0 and iteration < max_iteration): sig_check() new_x, new_y = new_x**2 - new_y**2 + x_coor, \ - 2*new_x*new_y + y_coor + 2*new_x*new_y + y_coor iteration += 1 # If the point escapes to infinity, assign the point a color @@ -177,7 +178,8 @@ cpdef fast_mandelbrot_plot(double x_center, double y_center, cpdef fast_external_ray(double theta, long D=30, long S=10, long R=100, - long pixel_count=500, double image_width=4, long prec=300): + long pixel_count=500, double image_width=4, + long prec=300): r""" Return a list of points that approximate the external ray for a given angle. @@ -241,7 +243,7 @@ cpdef fast_external_ray(double theta, long D=30, long S=10, long R=100, CF = ComplexField(prec) PI = CF.pi() I = CF.gen() - c_0, r_m, t_m, temp_c, C_k, D_k, old_c, x, y, dist + r_m, t_m, temp_c, C_k, D_k, old_c, x, y, dist int k, j, t double difference, m double error = pixel_count * 0.0001 @@ -252,8 +254,8 @@ cpdef fast_external_ray(double theta, long D=30, long S=10, long R=100, c_list = [CF(R*exp(2*PI*I*theta))] # Loop through each subinterval and approximate point on external ray. - for k in range(1,D+1): - for j in range(1,S+1): + for k in range(1, D+1): + for j in range(1, S+1): m = (k-1)*S + j r_m = CF(R**(2**(-m/S))) t_m = CF(r_m**(2**k) * exp(2*PI*I*theta * 2**k)) @@ -280,13 +282,13 @@ cpdef fast_external_ray(double theta, long D=30, long S=10, long R=100, # Convert Complex Field elements into tuples. for k in range(len(c_list)): - x,y = c_list[k].real(), c_list[k].imag() + x, y = c_list[k].real(), c_list[k].imag() c_list[k] = (x, y) return c_list cpdef convert_to_pixels(point_list, double x_0, double y_0, double width, - long number_of_pixels): + long number_of_pixels): r""" Convert cartesian coordinates to pixels within a specified window. @@ -330,7 +332,7 @@ cpdef convert_to_pixels(point_list, double x_0, double y_0, double width, cpdef get_line(start, end): r""" - Produces a list of pixel coordinates approximating a line from a starting + Produce a list of pixel coordinates approximating a line from a starting point to an ending point using the Bresenham's Line Algorithm. REFERENCE: @@ -405,17 +407,19 @@ cpdef get_line(start, end): return points # Commented out temporarily for safekeeping, but probably should be deleted -#def fast_julia_plot(double c_real, double c_imag, -# double x_center, double y_center, double image_width, -# long max_iteration, long pixel_count, long level_sep, -# long color_num, base_color): +# def fast_julia_plot(double c_real, double c_imag, +# double x_center, double y_center, double image_width, +# long max_iteration, long pixel_count, long level_sep, +# long color_num, base_color): cpdef fast_julia_plot(double c_real, double c_imag, - double x_center=0, double y_center=0, double image_width=4, - long max_iteration=500, long pixel_count=500, long level_sep=2, - long color_num=40, base_color=[50, 50, 50]): + double x_center=0, double y_center=0, + double image_width=4, + long max_iteration=500, long pixel_count=500, + long level_sep=2, + long color_num=40, base_color=[50, 50, 50]): r""" - Plots the Julia set for a given `c` value in the complex plane for the map `Q_c(z) = z^2 + c`. + Plot the Julia set for a given `c` value in the complex plane for the map `Q_c(z) = z^2 + c`. INPUT: @@ -460,9 +464,9 @@ cpdef fast_julia_plot(double c_real, double c_imag, """ cdef: - M, pixel, color_list - long i, j, col, row, level, color_value, iteration - double k, x_corner, y_corner, step_size, x_coor, y_coor, new_x, new_y, escape_radius_squared + color_list + long i, j, col, row, level, iteration + double x_corner, y_corner, step_size, x_coor, y_coor, new_x, new_y, escape_radius_squared # Make sure image_width is positive image_width = abs(image_width) @@ -472,7 +476,7 @@ cpdef fast_julia_plot(double c_real, double c_imag, escape_radius_squared = ((1.0 + sqrt(1.0 + 4.0*sqrt(c_real**2 + c_imag**2))))**2/4.0 # Initialize an image to the color black and access the pixels - J = Image("RGB", (pixel_count,pixel_count), 'black') + J = Image("RGB", (pixel_count, pixel_count), 'black') Jp = J.pixels() # Take the given base color and create a list of evenly spaced @@ -507,7 +511,7 @@ cpdef fast_julia_plot(double c_real, double c_imag, while (new_x**2 + new_y**2 <= escape_radius_squared and iteration < max_iteration): sig_check() new_x, new_y = new_x**2 - new_y**2 + c_real, \ - 2*new_x*new_y + c_imag + 2*new_x*new_y + c_imag iteration += 1 # If the point escapes to infinity, assign the point a color @@ -521,16 +525,17 @@ cpdef fast_julia_plot(double c_real, double c_imag, # Assign the pixel a color based on it's level. If we run out # of colors, assign it the last color in the list. if level < color_num: - Jp[col,row] = color_list[level] + Jp[col, row] = color_list[level] else: - Jp[col,row] = color_list[-1] + Jp[col, row] = color_list[-1] return J cpdef julia_helper(double c_real, double c_imag, double x_center=0, - double y_center=0, double image_width=4, long max_iteration=500, - long pixel_count=500, long level_sep=2, long color_num=40, - base_color=[50, 50, 50], point_color=[255, 0, 0]): + double y_center=0, double image_width=4, + long max_iteration=500, + long pixel_count=500, long level_sep=2, long color_num=40, + base_color=[50, 50, 50], point_color=[255, 0, 0]): r""" Helper function that returns the image of a Julia set for a given `c` value side by side with the Mandelbrot set with a point denoting @@ -584,44 +589,47 @@ cpdef julia_helper(double c_real, double c_imag, double x_center=0, # Initialize the Julia set J = fast_julia_plot(c_real, c_imag, x_center, y_center, image_width, - max_iteration, pixel_count, level_sep, color_num, base_color) + max_iteration, pixel_count, level_sep, + color_num, base_color) Jp = J.pixels() # Initialize the image with Julia set on left side # Add white border between images - G = Image("RGB", (2*pixel_count+1,pixel_count), 'white') + G = Image("RGB", (2*pixel_count+1, pixel_count), 'white') Gp = G.pixels() for i in range(pixel_count): for j in range(pixel_count): - Gp[i,j] = Jp[i,j] + Gp[i, j] = Jp[i, j] # Plot the Mandelbrot set on the right side M = fast_mandelbrot_plot(-1, 0, 4, 500, pixel_count, 1, 30, base_color) Mp = M.pixels() - for i in range(pixel_count+1,2*pixel_count): + for i in range(pixel_count+1, 2*pixel_count): for j in range(pixel_count): - Gp[i,j] = Mp[int(i-pixel_count),j] + Gp[i, j] = Mp[int(i-pixel_count), j] point_color = _color_to_RGB(point_color) # Add a cross representing c-value to the Mandelbrot set. CP = convert_to_pixels([(c_real, c_imag)], -1, 0, 4, pixel_count) - for i in range(-3,4): + for i in range(-3, 4): # Loop through x and y coordinates and check if they are in image if min(CP[0][0]+i, CP[0][1]) >= 0 and \ - max(CP[0][0]+i, CP[0][1]) < pixel_count: + max(CP[0][0]+i, CP[0][1]) < pixel_count: Gp[CP[0][0]+i+pixel_count+1, CP[0][1]] = tuple(point_color) if min(CP[0][0], CP[0][1]+i) >= 0 and \ - max(CP[0][0], CP[0][1]+i) < pixel_count: + max(CP[0][0], CP[0][1]+i) < pixel_count: Gp[CP[0][0]+pixel_count+1, CP[0][1]+i] = tuple(point_color) return G cpdef polynomial_mandelbrot(f, parameter=None, double x_center=0, - double y_center=0, image_width=4, int max_iteration=50, int pixel_count=500, - int level_sep=1, int color_num=30, base_color=Color('red')): + double y_center=0, image_width=4, + int max_iteration=50, int pixel_count=500, + int level_sep=1, int color_num=30, + base_color=Color('red')): r""" - Plots the Mandelbrot set in the complex plane for a family of polynomial maps. + Plot the Mandelbrot set in the complex plane for a family of polynomial maps. INPUT: @@ -684,7 +692,7 @@ cpdef polynomial_mandelbrot(f, parameter=None, double x_center=0, f_real, f_imag, f_temp, escape_time, cf_list, cf int i, j, d, k, col, row, iteration double C, L, Rad, x_corner, y_corner, x_coor, y_coor, \ - step_size, new_x, new_y + step_size, new_x, new_y I = CDF.gen() constant_c = True @@ -720,7 +728,7 @@ cpdef polynomial_mandelbrot(f, parameter=None, double x_center=0, image_width = abs(image_width) # Initialize an image to the color black and access the pixels - M = Image("RGB", (pixel_count,pixel_count), 'black') + M = Image("RGB", (pixel_count, pixel_count), 'black') pixel = M.pixels() # Take the given base color and create a list of evenly spaced @@ -738,21 +746,21 @@ cpdef polynomial_mandelbrot(f, parameter=None, double x_center=0, color_list[i] = tuple(color_list[i]) # Split function into real and imaginary parts - R = PolynomialRing(CC, [variable,parameter]) + R = PolynomialRing(CC, [variable, parameter]) if len(R.gens()) > 2: raise NotImplementedError("base ring must have only 2 variables") z, c = R.gens() f = R(str(f)) S = PolynomialRing(f.base_ring(), 'x,y,J,cr,ci') - x,y,J,cr,ci = S.gens() + x, y, J, cr, ci = S.gens() S2 = S.quotient_ring(J**2+1) phi = R.hom([x+y*J, cr+ci*J], S2) t = phi(f).lift() im = t.coefficient(J) re = t - im*J - f_real = fast_callable(re, vars=[x,y,cr,ci,J], domain=RDF) - f_imag = fast_callable(im, vars=[x,y,cr,ci,J], domain=RDF) + f_real = fast_callable(re, vars=[x, y, cr, ci, J], domain=RDF) + f_imag = fast_callable(im, vars=[x, y, cr, ci, J], domain=RDF) # Compute critical points try: @@ -765,9 +773,7 @@ cpdef polynomial_mandelbrot(f, parameter=None, double x_center=0, # If c is in the constant term of the polynomial, then the critical points # will be independent of c. if constant_c: - c_pts = [] - for pt in critical_pts: - c_pts.append([pt.real(), pt.imag()]) + c_pts = [[pt.real(), pt.imag()] for pt in critical_pts] # Calculate escape condition d = f.degree(z) @@ -811,8 +817,8 @@ cpdef polynomial_mandelbrot(f, parameter=None, double x_center=0, iteration = 0 while new_x**2 + new_y**2 <= Rad**2 and iteration < escape_time: sig_check() - new_x, new_y = f_real(new_x, new_y, x_coor, y_coor,1), \ - f_imag(new_x, new_y, x_coor, y_coor,1) + new_x, new_y = f_real(new_x, new_y, x_coor, y_coor, 1), \ + f_imag(new_x, new_y, x_coor, y_coor, 1) iteration += 1 # For each point, we take the minimum number of iterations @@ -832,17 +838,17 @@ cpdef polynomial_mandelbrot(f, parameter=None, double x_center=0, # Assign the pixel a color based on it's level. If we run out # of colors, assign it the last color in the list. if level < color_num: - pixel[col,row] = color_list[level] + pixel[col, row] = color_list[level] else: - pixel[col,row] = color_list[-1] + pixel[col, row] = color_list[-1] # If the critical points of f depend on c, we must compute the different # critical points for each c. else: # Solve for critical points symbollically. with SR.temp_var() as w: - df = f.derivative(z).polynomial(z).subs({z:w}) - critical_pts = solve(symbolic_expression(df)==0, w) + df = f.derivative(z).polynomial(z).subs({z: w}) + critical_pts = solve(symbolic_expression(df) == 0, w) c_pts = [] for pt in critical_pts: c_pts.append(fast_callable(pt.rhs(), vars=[c], domain=CDF)) @@ -868,7 +874,7 @@ cpdef polynomial_mandelbrot(f, parameter=None, double x_center=0, escape_time = max_iteration # Calculate escape condition for each c value - f_temp = f.subs({c:x_coor+y_coor*I}) + f_temp = f.subs({c: x_coor+y_coor*I}) cf_list = f_temp.coefficients() a_n = cf_list.pop(0).abs() C = 0 @@ -892,8 +898,8 @@ cpdef polynomial_mandelbrot(f, parameter=None, double x_center=0, iteration = 0 while new_x**2 + new_y**2 <= Rad**2 and iteration < escape_time: sig_check() - new_x, new_y = f_real(new_x, new_y, x_coor, y_coor,1), \ - f_imag(new_x, new_y, x_coor, y_coor,1) + new_x, new_y = f_real(new_x, new_y, x_coor, y_coor, 1), \ + f_imag(new_x, new_y, x_coor, y_coor, 1) iteration += 1 # For each point, we take the minimum number of iterations @@ -913,48 +919,48 @@ cpdef polynomial_mandelbrot(f, parameter=None, double x_center=0, # Assign the pixel a color based on it's level. If we run out # of colors, assign it the last color in the list. if level < color_num: - pixel[col,row] = color_list[level] + pixel[col, row] = color_list[level] else: - pixel[col,row] = color_list[-1] + pixel[col, row] = color_list[-1] return M cpdef general_julia(f, double x_center=0, double y_center=0, image_width=4, - int max_iteration=50, int pixel_count=500, int level_sep=1, int color_num=30, - base_color=[50,50,50]): + int max_iteration=50, int pixel_count=500, + int level_sep=1, int color_num=30, + base_color=[50, 50, 50]): r""" - Plots Julia sets for general polynomials. + Plot Julia sets for general polynomials. EXAMPLES:: - sage: from sage.dynamics.complex_dynamics.mandel_julia_helper import general_julia - sage: from sage.plot.colors import Color - sage: R. = CC[] - sage: f = z^3 - z + 1 - sage: general_julia(f) - 500x500px 24-bit RGB image + sage: from sage.dynamics.complex_dynamics.mandel_julia_helper import general_julia + sage: from sage.plot.colors import Color + sage: R. = CC[] + sage: f = z^3 - z + 1 + sage: general_julia(f) + 500x500px 24-bit RGB image :: - sage: from sage.dynamics.complex_dynamics.mandel_julia_helper import general_julia - sage: from sage.plot.colors import Color - sage: R. = CC[] - sage: f = z^5 - 1 - sage: general_julia(f) - 500x500px 24-bit RGB image + sage: from sage.dynamics.complex_dynamics.mandel_julia_helper import general_julia + sage: from sage.plot.colors import Color + sage: R. = CC[] + sage: f = z^5 - 1 + sage: general_julia(f) + 500x500px 24-bit RGB image """ cdef: - M, pixel, color_list, R, z, S, x, y, S2, phi, t, im, re, a_n, df, - critical_pts, f_real, f_imag, J - int i, j, d, k, col, row, iteration, ii - double C, L, Rad, x_corner, y_corner, x_coor, y_coor, step_size, new_x, new_y + M, pixel, color_list, z, a_n + int i, j, d, k, col, row, iteration + double C, L, Rad, x_corner, y_corner, x_coor, y_coor, step_size I = CDF.gen() # Make sure image_width is positive image_width = abs(image_width) # Initialize an image to the color black and access the pixels - M = Image("RGB", (pixel_count,pixel_count), 'black') + M = Image("RGB", (pixel_count, pixel_count), 'black') pixel = M.pixels() # Take the given base color and create a list of evenly spaced @@ -1022,7 +1028,7 @@ cpdef general_julia(f, double x_center=0, double y_center=0, image_width=4, # Assign the pixel a color based on it's level. If we run out # of colors, assign it the last color in the list. if level < color_num: - pixel[col,row] = color_list[level] + pixel[col, row] = color_list[level] else: - pixel[col,row] = color_list[-1] + pixel[col, row] = color_list[-1] return M diff --git a/src/sage/features/sat.py b/src/sage/features/sat.py index 6a05491ddb7..2d68e70376d 100644 --- a/src/sage/features/sat.py +++ b/src/sage/features/sat.py @@ -14,7 +14,7 @@ class Glucose(Executable): EXAMPLES:: sage: from sage.features.sat import Glucose - sage: GlucoseExecutable().is_present() # optional - glucose + sage: Glucose().is_present() # optional - glucose FeatureTestResult('glucose', True) """ def __init__(self, executable="glucose"): @@ -59,7 +59,7 @@ class Pycosat(PythonModule): EXAMPLES:: sage: from sage.features.sat import Pycosat - sage: PycosatExecutable().is_present() # optional - pycosat + sage: Pycosat().is_present() # optional - pycosat FeatureTestResult('pycosat', True) """ def __init__(self): @@ -81,7 +81,7 @@ class Pycryptosat(PythonModule): EXAMPLES:: sage: from sage.features.sat import Pycryptosat - sage: PycryptosatExecutable().is_present() # optional - pycryptosat + sage: Pycryptosat().is_present() # optional - pycryptosat FeatureTestResult('pycryptosat', True) """ def __init__(self): diff --git a/src/sage/functions/spike_function.py b/src/sage/functions/spike_function.py index 6fa011434d8..4f9f04f1f6a 100644 --- a/src/sage/functions/spike_function.py +++ b/src/sage/functions/spike_function.py @@ -125,7 +125,7 @@ def _eval(self, x): x = float(x) for i in range(len(self.support)): z = self.support[i] - if z - eps <= x and x <= z + eps: + if z - eps <= x <= z + eps: return self.height[i], i return float(0), -1 diff --git a/src/sage/geometry/hyperbolic_space/hyperbolic_coercion.py b/src/sage/geometry/hyperbolic_space/hyperbolic_coercion.py index 1e2c7270b39..1b6a89714fc 100644 --- a/src/sage/geometry/hyperbolic_space/hyperbolic_coercion.py +++ b/src/sage/geometry/hyperbolic_space/hyperbolic_coercion.py @@ -186,7 +186,7 @@ def image_isometry_matrix(self, x): [0 1] """ if x.det() < 0: -# x = I * x + # x = I * x return matrix([[1,-I],[-I,1]]) * x * matrix([[1,I],[I,1]]).conjugate()/Integer(2) return matrix([[1,-I],[-I,1]]) * x * matrix([[1,I],[I,1]])/Integer(2) diff --git a/src/sage/geometry/integral_points_generic_dense.pyx b/src/sage/geometry/integral_points_generic_dense.pyx index 5ff619f44d4..4709aa04fec 100644 --- a/src/sage/geometry/integral_points_generic_dense.pyx +++ b/src/sage/geometry/integral_points_generic_dense.pyx @@ -1,4 +1,4 @@ -#cython: wraparound=False, boundscheck=False +# cython: wraparound=False, boundscheck=False from sage.modules.vector_integer_dense cimport Vector_integer_dense as VectorClass from sage.matrix.matrix_dense cimport Matrix_dense as MatrixClass diff --git a/src/sage/geometry/integral_points_integer_dense.pyx b/src/sage/geometry/integral_points_integer_dense.pyx index 0151ffed5c0..c33e7246994 100644 --- a/src/sage/geometry/integral_points_integer_dense.pyx +++ b/src/sage/geometry/integral_points_integer_dense.pyx @@ -1,4 +1,4 @@ -#cython: wraparound=False, boundscheck=False +# cython: wraparound=False, boundscheck=False from sage.modules.vector_integer_dense cimport Vector_integer_dense as VectorClass from sage.matrix.matrix_integer_dense cimport Matrix_integer_dense as MatrixClass diff --git a/src/sage/geometry/polyhedral_complex.py b/src/sage/geometry/polyhedral_complex.py index fa4aab394d4..768c0cfe82a 100644 --- a/src/sage/geometry/polyhedral_complex.py +++ b/src/sage/geometry/polyhedral_complex.py @@ -269,7 +269,7 @@ class PolyhedralComplex(GenericCellComplex): """ def __init__(self, maximal_cells=None, backend=None, maximality_check=True, face_to_face_check=False, is_mutable=True, is_immutable=False, - ambient_dim=None): + ambient_dim=None) -> None: r""" Define a PolyhedralComplex. @@ -341,7 +341,7 @@ def __init__(self, maximal_cells=None, backend=None, maximality_check=True, if not is_mutable or is_immutable: self.set_immutable() - def cells(self, subcomplex=None): + def cells(self, subcomplex=None) -> dict: """ The cells of this polyhedral complex, in the form of a dictionary: the keys are integers, representing dimension, and the value @@ -419,7 +419,7 @@ def cell_iterator(self, increasing=True): if d in cells: yield from cells[d] - def _n_cells_sorted(self, n, subcomplex=None): + def _n_cells_sorted(self, n, subcomplex=None) -> list: """ Sorted list of cells of dimension ``n`` of this polyhedral complex. @@ -447,7 +447,7 @@ def _n_cells_sorted(self, n, subcomplex=None): return sorted(n_cells, key=lambda p: (p.vertices(), p.rays(), p.lines())) - def cells_sorted(self, subcomplex=None): + def cells_sorted(self, subcomplex=None) -> list: """ The sorted list of the cells of this polyhedral complex in non-increasing dimensions. @@ -469,10 +469,10 @@ def cells_sorted(self, subcomplex=None): """ cells = [] for n in range(self._dim, -1, -1): - cells += self._n_cells_sorted(n, subcomplex) + cells.extend(self._n_cells_sorted(n, subcomplex)) return cells - def maximal_cells(self): + def maximal_cells(self) -> dict: """ The maximal cells of this polyhedral complex, in the form of a dictionary: the keys are integers, representing dimension, and the @@ -546,7 +546,7 @@ def maximal_cell_iterator(self, increasing=False): if d in maximal_cells: yield from maximal_cells[d] - def n_maximal_cells(self, n): + def n_maximal_cells(self, n) -> list: r""" List of maximal cells of dimension ``n`` of this polyhedral complex. @@ -584,10 +584,9 @@ def n_maximal_cells(self, n): """ if n in self.maximal_cells(): return list(self.maximal_cells()[n]) - else: - return [] + return [] - def _n_maximal_cells_sorted(self, n): + def _n_maximal_cells_sorted(self, n) -> list: """ Sorted list of maximal cells of dimension ``n`` of this polyhedral complex. @@ -613,7 +612,7 @@ def _n_maximal_cells_sorted(self, n): return sorted(n_maximal_cells, key=lambda p: (p.vertices(), p.rays(), p.lines())) - def maximal_cells_sorted(self): + def maximal_cells_sorted(self) -> list: """ Return the sorted list of the maximal cells of this polyhedral complex by non-increasing dimensions. @@ -629,11 +628,11 @@ def maximal_cells_sorted(self): if self._maximal_cells_sorted is None: maximal_cells = [] for n in range(self._dim, -1, -1): - maximal_cells += self._n_maximal_cells_sorted(n) + maximal_cells.extend(self._n_maximal_cells_sorted(n)) self._maximal_cells_sorted = maximal_cells return self._maximal_cells_sorted - def is_maximal_cell(self, c): + def is_maximal_cell(self, c) -> bool: """ Return whether the given cell ``c`` is a maximal cell of ``self``. @@ -664,7 +663,7 @@ def is_maximal_cell(self, c): # return (c in self.n_maximal_cells(d)) # use set instead of list return (d in self.maximal_cells()) and (c in self.maximal_cells()[d]) - def is_cell(self, c): + def is_cell(self, c) -> bool: """ Return whether the given cell ``c`` is a cell of ``self``. @@ -798,7 +797,7 @@ def plot(self, **kwds): g += cell.plot(**options) return g - def is_pure(self): + def is_pure(self) -> bool: """ Test if this polyhedral complex is pure. @@ -828,10 +827,11 @@ def is_pure(self): """ return len(self._maximal_cells) == 1 - def is_full_dimensional(self): + def is_full_dimensional(self) -> bool: """ - Return whether this polyhedral complex is full-dimensional: - its dimension is equal to its ambient dimension. + Return whether this polyhedral complex is full-dimensional. + + This means that its dimension is equal to its ambient dimension. EXAMPLES:: @@ -846,7 +846,7 @@ def is_full_dimensional(self): """ return self._dim == self._ambient_dim - def __hash__(self): + def __hash__(self) -> int: """ Compute the hash value of ``self`` using its ``maximal_cells_sorted``. @@ -871,7 +871,7 @@ def __hash__(self): "call set_immutable()") return hash(tuple(self.maximal_cells_sorted())) - def __eq__(self, right): + def __eq__(self, right) -> bool: """ Two polyhedral complexes are equal iff their maximal cells are equal. @@ -889,7 +889,7 @@ def __eq__(self, right): return isinstance(right, PolyhedralComplex) and ( self.maximal_cells_sorted() == right.maximal_cells_sorted()) - def __ne__(self, right): + def __ne__(self, right) -> bool: """ Return ``True`` if ``self`` and ``right`` are not equal. @@ -943,7 +943,7 @@ def _an_element_(self): from sage.categories.sets_cat import EmptySetError raise EmptySetError("the complex is empty") - def __contains__(self, x): + def __contains__(self, x) -> bool: """ Return ``True`` if ``x`` is a polyhedron which is contained in this complex. @@ -1031,7 +1031,7 @@ def face_poset(self): self.cells() # poset is obtained and cached in cells() return self._face_poset - def is_subcomplex(self, other): + def is_subcomplex(self, other) -> bool: r""" Return whether ``self`` is a subcomplex of ``other``. @@ -1059,7 +1059,7 @@ def is_subcomplex(self, other): return False return True - def is_compact(self): + def is_compact(self) -> bool: """ Test for boundedness of the polyhedral complex. @@ -1128,7 +1128,7 @@ def graph(self): d[v] = [] return Graph(d) - def is_connected(self): + def is_connected(self) -> bool: """ Return whether ``self`` is connected. @@ -1252,7 +1252,7 @@ def connected_component(self, cell=None): is_immutable=self._is_immutable, backend=self._backend) - def connected_components(self): + def connected_components(self) -> list: """ Return the connected components of this polyhedral complex, as list of (sub-)PolyhedralComplexes. @@ -1303,11 +1303,10 @@ def connected_components(self): lists_of_facets = [ [f for f in self.maximal_cell_iterator() if f in faces] for faces in lists_of_faces] - results = [PolyhedralComplex(facets, maximality_check=False, - is_immutable=self._is_immutable, - backend=self._backend) - for facets in lists_of_facets] - return results + return [PolyhedralComplex(facets, maximality_check=False, + is_immutable=self._is_immutable, + backend=self._backend) + for facets in lists_of_facets] def n_skeleton(self, n): r""" @@ -1445,7 +1444,7 @@ def boundary_subcomplex(self): ans.set_immutable() return ans - def relative_boundary_cells(self): + def relative_boundary_cells(self) -> list: r""" Return the maximal cells of the relative-boundary sub-complex. @@ -1501,10 +1500,10 @@ def relative_boundary_cells(self): faces = self.n_cells(d - 1) ans = [face for face in faces if len(poset.upper_covers(face)) == 1] if not self.is_pure(): - ans += [p for p in poset.maximal_elements() if p.dimension() < d] + ans.extend(p for p in poset.maximal_elements() if p.dimension() < d) return ans - def is_convex(self): + def is_convex(self) -> bool: r""" Return whether the set of points in ``self`` is a convex set. @@ -1863,7 +1862,7 @@ def alexander_whitney(self, cell, dim_left): # this function overrides the standard one for GenericCellComplex, # this one counts the number of maximal cells, not all cells, to # avoid calling and computing self.cells() - def _repr_(self): + def _repr_(self) -> str: """ Print representation. @@ -1891,7 +1890,7 @@ def _repr_(self): else: return "Polyhedral complex with %s maximal cells" % num - def set_immutable(self): + def set_immutable(self) -> None: """ Make this polyhedral complex immutable. @@ -1906,7 +1905,7 @@ def set_immutable(self): """ self._is_immutable = True - def is_mutable(self): + def is_mutable(self) -> bool: """ Return whether ``self`` is mutable. @@ -1930,7 +1929,7 @@ def is_mutable(self): """ return not self._is_immutable - def is_immutable(self): + def is_immutable(self) -> bool: """ Return whether ``self`` is immutable. @@ -2224,7 +2223,7 @@ def remove_cell(self, cell, check=False): self._is_convex = None self._polyhedron = None - def is_simplicial_complex(self): + def is_simplicial_complex(self) -> bool: """ Test if this polyhedral complex is a simplicial complex. @@ -2243,7 +2242,7 @@ def is_simplicial_complex(self): """ return all(p.is_simplex() for p in self.maximal_cell_iterator()) - def is_polyhedral_fan(self): + def is_polyhedral_fan(self) -> bool: """ Test if this polyhedral complex is a polyhedral fan. @@ -2266,7 +2265,7 @@ def is_polyhedral_fan(self): vector(p.vertices_list()[0]) == p.ambient_space().zero()) for p in self.maximal_cell_iterator()) - def is_simplicial_fan(self): + def is_simplicial_fan(self) -> bool: """ Test if this polyhedral complex is a simplicial fan. @@ -2470,7 +2469,7 @@ def subdivide(self, make_simplicial=False, ############################################################ -def cells_list_to_cells_dict(cells_list): +def cells_list_to_cells_dict(cells_list) -> dict: r""" Helper function that returns the dictionary whose keys are the dimensions, and the value associated to an integer `d` is the set of `d`-dimensional diff --git a/src/sage/geometry/polyhedron/base_QQ.py b/src/sage/geometry/polyhedron/base_QQ.py index e17f043adb5..e54c1237cf1 100644 --- a/src/sage/geometry/polyhedron/base_QQ.py +++ b/src/sage/geometry/polyhedron/base_QQ.py @@ -213,10 +213,12 @@ def integral_points_count(self, verbose=False, use_Hrepresentation=False, @cached_method(do_pickle=True) def ehrhart_polynomial(self, engine=None, variable='t', verbose=False, - dual=None, irrational_primal=None, irrational_all_primal=None, - maxdet=None, no_decomposition=None, compute_vertex_cones=None, - smith_form=None, dualization=None, triangulation=None, - triangulation_max_height=None, **kwds): + dual=None, irrational_primal=None, + irrational_all_primal=None, maxdet=None, + no_decomposition=None, compute_vertex_cones=None, + smith_form=None, dualization=None, + triangulation=None, + triangulation_max_height=None, **kwds): r""" Return the Ehrhart polynomial of this polyhedron. @@ -348,12 +350,17 @@ def ehrhart_polynomial(self, engine=None, variable='t', verbose=False, sage: Q = loads(dumps(P)) sage: Q.ehrhart_polynomial.is_in_cache() True + + sage: L = Polyhedron(vertices=[[QQ(0)]]) + sage: L.ehrhart_polynomial() + 1 """ + from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing + from sage.rings.rational_field import QQ + R = PolynomialRing(QQ, variable) + # check if ``self`` is compact and has vertices in ZZ if self.is_empty(): - from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing - from sage.rings.rational_field import QQ - R = PolynomialRing(QQ, variable) return R.zero() if not self.is_compact(): @@ -361,10 +368,15 @@ def ehrhart_polynomial(self, engine=None, variable='t', verbose=False, if any(not v.is_integral() for v in self.vertex_generator()): raise TypeError("the polytope has nonintegral vertices, use ehrhart_quasipolynomial with backend 'normaliz'") + + if self.dimension() == 0: + return R.one() + # Passes to specific latte or normaliz subfunction depending on engine if engine is None: # set default engine to latte engine = 'latte' + if engine == 'latte': poly = self._ehrhart_polynomial_latte(verbose, dual, irrational_primal, irrational_all_primal, maxdet, diff --git a/src/sage/geometry/polyhedron/base_ZZ.py b/src/sage/geometry/polyhedron/base_ZZ.py index d17b40a1b3d..130b04e8ba2 100644 --- a/src/sage/geometry/polyhedron/base_ZZ.py +++ b/src/sage/geometry/polyhedron/base_ZZ.py @@ -295,11 +295,13 @@ def _ehrhart_polynomial_normaliz(self, variable='t'): raise TypeError("The polyhedron's backend should be 'normaliz'") @cached_method(do_pickle=True) - def ehrhart_polynomial(self, engine=None, variable='t', verbose=False, dual=None, - irrational_primal=None, irrational_all_primal=None, maxdet=None, - no_decomposition=None, compute_vertex_cones=None, smith_form=None, - dualization=None, triangulation=None, triangulation_max_height=None, - **kwds): + def ehrhart_polynomial(self, engine=None, variable='t', verbose=False, + dual=None, irrational_primal=None, + irrational_all_primal=None, maxdet=None, + no_decomposition=None, compute_vertex_cones=None, + smith_form=None, dualization=None, + triangulation=None, triangulation_max_height=None, + **kwds): r""" Return the Ehrhart polynomial of this polyhedron. @@ -458,12 +460,16 @@ def ehrhart_polynomial(self, engine=None, variable='t', verbose=False, dual=None sage: Q.ehrhart_polynomial.is_in_cache() # optional - latte_int True """ + from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing + from sage.rings.rational_field import QQ + R = PolynomialRing(QQ, variable) + if self.is_empty(): - from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing - from sage.rings.rational_field import QQ - R = PolynomialRing(QQ, variable) return R.zero() + if self.dimension() == 0: + return R.one() + if not self.is_compact(): raise ValueError("Ehrhart polynomial only defined for compact polyhedra") diff --git a/src/sage/graphs/base/c_graph.pxd b/src/sage/graphs/base/c_graph.pxd index 9cd670ccbc5..f1dc9857d93 100644 --- a/src/sage/graphs/base/c_graph.pxd +++ b/src/sage/graphs/base/c_graph.pxd @@ -1,9 +1,9 @@ -#************************************************************************** +# ************************************************************************* # Copyright (C) 2008-9 Robert L. Miller # # Distributed under the terms of the GNU General Public License (GPL) -# http://www.gnu.org/licenses/ -#************************************************************************** +# https://www.gnu.org/licenses/ +# ************************************************************************* from sage.data_structures.bitset cimport bitset_t from sage.graphs.base.graph_backends cimport GenericGraphBackend @@ -87,7 +87,7 @@ cdef class CGraphBackend(GenericGraphBackend): cdef int get_vertex_checked(self, u) except ? -2 cdef vertex_label(self, int u_int) cdef int check_labelled_vertex(self, u, bint reverse) except ? -1 - #cdef CGraph _cg # a child class should declare this accordingly + # cdef CGraph _cg # a child class should declare this accordingly cdef bint _directed cdef dict vertex_labels cdef dict vertex_ints diff --git a/src/sage/graphs/base/static_sparse_graph.pyx b/src/sage/graphs/base/static_sparse_graph.pyx index c27f0d9a8cc..0210122d5a9 100644 --- a/src/sage/graphs/base/static_sparse_graph.pyx +++ b/src/sage/graphs/base/static_sparse_graph.pyx @@ -328,7 +328,7 @@ cdef int init_short_digraph(short_digraph g, G, edge_labelled=False, g.neighbors[j][0] = i # Note: cannot use the dereference Cython operator here, do not # known why but the following line does not compile - #dereference(g.neighbors[j]) = i + # dereference(g.neighbors[j]) = i if edge_labelled: edge_labels[g.neighbors[j] - g.edges] = e[2] postincrement(g.neighbors[j]) # increment pointer to next item diff --git a/src/sage/graphs/connectivity.pyx b/src/sage/graphs/connectivity.pyx index 66f584fc466..2411f3dd4c9 100644 --- a/src/sage/graphs/connectivity.pyx +++ b/src/sage/graphs/connectivity.pyx @@ -55,6 +55,7 @@ Here is what the module can do: :meth:`is_triconnected` | Check whether the graph is triconnected. :meth:`spqr_tree` | Return a SPQR-tree representing the triconnected components of the graph. :meth:`spqr_tree_to_graph` | Return the graph represented by the SPQR-tree `T`. + :meth:`minimal_separators` | Return an iterator over the minimal separators of ``G``. Methods ------- @@ -134,11 +135,12 @@ def is_connected(G, forbidden_vertices=None): if not G.order(): return True + forbidden = None if forbidden_vertices is None else set(forbidden_vertices) + try: - return G._backend.is_connected(forbidden_vertices=forbidden_vertices) + return G._backend.is_connected(forbidden_vertices=forbidden) except AttributeError: # Search for a vertex in G that is not forbidden - forbidden = set(forbidden_vertices) if forbidden_vertices else set() if forbidden: for v in G: if v not in forbidden: @@ -200,6 +202,9 @@ def connected_components(G, sort=None, key=None, forbidden_vertices=None): sage: G = graphs.PathGraph(5) sage: connected_components(G, sort=True, forbidden_vertices=[2]) [[0, 1], [3, 4]] + sage: connected_components(G, sort=True, + ....: forbidden_vertices=G.neighbor_iterator(2, closed=True)) + [[0], [4]] TESTS: @@ -244,7 +249,7 @@ def connected_components(G, sort=None, key=None, forbidden_vertices=None): for v in G: if v not in seen: c = connected_component_containing_vertex(G, v, sort=sort, key=key, - forbidden_vertices=forbidden_vertices) + forbidden_vertices=seen) seen.update(c) components.append(c) components.sort(key=lambda comp: -len(comp)) @@ -423,12 +428,14 @@ def connected_component_containing_vertex(G, vertex, sort=None, key=None, if (not sort) and key: raise ValueError('sort keyword is False, yet a key function is given') + forbidden = None if forbidden_vertices is None else list(forbidden_vertices) + try: c = list(G._backend.depth_first_search(vertex, ignore_direction=True, - forbidden_vertices=forbidden_vertices)) + forbidden_vertices=forbidden)) except AttributeError: c = list(G.depth_first_search(vertex, ignore_direction=True, - forbidden_vertices=forbidden_vertices)) + forbidden_vertices=forbidden)) if sort: return sorted(c, key=key) @@ -1256,6 +1263,104 @@ def is_cut_vertex(G, u, weak=False): return is_vertex_cut(G, [u], weak=weak) +def minimal_separators(G, forbidden_vertices=None): + r""" + Return an iterator over the minimal separators of ``G``. + + A separator in a graph is a set of vertices whose removal increases the + number of connected components. In other words, a separator is a vertex + cut. This method implements the algorithm proposed in [BBC2000]_. + It computes the set `S` of minimal separators of a graph in `O(n^3)` time + per separator, and so overall in `O(n^3 |S|)` time. + + .. WARNING:: + + Note that all separators are recorded during the execution of the + algorithm and so the memory consumption of this method might be huge. + + INPUT: + + - ``G`` -- an undirected graph + + - ``forbidden_vertices`` -- list (default: ``None``); set of vertices to + avoid during the search + + EXAMPLES:: + + sage: P = graphs.PathGraph(5) + sage: sorted(sorted(sep) for sep in P.minimal_separators()) + [[1], [2], [3]] + sage: C = graphs.CycleGraph(6) + sage: sorted(sorted(sep) for sep in C.minimal_separators()) + [[0, 2], [0, 3], [0, 4], [1, 3], [1, 4], [1, 5], [2, 4], [2, 5], [3, 5]] + sage: sorted(sorted(sep) for sep in C.minimal_separators(forbidden_vertices=[0])) + [[2], [3], [4]] + sage: sorted(sorted(sep) for sep in (P + C).minimal_separators()) + [[1], [2], [3], [5, 7], [5, 8], [5, 9], [6, 8], + [6, 9], [6, 10], [7, 9], [7, 10], [8, 10]] + sage: sorted(sorted(sep) for sep in (P + C).minimal_separators(forbidden_vertices=[10])) + [[1], [2], [3], [6], [7], [8]] + + sage: G = graphs.RandomGNP(10, .3) + sage: all(G.is_vertex_cut(sep) for sep in G.minimal_separators()) + True + + TESTS:: + + sage: list(Graph().minimal_separators()) + [] + sage: list(Graph(1).minimal_separators()) + [] + sage: list(Graph(2).minimal_separators()) + [] + sage: from sage.graphs.connectivity import minimal_separators + sage: list(minimal_separators(DiGraph())) + Traceback (most recent call last): + ... + ValueError: the input must be an undirected graph + """ + from sage.graphs.graph import Graph + if not isinstance(G, Graph): + raise ValueError("the input must be an undirected graph") + + if forbidden_vertices is not None and G.order() >= 3: + # Build the subgraph with active vertices + G = G.subgraph(set(G).difference(forbidden_vertices), immutable=True) + + if G.order() < 3: + return + if not G.is_connected(): + for cc in G.connected_components(sort=False): + if len(cc) > 2: + yield from minimal_separators(G.subgraph(cc)) + return + + # Initialization - identify separators needing further inspection + cdef list to_explore = [] + for v in G: + # iterate over the connected components of G \ N[v] + for comp in G.connected_components(sort=False, forbidden_vertices=G.neighbor_iterator(v, closed=True)): + # The vertex boundary of comp in G is a separator + nh = G.vertex_boundary(comp) + if nh: + to_explore.append(frozenset(nh)) + + # Generation of all minimal separators + cdef set separators = set() + while to_explore: + sep = to_explore.pop() + if sep in separators: + continue + yield set(sep) + separators.add(sep) + for v in sep: + # iterate over the connected components of G \ sep \ N(v) + for comp in G.connected_components(sort=False, forbidden_vertices=sep.union(G.neighbor_iterator(v))): + nh = G.vertex_boundary(comp) + if nh: + to_explore.append(frozenset(nh)) + + def edge_connectivity(G, value_only=True, implementation=None, diff --git a/src/sage/graphs/distances_all_pairs.pyx b/src/sage/graphs/distances_all_pairs.pyx index 23d2e1c79d7..dc83c857240 100644 --- a/src/sage/graphs/distances_all_pairs.pyx +++ b/src/sage/graphs/distances_all_pairs.pyx @@ -122,7 +122,6 @@ Functions # https://www.gnu.org/licenses/ # **************************************************************************** -from sage.data_structures.binary_matrix cimport * from libc.string cimport memset from libc.stdint cimport uint64_t, UINT64_MAX from libc.stdint cimport uint32_t, INT32_MAX, UINT32_MAX @@ -130,9 +129,11 @@ from cysignals.memory cimport sig_malloc, sig_calloc, sig_free from cysignals.signals cimport sig_on, sig_off from memory_allocator cimport MemoryAllocator +from sage.data_structures.binary_matrix cimport * from sage.graphs.base.c_graph cimport CGraphBackend from sage.graphs.base.c_graph cimport CGraph - +from sage.graphs.base.static_sparse_backend cimport StaticSparseCGraph +from sage.graphs.base.static_sparse_backend cimport StaticSparseBackend from sage.graphs.base.static_sparse_graph cimport (short_digraph, init_short_digraph, init_reverse, @@ -446,15 +447,15 @@ def distances_all_pairs(G): sage: g = graphs.PetersenGraph() sage: distances_all_pairs(g) {0: {0: 0, 1: 1, 2: 2, 3: 2, 4: 1, 5: 1, 6: 2, 7: 2, 8: 2, 9: 2}, - 1: {0: 1, 1: 0, 2: 1, 3: 2, 4: 2, 5: 2, 6: 1, 7: 2, 8: 2, 9: 2}, - 2: {0: 2, 1: 1, 2: 0, 3: 1, 4: 2, 5: 2, 6: 2, 7: 1, 8: 2, 9: 2}, - 3: {0: 2, 1: 2, 2: 1, 3: 0, 4: 1, 5: 2, 6: 2, 7: 2, 8: 1, 9: 2}, - 4: {0: 1, 1: 2, 2: 2, 3: 1, 4: 0, 5: 2, 6: 2, 7: 2, 8: 2, 9: 1}, - 5: {0: 1, 1: 2, 2: 2, 3: 2, 4: 2, 5: 0, 6: 2, 7: 1, 8: 1, 9: 2}, - 6: {0: 2, 1: 1, 2: 2, 3: 2, 4: 2, 5: 2, 6: 0, 7: 2, 8: 1, 9: 1}, - 7: {0: 2, 1: 2, 2: 1, 3: 2, 4: 2, 5: 1, 6: 2, 7: 0, 8: 2, 9: 1}, - 8: {0: 2, 1: 2, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1, 7: 2, 8: 0, 9: 2}, - 9: {0: 2, 1: 2, 2: 2, 3: 2, 4: 1, 5: 2, 6: 1, 7: 1, 8: 2, 9: 0}} + 1: {0: 1, 1: 0, 2: 1, 3: 2, 4: 2, 5: 2, 6: 1, 7: 2, 8: 2, 9: 2}, + 2: {0: 2, 1: 1, 2: 0, 3: 1, 4: 2, 5: 2, 6: 2, 7: 1, 8: 2, 9: 2}, + 3: {0: 2, 1: 2, 2: 1, 3: 0, 4: 1, 5: 2, 6: 2, 7: 2, 8: 1, 9: 2}, + 4: {0: 1, 1: 2, 2: 2, 3: 1, 4: 0, 5: 2, 6: 2, 7: 2, 8: 2, 9: 1}, + 5: {0: 1, 1: 2, 2: 2, 3: 2, 4: 2, 5: 0, 6: 2, 7: 1, 8: 1, 9: 2}, + 6: {0: 2, 1: 1, 2: 2, 3: 2, 4: 2, 5: 2, 6: 0, 7: 2, 8: 1, 9: 1}, + 7: {0: 2, 1: 2, 2: 1, 3: 2, 4: 2, 5: 1, 6: 2, 7: 0, 8: 2, 9: 1}, + 8: {0: 2, 1: 2, 2: 2, 3: 1, 4: 2, 5: 1, 6: 1, 7: 2, 8: 0, 9: 2}, + 9: {0: 2, 1: 2, 2: 2, 3: 2, 4: 1, 5: 2, 6: 1, 7: 1, 8: 2, 9: 0}} """ from sage.rings.infinity import Infinity @@ -1806,6 +1807,17 @@ def diameter(G, algorithm=None, source=None): sage: G = graphs.PathGraph(1) sage: diameter(G, algorithm='iFUB') 0 + + Immutable graphs:: + + sage: G = graphs.RandomGNP(10, .5) + sage: G._backend + + sage: H = Graph(G, immutable=True) + sage: H._backend + + sage: diameter(G, algorithm='iFUB') == diameter(H, algorithm='iFUB') + True """ cdef uint32_t n = G.order() if n <= 1: @@ -1832,9 +1844,16 @@ def diameter(G, algorithm=None, source=None): # Copying the whole graph to obtain the list of neighbors quicker than by # calling out_neighbors. This data structure is well documented in the # module sage.graphs.base.static_sparse_graph - cdef list int_to_vertex = list(G) + cdef list int_to_vertex + cdef StaticSparseCGraph cg cdef short_digraph sd - init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_vertex) + if isinstance(G, StaticSparseBackend): + cg = G._cg + sd = cg.g + int_to_vertex = cg._vertex_to_labels + else: + int_to_vertex = list(G) + init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_vertex) cdef short_digraph rev_sd # to store copy of sd with edges reversed # and we map the source to an int in [0,n-1] @@ -1849,7 +1868,8 @@ def diameter(G, algorithm=None, source=None): bitset_init(seen, n) tab = sig_malloc(2* n * sizeof(uint32_t)) if not tab: - free_short_digraph(sd) + if not isinstance(G, StaticSparseBackend): + free_short_digraph(sd) bitset_free(seen) raise MemoryError() @@ -1875,7 +1895,8 @@ def diameter(G, algorithm=None, source=None): else: # algorithm == 'iFUB' LB = diameter_iFUB(sd, isource) - free_short_digraph(sd) + if not isinstance(G, StaticSparseBackend): + free_short_digraph(sd) if LB < 0 or LB > n: from sage.rings.infinity import Infinity @@ -1926,6 +1947,17 @@ def radius_DHV(G): Traceback (most recent call last): ... TypeError: this method works for unweighted undirected graphs only + + Immutable graphs:: + + sage: G = graphs.RandomGNP(10, .5) + sage: G._backend + + sage: H = Graph(G, immutable=True) + sage: H._backend + + sage: radius_DHV(G) == radius_DHV(H) + True """ if G.is_directed(): raise TypeError("this method works for unweighted undirected graphs only") @@ -1934,9 +1966,16 @@ def radius_DHV(G): if n <= 1: return 0 - cdef list int_to_vertex = list(G) + cdef list int_to_vertex + cdef StaticSparseCGraph cg cdef short_digraph sd - init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_vertex) + if isinstance(G, StaticSparseBackend): + cg = G._cg + sd = cg.g + int_to_vertex = cg._vertex_to_labels + else: + int_to_vertex = list(G) + init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_vertex) cdef uint32_t source, ecc_source cdef uint32_t antipode, ecc_antipode @@ -1946,6 +1985,8 @@ def radius_DHV(G): cdef MemoryAllocator mem = MemoryAllocator() cdef uint32_t * distances = mem.malloc(3 * n * sizeof(uint32_t)) if not distances: + if not isinstance(G, StaticSparseBackend): + free_short_digraph(sd) raise MemoryError() cdef uint32_t * waiting_list = distances + n @@ -1987,7 +2028,8 @@ def radius_DHV(G): LB = ecc_lower_bound[v] source = v # vertex with minimum eccentricity lower bound - free_short_digraph(sd) + if not isinstance(G, StaticSparseBackend): + free_short_digraph(sd) bitset_free(seen) if UB == UINT32_MAX: from sage.rings.infinity import Infinity @@ -2041,6 +2083,19 @@ def wiener_index(G): Traceback (most recent call last): ... ValueError: Wiener index is not defined for the empty graph + + TESTS: + + Immutable graphs:: + + sage: G = graphs.RandomGNP(10, .5) + sage: G._backend + + sage: H = Graph(G, immutable=True) + sage: H._backend + + sage: G.wiener_index() == H.wiener_index() + True """ if not G: raise ValueError("Wiener index is not defined for the empty graph") @@ -2052,8 +2107,13 @@ def wiener_index(G): # Copying the whole graph to obtain the list of neighbors quicker than by # calling out_neighbors. This data structure is well documented in the # module sage.graphs.base.static_sparse_graph + cdef StaticSparseCGraph cg cdef short_digraph sd - init_short_digraph(sd, G, edge_labelled=False, vertex_list=list(G)) + if isinstance(G, StaticSparseBackend): + cg = G._cg + sd = cg.g + else: + init_short_digraph(sd, G, edge_labelled=False, vertex_list=list(G)) # allocated some data structures cdef bitset_t seen @@ -2074,7 +2134,8 @@ def wiener_index(G): for v in range(0 if G.is_directed() else (u + 1), n): s += distances[v] - free_short_digraph(sd) + if not isinstance(G, StaticSparseBackend): + free_short_digraph(sd) bitset_free(seen) if s == UINT64_MAX: @@ -2342,6 +2403,18 @@ def szeged_index(G, algorithm=None): Traceback (most recent call last): ... ValueError: the 'low' algorithm cannot be used on digraphs + + Immutable graphs:: + + sage: G = graphs.RandomGNP(10, .3) + sage: G.add_edges(graphs.RandomTree(10).edges()) + sage: G._backend + + sage: H = Graph(G, immutable=True) + sage: H._backend + + sage: szeged_index(G) == szeged_index(H) + True """ if not G.is_connected(): raise ValueError("the Szeged index is defined for connected graphs only") @@ -2364,8 +2437,14 @@ def szeged_index(G, algorithm=None): if G.order() <= 1: return 0 + cdef StaticSparseCGraph cg cdef short_digraph sd - init_short_digraph(sd, G, edge_labelled=False, vertex_list=list(G)) + if isinstance(G, StaticSparseBackend): + cg = G._cg + sd = cg.g + else: + init_short_digraph(sd, G, edge_labelled=False, vertex_list=list(G)) + cdef uint64_t s if algorithm == "low": @@ -2373,7 +2452,8 @@ def szeged_index(G, algorithm=None): else: s = c_szeged_index_high_memory(sd) - free_short_digraph(sd) + if not isinstance(G, StaticSparseBackend): + free_short_digraph(sd) return s @@ -2441,13 +2521,31 @@ def distances_distribution(G): sage: D = digraphs.DeBruijn(2,3) # needs sage.combinat sage: D.distances_distribution() # needs sage.combinat {1: 1/4, 2: 11/28, 3: 5/14} + + TESTS: + + Immutable graphs:: + + sage: G = graphs.RandomGNP(10, .5) + sage: G._backend + + sage: H = Graph(G, immutable=True) + sage: H._backend + + sage: G.distances_distribution() == H.distances_distribution() + True """ cdef size_t n = G.order() if n <= 1: return {} + cdef StaticSparseCGraph cg cdef short_digraph sd - init_short_digraph(sd, G, edge_labelled=False, vertex_list=list(G)) + if isinstance(G, StaticSparseBackend): + cg = G._cg + sd = cg.g + else: + init_short_digraph(sd, G, edge_labelled=False, vertex_list=list(G)) cdef MemoryAllocator mem = MemoryAllocator() cdef uint32_t * distances = mem.allocarray(2 * n, sizeof(uint32_t)) @@ -2470,7 +2568,8 @@ def distances_distribution(G): for v in range(n): count[distances[v]] += 1 - free_short_digraph(sd) + if not isinstance(G, StaticSparseBackend): + free_short_digraph(sd) bitset_free(seen) from sage.rings.infinity import Infinity @@ -2554,6 +2653,17 @@ def antipodal_graph(G): Antipodal graph of Graph on 1 vertex: Looped graph on 1 vertex sage: antipodal_graph(Graph(2)).edges(sort=True, labels=False) [(0, 1)] + + Immutable graphs:: + + sage: G = graphs.RandomGNP(10, .5) + sage: G._backend + + sage: H = Graph(G, immutable=True) + sage: H._backend + + sage: antipodal_graph(G).is_isomorphic(antipodal_graph(H)) + True """ if not G: raise ValueError("the antipodal graph of the empty graph is not defined") @@ -2577,9 +2687,16 @@ def antipodal_graph(G): A.add_edges(itertools.product(c1, c2)) return A - cdef list int_to_vertex = list(G) + cdef list int_to_vertex + cdef StaticSparseCGraph cg cdef short_digraph sd - init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_vertex) + if isinstance(G, StaticSparseBackend): + cg = G._cg + sd = cg.g + int_to_vertex = cg._vertex_to_labels + else: + int_to_vertex = list(G) + init_short_digraph(sd, G, edge_labelled=False, vertex_list=int_to_vertex) cdef MemoryAllocator mem = MemoryAllocator() cdef uint32_t * distances = mem.allocarray(2 * n, sizeof(uint32_t)) @@ -2607,7 +2724,8 @@ def antipodal_graph(G): A.add_edge(u, int_to_vertex[vj]) j -= 1 - free_short_digraph(sd) + if not isinstance(G, StaticSparseBackend): + free_short_digraph(sd) bitset_free(seen) A.add_vertices(G) diff --git a/src/sage/graphs/generators/basic.py b/src/sage/graphs/generators/basic.py index aef8ea49935..960c95c4f57 100644 --- a/src/sage/graphs/generators/basic.py +++ b/src/sage/graphs/generators/basic.py @@ -20,13 +20,18 @@ from math import sin, cos, pi -def BullGraph(): +def BullGraph(immutable=False): r""" Return a bull graph with 5 nodes. A bull graph is named for its shape. It's a triangle with horns. See the :wikipedia:`Bull_graph` for more information. + INPUT: + + - ``immutable`` -- boolean (default: ``False``); whether to return an + immutable or a mutable graph + PLOTTING: Upon construction, the position dictionary is filled to override the @@ -84,13 +89,21 @@ def BullGraph(): True sage: x * (x^2 - x - 3) * (x^2 + x - 1) == charpoly True + + TESTS: + + Check the behavior of parameter ``immutable``:: + + sage: graphs.BullGraph(immutable=True).is_immutable() + True """ edge_list = [(0, 1), (0, 2), (1, 2), (1, 3), (2, 4)] pos_dict = {0: (0, 0), 1: (-1, 1), 2: (1, 1), 3: (-2, 2), 4: (2, 2)} - return Graph(edge_list, pos=pos_dict, name="Bull graph") + return Graph([range(5), edge_list], format='vertices_and_edges', + immutable=immutable, pos=pos_dict, name="Bull graph") -def ButterflyGraph(): +def ButterflyGraph(immutable=False): r""" Return the butterfly graph. @@ -103,6 +116,11 @@ def ButterflyGraph(): - :meth:`~sage.graphs.graph_generators.GraphGenerators.FriendshipGraph` + INPUT: + + - ``immutable`` -- boolean (default: ``False``); whether to return an + immutable or a mutable graph + EXAMPLES: The butterfly graph is a planar graph on 5 vertices and having 6 edges:: @@ -132,6 +150,13 @@ def ButterflyGraph(): True sage: G.chromatic_number() 3 + + TESTS: + + Check the behavior of parameter ``immutable``:: + + sage: graphs.ButterflyGraph(immutable=True).is_immutable() + True """ edge_dict = { 0: [3, 4], @@ -144,10 +169,11 @@ def ButterflyGraph(): 2: [1, -1], 3: [-1, -1], 4: [0, 0]} - return Graph(edge_dict, pos=pos_dict, name="Butterfly graph") + return Graph(edge_dict, format='dict_of_lists', + immutable=immutable, pos=pos_dict, name="Butterfly graph") -def CircularLadderGraph(n): +def CircularLadderGraph(n, immutable=False): r""" Return a circular ladder graph with `2 * n` nodes. @@ -166,6 +192,13 @@ def CircularLadderGraph(n): that all edges are visible (otherwise the 4 vertices of the graph would be placed on a single line). + INPUT: + + - ``n`` -- nonnegative integer + + - ``immutable`` -- boolean (default: ``False``); whether to return an + immutable or a mutable graph + EXAMPLES: Construct and show a circular ladder graph with 26 nodes:: @@ -187,20 +220,29 @@ def CircularLadderGraph(n): ....: j.append(n) sage: G = graphics_array(j) # needs sage.plot sage: G.show() # long time # needs sage.plot + + TESTS:: + + sage: G = graphs.CircularLadderGraph(4, immutable=True) + sage: G.is_immutable() + True """ - G = Graph(2 * n, name="Circular Ladder graph") + from itertools import chain + edges_1 = zip(range(n), chain(range(1, n), (0,))) + edges_2 = zip(range(n, 2 * n), chain(range(n + 1, 2 * n), (n,))) + edges_3 = ((i, i + n) for i in range(n)) + G = Graph([range(2 * n), chain(edges_1, edges_2, edges_3)], + format='vertices_and_edges', immutable=immutable, + name="Circular Ladder graph") G._circle_embedding(list(range(n)), radius=1, angle=pi/2) if n == 2: G._circle_embedding(list(range(4)), radius=1, angle=pi/2 + pi/8) else: G._circle_embedding(list(range(n, 2*n)), radius=2, angle=pi/2) - G.add_cycle(list(range(n))) - G.add_cycle(list(range(n, 2 * n))) - G.add_edges((i, i + n) for i in range(n)) return G -def ClawGraph(): +def ClawGraph(immutable=False): """ Return a claw graph. @@ -209,6 +251,11 @@ def ClawGraph(): PLOTTING: See :meth:`CompleteBipartiteGraph`. + INPUT: + + - ``immutable`` -- boolean (default: ``False``); whether to return an + immutable or a mutable graph + EXAMPLES: Show a Claw graph:: @@ -220,19 +267,34 @@ def ClawGraph(): sage: G = graphs.ClawGraph() sage: G Claw graph: Graph on 4 vertices + + TESTS: + + Check the behavior of parameter ``immutable``:: + + sage: graphs.ClawGraph(immutable=True).is_immutable() + True """ edge_list = [(0, 1), (0, 2), (0, 3)] pos_dict = {0: (0, 1), 1: (-1, 0), 2: (0, 0), 3: (1, 0)} - return Graph(edge_list, pos=pos_dict, name="Claw graph") + return Graph([range(4), edge_list], format='vertices_and_edges', + immutable=immutable, pos=pos_dict, name="Claw graph") -def CycleGraph(n): +def CycleGraph(n, immutable=False): r""" Return a cycle graph with `n` nodes. A cycle graph is a basic structure which is also typically called an `n`-gon. + INPUT: + + - ``n`` -- nonnegative integer; the number of vertices of the cycle graph + + - ``immutable`` -- boolean (default: ``False``); whether to return an + immutable or a mutable graph + PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, each cycle graph will be displayed with the first (0) node at the top, with the rest following in a @@ -299,26 +361,40 @@ def CycleGraph(n): Traceback (most recent call last): ... ValueError: parameter n must be a positive integer + + Check the behavior of parameter ``immutable``:: + + sage: graphs.CycleGraph(4, immutable=True).is_immutable() + True """ if n < 0: raise ValueError("parameter n must be a positive integer") - G = Graph(n, name="Cycle graph") + from itertools import chain + edges = zip(range(n), chain(range(1, n), (0,))) if n > 1 else [] + G = Graph([range(n), edges], format='vertices_and_edges', + immutable=immutable, name="Cycle graph") if n == 1: G.set_pos({0: (0, 0)}) else: G._circle_embedding(list(range(n)), angle=pi/2) - G.add_cycle(list(range(n))) return G -def CompleteGraph(n): +def CompleteGraph(n, immutable=False): r""" Return a complete graph on `n` nodes. A Complete Graph is a graph in which all nodes are connected to all other nodes. + INPUT: + + - ``n`` -- nonnegative integer; the number of vertices of the complete graph + + - ``immutable`` -- boolean (default: ``False``); whether to return an + immutable or a mutable graph + PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, each complete graph will be displayed with the first (0) node at the top, with @@ -392,17 +468,26 @@ def CompleteGraph(n): sage: posdict23 = graphs.CompleteGraph(23) sage: spring23.show() # long time # needs sage.plot sage: posdict23.show() # long time # needs sage.plot + + TESTS: + + Check the behavior of parameter ``immutable``:: + + sage: graphs.CompleteGraph(4, immutable=True).is_immutable() + True """ - G = Graph(n, name="Complete graph") + from itertools import combinations + G = Graph([range(n), combinations(range(n), 2)], + format='vertices_and_edges', immutable=immutable, + name="Complete graph") if n == 1: G.set_pos({0: (0, 0)}) else: G._circle_embedding(list(range(n)), angle=pi/2) - G.add_edges((i, j) for i in range(n) for j in range(i + 1, n)) return G -def CorrelationGraph(seqs, alpha, include_anticorrelation): +def CorrelationGraph(seqs, alpha, include_anticorrelation, immutable=False): r""" Return a correlation graph with a node per sequence in ``seqs``. @@ -422,6 +507,9 @@ def CorrelationGraph(seqs, alpha, include_anticorrelation): - ``include_anticorrelation`` -- boolean; whether to add edges between nodes with correlation coefficient less than ``-alpha`` or not + - ``immutable`` -- boolean (default: ``False``); whether to return an + immutable or a mutable graph + EXAMPLES:: sage: # needs numpy @@ -436,6 +524,17 @@ def CorrelationGraph(seqs, alpha, include_anticorrelation): [(0, 0, None), (0, 1, None), (1, 1, None), (2, 2, None)] sage: CG3.edges(sort=False) [(0, 0, None), (0, 1, None), (0, 2, None), (1, 1, None), (1, 2, None), (2, 2, None)] + + TESTS: + + Check the behavior of parameter ``immutable``:: + + sage: # needs numpy + sage: from sage.graphs.generators.basic import CorrelationGraph + sage: CorrelationGraph(data, 0.9, False, immutable=True).is_immutable() + True + sage: CorrelationGraph(data, 0.9, True, immutable=True).is_immutable() + True """ from numpy import corrcoef from sage.matrix.constructor import Matrix @@ -452,10 +551,11 @@ def CorrelationGraph(seqs, alpha, include_anticorrelation): adjacency_matrix = Matrix(boolean_adjacency_matrix.astype(int)) # call graph constructor - return Graph(adjacency_matrix, format='adjacency_matrix', name="Correlation Graph") + return Graph(adjacency_matrix, format='adjacency_matrix', + immutable=immutable, name="Correlation Graph") -def CompleteBipartiteGraph(p, q, set_position=True): +def CompleteBipartiteGraph(p, q, set_position=True, immutable=False, name=None): r""" Return a Complete Bipartite Graph on `p + q` vertices. @@ -471,6 +571,12 @@ def CompleteBipartiteGraph(p, q, set_position=True): assign positions to the vertices so that the set of cardinality `p` is on the line `y=1` and the set of cardinality `q` is on the line `y=0`. + - ``immutable`` -- boolean (default: ``False``); whether to return an + immutable or a mutable graph + + - ``name`` -- string (default: ``None``); used as the name of the returned + graph when set + PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, each complete bipartite graph will be displayed with the first `p` nodes on the top row (at `y=1`) from @@ -566,12 +672,24 @@ def CompleteBipartiteGraph(p, q, set_position=True): Traceback (most recent call last): ... ValueError: the arguments p(=1) and q(=-1) must be positive integers + + Check the behavior of parameter ``immutable``:: + + sage: graphs.CompleteBipartiteGraph(1, 2, immutable=True).is_immutable() + True + + Check the behavior of parameter ``name``:: + + sage: graphs.CompleteBipartiteGraph(1, 2, name='foo') + foo: Graph on 3 vertices """ if p < 0 or q < 0: raise ValueError('the arguments p(={}) and q(={}) must be positive integers'.format(p, q)) - G = Graph(p + q, name="Complete bipartite graph of order {}+{}".format(p, q)) - G.add_edges((i, j) for i in range(p) for j in range(p, p + q)) + name = f"Complete bipartite graph of order {p}+{q}" if name is None else name + edges = ((i, j) for i in range(p) for j in range(p, p + q)) + G = Graph([range(p + q), edges], format='vertices_and_edges', + immutable=immutable, name=name) # We now assign positions to vertices: # - vertices 0,..,p-1 are placed on the line (0, 1) to (max(p, q), 1) @@ -585,7 +703,7 @@ def CompleteBipartiteGraph(p, q, set_position=True): return G -def CompleteMultipartiteGraph(L): +def CompleteMultipartiteGraph(L, immutable=False): r""" Return a complete multipartite graph. @@ -593,6 +711,9 @@ def CompleteMultipartiteGraph(L): - ``L`` -- list of integers; the respective sizes of the components + - ``immutable`` -- boolean (default: ``False``); whether to return an + immutable or a mutable graph + PLOTTING: Produce a layout of the vertices so that vertices in the same vertex set are adjacent and clearly separated from vertices in other vertex sets. @@ -616,53 +737,74 @@ def CompleteMultipartiteGraph(L): sage: g.chromatic_number() 3 + + TESTS: + + Prevent negative dimensions:: + + sage: graphs.CompleteMultipartiteGraph([1, -1, 2]) + Traceback (most recent call last): + ... + ValueError: the sizes of the components must be positive integers + + Check the bahavior of parameter ``immutable``:: + + sage: graphs.CompleteMultipartiteGraph([1], immutable=True).is_immutable() + True + sage: graphs.CompleteMultipartiteGraph([1, 2], immutable=True).is_immutable() + True + sage: graphs.CompleteMultipartiteGraph([1, 2, 3], immutable=True).is_immutable() + True """ + if any(p < 0 for p in L): + raise ValueError("the sizes of the components must be positive integers") + r = len(L) # getting the number of partitions name = "Multipartite Graph with set sizes {}".format(L) if not r: - g = Graph() - elif r == 1: - g = Graph(L[0]) + return Graph(name=name, immutable=immutable) + if r == 1: + g = Graph(L[0], immutable=immutable, name=name) g._line_embedding(range(L[0]), first=(0, 0), last=(L[0], 0)) - elif r == 2: - g = CompleteBipartiteGraph(L[0], L[1]) - g.name(name) - else: - # This position code gives bad results on bipartite or isolated graphs - points = [(cos(2 * pi * i / r), sin(2 * pi * i / r)) for i in range(r)] - slopes = [(points[(i + 1) % r][0] - points[i % r][0], - points[(i + 1) % r][1] - points[i % r][1]) for i in range(r)] - - counter = 0 - positions = {} - for i in range(r): - vertex_set_size = L[i] + 1 - for j in range(1, vertex_set_size): - x = points[i][0] + slopes[i][0] * j / vertex_set_size - y = points[i][1] + slopes[i][1] * j / vertex_set_size - positions[counter] = (x, y) - counter += 1 - - g = Graph(sum(L)) - s = 0 - for i in L: - g.add_clique(range(s, s + i)) - s += i - - g = g.complement() - g.set_pos(positions) + return g + if r == 2: + return CompleteBipartiteGraph(L[0], L[1], immutable=immutable, name=name) + + # This position code gives bad results on bipartite or isolated graphs + points = [(cos(2 * pi * i / r), sin(2 * pi * i / r)) for i in range(r)] + slopes = [(points[(i + 1) % r][0] - points[i % r][0], + points[(i + 1) % r][1] - points[i % r][1]) for i in range(r)] + + counter = 0 + parts = [] + positions = {} + for i, size in enumerate(L): + parts.append(list(range(counter, counter + size))) + vertex_set_size = size + 1 + for j in range(1, vertex_set_size): + x = points[i][0] + slopes[i][0] * j / vertex_set_size + y = points[i][1] + slopes[i][1] * j / vertex_set_size + positions[counter] = (x, y) + counter += 1 - g.name(name) - return g + from itertools import combinations + edges = ((a, b) for A, B in combinations(parts, 2) for a in A for b in B) + return Graph([range(counter), edges], format='vertices_and_edges', + immutable=immutable, pos=positions, name=name) -def DiamondGraph(): +def DiamondGraph(immutable=False): """ Return a diamond graph with 4 nodes. A diamond graph is a square with one pair of diagonal nodes connected. + INPUT: + + - ``immutable`` -- boolean (default: ``False``); whether to return an + immutable or a mutable graph + PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the diamond graph is drawn as a diamond, with the first node on top, second on the left, third on the right, @@ -674,18 +816,31 @@ def DiamondGraph(): sage: g = graphs.DiamondGraph() sage: g.show() # long time # needs sage.plot + + TESTS: + + Check the behavior of parameter ``immutable``:: + + sage: graphs.DiamondGraph(immutable=True).is_immutable() + True """ pos_dict = {0: (0, 1), 1: (-1, 0), 2: (1, 0), 3: (0, -1)} edges = [(0, 1), (0, 2), (1, 2), (1, 3), (2, 3)] - return Graph(edges, pos=pos_dict, name="Diamond Graph") + return Graph([range(4), edges], format='vertices_and_edges', + immutable=immutable, pos=pos_dict, name="Diamond Graph") -def GemGraph(): +def GemGraph(immutable=False): """ Return a gem graph with 5 nodes. A gem graph is a fan graph (4,1). + INPUT: + + - ``immutable`` -- boolean (default: ``False``); whether to return an + immutable or a mutable graph + PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the gem graph is drawn as a gem, with the sharp part on the bottom. @@ -696,18 +851,31 @@ def GemGraph(): sage: g = graphs.GemGraph() sage: g.show() # long time # needs sage.plot + + TESTS: + + Check the behavior of parameter ``immutable``:: + + sage: graphs.GemGraph(immutable=True).is_immutable() + True """ pos_dict = {0: (0.5, 0), 1: (0, 0.75), 2: (0.25, 1), 3: (0.75, 1), 4: (1, 0.75)} edges = [(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (2, 3), (3, 4)] - return Graph(edges, pos=pos_dict, name="Gem Graph") + return Graph([range(5), edges], format='vertices_and_edges', + immutable=immutable, pos=pos_dict, name="Gem Graph") -def ForkGraph(): +def ForkGraph(immutable=False): """ Return a fork graph with 5 nodes. A fork graph, sometimes also called chair graph, is 5 vertex tree. + INPUT: + + - ``immutable`` -- boolean (default: ``False``); whether to return an + immutable or a mutable graph + PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the fork graph is drawn as a fork, with the sharp part on the bottom. @@ -718,16 +886,29 @@ def ForkGraph(): sage: g = graphs.ForkGraph() sage: g.show() # long time # needs sage.plot + + TESTS: + + Check the behavior of parameter ``immutable``:: + + sage: graphs.ForkGraph(immutable=True).is_immutable() + True """ pos_dict = {0: (0, 0), 1: (1, 0), 2: (0, 1), 3: (1, 1), 4: (0, 2)} edges = [(0, 2), (2, 3), (3, 1), (2, 4)] - return Graph(edges, pos=pos_dict, name="Fork Graph") + return Graph([range(5), edges], format='vertices_and_edges', + immutable=immutable, pos=pos_dict, name="Fork Graph") -def DartGraph(): +def DartGraph(immutable=False): """ Return a dart graph with 5 nodes. + INPUT: + + - ``immutable`` -- boolean (default: ``False``); whether to return an + immutable or a mutable graph + PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the dart graph is drawn as a dart, with the sharp part on the bottom. @@ -738,19 +919,32 @@ def DartGraph(): sage: g = graphs.DartGraph() sage: g.show() # long time # needs sage.plot + + TESTS: + + Check the behavior of parameter ``immutable``:: + + sage: graphs.DartGraph(immutable=True).is_immutable() + True """ pos_dict = {0: (0, 1), 1: (-1, 0), 2: (1, 0), 3: (0, -1), 4: (0, 0)} edges = [(0, 1), (0, 2), (1, 4), (2, 4), (0, 4), (3, 4)] - return Graph(edges, pos=pos_dict, name="Dart Graph") + return Graph([range(5), edges], format='vertices_and_edges', + immutable=immutable, pos=pos_dict, name="Dart Graph") -def EmptyGraph(): +def EmptyGraph(immutable=False): """ Return an empty graph (0 nodes and 0 edges). This is useful for constructing graphs by adding edges and vertices individually or in a loop. + INPUT: + + - ``immutable`` -- boolean (default: ``False``); whether to return an + immutable or a mutable graph + PLOTTING: When plotting, this graph will use the default spring-layout algorithm, unless a position dictionary is specified. @@ -779,11 +973,18 @@ def EmptyGraph(): sage: for i in range(1, 4): ....: empty2.add_edge(4,i) # add edges {[1:4],[2:4],[3:4]} sage: empty2.show() # long time # needs sage.plot + + TESTS: + + Check the behavior of parameter ``immutable``:: + + sage: graphs.EmptyGraph(immutable=True).is_immutable() + True """ - return Graph(sparse=True) + return Graph(sparse=True, immutable=immutable) -def ToroidalGrid2dGraph(p, q): +def ToroidalGrid2dGraph(p, q, immutable=False): r""" Return a toroidal 2-dimensional grid graph with `p \times q` nodes (`p` rows and `q` columns). @@ -792,6 +993,13 @@ def ToroidalGrid2dGraph(p, q): grid graph with identical parameters to which are added the edges `((i, 0), (i, q - 1))` and `((0, i), (p - 1, i))`. + INPUT: + + - ``p, q`` -- nonnegative integers; the sides of the toroidal grid + + - ``immutable`` -- boolean (default: ``False``); whether to return an + immutable or a mutable graph + EXAMPLES: The toroidal 2-dimensional grid is a regular graph, while the usual @@ -805,14 +1013,21 @@ def ToroidalGrid2dGraph(p, q): False sage: tgrid.is_regular() True + + TESTS: + + Check the behavior of parameter ``immutable``:: + + sage: graphs.ToroidalGrid2dGraph(2, 3, immutable=True).is_immutable() + True """ - g = Grid2dGraph(p, q, set_positions=True) + name = f"Toroidal 2D Grid Graph with parameters {p},{q}" + g = Grid2dGraph(p, q, set_positions=True, immutable=False) + g.name(name) g.add_edges([((i, 0), (i, q - 1)) for i in range(p)]) g.add_edges([((0, i), (p - 1, i)) for i in range(q)]) - g.name("Toroidal 2D Grid Graph with parameters {},{}".format(p, q)) - pos = g._pos p += 0. q += 0. @@ -824,10 +1039,12 @@ def ToroidalGrid2dGraph(p, q): y += 0.25 * (1.0 + v * (v - q + 1) / vf) pos[u, v] = (x, y) + if immutable: + return Graph(g, immutable=True, pos=g.get_pos(), name=name) return g -def Toroidal6RegularGrid2dGraph(p, q): +def Toroidal6RegularGrid2dGraph(p, q, immutable=False): r""" Return a toroidal 6-regular grid. @@ -842,6 +1059,9 @@ def Toroidal6RegularGrid2dGraph(p, q): - ``p``, ``q`` -- integers + - ``immutable`` -- boolean (default: ``False``); whether to return an + immutable or a mutable graph + EXAMPLES: The toroidal 6-regular grid on `25` elements:: @@ -870,19 +1090,27 @@ def Toroidal6RegularGrid2dGraph(p, q): Traceback (most recent call last): ... ValueError: parameters p and q must be integers larger than 3 + + Check the behavior of parameter ``immutable``:: + + sage: graphs.Toroidal6RegularGrid2dGraph(4, 4, immutable=True).is_immutable() + True """ if p <= 3 or q <= 3: raise ValueError("parameters p and q must be integers larger than 3") - g = ToroidalGrid2dGraph(p, q) + g = ToroidalGrid2dGraph(p, q, immutable=False) for u, v in g: g.add_edge((u, v), ((u + 1) % p, (v + 1) % q)) - g.name("Toroidal Hexagonal Grid graph on {}x{} elements".format(p, q)) + name = f"Toroidal Hexagonal Grid graph on {p}x{q} elements" + if immutable: + return Graph(g, immutable=True, pos=g.get_pos(), name=name) + g.name(name) return g -def Grid2dGraph(p, q, set_positions=True): +def Grid2dGraph(p, q, set_positions=True, immutable=False, name=None): r""" Return a `2`-dimensional grid graph with `p \times q` nodes (`p` rows and `q` columns). @@ -898,6 +1126,12 @@ def Grid2dGraph(p, q, set_positions=True): - ``set_positions`` -- boolean (default: ``True``); whether to set the position of the nodes + - ``immutable`` -- boolean (default: ``False``); whether to return an + immutable or a mutable graph + + - ``name`` -- string (default: ``None``); used as the name of the returned + graph when set + PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, nodes are labelled in (row, column) pairs with `(0, 0)` in the top left corner. Edges will always be @@ -929,26 +1163,33 @@ def Grid2dGraph(p, q, set_positions=True): sage: g = graphs.Grid2dGraph(5,7) sage: g.name() '2D Grid Graph for [5, 7]' + + Check the behavior of parameter ``ìmmutable``:: + + sage: graphs.Grid2dGraph(2, 3, immutable=True).is_immutable() + True + + Check the behavior of parameter ``name``:: + + sage: graphs.Grid2dGraph(2, 3, name='foo') + foo: Graph on 6 vertices """ if p <= 0 or q <= 0: raise ValueError("parameters p and q must be positive integers") - pos_dict = {} + vertices = ((i, j) for i in range(p) for j in range(q)) + from itertools import chain + edges = chain((((i, j), (i + 1, j)) for i in range(p - 1) for j in range(q)), + (((i, j), (i, j + 1)) for i in range(p) for j in range(q - 1))) + pos_dict = None if set_positions: - for i in range(p): - y = -i - for j in range(q): - x = j - pos_dict[i, j] = (x, y) + pos_dict = {(i, j): (j, -i) for i in range(p) for j in range(q)} + return Graph([vertices, edges], format='vertices_and_edges', + immutable=immutable, pos=pos_dict, + name=f"2D Grid Graph for [{p}, {q}]" if name is None else name) - G = Graph(pos=pos_dict, name="2D Grid Graph for [{}, {}]".format(p, q)) - G.add_vertices((i, j) for i in range(p) for j in range(q)) - G.add_edges(((i, j), (i + 1, j)) for i in range(p - 1) for j in range(q)) - G.add_edges(((i, j), (i, j + 1)) for i in range(p) for j in range(q - 1)) - return G - -def GridGraph(dim_list): +def GridGraph(dim_list, immutable=False): r""" Return an `n`-dimensional grid graph. @@ -957,6 +1198,9 @@ def GridGraph(dim_list): - ``dim_list`` -- list of integers representing the number of nodes to extend in each dimension + - ``immutable`` -- boolean (default: ``False``); whether to return an + immutable or a mutable graph + PLOTTING: When plotting, this graph will use the default spring-layout algorithm, unless a position dictionary is specified. @@ -1028,36 +1272,52 @@ def GridGraph(dim_list): Traceback (most recent call last): ... ValueError: all dimensions must be positive integers + + Check the behavior of parameter ``ìmmutable``:: + + sage: graphs.GridGraph([], immutable=True).is_immutable() + True + sage: graphs.GridGraph([2], immutable=True).is_immutable() + True + sage: graphs.GridGraph([2, 2], immutable=True).is_immutable() + True + sage: graphs.GridGraph([2, 2, 2], immutable=True).is_immutable() + True """ dim = [int(a) for a in dim_list] if any(a <= 0 for a in dim): raise ValueError("all dimensions must be positive integers") - g = Graph() + name = "Grid Graph for {}".format(dim) n_dim = len(dim) + if not n_dim: + return Graph(name=name, immutable=immutable) if n_dim == 1: # Vertices are labeled from 0 to dim[0]-1 - g = PathGraph(dim[0]) - elif n_dim == 2: + return PathGraph(dim[0], immutable=immutable, name=name) + if n_dim == 2: # We use the Grid2dGraph generator to also get the positions - g = Grid2dGraph(*dim) - elif n_dim > 2: - # Vertices are tuples of dimension n_dim, and the graph contains at - # least vertex (0, 0, ..., 0) - g.add_vertex(tuple([0] * n_dim)) - import itertools - for u in itertools.product(*[range(d) for d in dim]): + return Grid2dGraph(*dim, immutable=immutable, name=name) + + # Now, n_dim > 2 and we don't set positions + # Vertices are tuples of dimension n_dim, and the graph contains at + # least vertex (0, 0, ..., 0) + V = [tuple([0] * n_dim)] + + def edges(): + from itertools import product + for u in product(*[range(d) for d in dim]): for i in range(n_dim): if u[i] + 1 < dim[i]: v = list(u) v[i] = u[i] + 1 - g.add_edge(u, tuple(v)) + yield (u, tuple(v)) - g.name("Grid Graph for {}".format(dim)) - return g + return Graph([V, edges()], format='vertices_and_edges', + immutable=immutable, name=name) -def HouseGraph(): +def HouseGraph(immutable=False): """ Return a house graph with 5 nodes. @@ -1072,19 +1332,32 @@ def HouseGraph(): connecting the roof to the wall. The fifth node is the top of the roof, connected only to the third and fourth. + INPUT: + + - ``immutable`` -- boolean (default: ``False``); whether to return an + immutable or a mutable graph + EXAMPLES: Construct and show a house graph:: sage: g = graphs.HouseGraph() sage: g.show() # long time # needs sage.plot + + TESTS: + + Check the behavior of parameter ``immutable``:: + + sage: graphs.HouseGraph(immutable=True).is_immutable() + True """ pos_dict = {0: (-1, 0), 1: (1, 0), 2: (-1, 1), 3: (1, 1), 4: (0, 2)} edges = [(0, 1), (0, 2), (1, 3), (2, 3), (2, 4), (3, 4)] - return Graph(edges, pos=pos_dict, name="House Graph") + return Graph([range(5), edges], format='vertices_and_edges', + immutable=immutable, pos=pos_dict, name="House Graph") -def HouseXGraph(): +def HouseXGraph(immutable=False): """ Return a house X graph with 5 nodes. @@ -1100,19 +1373,32 @@ def HouseXGraph(): connecting the roof to the wall. The fifth node is the top of the roof, connected only to the third and fourth. + INPUT: + + - ``immutable`` -- boolean (default: ``False``); whether to return an + immutable or a mutable graph + EXAMPLES: Construct and show a house X graph:: sage: g = graphs.HouseXGraph() sage: g.show() # long time # needs sage.plot + + TESTS: + + Check the behavior of parameter ``immutable``:: + + sage: graphs.HouseXGraph(immutable=True).is_immutable() + True """ pos_dict = {0: (-1, 0), 1: (1, 0), 2: (-1, 1), 3: (1, 1), 4: (0, 2)} edges = [(0, 1), (0, 2), (0, 3), (1, 2), (1, 3), (2, 3), (2, 4), (3, 4)] - return Graph(edges, pos=pos_dict, name="House Graph") + return Graph([range(5), edges], format='vertices_and_edges', + immutable=immutable, pos=pos_dict, name="House Graph") -def LadderGraph(n): +def LadderGraph(n, immutable=False): r""" Return a ladder graph with `2 * n` nodes. @@ -1124,6 +1410,13 @@ def LadderGraph(n): displayed horizontally, with the first n nodes displayed left to right on the top horizontal line. + INPUT: + + - ``n`` -- a nonnegative integer; number of nodes is `2n` + + - ``immutable`` -- boolean (default: ``False``); whether to return an + immutable or a mutable graph + EXAMPLES: Construct and show a ladder graph with 14 nodes:: @@ -1146,21 +1439,28 @@ def LadderGraph(n): ....: j.append(n) sage: G = graphics_array(j) sage: G.show() # long time + + TESTS: + + Check the behavior of parameter ``immutable``:: + + sage: graphs.LadderGraph(4, immutable=True).is_immutable() + True """ - pos_dict = {} - for i in range(n): - pos_dict[i] = (i, 1) + pos_dict = {i: (i, 1) for i in range(n)} for i in range(n, 2 * n): x = i - n pos_dict[i] = (x, 0) - G = Graph(2 * n, pos=pos_dict, name="Ladder graph") - G.add_path(list(range(n))) - G.add_path(list(range(n, 2 * n))) - G.add_edges((i, i + n) for i in range(n)) - return G + from itertools import chain + edges_1 = zip(range(n), range(1, n)) + edges_2 = zip(range(n, 2 * n), range(n + 1, 2 * n)) + edges_3 = ((i, i + n) for i in range(n)) + return Graph([range(2 * n), chain(edges_1, edges_2, edges_3)], + format='vertices_and_edges', immutable=immutable, + pos=pos_dict, name="Ladder graph") -def MoebiusLadderGraph(n): +def MoebiusLadderGraph(n, immutable=False): r""" Return a Möbius ladder graph with `2n` nodes @@ -1184,6 +1484,9 @@ def MoebiusLadderGraph(n): - ``n`` -- a nonnegative integer; number of nodes is `2n` + - ``immutable`` -- boolean (default: ``False``); whether to return an + immutable or a mutable graph + OUTPUT: - ``G`` -- a Möbius ladder graph of order `2n`; note that a @@ -1221,6 +1524,11 @@ def MoebiusLadderGraph(n): ... ValueError: parameter n must be a nonnegative integer + Check the behavior of parameter ``immutable``:: + + sage: graphs.MoebiusLadderGraph(4, immutable=True).is_immutable() + True + REFERENCES: - :wikipedia:`Möbius_ladder` @@ -1237,14 +1545,17 @@ def MoebiusLadderGraph(n): if n < 0: raise ValueError("parameter n must be a nonnegative integer") - G = Graph(2 * n, name="Moebius ladder graph") + from itertools import chain + edges_1 = zip(range(2 * n), chain(range(1, 2 * n), (0,))) + edges_2 = ((i, i + n) for i in range(n)) + G = Graph([range(2 * n), chain(edges_1, edges_2)], + format='vertices_and_edges', immutable=immutable, + name="Moebius ladder graph") G._circle_embedding(list(range(2 * n)), angle=pi/2) - G.add_cycle(list(range(2 * n))) - G.add_edges((i, i + n) for i in range(n)) return G -def PathGraph(n, pos=None): +def PathGraph(n, pos=None, immutable=False, name=None): r""" Return a path graph with `n` nodes. @@ -1254,12 +1565,18 @@ def PathGraph(n, pos=None): INPUT: - - ``n`` -- number of nodes of the path graph + - ``n`` -- nonnegative integer; number of nodes of the path graph - ``pos`` -- string (default: ``None``); indicates the embedding to use between 'circle', 'line' or the default algorithm. See the plotting section below for more detail. + - ``immutable`` -- boolean (default: ``False``); whether to return an + immutable or a mutable graph + + - ``name`` -- string (default: ``None``); used as the name of the returned + graph when set + PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, the graph may be drawn in one of two ways: The 'line' argument will draw the graph in a horizontal line (left @@ -1271,23 +1588,19 @@ def PathGraph(n, pos=None): argument) the graph will be drawn as a 'circle' if `10 < n < 41` and as a 'line' for all other `n`. - EXAMPLES: Show default drawing by size: 'line': `n \leq 10` + EXAMPLES: - :: + Show default drawing by size: 'line': `n \leq 10`:: sage: p = graphs.PathGraph(10) sage: p.show() # long time # needs sage.plot - 'circle': `10 < n < 41` - - :: + 'circle': `10 < n < 41`:: sage: q = graphs.PathGraph(25) sage: q.show() # long time # needs sage.plot - 'line': `n \geq 41` - - :: + 'line': `n \geq 41`:: sage: r = graphs.PathGraph(55) sage: r.show() # long time # needs sage.plot @@ -1296,8 +1609,22 @@ def PathGraph(n, pos=None): sage: s = graphs.PathGraph(5,'circle') sage: s.show() # long time # needs sage.plot + + TESTS: + + Check the behavior of parameter ``immutable``:: + + sage: graphs.PathGraph(4, immutable=True).is_immutable() + True + + Check the behavior of parameter ``name``:: + + sage: graphs.PathGraph(4, name='foo') + foo: Graph on 4 vertices """ - G = Graph(n, name="Path graph") + edges = ((i, i + 1) for i in range(n - 1)) + G = Graph([range(n), edges], format='vertices_and_edges', + immutable=immutable, name="Path graph" if name is None else name) pos_dict = {} @@ -1347,17 +1674,23 @@ def PathGraph(n, pos=None): counter += 1 G.set_pos(pos_dict) - G.add_edges((i, i + 1) for i in range(n - 1)) return G -def StarGraph(n): +def StarGraph(n, immutable=False): r""" Return a star graph with `n + 1` nodes. A Star graph is a basic structure where one node is connected to all other nodes. + INPUT: + + - ``n`` -- a nonnegative integer; number of nodes is `n + 1` + + - ``immutable`` -- boolean (default: ``False``); whether to return an + immutable or a mutable graph + PLOTTING: Upon construction, the position dictionary is filled to override the spring-layout algorithm. By convention, each star graph will be displayed with the first (0) node in the center, the second node (1) at the @@ -1420,8 +1753,16 @@ def StarGraph(n): ....: j.append(n) sage: G = graphics_array(j) sage: G.show() # long time + + TESTS: + + Check the behavior of parameter ``immutable``:: + + sage: graphs.StarGraph(4, immutable=True).is_immutable() + True """ - G = Graph({0: list(range(1, n + 1))}, name="Star graph", format='dict_of_lists') + G = Graph({0: list(range(1, n + 1))}, format='dict_of_lists', + immutable=immutable, name="Star graph") G.set_pos({0: (0, 0)}) G._circle_embedding(list(range(1, n + 1)), angle=pi/2) return G diff --git a/src/sage/graphs/generic_graph.py b/src/sage/graphs/generic_graph.py index bb804bcfd1b..acbf386833f 100644 --- a/src/sage/graphs/generic_graph.py +++ b/src/sage/graphs/generic_graph.py @@ -763,20 +763,40 @@ def __mul__(self, n): sage: G = graphs.CycleGraph(3) sage: H = G * 3; H - Cycle graph disjoint_union Cycle graph disjoint_union Cycle graph: Graph on 9 vertices + Disjoint union of 3 copies of Cycle graph: Graph on 9 vertices sage: H.vertices(sort=True) [0, 1, 2, 3, 4, 5, 6, 7, 8] sage: H = G * 1; H Cycle graph: Graph on 3 vertices + + TESTS:: + + sage: Graph(1) * -1 + Traceback (most recent call last): + ... + TypeError: multiplication of a graph and a nonpositive integer is not defined + sage: Graph(1) * 2.5 + Traceback (most recent call last): + ... + TypeError: multiplication of a graph and something other than an integer is not defined """ if isinstance(n, (int, Integer)): if n < 1: raise TypeError('multiplication of a graph and a nonpositive integer is not defined') if n == 1: return copy(self) - return sum([self] * (n - 1), self) - else: - raise TypeError('multiplication of a graph and something other than an integer is not defined') + ns = self.order() + ntot = n * ns + vint = {u: i for i, u in enumerate(self)} + edges = ((i, j, l) for u, v, l in self.edge_iterator() + for i, j in zip(range(vint[u], ntot, ns), + range(vint[v], ntot, ns))) + return self.__class__([range(ntot), edges], format='vertices_and_edges', + loops=self.allows_loops(), + multiedges=self.allows_multiple_edges(), + immutable=self.is_immutable(), + name=f"Disjoint union of {n} copies of {str(self)}") + raise TypeError('multiplication of a graph and something other than an integer is not defined') def __ne__(self, other): """ @@ -809,7 +829,7 @@ def __rmul__(self, n): sage: G = graphs.CycleGraph(3) sage: H = int(3) * G; H - Cycle graph disjoint_union Cycle graph disjoint_union Cycle graph: Graph on 9 vertices + Disjoint union of 3 copies of Cycle graph: Graph on 9 vertices sage: H.vertices(sort=True) [0, 1, 2, 3, 4, 5, 6, 7, 8] """ diff --git a/src/sage/graphs/graph.py b/src/sage/graphs/graph.py index 7c640ee3c70..e60f444a089 100644 --- a/src/sage/graphs/graph.py +++ b/src/sage/graphs/graph.py @@ -5271,42 +5271,12 @@ def to_directed(self, data_structure=None, sparse=None): sage: D.get_vertices() {0: 'foo', 1: None, 2: None} """ - if sparse is not None: - if data_structure is not None: - raise ValueError("The 'sparse' argument is an alias for " - "'data_structure'. Please do not define both.") - data_structure = "sparse" if sparse else "dense" - - if data_structure is None: - from sage.graphs.base.dense_graph import DenseGraphBackend - from sage.graphs.base.sparse_graph import SparseGraphBackend - if isinstance(self._backend, DenseGraphBackend): - data_structure = "dense" - elif isinstance(self._backend, SparseGraphBackend): - data_structure = "sparse" - else: - data_structure = "static_sparse" - from sage.graphs.digraph import DiGraph - D = DiGraph(name=self.name(), - pos=self.get_pos(), - multiedges=self.allows_multiple_edges(), - loops=self.allows_loops(), - data_structure=(data_structure if data_structure != "static_sparse" - else "sparse")) # we need a mutable copy - - D.add_vertices(self.vertex_iterator()) - D.set_vertices(self.get_vertices()) - for u, v, l in self.edge_iterator(): - D.add_edge(u, v, l) - D.add_edge(v, u, l) - if hasattr(self, '_embedding'): - D._embedding = copy(self._embedding) - D._weighted = self._weighted - - if data_structure == "static_sparse": - D = D.copy(data_structure=data_structure) - - return D + from sage.graphs.orientations import _initialize_digraph + from itertools import chain + edges = chain(self.edge_iterator(), + ((v, u, l) for u, v, l in self.edge_iterator())) + return _initialize_digraph(self, edges, name=self.name(), + data_structure=data_structure, sparse=sparse) @doc_index("Basic methods") def to_undirected(self): @@ -5530,7 +5500,7 @@ def twograph(self): # Triangles K3 = Graph({1: [2, 3], 2: [3]}, format='dict_of_lists') for x, y, z in G.subgraph_search_iterator(K3, return_graphs=False): - if x < y and y < z: + if x < y < z: T.append([x, y, z]) # Triples with just one edge @@ -9300,6 +9270,7 @@ def bipartite_double(self, extended=False): from sage.graphs.orientations import eulerian_orientation from sage.graphs.connectivity import bridges, cleave, spqr_tree from sage.graphs.connectivity import is_triconnected + from sage.graphs.connectivity import minimal_separators from sage.graphs.comparability import is_comparability from sage.graphs.comparability import is_permutation geodetic_closure = LazyImport('sage.graphs.convexity_properties', 'geodetic_closure', at_startup=True) @@ -9360,6 +9331,7 @@ def bipartite_double(self, extended=False): "cleave" : "Connectivity, orientations, trees", "spqr_tree" : "Connectivity, orientations, trees", "is_triconnected" : "Connectivity, orientations, trees", + "minimal_separators" : "Connectivity, orientations, trees", "is_dominating" : "Domination", "is_redundant" : "Domination", "private_neighbors" : "Domination", diff --git a/src/sage/graphs/graph_database.py b/src/sage/graphs/graph_database.py index 8549b208af6..b0fa83f55d4 100644 --- a/src/sage/graphs/graph_database.py +++ b/src/sage/graphs/graph_database.py @@ -428,7 +428,7 @@ class located in :mod:`sage.databases.sql_db` to make the query SQLQuery.__init__(self, graph_db) # if display_cols is None: - # raise TypeError, 'Nonetype display_cols cannot retrieve data.' + # raise TypeError('Nonetype display_cols cannot retrieve data') master_join = {} diff --git a/src/sage/graphs/graph_generators.py b/src/sage/graphs/graph_generators.py index 812a16e8b4d..67fc724613d 100644 --- a/src/sage/graphs/graph_generators.py +++ b/src/sage/graphs/graph_generators.py @@ -486,9 +486,6 @@ def wrap_name(x): # https://www.gnu.org/licenses/ # **************************************************************************** -# import from Python standard library - -# import from Sage library from . import graph @@ -573,14 +570,19 @@ class GraphGenerators: - ``sparse`` -- (default: ``True``) whether to use a sparse or dense data structure. See the documentation of :class:`~sage.graphs.graph.Graph`. - - ``copy`` -- boolean; if set to ``True`` (default) - this method makes copies of the graphs before returning - them. If set to ``False`` the method returns the graph it - is working on. The second alternative is faster, but modifying - any of the graph instances returned by the method may break - the function's behaviour, as it is using these graphs to - compute the next ones: only use ``copy = False`` when - you stick to *reading* the graphs returned. + - ``copy`` -- boolean (default: ``True``); whether to return copies. If set + to ``False`` the method returns the graph it is working on. The second + alternative is faster, but modifying any of the graph instances returned + by the method may break the function's behaviour, as it is using these + graphs to compute the next ones: only use ``copy=False`` when you stick + to *reading* the graphs returned. + + This parameter is ignored when ``immutable`` is set to ``True``, in which + case returned graphs are always copies. + + - ``immutable`` -- boolean (default: ``False``); whether to return immutable + or mutable graphs. When set to ``True``, this parameter implies + ``copy=True``. EXAMPLES: @@ -736,6 +738,23 @@ class GraphGenerators: 2 2 + Returned graphs can be mutable or immutable:: + + sage: G = next(graphs(3, immutable=False)) + sage: G.delete_vertex(0) + sage: G = next(graphs(3, immutable=True)) + sage: G.delete_vertex(0) + Traceback (most recent call last): + ... + ValueError: graph is immutable; please change a copy instead (use function copy()) + sage: G = next(graphs(4, degree_sequence=[3]*4)) + sage: G.delete_vertex(0) + sage: G = next(graphs(4, degree_sequence=[3]*4, immutable=True)) + sage: G.delete_vertex(0) + Traceback (most recent call last): + ... + ValueError: graph is immutable; please change a copy instead (use function copy()) + REFERENCE: - Brendan D. McKay, Isomorph-Free Exhaustive generation. *Journal @@ -747,7 +766,8 @@ class GraphGenerators: ########################################################################### def __call__(self, vertices=None, property=None, augment='edges', size=None, - degree_sequence=None, loops=False, sparse=True, copy=True): + degree_sequence=None, loops=False, sparse=True, copy=True, + immutable=False): """ Access the generator of isomorphism class representatives. Iterates over distinct, exhaustive representatives. See the docstring @@ -795,18 +815,14 @@ def __call__(self, vertices=None, property=None, augment='edges', size=None, # Use nauty for the basic case, as it is much faster. if (vertices and property is None and size is None and degree_sequence is None and not loops and augment == 'edges' and - sparse and copy): - for g in graphs.nauty_geng(vertices): - yield g + sparse and (copy or immutable)): + yield from graphs.nauty_geng(vertices, immutable=immutable) return if property is None: def property(x): return True - from sage.graphs.graph import Graph - from copy import copy as copyfun - if degree_sequence is not None: if vertices is None: raise NotImplementedError @@ -840,19 +856,19 @@ def extra_property(x): if augment == 'vertices': if vertices is None: raise NotImplementedError - g = Graph(loops=loops, sparse=sparse) + g = graph.Graph(loops=loops, sparse=sparse) for gg in canaug_traverse_vert(g, [], vertices, property, loops=loops, sparse=sparse): if extra_property(gg): - yield copyfun(gg) if copy else gg + yield gg.copy(immutable=immutable) if copy or immutable else gg elif augment == 'edges': if vertices is None: from sage.rings.integer import Integer vertices = Integer(0) while True: for g in self(vertices, loops=loops, sparse=sparse): - yield copyfun(g) if copy else g + yield g.copy(immutable=immutable) if copy or immutable else g vertices += 1 - g = Graph(vertices, loops=loops, sparse=sparse) + g = graph.Graph(vertices, loops=loops, sparse=sparse) gens = [] for i in range(vertices - 1): gen = list(range(i)) @@ -862,11 +878,11 @@ def extra_property(x): gens.append(gen) for gg in canaug_traverse_edge(g, gens, property, loops=loops, sparse=sparse): if extra_property(gg): - yield copyfun(gg) if copy else gg + yield gg.copy(immutable=immutable) if copy or immutable else gg else: raise NotImplementedError - def nauty_geng(self, options='', debug=False): + def nauty_geng(self, options='', debug=False, immutable=False): r""" Return a generator which creates graphs from nauty's geng program. @@ -885,6 +901,9 @@ def nauty_geng(self, options='', debug=False): the program with some information on the arguments, while a line beginning with ">E" indicates an error with the input. + - ``immutable`` -- boolean (default: ``False``); whether to return + immutable or mutable graphs + The possible options, obtained as output of ``geng --help``:: n : the number of vertices @@ -1006,10 +1025,9 @@ def nauty_geng(self, options='', debug=False): except StopIteration: # Exhausted list of graphs from nauty geng return - G = graph.Graph(s[:-1], format='graph6') - yield G + yield graph.Graph(s[:-1], format='graph6', immutable=immutable) - def nauty_genbg(self, options='', debug=False): + def nauty_genbg(self, options='', debug=False, immutable=False): r""" Return a generator which creates bipartite graphs from nauty's ``genbgL`` program. @@ -1029,6 +1047,9 @@ def nauty_genbg(self, options='', debug=False): the program with some information on the arguments, while a line beginning with ">E" indicates an error with the input. + - ``immutable`` -- boolean (default: ``False``); whether to return + immutable or mutable graphs + The possible options, obtained as output of ``genbgL --help``:: n1 : the number of vertices in the first class. @@ -1207,10 +1228,10 @@ def nauty_genbg(self, options='', debug=False): except StopIteration: # Exhausted list of bipartite graphs from nauty genbgL return - G = BipartiteGraph(s[:-1], format='graph6', partition=partition) - yield G + yield BipartiteGraph(s[:-1], format='graph6', partition=partition, + immutable=immutable) - def nauty_genktreeg(self, options='', debug=False): + def nauty_genktreeg(self, options='', debug=False, immutable=False): r""" Return a generator which creates all `k`-trees using nauty.. @@ -1235,6 +1256,9 @@ def nauty_genktreeg(self, options='', debug=False): the program with some information on the arguments, while a line beginning with ">E" indicates an error with the input. + - ``immutable`` -- boolean (default: ``False``); whether to return + immutable or mutable graphs + The possible options, obtained as output of ``genktreeg --help``:: n : the number of vertices @@ -1322,10 +1346,10 @@ def nauty_genktreeg(self, options='', debug=False): except StopIteration: # Exhausted list of graphs from nauty geng return - G = graph.Graph(s[:-1], format='graph6') - yield G + yield graph.Graph(s[:-1], format='graph6', immutable=immutable) - def cospectral_graphs(self, vertices, matrix_function=None, graphs=None): + def cospectral_graphs(self, vertices, matrix_function=None, graphs=None, + immutable=False): r""" Find all sets of graphs on ``vertices`` vertices (with possible restrictions) which are cospectral with respect to a @@ -1352,6 +1376,9 @@ def cospectral_graphs(self, vertices, matrix_function=None, graphs=None): are tested for cospectral sets. In this case, ``vertices`` is ignored. + - ``immutable`` -- boolean (default: ``False``); whether to return + immutable or mutable graphs + OUTPUT: A list of lists of graphs. Each sublist will be a list of @@ -1424,11 +1451,15 @@ def cospectral_graphs(self, vertices, matrix_function=None, graphs=None): if matrix_function is None: matrix_function = lambda g: g.adjacency_matrix() + def prop(x): + return True + from sage.graphs.graph_generators import graphs as graph_gen if graphs is None: - graph_list = graph_gen(vertices, property=lambda _: True) + graph_list = graph_gen(vertices, property=prop, immutable=immutable) elif callable(graphs): - graph_list = iter(g for g in graph_gen(vertices, property=lambda _: True) if graphs(g)) + graph_list = (g for g in graph_gen(vertices, property=prop, + immutable=immutable) if graphs(g)) else: graph_list = iter(graphs) @@ -1445,7 +1476,7 @@ def cospectral_graphs(self, vertices, matrix_function=None, graphs=None): return cospectral_graphs - def _read_planar_code(self, code_input): + def _read_planar_code(self, code_input, immutable=False): r""" Return a generator for the plane graphs in planar code format in the file code_input (see [BM2016]_). @@ -1464,6 +1495,9 @@ def _read_planar_code(self, code_input): - ``code_input`` -- a file containing valid planar code data + - ``immutable`` -- boolean (default: ``False``); whether to return + immutable or mutable graphs + OUTPUT: A generator which will produce the plane graphs as Sage graphs @@ -1545,14 +1579,14 @@ def _read_planar_code(self, code_input): if Ni > 1: edges_g[i + 1] += [i + 1] * (Ni // 2) has_loops = True - G = graph.Graph(edges_g, loops=has_loops) + G = graph.Graph(edges_g, loops=has_loops, immutable=immutable) if not (G.has_multiple_edges() or has_loops): embed_g = {i + 1: di for i, di in enumerate(g)} G.set_embedding(embed_g) yield G - def fullerenes(self, order, ipr=False): + def fullerenes(self, order, ipr=False, immutable=False): r""" Return a generator which creates fullerene graphs using the buckygen generator (see [BGM2012]_). @@ -1562,10 +1596,13 @@ def fullerenes(self, order, ipr=False): - ``order`` -- a positive even integer smaller than or equal to 254 This specifies the number of vertices in the generated fullerenes - - ``ipr`` -- (default: ``False``) if ``True`` only fullerenes that - satisfy the Isolated Pentagon Rule are generated. This means that + - ``ipr`` -- boolean (default: ``False``); if ``True`` only fullerenes + that satisfy the Isolated Pentagon Rule are generated. This means that no pentagonal faces share an edge. + - ``immutable`` -- boolean (default: ``False``); whether to return + immutable or mutable graphs + OUTPUT: A generator which will produce the fullerene graphs as Sage graphs @@ -1657,9 +1694,9 @@ def fullerenes(self, order, ipr=False): sp.stdout.reconfigure(newline='') - yield from graphs._read_planar_code(sp.stdout) + yield from graphs._read_planar_code(sp.stdout, immutable=immutable) - def fusenes(self, hexagon_count, benzenoids=False): + def fusenes(self, hexagon_count, benzenoids=False, immutable=False): r""" Return a generator which creates fusenes and benzenoids using the benzene generator (see [BCH2002]_). Fusenes are planar @@ -1671,8 +1708,11 @@ def fusenes(self, hexagon_count, benzenoids=False): - ``hexagon_count`` -- positive integer smaller than or equal to 30; this specifies the number of hexagons in the generated benzenoids - - ``benzenoids`` -- (default: ``False``) if ``True`` only benzenoids are - generated + - ``benzenoids`` -- boolean (default: ``False``); if ``True`` only + benzenoids are generated + + - ``immutable`` -- boolean (default: ``False``); whether to return + immutable or mutable graphs OUTPUT: @@ -1745,10 +1785,9 @@ def fusenes(self, hexagon_count, benzenoids=False): sp.stdout.reconfigure(newline='') - for G in graphs._read_planar_code(sp.stdout): - yield G + yield from graphs._read_planar_code(sp.stdout, immutable=immutable) - def plantri_gen(self, options=""): + def plantri_gen(self, options="", immutable=False): r""" Iterator over planar graphs created using the ``plantri`` generator. @@ -1771,6 +1810,9 @@ def plantri_gen(self, options=""): output of plantri to be in "planar code" format, so do not set an option to change this default or results will be unpredictable. + - ``immutable`` -- boolean (default: ``False``); whether to return + immutable or mutable graphs + The possible options are:: n : the number of vertices (the only compulsory parameter). @@ -1932,7 +1974,7 @@ def plantri_gen(self, options=""): sp.stdout.reconfigure(newline='') try: - yield from graphs._read_planar_code(sp.stdout) + yield from graphs._read_planar_code(sp.stdout, immutable=immutable) except AssertionError: raise AttributeError("invalid options '{}'".format(options)) @@ -1943,7 +1985,8 @@ def planar_graphs(self, order, minimum_degree=None, maximum_edges=None, maximum_face_size=None, only_bipartite=False, - dual=False): + dual=False, + immutable=False): r""" An iterator over connected planar graphs using the plantri generator. @@ -1995,6 +2038,9 @@ def planar_graphs(self, order, minimum_degree=None, - ``dual`` -- (default: ``False``) if ``True`` return instead the planar duals of the generated graphs + - ``immutable`` -- boolean (default: ``False``); whether to return + immutable or mutable graphs + OUTPUT: An iterator which will produce all planar graphs with the given @@ -2160,7 +2206,7 @@ def planar_graphs(self, order, minimum_degree=None, if order == 1: if minimum_degree == 0: - G = graph.Graph(1) + G = graph.Graph(1, immutable=immutable) G.set_embedding({0: []}) yield G return @@ -2174,10 +2220,11 @@ def planar_graphs(self, order, minimum_degree=None, edges, faces, order) - yield from graphs.plantri_gen(command) + yield from graphs.plantri_gen(command, immutable=immutable) def triangulations(self, order, minimum_degree=None, minimum_connectivity=None, - exact_connectivity=False, only_eulerian=False, dual=False): + exact_connectivity=False, only_eulerian=False, dual=False, + immutable=False): r""" An iterator over connected planar triangulations using the plantri generator. @@ -2215,6 +2262,9 @@ def triangulations(self, order, minimum_degree=None, minimum_connectivity=None, - ``dual`` -- (default: ``False``) if ``True`` return instead the planar duals of the generated graphs + - ``immutable`` -- boolean (default: ``False``); whether to return + immutable or mutable graphs + OUTPUT: An iterator which will produce all planar triangulations with the given @@ -2360,10 +2410,11 @@ def triangulations(self, order, minimum_degree=None, minimum_connectivity=None, 'd' if dual else '', order) - yield from graphs.plantri_gen(command) + yield from graphs.plantri_gen(command, immutable=immutable) def quadrangulations(self, order, minimum_degree=None, minimum_connectivity=None, - no_nonfacial_quadrangles=False, dual=False): + no_nonfacial_quadrangles=False, dual=False, + immutable=False): r""" An iterator over planar quadrangulations using the plantri generator. @@ -2397,6 +2448,9 @@ def quadrangulations(self, order, minimum_degree=None, minimum_connectivity=None - ``dual`` -- (default: ``False``) if ``True`` return instead the planar duals of the generated graphs + - ``immutable`` -- boolean (default: ``False``); whether to return + immutable or mutable graphs + OUTPUT: An iterator which will produce all planar quadrangulations with the given @@ -2495,7 +2549,7 @@ def quadrangulations(self, order, minimum_degree=None, minimum_connectivity=None 'd' if dual else '', order) - yield from graphs.plantri_gen(command) + yield from graphs.plantri_gen(command, immutable=immutable) ########################################################################### # Basic Graphs diff --git a/src/sage/graphs/graph_latex.py b/src/sage/graphs/graph_latex.py index f50758496c4..5a61fc33659 100644 --- a/src/sage/graphs/graph_latex.py +++ b/src/sage/graphs/graph_latex.py @@ -1201,7 +1201,7 @@ def set_option(self, option_name, option_value=None): raise TypeError('%s option must be a dictionary, not %s' % (name, value)) else: for key, p in value.items(): - if not (type(p) in [float, RealLiteral] and (0 <= p) and (p <= 1)) and (p not in label_places): + if not (isinstance(p, (float, RealLiteral)) and (0 <= p <= 1)) and (p not in label_places): raise ValueError('%s option for %s needs to be a number between 0.0 and 1.0 or a place (like "above"), not %s' % (name, key, p)) elif name == 'loop_placements': if not isinstance(value, dict): diff --git a/src/sage/graphs/isgci.py b/src/sage/graphs/isgci.py index f8bcf801d7e..74f0ec0b0b5 100644 --- a/src/sage/graphs/isgci.py +++ b/src/sage/graphs/isgci.py @@ -500,7 +500,7 @@ def __eq__(self, other): sage: graph_classes.Chordal == graph_classes.Tree Unknown """ - return self >= other and other >= self + return self >= other >= self def __lt__(self, other): r""" diff --git a/src/sage/graphs/orientations.py b/src/sage/graphs/orientations.py index af9c795f535..842d3e5c4f7 100644 --- a/src/sage/graphs/orientations.py +++ b/src/sage/graphs/orientations.py @@ -20,7 +20,7 @@ :meth:`random_orientation` | Return a random orientation of a graph `G` :meth:`minimum_outdegree_orientation` | Return an orientation of `G` with the smallest possible maximum outdegree. :meth:`bounded_outdegree_orientation` | Return an orientation of `G` such that every vertex `v` has out-degree less than `b(v)`. - :meth:`eulerian_orientation(G)` | Return a DiGraph which is an Eulerian orientation of the graph `G`. + :meth:`eulerian_orientation` | Return an Eulerian orientation of the graph `G`. Authors ------- @@ -47,6 +47,165 @@ from sage.graphs.digraph import DiGraph +def _initialize_digraph(G, edges, name=None, weighted=None, sparse=None, + data_structure=None, immutable=None, hash_labels=None): + r""" + Helper method to return a directed graph built from ``G``. + + This method returns a digraph with the same set of vertices than the input + graph ``G`` and with specified edges. The data structure can be + specified. Furthermore, all attributes of the graph are copied to the + returned digraph. + + INPUT: + + - ``G`` -- a graph + + - ``edges`` -- iterable; the edges of the digraph to return + + - ``name`` -- string (default: ``None``); the name of the digraph to + return. By default (``None``), the returned digraph has the same name as + the input graph ``G``. + + - ``weighted`` -- boolean (default: ``None``); weightedness for the oriented + digraph. By default (``None``), the graph and its orientation will behave + the same. + + - ``sparse`` -- boolean (default: ``None``); ``sparse=True`` is an alias for + ``data_structure="sparse"``, and ``sparse=False`` is an alias for + ``data_structure="dense"``. Only used when ``data_structure=None``. + + - ``data_structure`` -- string (default: ``None``); one of ``'sparse'``, + ``'static_sparse'``, or ``'dense'``. See the documentation of + :class:`DiGraph`. + + - ``immutable`` -- boolean (default: ``None``); whether to create a + mutable/immutable digraph. Only used when ``data_structure=None``. + + * ``immutable=None`` (default) means that the graph and its orientation + will behave the same way. + + * ``immutable=True`` is a shortcut for ``data_structure='static_sparse'`` + + * ``immutable=False`` means that the created digraph is mutable. When used + to orient an immutable graph, the data structure used is ``'sparse'`` + unless anything else is specified. + + - ``hash_labels`` -- boolean (default: ``None``); whether to include edge + labels during hashing of the oriented digraph. This parameter defaults to + ``True`` if the graph is weighted. This parameter is ignored when + parameter ``immutable`` is not ``True``. Beware that trying to hash + unhashable labels will raise an error. + + EXAMPLES:: + + sage: from sage.graphs.orientations import _initialize_digraph + sage: G = Graph([(1, 2)], immutable=True, loops=True, multiedges=True) + sage: D = _initialize_digraph(G, []) + sage: D.is_immutable() + True + sage: D.allows_loops() + True + sage: D.allows_multiple_edges() + True + sage: D.edges() + [] + sage: D.add_edge((2, 3)) + Traceback (most recent call last): + ... + ValueError: graph is immutable; please change a copy instead (use function copy()) + sage: G = Graph([(1, 2)]) + sage: D = _initialize_digraph(G, []) + sage: D.vertices() + [1, 2] + sage: D.edges() + [] + sage: D.add_edge((2, 3)); D.edges() + [(2, 3, None)] + + TESTS:: + + sage: from sage.graphs.orientations import _initialize_digraph + sage: _initialize_digraph(Graph(), [], data_structure='sparse', immutable=False) + Traceback (most recent call last): + ... + ValueError: you cannot define 'immutable' or 'sparse' when 'data_structure' has a value + sage: _initialize_digraph(Graph(), [], data_structure='sparse', sparse=True) + Traceback (most recent call last): + ... + ValueError: you cannot define 'immutable' or 'sparse' when 'data_structure' has a value + """ + # Which data structure should be used ? + if data_structure is not None: + # data_structure is already defined so there is nothing left to do + # here. Did the user try to define too much ? + if immutable is not None or sparse is not None: + raise ValueError("you cannot define 'immutable' or 'sparse' " + "when 'data_structure' has a value") + # At this point, data_structure is None. + elif immutable is True: + data_structure = 'static_sparse' + if sparse is False: + raise ValueError("there is no dense immutable backend at the moment") + elif immutable is False: + # If the user requests a mutable digraph and input is immutable, we + # choose the 'sparse' cgraph backend. Unless the user explicitly + # asked for something different. + if G.is_immutable(): + data_structure = 'dense' if sparse is False else 'sparse' + # At this point, data_structure and immutable are None. + elif sparse is True: + data_structure = "sparse" + elif sparse is False: + data_structure = "dense" + + if data_structure is None: + from sage.graphs.base.dense_graph import DenseGraphBackend + from sage.graphs.base.sparse_graph import SparseGraphBackend + if isinstance(G._backend, DenseGraphBackend): + data_structure = "dense" + elif isinstance(G._backend, SparseGraphBackend): + data_structure = "sparse" + else: + data_structure = "static_sparse" + + if name is None: + name = G.name() + if weighted is None: + weighted = G.weighted() + if hash_labels is None: + hash_labels = G._hash_labels + + D = DiGraph(data=[G, edges], + format='vertices_and_edges', + data_structure=data_structure, + multiedges=G.allows_multiple_edges(), + loops=G.allows_loops(), + weighted=weighted, + pos=copy(G.get_pos()), + name=name, + hash_labels=hash_labels) + + D.set_vertices(G.get_vertices()) + + attributes_to_copy = ('_assoc', '_embedding') + for attr in attributes_to_copy: + if hasattr(G, attr): + copy_attr = {} + old_attr = getattr(G, attr) + if isinstance(old_attr, dict): + for v, value in old_attr.items(): + try: + copy_attr[v] = value.copy() + except AttributeError: + copy_attr[v] = copy(value) + setattr(D, attr, copy_attr) + else: + setattr(D, attr, copy(old_attr)) + + return D + + def orient(G, f, weighted=None, data_structure=None, sparse=None, immutable=None, hash_labels=None): r""" @@ -164,64 +323,11 @@ def orient(G, f, weighted=None, data_structure=None, sparse=None, sage: H.orient(foo, data_structure=None, immutable=None, sparse=None)._backend """ - # Which data structure should be used ? - if data_structure is not None: - # data_structure is already defined so there is nothing left to do - # here. Did the user try to define too much ? - if immutable is not None or sparse is not None: - raise ValueError("you cannot define 'immutable' or 'sparse' " - "when 'data_structure' has a value") - # At this point, data_structure is None. - elif immutable is True: - data_structure = 'static_sparse' - if sparse is False: - raise ValueError("there is no dense immutable backend at the moment") - elif immutable is False: - # If the user requests a mutable digraph and input is immutable, we - # choose the 'sparse' cgraph backend. Unless the user explicitly - # asked for something different. - if G.is_immutable(): - data_structure = 'dense' if sparse is False else 'sparse' - elif sparse is True: - data_structure = "sparse" - elif sparse is False: - data_structure = "dense" - - if data_structure is None: - from sage.graphs.base.dense_graph import DenseGraphBackend - if isinstance(G._backend, DenseGraphBackend): - data_structure = "dense" - else: - data_structure = "sparse" - - if weighted is None: - weighted = G.weighted() - edges = (f(e) for e in G.edge_iterator()) - D = DiGraph([G, edges], format='vertices_and_edges', - data_structure=data_structure, - loops=G.allows_loops(), - multiedges=G.allows_multiple_edges(), - name=f"Orientation of {G.name()}", - pos=copy(G._pos), weighted=weighted, - hash_labels=hash_labels) - - attributes_to_copy = ('_assoc', '_embedding') - for attr in attributes_to_copy: - if hasattr(G, attr): - copy_attr = {} - old_attr = getattr(G, attr) - if isinstance(old_attr, dict): - for v, value in old_attr.items(): - try: - copy_attr[v] = value.copy() - except AttributeError: - copy_attr[v] = copy(value) - setattr(D, attr, copy_attr) - else: - setattr(D, attr, copy(old_attr)) - - return D + name = f"Orientation of {G.name()}" + return _initialize_digraph(G, edges, name=name, weighted=weighted, + data_structure=data_structure, sparse=sparse, + immutable=immutable, hash_labels=hash_labels) def orientations(G, data_structure=None, sparse=None): @@ -310,7 +416,7 @@ def orientations(G, data_structure=None, sparse=None): sage: next(G.orientations(data_structure='sparse', sparse=True))._backend Traceback (most recent call last): ... - ValueError: cannot specify both 'sparse' and 'data_structure' + ValueError: you cannot define 'immutable' or 'sparse' when 'data_structure' has a value sage: next(G.orientations(sparse=True))._backend sage: next(G.orientations(sparse=False))._backend @@ -336,51 +442,21 @@ def orientations(G, data_structure=None, sparse=None): sage: next(G.orientations()).get_embedding() == {} True """ - if sparse is not None: - if data_structure is not None: - raise ValueError("cannot specify both 'sparse' and 'data_structure'") - data_structure = "sparse" if sparse else "dense" - if data_structure is None: - from sage.graphs.base.dense_graph import DenseGraphBackend - from sage.graphs.base.sparse_graph import SparseGraphBackend - if isinstance(G._backend, DenseGraphBackend): - data_structure = "dense" - elif isinstance(G._backend, SparseGraphBackend): - data_structure = "sparse" - else: - data_structure = "static_sparse" - name = G.name() if name: name = 'An orientation of ' + name if not G.size(): - D = DiGraph(data=[G, []], - format='vertices_and_edges', - name=name, - pos=G._pos, - multiedges=G.allows_multiple_edges(), - loops=G.allows_loops(), - data_structure=data_structure) - if hasattr(G, '_embedding'): - D._embedding = copy(G._embedding) - yield D + yield _initialize_digraph(G, [], name=name, + data_structure=data_structure, sparse=sparse) return E = [[(u, v, label), (v, u, label)] if u != v else [(u, v, label)] for u, v, label in G.edge_iterator()] from itertools import product for edges in product(*E): - D = DiGraph(data=[G, edges], - format='vertices_and_edges', - name=name, - pos=G._pos, - multiedges=G.allows_multiple_edges(), - loops=G.allows_loops(), - data_structure=data_structure) - if hasattr(G, '_embedding'): - D._embedding = copy(G._embedding) - yield D + yield _initialize_digraph(G, edges, name=name, + data_structure=data_structure, sparse=sparse) def acyclic_orientations(G): @@ -644,7 +720,8 @@ def helper(G, globO, m, k): # Iterate over acyclic orientations and create relabeled graphs for orientation in orientations: - D = DiGraph([(u, v) if label else (v, u) for (u, v), label in orientation.items()]) + edges = ((u, v) if label else (v, u) for (u, v), label in orientation.items()) + D = _initialize_digraph(G, edges) D.relabel(perm=reverse_vertex_labels, inplace=True) yield D @@ -711,7 +788,13 @@ def strong_orientation(G): sage: g.strong_orientation() Multi-digraph on 3 vertices """ - d = DiGraph(multiedges=G.allows_multiple_edges()) + from sage.graphs.base.dense_graph import DenseGraphBackend + if isinstance(G._backend, DenseGraphBackend): + data_structure = "dense" + else: + data_structure = "sparse" + d = _initialize_digraph(G, [], data_structure=data_structure) + i = 0 # The algorithm works through a depth-first search. Any edge used in the @@ -1019,25 +1102,14 @@ def random_orientation(G): if not isinstance(G, Graph): raise ValueError("the input parameter must be a Graph") - D = DiGraph(data=[G.vertices(sort=False), []], - format='vertices_and_edges', - multiedges=G.allows_multiple_edges(), - loops=G.allows_loops(), - weighted=G.weighted(), - pos=G.get_pos(), - name="Random orientation of {}".format(G.name())) - if hasattr(G, '_embedding'): - D._embedding = copy(G._embedding) - from sage.misc.prandom import getrandbits rbits = getrandbits(G.size()) + edges = [] for u, v, l in G.edge_iterator(): - if rbits % 2: - D.add_edge(u, v, l) - else: - D.add_edge(v, u, l) + edges.append((u, v, l) if rbits % 2 else (v, u, l)) rbits >>= 1 - return D + + return _initialize_digraph(G, edges, name=f"Random orientation of {G.name()}") def minimum_outdegree_orientation(G, use_edge_labels=False, solver=None, verbose=0, @@ -1155,15 +1227,8 @@ def outgoing(u, e, variable): orientation = p.get_values(orientation, convert=bool, tolerance=integrality_tolerance) - # All the edges from G are doubled in O ( one in each direction ) - O = DiGraph(G) - - # Builds the list of edges that should be removed - edges = (e[::-1] if orientation[frozenset(e)] else e - for e in G.edge_iterator(labels=False)) - O.delete_edges(edges) - - return O + # Return the resulting orientation + return G.orient(lambda e: e if orientation[frozenset(e[:2])] else (e[1], e[0], e[2])) def bounded_outdegree_orientation(G, bound, solver=None, verbose=False, @@ -1328,27 +1393,18 @@ def bounded_outdegree_orientation(G, bound, solver=None, verbose=False, if value != G.size(): raise ValueError("No orientation exists for the given bound") - D = DiGraph() - D.add_vertices(vertices) - # The flow graph may not contain all the vertices, if they are # not part of the flow... + edges = ((vertices[u], vertices[vv if vv != u else uu]) + for u in (x for x in range(n) if x in flow) + for uu, vv in flow.neighbors_out(u)) - for u in [x for x in range(n) if x in flow]: - - for uu, vv in flow.neighbors_out(u): - v = vv if vv != u else uu - D.add_edge(vertices[u], vertices[v]) - - # I do not like when a method destroys the embedding ;-) - D.set_pos(G.get_pos()) - - return D + return _initialize_digraph(G, edges) def eulerian_orientation(G): r""" - Return a DiGraph which is an Eulerian orientation of the graph `G`. + Return an Eulerian orientation of the graph `G`. An Eulerian graph being a graph such that any vertex has an even degree, an Eulerian orientation of a graph is an orientation of its edges such that @@ -1405,7 +1461,7 @@ def eulerian_orientation(G): sage: E4.eulerian_orientation() Digraph on 4 vertices """ - d = DiGraph([G, []], format='vertices_and_edges') + d = _initialize_digraph(G, [], sparse=True, immutable=False) if not G.size(): return d diff --git a/src/sage/groups/abelian_gps/abelian_group.py b/src/sage/groups/abelian_gps/abelian_group.py index 67a861555cb..d19657c2e40 100644 --- a/src/sage/groups/abelian_gps/abelian_group.py +++ b/src/sage/groups/abelian_gps/abelian_group.py @@ -1861,7 +1861,7 @@ def equals(left, right): return left.is_isomorphic(right) if left_ambient is not right_ambient: return False - return left <= right and right <= left + return left <= right <= left __eq__ = equals diff --git a/src/sage/groups/perm_gps/partn_ref2/refinement_generic.pyx b/src/sage/groups/perm_gps/partn_ref2/refinement_generic.pyx index af1960e4632..c6b71e5cd77 100644 --- a/src/sage/groups/perm_gps/partn_ref2/refinement_generic.pyx +++ b/src/sage/groups/perm_gps/partn_ref2/refinement_generic.pyx @@ -693,7 +693,7 @@ cdef class PartitionRefinement_generic: self._fixed_not_minimized.append(pos) self._backtrack() # backtracking - #restore the old state and continue backtracking + # restore the old state and continue backtracking self._part.depth = old_partition_depth self._fixed_minimized = self._fixed_minimized[:old_fixed_minimized_len] self._fixed_not_minimized = copy(old_fixed_not_minimized) diff --git a/src/sage/interacts/library_cython.pyx b/src/sage/interacts/library_cython.pyx index 52c68dd5922..e68a8bcd2a3 100644 --- a/src/sage/interacts/library_cython.pyx +++ b/src/sage/interacts/library_cython.pyx @@ -5,14 +5,14 @@ AUTHORS: - Harald Schilly (2011-01-16): initial version (#9623) partially based on work by Lauri Ruotsalainen """ -#***************************************************************************** +# *************************************************************************** # Copyright (C) 2011 Harald Schilly # # Distributed under the terms of the GNU General Public License (GPL) # as published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # https://www.gnu.org/licenses/ -#***************************************************************************** +# *************************************************************************** cpdef julia(ff_j, z, int iterations): @@ -97,11 +97,11 @@ cpdef cellular(rule, int N): """ from numpy import zeros cdef int j, k, l - M=zeros((N, 2*N+2), dtype=int) - M[0,N]=1 + M = zeros((N, 2*N+2), dtype=int) + M[0, N] = 1 for j in range(1, N): for k in range(0, 2*N): l = 4 * M[j-1, k-1] + 2 * M[j-1, k] + M[j-1, k+1] - M[j,k] = rule[l] + M[j, k] = rule[l] return M diff --git a/src/sage/interfaces/expect.py b/src/sage/interfaces/expect.py index 91f8efcf651..ff424335d56 100644 --- a/src/sage/interfaces/expect.py +++ b/src/sage/interfaces/expect.py @@ -1328,8 +1328,8 @@ def _synchronize(self, cmd='1+%s;\n'): sage: R. = QQ[]; f = x^3 + x + 1; g = x^3 - x - 1; r = f.resultant(g); gap(ZZ); singular(R) Integers polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 1 + // coefficients: QQ... + // number of vars : 1 // block 1 : ordering lp // : names x // block 2 : ordering C diff --git a/src/sage/interfaces/interface.py b/src/sage/interfaces/interface.py index bd1095e8c70..22fb4b8487c 100644 --- a/src/sage/interfaces/interface.py +++ b/src/sage/interfaces/interface.py @@ -817,8 +817,8 @@ def __reduce__(self): sage: S = singular.ring(0, ('x')) sage: loads(dumps(S)) polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 1 + // coefficients: QQ... + // number of vars : 1 // block 1 : ordering lp // : names x // block 2 : ordering C diff --git a/src/sage/interfaces/lie.py b/src/sage/interfaces/lie.py index 1824d2efcdb..e89419e68f6 100644 --- a/src/sage/interfaces/lie.py +++ b/src/sage/interfaces/lie.py @@ -285,6 +285,8 @@ # https://www.gnu.org/licenses/ # ########################################################################## +from itertools import chain +import os from .expect import Expect, ExpectElement, ExpectFunction, FunctionElement from sage.interfaces.interface import AsciiArtString @@ -293,7 +295,6 @@ from sage.misc.sage_eval import sage_eval from sage.interfaces.tab_completion import ExtraTabCompletion from sage.misc.instancedoc import instancedoc -import os COMMANDS_CACHE = '%s/lie_commandlist_cache.sobj' % DOT_SAGE @@ -448,9 +449,7 @@ def _read_info_files(self, use_disk_cache=True): info.close() # Build the list of all possible command completions - l = [] - for key in commands: - l += commands[key] + l = list(chain(*commands.values())) # Save the data self._tab_completion_dict = commands @@ -574,7 +573,7 @@ def version(self) -> str: EXAMPLES:: sage: lie.version() # optional - lie - '2.2' + '2...' """ return lie_version() @@ -943,7 +942,7 @@ def lie_version(): sage: from sage.interfaces.lie import lie_version sage: lie_version() # optional - lie - '2.2' + '2...' """ with open(os.path.join(LIE_INFO_DIR, 'INFO.0')) as f: lines = f.readlines() diff --git a/src/sage/interfaces/quit.py b/src/sage/interfaces/quit.py index c7c1643be83..39d5c4b60c7 100644 --- a/src/sage/interfaces/quit.py +++ b/src/sage/interfaces/quit.py @@ -12,13 +12,24 @@ # https://www.gnu.org/licenses/ ################################################################################ +from __future__ import annotations + import os +import subprocess +import sys +from typing import TYPE_CHECKING +from sage.env import DOT_SAGE, HOSTNAME from sage.misc.cachefunc import cached_function +if TYPE_CHECKING: + from weakref import ReferenceType + + from sage.interfaces.expect import Expect + @cached_function -def sage_spawned_process_file(): +def sage_spawned_process_file() -> str: """ EXAMPLES:: @@ -29,23 +40,22 @@ def sage_spawned_process_file(): # This is the old value of SAGE_TMP. Until sage-cleaner is # completely removed, we need to leave these spawned_processes # files where sage-cleaner will look for them. - from sage.env import DOT_SAGE, HOSTNAME d = os.path.join(DOT_SAGE, "temp", HOSTNAME, str(os.getpid())) os.makedirs(d, exist_ok=True) return os.path.join(d, "spawned_processes") -def register_spawned_process(pid, cmd=''): +def register_spawned_process(pid: int, cmd: str = "") -> None: """ Write a line to the ``spawned_processes`` file with the given ``pid`` and ``cmd``. """ - if cmd != '': + if cmd != "": cmd = cmd.strip().split()[0] # This is safe, since only this process writes to this file. try: - with open(sage_spawned_process_file(), 'a') as o: - o.write('%s %s\n' % (pid, cmd)) + with open(sage_spawned_process_file(), "a") as file: + file.write("%s %s\n" % (pid, cmd)) except OSError: pass else: @@ -53,13 +63,14 @@ def register_spawned_process(pid, cmd=''): # the cleaner ourselves upon being told that there will be # something to clean. from sage.interfaces.cleaner import start_cleaner + start_cleaner() -expect_objects = [] +expect_objects: list[ReferenceType[Expect]] = [] -def expect_quitall(verbose=False): +def expect_quitall(verbose: bool = False) -> None: """ EXAMPLES:: @@ -74,17 +85,17 @@ def expect_quitall(verbose=False): sage: sage.interfaces.quit.expect_quitall(verbose=True) # needs sage.libs.pari Exiting PARI/GP interpreter with PID ... running .../gp --fast --emacs --quiet --stacksize 10000000 """ - for P in expect_objects: - R = P() - if R is not None: + for reference in expect_objects: + process = reference() + if process is not None: try: - R.quit(verbose=verbose) + process.quit(verbose=verbose) except RuntimeError: pass kill_spawned_jobs() -def kill_spawned_jobs(verbose=False): +def kill_spawned_jobs(verbose: bool = False): """ INPUT: @@ -110,19 +121,23 @@ def kill_spawned_jobs(verbose=False): if not os.path.exists(fname): return - with open(fname) as f: - for L in f: - i = L.find(' ') - pid = L[:i].strip() + with open(fname) as file: + for line in file: + i = line.find(" ") + pid = line[:i].strip() try: if verbose: print("Killing spawned job %s" % pid) - os.killpg(int(pid), 9) + if sys.platform == "win32": + # From https://stackoverflow.com/a/47756757/873661 + subprocess.call(["taskkill", "/F", "/T", "/PID", pid]) + else: + os.killpg(int(pid), 9) except OSError: pass -def is_running(pid): +def is_running(pid: int) -> bool: """ Return ``True`` if and only if there is a process with id pid running. """ @@ -133,11 +148,11 @@ def is_running(pid): return False -def invalidate_all(): +def invalidate_all() -> None: """ Invalidate all of the expect interfaces. - This is used, e.g., by the fork-based @parallel decorator. + This is used, e.g., by the fork-based ``@parallel`` decorator. EXAMPLES:: @@ -157,7 +172,7 @@ def invalidate_all(): sage: a, b # needs sage.libs.pari sage.symbolic (2, 3) """ - for I in expect_objects: - I1 = I() - if I1: - I1.detach() + for reference in expect_objects: + process = reference() + if process: + process.detach() diff --git a/src/sage/interfaces/singular.py b/src/sage/interfaces/singular.py index d110c17bf16..59d01f4493d 100644 --- a/src/sage/interfaces/singular.py +++ b/src/sage/interfaces/singular.py @@ -39,8 +39,8 @@ sage: R1 = singular.ring(0, '(x,y)', 'dp') sage: R1 polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 2 + // coefficients: QQ... + // number of vars : 2 // block 1 : ordering dp // : names x y // block 2 : ordering C @@ -220,12 +220,12 @@ sage: singular.lib('polylib.lib') sage: singular.ring(32003, '(a,b,c,d,e,f)', 'lp') - polynomial ring, over a field, global ordering - // coefficients: ZZ/32003 - // number of vars : 6 - // block 1 : ordering lp - // : names a b c d e f - // block 2 : ordering C + polynomial ring, over a field, global ordering + // coefficients: ZZ/32003... + // number of vars : 6 + // block 1 : ordering lp + // : names a b c d e f + // block 2 : ordering C sage: I = singular.ideal('cyclic(6)') sage: g = singular('groebner(I)') Traceback (most recent call last): @@ -1074,8 +1074,8 @@ def ring(self, char=0, vars='(x)', order='lp', check=None): sage: R = singular.ring(0, '(x,y,z)', 'dp') sage: R polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 3 + // coefficients: QQ... + // number of vars : 3 // block 1 : ordering dp // : names x y z // block 2 : ordering C @@ -1153,16 +1153,16 @@ def set_ring(self, R): sage: S = singular.ring('real', '(a,b)', 'lp') sage: singular.current_ring() polynomial ring, over a field, global ordering - // coefficients: Float() - // number of vars : 2 + // coefficients: Float()... + // number of vars : 2 // block 1 : ordering lp // : names a b // block 2 : ordering C sage: singular.set_ring(R) sage: singular.current_ring() polynomial ring, over a field, local ordering - // coefficients: ZZ/7 - // number of vars : 2 + // coefficients: ZZ/7... + // number of vars : 2 // block 1 : ordering ds // : names a b // block 2 : ordering C @@ -1203,15 +1203,15 @@ def current_ring(self): sage: r = PolynomialRing(GF(127),3,'xyz', order='invlex') sage: r._singular_() polynomial ring, over a field, global ordering - // coefficients: ZZ/127 - // number of vars : 3 + // coefficients: ZZ/127... + // number of vars : 3 // block 1 : ordering ip // : names x y z // block 2 : ordering C sage: singular.current_ring() polynomial ring, over a field, global ordering - // coefficients: ZZ/127 - // number of vars : 3 + // coefficients: ZZ/127... + // number of vars : 3 // block 1 : ordering ip // : names x y z // block 2 : ordering C @@ -1430,8 +1430,8 @@ def __copy__(self): sage: cpQ.set_ring() sage: cpQ polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 2 + // coefficients: QQ... + // number of vars : 2 // block 1 : ordering dp // : names x y // block 2 : ordering C @@ -1996,8 +1996,8 @@ def _sage_(self, R=None): sage: singular('basering') polynomial ring, over a domain, global ordering - // coefficients: ZZ - // number of vars : 3 + // coefficients: ZZ... + // number of vars : 3 // block 1 : ordering lp // : names x y z // block 2 : ordering C @@ -2087,16 +2087,16 @@ def set_ring(self): sage: S = singular.ring('real', '(a,b)', 'lp') sage: singular.current_ring() polynomial ring, over a field, global ordering - // coefficients: Float() - // number of vars : 2 + // coefficients: Float()... + // number of vars : 2 // block 1 : ordering lp // : names a b // block 2 : ordering C sage: R.set_ring() sage: singular.current_ring() polynomial ring, over a field, local ordering - // coefficients: ZZ/7 - // number of vars : 2 + // coefficients: ZZ/7... + // number of vars : 2 // block 1 : ordering ds // : names a b // block 2 : ordering C diff --git a/src/sage/knots/free_knotinfo_monoid.py b/src/sage/knots/free_knotinfo_monoid.py index d62e6743c79..8b1edb0e602 100644 --- a/src/sage/knots/free_knotinfo_monoid.py +++ b/src/sage/knots/free_knotinfo_monoid.py @@ -339,8 +339,7 @@ def hp_mirr(hp): if SymmetryMutant.concordance_inverse in hp_sym.keys(): hp_sym[SymmetryMutant.concordance_inverse] = hpm - for sym_mut in hp_sym.keys(): - hps = hp_sym[sym_mut] + for sym_mut, hps in hp_sym.items(): if hps.divides(hpoly): Kgen = self((K, sym_mut)) h = hpoly // hps diff --git a/src/sage/knots/link.py b/src/sage/knots/link.py index e6d23ac01b6..2c5f59ef19f 100644 --- a/src/sage/knots/link.py +++ b/src/sage/knots/link.py @@ -1181,25 +1181,26 @@ def _khovanov_homology_cached(self, height, ring=ZZ): for st in states: i, j = st[3], st[4] if j == height: - if (i,j) in bases: - bases[i,j].append(st) + if (i, j) in bases: + bases[i, j].append(st) else: - bases[i,j] = [st] + bases[i, j] = [st] complexes = {} - for (i, j) in bases: - if (i+1, j) in bases: - m = matrix(ring, len(bases[(i,j)]), len(bases[(i+1,j)])) + for (i, j), bij in bases.items(): + if (i + 1, j) in bases: + m = matrix(ring, len(bij), len(bases[(i + 1, j)])) for ii in range(m.nrows()): - V1 = bases[(i,j)][ii] + V1 = bij[ii] for jj in range(m.ncols()): - V2 = bases[(i+1, j)][jj] + V2 = bases[(i + 1, j)][jj] V20 = V2[0] - difs = [index for index,value in enumerate(V1[0]) if value != V20[index]] + difs = [index for index, value in enumerate(V1[0]) + if value != V20[index]] if len(difs) == 1 and not (V2[2].intersection(V1[1]) or V2[1].intersection(V1[2])): - m[ii,jj] = (-1)**sum(V2[0][x] for x in range(difs[0]+1, ncross)) + m[ii, jj] = (-1)**sum(V2[0][x] for x in range(difs[0]+1, ncross)) # Here we have the matrix constructed, now we have to put it in the dictionary of complexes else: - m = matrix(ring, len(bases[(i,j)]), 0) + m = matrix(ring, len(bij), 0) complexes[i] = m.transpose() if (i-1, j) not in bases: complexes[i-1] = matrix(ring, len(bases[(i,j)]), 0) diff --git a/src/sage/libs/singular/decl.pxd b/src/sage/libs/singular/decl.pxd index 3980a856368..3b4a2581f85 100644 --- a/src/sage/libs/singular/decl.pxd +++ b/src/sage/libs/singular/decl.pxd @@ -152,6 +152,7 @@ cdef extern from "singular/Singular/libsingular.h": void (*cfNormalize)(number* a, const n_Procs_s* r) bint (*cfDivBy)(number* a, number* b, const n_Procs_s* r) + bint (*cfGreater)(number* a, number* b, const n_Procs_s* ) bint (*cfEqual)(number* a,number* b, const n_Procs_s* ) bint (*cfIsZero)(number* a, const n_Procs_s* ) # algebraic number comparison with zero bint (*cfIsOne)(number* a, const n_Procs_s* ) # algebraic number comparison with one diff --git a/src/sage/libs/singular/function.pyx b/src/sage/libs/singular/function.pyx index 67cadf5d35c..87f0b7bab69 100644 --- a/src/sage/libs/singular/function.pyx +++ b/src/sage/libs/singular/function.pyx @@ -276,8 +276,8 @@ cdef class RingWrap: sage: l = ringlist(P) sage: ring = singular_function("ring") sage: ring(l, ring=P)._output() - // coefficients: QQ - // number of vars : 3 + // coefficients: QQ... + // number of vars : 3 // block 1 : ordering dp // : names x y z // block 2 : ordering C diff --git a/src/sage/libs/singular/polynomial.pyx b/src/sage/libs/singular/polynomial.pyx index a6023aaa2ae..19e3d593279 100644 --- a/src/sage/libs/singular/polynomial.pyx +++ b/src/sage/libs/singular/polynomial.pyx @@ -254,45 +254,62 @@ cdef int singular_polynomial_cmp(poly *p, poly *q, ring *r) noexcept: sage: (2/3*x^2 + 1/2*y + 3) > (2/3*x^2 + 1/4*y + 10) True + + TESTS: + + Ensure that comparison is transitive (as long as ``cfGreater`` is transitive and + consistent with ``cfGreaterZero``, see :issue:`39018` for more details):: + + sage: P. = GF(5)[] + sage: P(1) > P(4) + False + sage: P(4) > P(2) + True + sage: P(2) > P(1) + True + + :: + + sage: R. = Integers(10)[] + sage: l = [i*x+j*y+k for i in range(10) for j in range(10) for k in range(10)] + sage: l.sort() + sage: for i in range(len(l)): + ....: for b in l[:i]: + ....: assert b < l[i], (b, l[i]) + + More tests for :issue:`35681`:: + + sage: P. = ZZ[] + sage: P(0) > P(-1) + True """ cdef number *h - cdef int ret = 0 + cdef int tmp if r != currRing: rChangeCurrRing(r) - # handle special cases first (slight slowdown, as special cases - # are - well - special - if p == NULL: - if q == NULL: - # compare 0, 0 - return 0 - elif p_IsConstant(q,r): - # compare 0, const - return 1-2*r.cf.cfGreaterZero(p_GetCoeff(q,r), r.cf) # -1: <, 1: > # - elif q == NULL: - if p_IsConstant(p,r): - # compare const, 0 - return -1+2*r.cf.cfGreaterZero(p_GetCoeff(p,r), r.cf) # -1: <, 1: > - - while ret==0 and p!=NULL and q!=NULL: - ret = p_Cmp( p, q, r) - - if ret==0: - h = r.cf.cfSub(p_GetCoeff(p, r),p_GetCoeff(q, r),r.cf) - # compare coeffs - ret = -1+r.cf.cfIsZero(h,r.cf)+2*r.cf.cfGreaterZero(h, r.cf) # -1: <, 0:==, 1: > - n_Delete(&h, r.cf) - p = pNext(p) - q = pNext(q) + while True: + if p == NULL: + if q == NULL: + return 0 + return -1 if r.cf.cfGreaterZero(p_GetCoeff(q, r), r.cf) else 1 + elif q == NULL: + return 1 if r.cf.cfGreaterZero(p_GetCoeff(p, r), r.cf) else -1 + + tmp = p_Cmp(p, q, r) + if tmp != 0: + if tmp < 0: + return -1 if r.cf.cfGreaterZero(p_GetCoeff(q, r), r.cf) else 1 + else: + return 1 if r.cf.cfGreaterZero(p_GetCoeff(p, r), r.cf) else -1 - if ret==0: - if p==NULL and q != NULL: - ret = -1 - elif p!=NULL and q==NULL: - ret = 1 + # compare coefficients + if not r.cf.cfEqual(p_GetCoeff(p, r), p_GetCoeff(q, r), r.cf): + return 1 if r.cf.cfGreater(p_GetCoeff(p, r), p_GetCoeff(q, r), r.cf) else -1 - return ret + p = pNext(p) + q = pNext(q) cdef int singular_polynomial_mul(poly** ret, poly *p, poly *q, ring *r) except -1: """ diff --git a/src/sage/libs/singular/ring.pyx b/src/sage/libs/singular/ring.pyx index 1d8dd844385..4f7e288e2ad 100644 --- a/src/sage/libs/singular/ring.pyx +++ b/src/sage/libs/singular/ring.pyx @@ -162,7 +162,7 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: sage: sing_print = singular_function('print') sage: print(sing_print(R)) polynomial ring, over a field, global ordering - // coefficients: ZZ/7(a, b) + // coefficients: ZZ/7(a, b)... // number of vars : 3 // block 1 : ordering dp // : names x y z @@ -175,7 +175,7 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: sage: from sage.libs.singular.function import singular_function sage: print(sing_print(R)) polynomial ring, over a field, global ordering - // coefficients: QQ(s, t) + // coefficients: QQ(s, t)... // number of vars : 3 // block 1 : ordering dp // : names x y z @@ -185,21 +185,21 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: sage: R = PolynomialRing(GF(2), ("a", "b"), implementation="singular"); print(sing_print(R)) polynomial ring, over a field, global ordering - // coefficients: ZZ/2 + // coefficients: ZZ/2... // number of vars : 2 // block 1 : ordering dp // : names a b // block 2 : ordering C sage: R = PolynomialRing(GF(3), ("a", "b"), implementation="singular"); print(sing_print(R)) polynomial ring, over a field, global ordering - // coefficients: ZZ/3 + // coefficients: ZZ/3... // number of vars : 2 // block 1 : ordering dp // : names a b // block 2 : ordering C sage: R = PolynomialRing(GF(1000000007), ("a", "b"), implementation="singular"); print(sing_print(R)) polynomial ring, over a field, global ordering - // coefficients: ZZ/1000000007 + // coefficients: ZZ/1000000007... // number of vars : 2 // block 1 : ordering dp // : names a b @@ -210,14 +210,14 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: sage: R = PolynomialRing(Zmod(2), ("a", "b"), implementation="singular"); print(sing_print(R)) polynomial ring, over a ring (with zero-divisors), global ordering - // coefficients: ZZ/(2) + // coefficients: ZZ/(2)... // number of vars : 2 // block 1 : ordering dp // : names a b // block 2 : ordering C sage: R = PolynomialRing(Zmod(3), ("a", "b"), implementation="singular"); print(sing_print(R)) polynomial ring, over a ring (with zero-divisors), global ordering - // coefficients: ZZ/(3) + // coefficients: ZZ/(3)... // number of vars : 2 // block 1 : ordering dp // : names a b @@ -227,7 +227,7 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: sage: R = PolynomialRing(GF(2^128+51), ("a", "b"), implementation="singular"); print(sing_print(R)) polynomial ring, over a ring (with zero-divisors), global ordering - // coefficients: ZZ/bigint(340282366920938463463374607431768211507) + // coefficients: ZZ/bigint(340282366920938463463374607431768211507)... // number of vars : 2 // block 1 : ordering dp // : names a b @@ -238,7 +238,7 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: sage: R = PolynomialRing(GF(2^160), ("a", "b"), implementation="singular"); print(sing_print(R)) polynomial ring, over a field, global ordering - // coefficients: ZZ/2[z160]/(z160^160+z160^159+z160^155+z160^154+z160^153+z160^152+z160^151+z160^149+z160^148+z160^147+z160^146+z160^145+z160^144+z160^143+z160^141+z160^139+z160^137+z160^131+z160^129+z160^128+z160^127+z160^126+z160^123+z160^122+z160^121+z160^117+z160^116+z160^115+z160^113+z160^111+z160^110+z160^108+z160^106+z160^102+z160^100+z160^99+z160^97+z160^96+z160^95+z160^94+z160^93+z160^92+z160^91+z160^87+z160^86+z160^82+z160^80+z160^79+z160^78+z160^74+z160^73+z160^72+z160^71+z160^70+z160^67+z160^66+z160^65+z160^62+z160^59+z160^58+z160^57+z160^55+z160^54+z160^53+z160^52+z160^51+z160^49+z160^47+z160^44+z160^40+z160^35+z160^32+z160^30+z160^28+z160^27+z160^26+z160^24+z160^23+z160^21+z160^20+z160^18+z160^16+z160^11+z160^10+z160^8+z160^7+1) + // coefficients: ZZ/2[z160]/(z160^160+z160^159+z160^155+z160^154+z160^153+z160^152+z160^151+z160^149+z160^148+z160^147+z160^146+z160^145+z160^144+z160^143+z160^141+z160^139+z160^137+z160^131+z160^129+z160^128+z160^127+z160^126+z160^123+z160^122+z160^121+z160^117+z160^116+z160^115+z160^113+z160^111+z160^110+z160^108+z160^106+z160^102+z160^100+z160^99+z160^97+z160^96+z160^95+z160^94+z160^93+z160^92+z160^91+z160^87+z160^86+z160^82+z160^80+z160^79+z160^78+z160^74+z160^73+z160^72+z160^71+z160^70+z160^67+z160^66+z160^65+z160^62+z160^59+z160^58+z160^57+z160^55+z160^54+z160^53+z160^52+z160^51+z160^49+z160^47+z160^44+z160^40+z160^35+z160^32+z160^30+z160^28+z160^27+z160^26+z160^24+z160^23+z160^21+z160^20+z160^18+z160^16+z160^11+z160^10+z160^8+z160^7+1)... // number of vars : 2 // block 1 : ordering dp // : names a b @@ -248,7 +248,7 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: sage: R = PolynomialRing(Zmod(2^32), ("a", "b"), implementation="singular"); print(sing_print(R)) polynomial ring, over a ring (with zero-divisors), global ordering - // coefficients: ZZ/(2^32) + // coefficients: ZZ/(2^32)... // number of vars : 2 // block 1 : ordering dp // : names a b @@ -258,7 +258,7 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: sage: R = PolynomialRing(Zmod(2^1000), ("a", "b"), implementation="singular"); print(sing_print(R)) polynomial ring, over a ring (with zero-divisors), global ordering - // coefficients: ZZ/(bigint(2)^1000) + // coefficients: ZZ/(bigint(2)^1000)... // number of vars : 2 // block 1 : ordering dp // : names a b @@ -268,7 +268,7 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: sage: R = PolynomialRing(Zmod(3^300), ("a", "b"), implementation="singular"); print(sing_print(R)) polynomial ring, over a ring (with zero-divisors), global ordering - // coefficients: ZZ/(bigint(3)^300) + // coefficients: ZZ/(bigint(3)^300)... // number of vars : 2 // block 1 : ordering dp // : names a b @@ -278,7 +278,7 @@ cdef ring *singular_ring_new(base_ring, n, names, term_order) except NULL: sage: R = PolynomialRing(Zmod(15^20), ("a", "b"), implementation="singular"); print(sing_print(R)) polynomial ring, over a ring (with zero-divisors), global ordering - // coefficients: ZZ/bigint(332525673007965087890625) + // coefficients: ZZ/bigint(332525673007965087890625)... // number of vars : 2 // block 1 : ordering dp // : names a b diff --git a/src/sage/libs/sirocco.pyx b/src/sage/libs/sirocco.pyx index ca3b267fa66..7be4d96e7ac 100644 --- a/src/sage/libs/sirocco.pyx +++ b/src/sage/libs/sirocco.pyx @@ -1,4 +1,4 @@ -#cython: boundscheck=False, wraparound=False +# cython: boundscheck=False, wraparound=False # distutils: libraries = sirocco # distutils: language = c++ # sage_setup: distribution = sagemath-sirocco diff --git a/src/sage/manifolds/differentiable/integrated_curve.py b/src/sage/manifolds/differentiable/integrated_curve.py index 8b2d1f0251c..2d07ad8f50a 100644 --- a/src/sage/manifolds/differentiable/integrated_curve.py +++ b/src/sage/manifolds/differentiable/integrated_curve.py @@ -504,10 +504,11 @@ def __init__(self, parent, equations_rhs, velocities, parameters = set() # extract all the variables appearing in the equations: for eqn in equations_rhs: - if isinstance(eqn, Expression): # some right hand sides - # might merely be real numbers and not expressions, so that - # they do not contain any variable, and method 'variables' - # could not be called on them + if isinstance(eqn, Expression): + # some right hand sides + # might merely be real numbers and not expressions, so that + # they do not contain any variable, and method 'variables' + # could not be called on them parameters = parameters.union(eqn.variables()) # remove the Expressions that should not be treated as # parameters (i.e. the coordinate functions, the velocities and @@ -521,7 +522,7 @@ def __init__(self, parent, equations_rhs, velocities, # extract all the variables appearing in the initial point # coordinates: for coord in initial_pt_coords: - if isinstance(coord,Expression): + if isinstance(coord, Expression): parameters = parameters.union(coord.variables()) # extract all the variables appearing in the initial tangent # vector components: @@ -548,9 +549,9 @@ def __init__(self, parent, equations_rhs, velocities, # define all attributes if not isinstance(equations_rhs, dict): - self._equations_rhs = list(equations_rhs) # converts to list + self._equations_rhs = list(equations_rhs) # converts to list # since might not already be a list (which is later required) - else: # case multi charts + else: # case multi charts self._equations_rhs = equations_rhs self._across_charts = across_charts @@ -565,14 +566,15 @@ def __init__(self, parent, equations_rhs, velocities, M = M.numpy() for i in range(dim): for j in range(dim): - M[i,j] = fast_callable(SR(M[i, j]), vars=list(CoF[1]._chart[:]), domain=float) + M[i, j] = fast_callable(SR(M[i, j]), vars=list(CoF[1]._chart[:]), domain=float) import numpy as np + def fast_CoF(pos, vel, M=M): - # using default arguments for binding (ugly python) - #print(det(*pos)) - return list(np.dot( [[M[j, i](*pos) for i in range(dim)] - for j in range(dim)], vel)) + # using default arguments for binding (ugly python) + # print(det(*pos)) + return list(np.dot([[M[j, i](*pos) for i in range(dim)] + for j in range(dim)], vel)) self._fast_changes_of_frame[CoF] = fast_CoF @@ -582,7 +584,7 @@ def fast_CoF(pos, vel, M=M): for f in transf] self._fast_changes_of_chart[CoC] = fast_transf - self._velocities = list(velocities) # converts to list + self._velocities = list(velocities) # converts to list # since might not already be a list (which is later required) self._curve_parameter = curve_parameter self._initial_tangent_vector = initial_tangent_vector @@ -1126,9 +1128,9 @@ def solve(self, step=None, method='odeint', solution_key=None, for i in range(dim): if isinstance(eqns_num[i], Expression): # some right - # hand sides might merely be real numbers and not - # expressions, so that they do not contain any variable, - # and hence no substitution is required + # hand sides might merely be real numbers and not + # expressions, so that they do not contain any variable, + # and hence no substitution is required eqns_num[i] = eqns_num[i].substitute(parameters_values) for i in range(dim): @@ -1147,10 +1149,11 @@ def solve(self, step=None, method='odeint', solution_key=None, t_max = numerical_approx(t_max) for i in range(dim): - if not isinstance(eqns_num[i], Expression): # in case of a - # right hand side that is not an Expression (and then is a - # number), it is needed to be converted to an Expression - # since some solvers called below require only expressions + if not isinstance(eqns_num[i], Expression): + # in case of a + # right hand side that is not an Expression (and then is a + # number), it is needed to be converted to an Expression + # since some solvers called below require only expressions eqns_num[i] = SR(eqns_num[i]) if step is None: diff --git a/src/sage/manifolds/differentiable/manifold_homset.py b/src/sage/manifolds/differentiable/manifold_homset.py index 98fdf8998f5..1ce82e51ae1 100644 --- a/src/sage/manifolds/differentiable/manifold_homset.py +++ b/src/sage/manifolds/differentiable/manifold_homset.py @@ -892,9 +892,10 @@ def _an_element_(self): # chart used on the codomain. if dom == codom: param = var('s') - if t == param: # the canonical coordinate of the domain - # might be the expression 's' even though it was affected - # above to the variable 't' + if t == param: + # the canonical coordinate of the domain + # might be the expression 's' even though it was affected + # above to the variable 't' param = var('u') else: param = t @@ -903,8 +904,8 @@ def _an_element_(self): # where a certain integrated curve may be defined: H = Hom(dom, codom) c = H.an_element() - x0_A = c.expr()[0].substitute({t:1}) - x0_B = c.expr()[0].substitute({t:0}) # necessarily, x0_A < x0_B + x0_A = c.expr()[0].substitute({t: 1}) + x0_B = c.expr()[0].substitute({t: 0}) # necessarily, x0_A < x0_B p_coords = [x0_A] + list(c.expr()[1:dim]) p = codom.point(p_coords) diff --git a/src/sage/manifolds/differentiable/tensorfield.py b/src/sage/manifolds/differentiable/tensorfield.py index 50ed9fe7a80..5e6c5438914 100644 --- a/src/sage/manifolds/differentiable/tensorfield.py +++ b/src/sage/manifolds/differentiable/tensorfield.py @@ -547,7 +547,7 @@ def __bool__(self): # #### End of required methods for ModuleElement (beside arithmetic) ##### - def _repr_(self): + def _repr_(self) -> str: r""" String representation of ``self``. @@ -564,7 +564,7 @@ def _repr_(self): if self._name is not None: description += self._name + " " else: - # Generic case + # Generic case description = "Tensor field " if self._name is not None: description += self._name + " " diff --git a/src/sage/matrix/matrix_mod2_dense.pyx b/src/sage/matrix/matrix_mod2_dense.pyx index 676a2fc7f49..a1e79eda019 100644 --- a/src/sage/matrix/matrix_mod2_dense.pyx +++ b/src/sage/matrix/matrix_mod2_dense.pyx @@ -1799,6 +1799,12 @@ cdef class Matrix_mod2_dense(matrix_dense.Matrix_dense): # dense or sparse sage: A.set_immutable() sage: loads(dumps(A)).is_immutable() True + + Check that :issue:`39367` is achieved:: + + sage: l = len(dumps(random_matrix(GF(2), 2000, 2000))); l # random # previously ~ 785000 + 610207 + sage: assert l < 650000 """ cdef int i,j, r,c, size @@ -1817,11 +1823,17 @@ cdef class Matrix_mod2_dense(matrix_dense.Matrix_dense): # dense or sparse if mzd_read_bit(self._entries, i, j): gdImageSetPixel(im, j, i, black ) - cdef signed char *buf = gdImagePngPtr(im, &size) + cdef char *buf + try: + buf = gdImagePngPtr(im, &size) + finally: + gdImageDestroy(im) - data = [buf[i] for i in range(size)] - gdFree(buf) - gdImageDestroy(im) + cdef bytes data + try: + data = buf[:size] + finally: # recommended by https://cython.readthedocs.io/en/latest/src/tutorial/strings.html + gdFree(buf) return unpickle_matrix_mod2_dense_v2, (r,c, data, size, self._is_immutable) cpdef _export_as_string(self): @@ -2195,6 +2207,28 @@ def unpickle_matrix_mod2_dense_v2(r, c, data, size, immutable=False): sage: loads(s) [1 0] [0 1] + + Check that old pickles before :issue:`39367` still work:: + + sage: loads(bytes.fromhex( # hexstring produced with dumps(matrix.zero(GF(2),10,10)).hex() + ....: '789c6b604a2e4e4c4fd5cb4d2c29caac8052f1b9f92946f129a979c5a95ca5' + ....: '790599c9d939a9f11852f165465c850c1ade5cde5cb1858c1a5e9dfffffff7' + ....: '0ef0f6f376f7e6050a4a01310318f27a7b7a7b78bb780741f95c709ad19b19' + ....: 'c2f6da0ed4ecf5076442acd73f100551c20634d0c73bc4db15aaec3f481982' + ....: '580a226e8288f920e22e4223a77701d0ce48ef62308fcfeb084c0aca64f49a' + ....: '0aa2b4bdf9bca5a15af880ce74f17604dac6e135132499ecf50344d57b3580' + ....: '75789b7b330195b103fd21e85deeb51064e362908c2f441d03147a025debe7' + ....: 'ede2b50e24e8e49de0d50464a47ae775961432051532eb0100093b9ba3')) + [0 0 0 0 0 0 0 0 0 0] + [0 0 0 0 0 0 0 0 0 0] + [0 0 0 0 0 0 0 0 0 0] + [0 0 0 0 0 0 0 0 0 0] + [0 0 0 0 0 0 0 0 0 0] + [0 0 0 0 0 0 0 0 0 0] + [0 0 0 0 0 0 0 0 0 0] + [0 0 0 0 0 0 0 0 0 0] + [0 0 0 0 0 0 0 0 0 0] + [0 0 0 0 0 0 0 0 0 0] """ from sage.matrix.constructor import Matrix from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF @@ -2206,15 +2240,21 @@ def unpickle_matrix_mod2_dense_v2(r, c, data, size, immutable=False): if r == 0 or c == 0: return A - cdef signed char *buf = check_malloc(size) - for i from 0 <= i < size: - buf[i] = data[i] - - sig_on() - cdef gdImagePtr im = gdImageCreateFromPngPtr(size, buf) - sig_off() + cdef signed char *buf + cdef gdImagePtr im + if isinstance(data, bytes): + sig_on() + im = gdImageCreateFromPngPtr(size, data) + sig_off() + else: + buf = check_malloc(size) + for i from 0 <= i < size: + buf[i] = data[i] - sig_free(buf) + sig_on() + im = gdImageCreateFromPngPtr(size, buf) + sig_off() + sig_free(buf) if gdImageSX(im) != c or gdImageSY(im) != r: raise TypeError("Pickled data dimension doesn't match.") diff --git a/src/sage/matrix/symplectic_basis.py b/src/sage/matrix/symplectic_basis.py index 47dc053a9ce..de8cb9401df 100644 --- a/src/sage/matrix/symplectic_basis.py +++ b/src/sage/matrix/symplectic_basis.py @@ -368,7 +368,7 @@ def _smallest_element_position_or_None(E, pivot): for i in range(pivot, n): for j in range(pivot, n): v = E[j, i] - if 0 < v and v < min: + if 0 < v < min: min = v found = (j, i) return found diff --git a/src/sage/matroids/basis_matroid.pyx b/src/sage/matroids/basis_matroid.pyx index 73c75f27b01..6a6823246d2 100644 --- a/src/sage/matroids/basis_matroid.pyx +++ b/src/sage/matroids/basis_matroid.pyx @@ -136,7 +136,7 @@ cdef class BasisMatroid(BasisExchangeMatroid): """ def __init__(self, M=None, groundset=None, bases=None, nonbases=None, rank=None): """ - See class definition for full documentation. + See the class definition for full documentation. EXAMPLES:: @@ -1086,9 +1086,9 @@ cdef class BasisMatroid(BasisExchangeMatroid): .. WARNING:: - This method is linked to __richcmp__ (in Cython) and __cmp__ or - __eq__/__ne__ (in Python). If you override one, you should (and in - Cython: MUST) override the other! + This method is linked to ``__richcmp__`` (in Cython) and ``__cmp__`` + or ``__eq__``/``__ne__`` (in Python). If you override one, you + should (and, in Cython, \emph{must}) override the other! EXAMPLES:: diff --git a/src/sage/matroids/circuit_closures_matroid.pyx b/src/sage/matroids/circuit_closures_matroid.pyx index 72cd1c4fc16..ea30d97b72c 100644 --- a/src/sage/matroids/circuit_closures_matroid.pyx +++ b/src/sage/matroids/circuit_closures_matroid.pyx @@ -127,7 +127,7 @@ cdef class CircuitClosuresMatroid(Matroid): def __init__(self, M=None, groundset=None, circuit_closures=None): """ - Initialization of the matroid. See class docstring for full + Initialization of the matroid. See the class docstring for full documentation. EXAMPLES:: @@ -427,9 +427,9 @@ cdef class CircuitClosuresMatroid(Matroid): .. WARNING:: - This method is linked to __richcmp__ (in Cython) and __cmp__ or - __eq__/__ne__ (in Python). If you override one, you should - (and in Cython: MUST) override the other! + This method is linked to ``__richcmp__`` (in Cython) and ``__cmp__`` + or ``__eq__``/``__ne__`` (in Python). If you override one, you + should (and, in Cython, \emph{must}) override the other! EXAMPLES:: diff --git a/src/sage/matroids/circuits_matroid.pyx b/src/sage/matroids/circuits_matroid.pyx index a93efd85b33..5158de99c34 100644 --- a/src/sage/matroids/circuits_matroid.pyx +++ b/src/sage/matroids/circuits_matroid.pyx @@ -57,7 +57,7 @@ cdef class CircuitsMatroid(Matroid): def __init__(self, M=None, groundset=None, circuits=None, nsc_defined=False): """ - Initialization of the matroid. See class docstring for full + Initialization of the matroid. See the class docstring for full documentation. TESTS:: @@ -320,9 +320,9 @@ cdef class CircuitsMatroid(Matroid): .. WARNING:: - This method is linked to __richcmp__ (in Cython) and __cmp__ or - __eq__/__ne__ (in Python). If you override one, you should - (and in Cython: MUST) override the other! + This method is linked to ``__richcmp__`` (in Cython) and ``__cmp__`` + or ``__eq__``/``__ne__`` (in Python). If you override one, you + should (and, in Cython, \emph{must}) override the other! EXAMPLES:: diff --git a/src/sage/matroids/dual_matroid.py b/src/sage/matroids/dual_matroid.py index 3c7c92e6c9c..59dcfa73cc9 100644 --- a/src/sage/matroids/dual_matroid.py +++ b/src/sage/matroids/dual_matroid.py @@ -83,7 +83,7 @@ class DualMatroid(Matroid): def __init__(self, matroid): """ - See class definition for documentation. + See the class definition for documentation. EXAMPLES:: @@ -400,9 +400,9 @@ def __hash__(self): .. WARNING:: - This method is linked to __richcmp__ (in Cython) and __cmp__ or - __eq__/__ne__ (in Python). If you override one, you should (and in - Cython: MUST) override the other! + This method is linked to ``__richcmp__`` (in Cython) and ``__cmp__`` + or ``__eq__``/``__ne__`` (in Python). If you override one, you + should (and, in Cython, \emph{must}) override the other! EXAMPLES:: diff --git a/src/sage/matroids/extension.pyx b/src/sage/matroids/extension.pyx index 83b792e8d2b..3d945b88d96 100644 --- a/src/sage/matroids/extension.pyx +++ b/src/sage/matroids/extension.pyx @@ -301,7 +301,7 @@ cdef class LinearSubclasses: """ def __init__(self, M, line_length=None, subsets=None, splice=None): """ - See class docstring for full documentation. + See the class docstring for full documentation. EXAMPLES:: @@ -466,7 +466,7 @@ cdef class MatroidExtensions(LinearSubclasses): """ def __init__(self, M, e, line_length=None, subsets=None, splice=None, orderly=False): """ - See class docstring for full documentation. + See the class docstring for full documentation. EXAMPLES:: diff --git a/src/sage/matroids/flats_matroid.pyx b/src/sage/matroids/flats_matroid.pyx index ff1b21fec0c..c952172b670 100644 --- a/src/sage/matroids/flats_matroid.pyx +++ b/src/sage/matroids/flats_matroid.pyx @@ -55,7 +55,7 @@ cdef class FlatsMatroid(Matroid): def __init__(self, M=None, groundset=None, flats=None): """ - Initialization of the matroid. See class docstring for full + Initialization of the matroid. See the class docstring for full documentation. TESTS:: @@ -279,9 +279,9 @@ cdef class FlatsMatroid(Matroid): .. WARNING:: - This method is linked to __richcmp__ (in Cython) and __cmp__ or - __eq__/__ne__ (in Python). If you override one, you should - (and in Cython: MUST) override the other! + This method is linked to ``__richcmp__`` (in Cython) and ``__cmp__`` + or ``__eq__``/``__ne__`` (in Python). If you override one, you + should (and, in Cython, \emph{must}) override the other! EXAMPLES:: diff --git a/src/sage/matroids/gammoid.py b/src/sage/matroids/gammoid.py new file mode 100644 index 00000000000..a7b022748f8 --- /dev/null +++ b/src/sage/matroids/gammoid.py @@ -0,0 +1,598 @@ +r""" +Gammoids + +Let `D` be a directed graph and let `E` and `T` be not necessarily disjoint +sets of vertices of `D`. Say a subset `X` of `E` is in a collection `I` if +`X` can be linked into a subset of `T`. This defines a gammoid `(E, I)`, +where `E` is the groundset of a matroid and `I` is its independent sets. + +Some authors use a reverse convention, where instead of a set `T` of roots, +they have a starting set `S` that is linked into subsets of `E`. Here we use +the convention that the vertices `T` are at the end of the directed paths, +not the beginning. + +To construct a gammoid, first import Gammoid from +:mod:`sage.matroids.gammoid`. +A digraph and a list of roots from the vertex set are required for input:: + + sage: from sage.matroids.gammoid import * + sage: edgelist = [(0,1),(1,2),(2,3),(3,4)] + sage: D = DiGraph(edgelist) + sage: M = Gammoid(D, roots=[4]); M + Gammoid of rank 1 on 5 elements + sage: N = Gammoid(D, roots=[4], groundset=range(1,5)); N + Gammoid of rank 1 on 4 elements + sage: M.delete(0) == N + True + sage: N.is_isomorphic(matroids.Uniform(1,4)) + True + sage: O = Gammoid(D, roots=[3]); O + Gammoid of rank 1 on 5 elements + sage: O.rank([0]) + 1 + sage: O.rank([4]) + 0 + +AUTHORS: + +- Zachary Gershkoff (2017-08-25): initial version +""" + +# ***************************************************************************** +# Copyright (C) 2017 Zachary Gershkoff +# +# +# Distributed under the terms of the GNU General Public License (GPL) +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# http://www.gnu.org/licenses/ +# ***************************************************************************** + +from sage.graphs.digraph import DiGraph +from sage.matroids.matroid import Matroid +from sage.matroids.minor_matroid import MinorMatroid + + +class Gammoid(Matroid): + r""" + The gammoid class. + + INPUT: + + - ``D`` -- a loopless digraph representing the gammoid + - ``roots`` -- a subset of the vertices + - ``groundset`` -- (optional) a subset of the vertices + + OUTPUT: :class:`Gammoid`; if ``groundset`` is not specified, + the entire vertex set is used (and the gammoid will be strict) + + EXAMPLES:: + + sage: from sage.matroids.gammoid import Gammoid + sage: D = digraphs.TransitiveTournament(5) + sage: M = Gammoid(D, roots=[3, 4]); M + Gammoid of rank 2 on 5 elements + sage: M.is_isomorphic(matroids.Uniform(2, 5)) + True + sage: D.add_vertex(6) + sage: N = Gammoid(D, roots=[3, 4]) + sage: N.loops() + frozenset({6}) + sage: O = Gammoid(D, roots=[3, 4, 6]) + sage: O.coloops() + frozenset({6}) + sage: O.full_rank() + 3 + sage: P = Gammoid(D, roots=[3, 4], groundset=[0, 2, 3]); P + Gammoid of rank 2 on 3 elements + """ + + def __init__(self, D, roots, groundset=None): + """ + See the class definition for full documentation. + + EXAMPLES:: + + sage: from sage.matroids.gammoid import Gammoid + sage: edgedict = {1: [2], 2: [3], 4: [1, 5], 5: [2, 3, 8], + ....: 6: [4, 7], 7: [5, 8]} + sage: D = DiGraph(edgedict) + sage: M = Gammoid(D, roots=[1, 2, 3]) + sage: N1 = Gammoid(D, groundset=range(1, 8), roots=[1, 2, 3]) + sage: N2 = M.delete(8) + sage: N1 == N2 + True + + TESTS:: + + sage: from sage.matroids.gammoid import Gammoid + sage: D = DiGraph([(0, 0), (0, 1), (1, 1)], loops=True) + sage: M = Gammoid(D, roots=[1]) + Traceback (most recent call last): + ... + ValueError: cannot add edge from 0 to 0 in graph without loops + sage: D = DiGraph([(0, 1), (0, 1)], multiedges=True) + sage: M = Gammoid(D, roots=[1]) + sage: M.is_isomorphic(matroids.Uniform(1, 2)) + True + sage: M = Gammoid(D, roots=[3]) + Traceback (most recent call last): + ... + ValueError: roots must be a subset of the vertices + sage: M = Gammoid(D, roots=[1], groundset=[3]) + Traceback (most recent call last): + ... + ValueError: groundset must be a subset of the vertices + + :: + + sage: from sage.matroids.gammoid import Gammoid + sage: edgedict = {1: [2], 2: [3], 4: [1, 5], 5: [2, 3, 8], + ....: 6: [4, 7], 7: [5, 8]} + sage: D = DiGraph(edgedict) + sage: M = Gammoid(D, roots=[]); M + Gammoid of rank 0 on 8 elements + sage: M = Gammoid(D, roots=[], groundset=[]); M + Gammoid of rank 0 on 0 elements + + :: + + sage: from sage.matroids.gammoid import Gammoid + sage: M = Gammoid(digraphs.TransitiveTournament(5), roots=[3, 4]) + sage: TestSuite(M).run() + sage: TestSuite(M).run(verbose=True) + running ._test_category() . . . pass + running ._test_new() . . . pass + running ._test_not_implemented_methods() . . . pass + running ._test_pickling() . . . pass + """ + self._roots = frozenset(roots) + vertices = frozenset(D.vertices()) + if not self._roots.issubset(vertices): + raise ValueError("roots must be a subset of the vertices") + + if groundset is None: + self._groundset = vertices + else: + self._groundset = frozenset(groundset) + if not self._groundset.issubset(vertices): + raise ValueError("groundset must be a subset of the vertices") + + # self._D is used for computations + # self._G is used for referencing and hashing + # loops will cause an error here, but multiedges will be ignored + self._D = DiGraph([D.vertices(), D.edges(labels=False)]) + self._prune_vertices() + self._G = self._D.copy(immutable=True) + self._rootv = self._D.add_vertex() + for v in roots: + self._D.add_edge(v, self._rootv) + + def _prune_vertices(self): + """ + Remove irrelevant vertices from the internal digraph. + + This will remove vertices that are not part of the groundset and + cannot be used in a valid path between an element and a root. + However, this will not remove a cycle of such vertices. + + EXAMPLES:: + + sage: from sage.matroids.gammoid import Gammoid + sage: D = digraphs.TransitiveTournament(5) + sage: D.add_vertex(6) + sage: M = Gammoid(D, roots=[3, 4], groundset=[0, 1, 4]) + sage: M.digraph().vertices() + [0, 1, 2, 3, 4] + """ + vertices_c = self._roots.union(self._groundset) + extra_sources = set(self._D.sources()).difference(vertices_c) + extra_sinks = set(self._D.sinks()).difference(vertices_c) + while extra_sources or extra_sinks: + self._D.delete_vertices(set(extra_sources).union(extra_sinks)) + extra_sources = set(self._D.sources()).difference(vertices_c) + extra_sinks = set(self._D.sinks()).difference(vertices_c) + + def __hash__(self): + r""" + Return an invariant of the matroid. + + This function is called when matroids are added to a set. It is very + desirable to override it so it can distinguish matroids on the same + groundset, which is a very typical use case! + + .. WARNING:: + + This method is linked to ``__richcmp__`` (in Cython) and ``__cmp__`` + or ``__eq__``/``__ne__`` (in Python). If you override one, you + should (and, in Cython, \emph{must}) override the other! + + EXAMPLES:: + + sage: from sage.matroids.gammoid import Gammoid + sage: D = digraphs.TransitiveTournament(5) + sage: M1 = Gammoid(D, roots=[3, 4]) + sage: M2 = Gammoid(D, roots=[2, 3]) + sage: hash(M1) == hash(M2) + False + sage: N1 = M1.delete(2) + sage: N2 = Gammoid(D, roots=[3, 4], groundset=[0, 1, 3, 4]) + sage: hash(N1) == hash(N2) + True + sage: D.delete_edge(0, 4) + sage: M3 = Gammoid(D, roots=[3, 4]) + sage: hash(M1) == hash(M3) + False + """ + return hash((self._G, self._groundset, self._roots)) + + def __eq__(self, other): + """ + Compare two matroids. + + For two graphic matroids to be equal, all attributes of the underlying + graphs must be equal. + + INPUT: + + - ``other`` -- matroid + + OUTPUT: ``True`` if ``self`` and ``other`` have the same digraph, + roots, and groundset; ``False`` otherwise + + EXAMPLES:: + + sage: from sage.matroids.gammoid import Gammoid + sage: D = digraphs.TransitiveTournament(5) + sage: M1 = Gammoid(D, roots=[3, 4]) + sage: M2 = Gammoid(D, roots=[2, 3]) + sage: M1 == M2 + False + sage: N1 = M1.delete(2) + sage: N2 = Gammoid(D, roots=[3, 4], groundset=[0, 1, 3, 4]) + sage: N1 == N2 + True + """ + if not isinstance(other, Gammoid): + return False + # The roots are implied by self._D + return (self._D == other._D and self._groundset == other._groundset) + + def __ne__(self, other): + """ + Compare two matroids. + + INPUT: + + - ``other`` -- matroid + + OUTPUT: ``False`` if ``self`` and ``other`` have the same digraphs, + roots, and groundset; ``True`` otherwise + + EXAMPLES:: + + sage: from sage.matroids.gammoid import Gammoid + sage: edgedict = {1: [2], 2: [3], 4: [1, 5], 5: [2, 3, 8], 6: [4, 7], + ....: 7: [5, 8]} + sage: D = DiGraph(edgedict) + sage: M = Gammoid(D, roots=[1, 2, 3]) + sage: D.relabel([1, 2, 3, 4, 5, 6, 7, 'a']) + sage: N = Gammoid(D, roots=[1, 2, 3]) + sage: M == N + False + sage: M.delete(8) == N.delete('a') + True + """ + return (not self == other) + + def __reduce__(self): + """ + Save the matroid for later reloading. + + OUTPUT: + + A tuple ``(unpickle, (version, data))``, where ``unpickle`` is the + name of a function that, when called with ``(version, data)``, + produces a matroid isomorphic to ``self``. ``version`` is an integer + (currently 0) and ``data`` is a tuple ``(E, F, name)`` where ``E`` is + the groundset, ``F`` is the dictionary of flats, and ``name`` is a + custom name. + + EXAMPLES:: + + sage: from sage.matroids.gammoid import Gammoid + sage: edgelist = [(0, 4), (0, 5), (1, 0), (1, 4), (2, 0), (2, 1), (2, 3), + ....: (2, 6), (3, 4), (3, 5), (4, 0), (5, 2), (6, 5)] + sage: D = DiGraph(edgelist) + sage: M = Gammoid(D, roots=[4, 5, 6]) + sage: M.rename("Example Gammoid: " + repr(M)) + sage: M == loads(dumps(M)), loads(dumps(M)) # indirect doctest + (True, Example Gammoid: Gammoid of rank 3 on 7 elements) + sage: M.reset_name() + sage: loads(dumps(M)) + Gammoid of rank 3 on 7 elements + """ + import sage.matroids.unpickling + data = (self._D, self._roots, self._groundset, self.get_custom_name()) + version = 0 + return sage.matroids.unpickling.unpickle_gammoid, (version, data) + + def digraph(self): + """ + Return the digraph associated with the gammoid. + + EXAMPLES:: + + sage: from sage.matroids.gammoid import Gammoid + sage: edgelist = [(0, 4), (0, 5), (1, 0), (1, 4), (2, 0), (2, 1), (2, 3), + ....: (2, 6), (3, 4), (3, 5), (4, 0), (5, 2), (6, 5)] + sage: D = DiGraph(edgelist) + sage: M = Gammoid(D, roots=[4, 5, 6]) + sage: M.digraph() == D + True + """ + return self._G.copy(data_structure='sparse') + + def digraph_plot(self): + """ + Plot the graph with color-coded vertices. + + Vertices that are elements but not roots will be shown as blue. Vertices that + are roots but not elements are red. Vertices that are both are pink, and vertices + that are neither are grey. + + EXAMPLES:: + + sage: from sage.matroids.gammoid import Gammoid + sage: D = digraphs.TransitiveTournament(4) + sage: M = Gammoid(D, roots=[2, 3]) + sage: M.digraph_plot() + Graphics object consisting of 11 graphics primitives + """ + self._inter = frozenset(self._roots.intersection(self._groundset)) + self._buckets = frozenset(self._roots.difference(self._inter)) + self._ending = frozenset(self._groundset.difference(self._inter)) + self._therest = set(self._G.vertices()).difference(self._roots) + self._therest = frozenset(self._therest.difference(self._groundset)) + # Vertices just in buckets set are red "#D55E00" + # Vertices just in the ending set are blue "#0072B2" + # Vertices in both are pink "#CC79A7" + # Vertices in neither are grey "#999999" + d = {"#D55E00": list(self._buckets), "#CC79A7": list(self._inter), + "#0072B2": list(self._ending), "#999999": list(self._therest)} + return self._G.plot(vertex_colors=d) + + def _rank(self, X): + """ + Return the rank of a set. + + EXAMPLES:: + + sage: from sage.matroids.gammoid import Gammoid + sage: D = digraphs.TransitiveTournament(4) + sage: M = Gammoid(D, roots=[2, 3]) + sage: M.rank([2]) + 1 + sage: M.full_rank() + 2 + sage: M.rank(M.groundset()) + 2 + """ + source = self._D.add_vertex() + for x in X: + self._D.add_edge(source, x) + + rank = len(self._D.vertex_disjoint_paths(source, self._rootv)) + self._D.delete_vertex(source) + return rank + + def groundset(self): + """ + Return the groundset of the matroid. + + EXAMPLES:: + + sage: from sage.matroids.gammoid import Gammoid + sage: edgelist = [(0, 4), (0, 5), (1, 0), (1, 4), (2, 0), (2, 1), (2, 3), + ....: (2, 6), (3, 4), (3, 5), (4, 0), (5, 2), (6, 5)] + sage: D = DiGraph(edgelist) + sage: M = Gammoid(D, roots=[4, 5, 6]) + sage: sorted(M.groundset()) + [0, 1, 2, 3, 4, 5, 6] + """ + return self._groundset + + def _repr_(self): + """ + Return a string representation of the matroid. + + EXAMPLES: + + sage: from sage.matroids.gammoid import Gammoid + sage: edgelist = [(0, 4), (0, 5), (1, 0), (1, 4), (2, 0), (2, 1), (2, 3), + ....: (2, 6), (3, 4), (3, 5), (4, 0), (5, 2), (6, 5)] + sage: D = DiGraph(edgelist) + sage: M = Gammoid(D, roots=[4, 5, 6]); M + Gammoid of rank 3 on 7 elements + """ + self._mrank = str(self._rank(self._groundset)) + self._elts = str(len(self._groundset)) + return "Gammoid of rank " + self._mrank + " on " + self._elts + " elements" + + def _minor(self, contractions=frozenset(), deletions=frozenset()): + """ + Return a minor. + + INPUT: + + - ``contractions`` -- frozenset; subset of ``self.groundset()`` to be contracted + - ``deletions`` -- frozenset; subset of ``self.groundset()`` to be deleted + + Assumptions: contractions are independent, deletions are coindependent, + contractions and deletions are disjoint. + + OUTPUT: + + If there are contractions, a :class:`MinorMatroid`. If not, a :class:`Gammoid`. + + EXAMPLES:: + + sage: from sage.matroids.gammoid import Gammoid + sage: edgedict = {1: [2], 2: [3], 4: [1,5], 5: [2, 3, 8], + ....: 6: [4, 7], 7: [5, 8]} + sage: D = DiGraph(edgedict) + sage: M = Gammoid(D, roots=[1, 2, 3]); M + Gammoid of rank 3 on 8 elements + sage: N1 = M.delete([3, 4]) + sage: N1.groundset() + frozenset({1, 2, 5, 6, 7, 8}) + """ + # Unlike TransversalMatroid, we don't check for coloops to delete + # because that would mean altering the roots + if deletions: + new_groundset = self.groundset().difference(deletions) + N = Gammoid(self.digraph(), self._roots, new_groundset) + else: + N = self + + if contractions: + return MinorMatroid(N, contractions=contractions, deletions=frozenset()) + else: + return N + + def gammoid_extension(self, vertex, neighbors=[]): + """ + Return a gammoid extended by an element. + + The new element can be a vertex of the digraph that is not in the starting set, + or it can be a new source vertex. + + INPUT: + + - ``vertex`` -- a vertex of the gammoid's digraph that is not already in the + groundset, or a new vertex + - ``neighbors`` -- (optional) a set of vertices of the digraph + + OUTPUT: + + A :class:`Gammoid`. If ``vertex`` is not already in the graph, then the + new vertex will be have edges to ``neighbors``. The new vertex will have + in degree `0` regardless of whether or not ``neighbors`` is specified. + + EXAMPLES:: + + sage: from sage.matroids.gammoid import Gammoid + sage: edgedict = {1: [2], 2: [3], 4: [1, 5], 5: [2, 3, 8], + ....: 6: [4, 7], 7: [5, 8]} + sage: D = DiGraph(edgedict) + sage: M = Gammoid(D, roots=[2, 3, 4], groundset=range(2, 9)) + sage: M1 = M.gammoid_extension(1) + sage: M1.groundset() + frozenset({1, 2, 3, 4, 5, 6, 7, 8}) + sage: N = Gammoid(D, roots=[2, 3, 4]) + sage: M1 == N + True + sage: M1.delete(1) + Gammoid of rank 3 on 7 elements + sage: M == M1.delete(1) + True + sage: M2 = M.gammoid_extension(9); sorted(M2.loops()) + [8, 9] + sage: M4 = M.gammoid_extension(9, [1, 2, 3]) + sage: M4.digraph().neighbors_out(9) + [1, 2, 3] + sage: M4.digraph().neighbors_in(9) + [] + + TESTS:: + + sage: from sage.matroids.gammoid import Gammoid + sage: edgedict = {1: [2], 2: [3], 4: [1, 5], 5: [2, 3, 8], + ....: 6: [4, 7], 7: [5, 8]} + sage: D = DiGraph(edgedict) + sage: M = Gammoid(D, roots=[2, 3, 4], groundset=range(2, 9)) + sage: M.gammoid_extension(2) + Traceback (most recent call last): + ... + ValueError: cannot extend by element already in groundset + sage: M.gammoid_extension(1, [2, 3, 4]) + Traceback (most recent call last): + ... + ValueError: neighbors of vertex in digraph cannot be changed + sage: M.gammoid_extension(9, [9]) + Traceback (most recent call last): + ... + ValueError: neighbors must already be in graph + """ + if vertex in self._groundset: + raise ValueError("cannot extend by element already in groundset") + elif vertex in self._G: + if neighbors: + raise ValueError("neighbors of vertex in digraph cannot be changed") + new_groundset = set(self._groundset).union([vertex]) + return Gammoid(D=self._G, roots=self._roots, + groundset=new_groundset) + else: + if not set(neighbors).issubset(self._G.vertices()): + raise ValueError("neighbors must already be in graph") + D = self.digraph() + D.add_vertex(vertex) + for n in neighbors: + D.add_edge(vertex, n) + new_groundset = set(self._groundset).union([vertex]) + return Gammoid(D=D, roots=self._roots, groundset=new_groundset) + + def gammoid_extensions(self, vertices=None): + """ + Return an iterator of Gammoid extensions. + + This will only consider extensions from vertices that are already present + in the digraph. + + INPUT: + + - ``vertices`` -- (optional) a list of vertices not in the digraph + + OUTPUT: + + An iterator of Gammoids. If ``vertices`` is not specified, every vertex + not already in the groundset will be considered. + + EXAMPLES:: + + sage: from sage.matroids.gammoid import Gammoid + sage: M = Gammoid(digraphs.TransitiveTournament(5), roots=[3, 4], + ....: groundset=[0, 1, 4]) + sage: [sorted(M1.groundset()) for M1 in M.gammoid_extensions()] + [[0, 1, 2, 4], [0, 1, 3, 4]] + sage: N = Gammoid(digraphs.TransitiveTournament(5), roots=[3, 4]) + sage: [sorted(N1.groundset()) for N1 in N.gammoid_extensions()] + [] + + :: + + sage: from sage.matroids.gammoid import Gammoid + sage: edgelist =[(i, i+1) for i in range(10)] + sage: M = Gammoid(DiGraph(edgelist), roots=[9], groundset=[0]) + sage: sum(1 for M1 in M.gammoid_extensions(vertices=[3, 4, 5])) + 3 + sage: sum(1 for M1 in M.gammoid_extensions()) + 9 + sage: set([M1.is_isomorphic(matroids.Uniform(1, 2)) + ....: for M1 in M.gammoid_extensions()]) + {True} + sage: len([M1 for M1 in M.gammoid_extensions([0, 1, 2])]) + Traceback (most recent call last): + ... + ValueError: vertices must be in the digraph and not already in the groundset + """ + free_vertices = set(self._G.vertices()).difference(self._groundset) + if vertices is None: + vertices = free_vertices + else: + vertices = set(vertices) + if not vertices.issubset(free_vertices): + raise ValueError("vertices must be in the digraph and not already in the groundset") + for v in vertices: + new_groundset = self._groundset.union([v]) + yield Gammoid(self._G, self._roots, new_groundset) diff --git a/src/sage/matroids/graphic_matroid.pyx b/src/sage/matroids/graphic_matroid.pyx index c718535b4aa..dfcc362f28b 100644 --- a/src/sage/matroids/graphic_matroid.pyx +++ b/src/sage/matroids/graphic_matroid.pyx @@ -1,6 +1,6 @@ # sage.doctest: optional - sage.graphs r""" -Graphic Matroids +Graphic matroids Let `G = (V,E)` be a graph and let `C` be the collection of the edge sets of cycles in `G`. The corresponding graphic matroid `M(G)` has groundset `E` @@ -152,7 +152,7 @@ cdef class GraphicMatroid(Matroid): def __init__(self, G, groundset=None): """ - See class definition for full documentation. + See the class definition for full documentation. EXAMPLES:: @@ -273,8 +273,7 @@ cdef class GraphicMatroid(Matroid): """ cdef DisjointSet_of_hashables DS_vertices cdef list edges = self.groundset_to_edges(X) - cdef set vertices = set([u for (u, v, l) in edges]).union( - [v for (u, v, l) in edges]) + cdef set vertices = set([u for (u, v, l) in edges]).union([v for (u, v, l) in edges]) # This counts components: DS_vertices = DisjointSet_of_hashables(vertices) for (u, v, l) in edges: @@ -343,9 +342,9 @@ cdef class GraphicMatroid(Matroid): .. WARNING:: - This method is linked to __richcmp__ (in Cython) and __cmp__ or - __eq__/__ne__ (in Python). If you override one, you should (and in - Cython: MUST) override the other! + This method is linked to ``__richcmp__`` (in Cython) and ``__cmp__`` + or ``__eq__``/``__ne__`` (in Python). If you override one, you + should (and, in Cython, \emph{must}) override the other! EXAMPLES:: @@ -476,9 +475,9 @@ cdef class GraphicMatroid(Matroid): EXAMPLES:: sage: M = matroids.CompleteGraphic(5) - sage: M._minor(deletions=frozenset([0,1,2]), contractions=frozenset([])) + sage: M._minor(deletions=frozenset([0,1,2]), contractions=frozenset()) Graphic matroid of rank 4 on 7 elements - sage: M._minor(deletions=frozenset([]), contractions=frozenset([0,1,2])) + sage: M._minor(deletions=frozenset(), contractions=frozenset([0,1,2])) Graphic matroid of rank 1 on 7 elements sage: M = Matroid(range(15), graphs.PetersenGraph()) sage: N = M._minor(deletions=frozenset([0, 3, 5, 9]), diff --git a/src/sage/matroids/lean_matrix.pyx b/src/sage/matroids/lean_matrix.pyx index 82de4b9a648..11f47bd3abd 100644 --- a/src/sage/matroids/lean_matrix.pyx +++ b/src/sage/matroids/lean_matrix.pyx @@ -673,7 +673,7 @@ cdef class GenericMatrix(LeanMatrix): def __init__(self, long nrows, long ncols, M=None, ring=None): """ - See class docstring for full information. + See the class docstring for full information. EXAMPLES:: @@ -982,7 +982,7 @@ cdef class BinaryMatrix(LeanMatrix): def __init__(self, long m, long n, object M=None, object ring=None): """ - See class docstring for full specification. + See the class docstring for full specification. EXAMPLES:: @@ -1605,7 +1605,7 @@ cdef class TernaryMatrix(LeanMatrix): def __init__(self, long m, long n, M=None, ring=None): """ - See class docstring for full specification. + See the class docstring for full specification. EXAMPLES:: @@ -2157,7 +2157,7 @@ cdef class QuaternaryMatrix(LeanMatrix): def __init__(self, long m, long n, M=None, ring=None): """ - See class docstring for full specification. + See the class docstring for full specification. EXAMPLES:: @@ -2775,7 +2775,7 @@ cdef class PlusMinusOneMatrix(LeanMatrix): def __init__(self, long nrows, long ncols, M=None, ring=None): """ - See class docstring for full information. + See the class docstring for full information. EXAMPLES:: @@ -3209,7 +3209,7 @@ cdef class RationalMatrix(LeanMatrix): def __init__(self, long nrows, long ncols, M=None, ring=None): """ - See class docstring for full information. + See the class docstring for full information. EXAMPLES:: diff --git a/src/sage/matroids/linear_matroid.pyx b/src/sage/matroids/linear_matroid.pyx index 02d1d3c28d9..7259f9f1dc0 100644 --- a/src/sage/matroids/linear_matroid.pyx +++ b/src/sage/matroids/linear_matroid.pyx @@ -259,7 +259,7 @@ cdef class LinearMatroid(BasisExchangeMatroid): """ def __init__(self, matrix=None, groundset=None, reduced_matrix=None, ring=None, keep_initial_representation=True): """ - See class definition for full documentation. + See the class definition for full documentation. EXAMPLES:: @@ -1285,9 +1285,9 @@ cdef class LinearMatroid(BasisExchangeMatroid): .. WARNING:: - This method is linked to __richcmp__ (in Cython) and __cmp__ or - __eq__/__ne__ (in Python). If you override one, you should (and in - Cython: MUST) override the other! + This method is linked to ``__richcmp__`` (in Cython) and ``__cmp__`` + or ``__eq__``/``__ne__`` (in Python). If you override one, you + should (and, in Cython, \emph{must}) override the other! EXAMPLES:: @@ -3078,7 +3078,7 @@ cdef class BinaryMatroid(LinearMatroid): """ def __init__(self, matrix=None, groundset=None, reduced_matrix=None, ring=None, keep_initial_representation=True, basis=None): """ - See class definition for full documentation. + See the class definition for full documentation. .. NOTE:: @@ -4111,7 +4111,7 @@ cdef class TernaryMatroid(LinearMatroid): """ def __init__(self, matrix=None, groundset=None, reduced_matrix=None, ring=None, keep_initial_representation=True, basis=None): """ - See class definition for full documentation. + See the class definition for full documentation. .. NOTE:: @@ -4989,7 +4989,7 @@ cdef class QuaternaryMatroid(LinearMatroid): """ def __init__(self, matrix=None, groundset=None, reduced_matrix=None, ring=None, keep_initial_representation=True, basis=None): """ - See class definition for full documentation. + See the class definition for full documentation. .. NOTE:: @@ -5694,7 +5694,7 @@ cdef class RegularMatroid(LinearMatroid): """ def __init__(self, matrix=None, groundset=None, reduced_matrix=None, ring=None, keep_initial_representation=True): """ - See class definition for full documentation. + See the class definition for full documentation. .. NOTE:: diff --git a/src/sage/matroids/matroid.pyx b/src/sage/matroids/matroid.pyx index fab7b9008bf..cee2b831e5b 100644 --- a/src/sage/matroids/matroid.pyx +++ b/src/sage/matroids/matroid.pyx @@ -1634,7 +1634,7 @@ cdef class Matroid(SageObject): S = frozenset(X) while cur != len(S): cur = len(S) - cl = frozenset([]) + cl = frozenset() for T in combinations(S, min(k, cur)): cl = cl.union(self._closure(frozenset(T))) S = cl @@ -3944,9 +3944,9 @@ cdef class Matroid(SageObject): .. WARNING:: - This method is linked to ``__richcmp__`` (in Cython) and - ``__cmp__`` or ``__eq__``/``__ne__`` (in Python). If you override - one, you should (and in Cython: MUST) override the other! + This method is linked to ``__richcmp__`` (in Cython) and ``__cmp__`` + or ``__eq__``/``__ne__`` (in Python). If you override one, you + should (and, in Cython, \emph{must}) override the other! EXAMPLES:: @@ -4339,7 +4339,7 @@ cdef class Matroid(SageObject): return None l = newlabel(self.groundset()) return self._extension(l, [])._minor(contractions=frozenset([l]), - deletions=frozenset([])) + deletions=frozenset()) cpdef has_minor(self, N, bint certificate=False): """ @@ -4684,7 +4684,7 @@ cdef class Matroid(SageObject): extension by a loop:: sage: M = matroids.catalog.Vamos() - sage: frozenset([]) in M.modular_cut(['ab', 'cd']) + sage: frozenset() in M.modular_cut(['ab', 'cd']) True In any extension of the matroid `S_8 \setminus h`, a point on the @@ -4943,14 +4943,14 @@ cdef class Matroid(SageObject): 3 """ E = set(self.groundset()) - E.difference_update(self._closure(frozenset([]))) # groundset minus loops + E.difference_update(self._closure(frozenset())) # groundset minus loops res = set([]) while E: e = E.pop() res.add(e) E.difference_update(self._closure(frozenset([e]))) - return self._minor(contractions=frozenset([]), + return self._minor(contractions=frozenset(), deletions=self.groundset().difference(res)) cpdef cosimplify(self): @@ -4979,7 +4979,7 @@ cdef class Matroid(SageObject): 3 """ E = set(self.groundset()) - E.difference_update(self._coclosure(frozenset([]))) # groundset minus coloops + E.difference_update(self._coclosure(frozenset())) # groundset minus coloops res = set([]) while E: @@ -4987,7 +4987,7 @@ cdef class Matroid(SageObject): res.add(e) E.difference_update(self._coclosure(frozenset([e]))) return self._minor(contractions=self.groundset().difference(res), - deletions=frozenset([])) + deletions=frozenset()) cpdef is_simple(self): """ @@ -7709,12 +7709,12 @@ cdef class Matroid(SageObject): # check if edge (u,v) exists in the auxiliary digraph exist = False if ((u in Y) and (v in E-Y) and - (self.is_dependent(Y|{v})) and - (self.is_independent((Y|{v}) - {u}))): + self.is_dependent(Y|{v}) and + self.is_independent((Y|{v}) - {u})): exist = True if ((u in E-Y) and (v in Y) and (not other.is_independent(Y|{u})) and - (other.is_independent((Y|{u}) - {v}))): + (other.is_independent((Y|{u}) - {v}))): exist = True if exist: stack.append(v) diff --git a/src/sage/matroids/meson.build b/src/sage/matroids/meson.build index 8fd8ae12895..bb72248b0ae 100644 --- a/src/sage/matroids/meson.build +++ b/src/sage/matroids/meson.build @@ -15,6 +15,7 @@ py.install_sources( 'dual_matroid.py', 'extension.pxd', 'flats_matroid.pxd', + 'gammoid.py', 'graphic_matroid.pxd', 'lean_matrix.pxd', 'linear_matroid.pxd', @@ -25,6 +26,7 @@ py.install_sources( 'named_matroids.py', 'rank_matroid.py', 'set_system.pxd', + 'transversal_matroid.pxd', 'union_matroid.pxd', 'utilities.py', subdir: 'sage/matroids', @@ -40,6 +42,7 @@ extension_data = { 'linear_matroid' : files('linear_matroid.pyx'), 'matroid' : files('matroid.pyx'), 'set_system' : files('set_system.pyx'), + 'transversal_matroid' : files('transversal_matroid.pyx'), 'union_matroid' : files('union_matroid.pyx'), 'unpickling' : files('unpickling.pyx'), 'flats_matroid' : files('flats_matroid.pyx'), diff --git a/src/sage/matroids/minor_matroid.py b/src/sage/matroids/minor_matroid.py index 68cce818f8d..3bfec4bf2a4 100644 --- a/src/sage/matroids/minor_matroid.py +++ b/src/sage/matroids/minor_matroid.py @@ -127,7 +127,7 @@ class wraps around any matroid to provide an abstract minor. It def __init__(self, matroid, contractions=None, deletions=None): """ - See class docstring for documentation. + See the class docstring for documentation. EXAMPLES:: @@ -372,9 +372,9 @@ def __hash__(self): .. WARNING:: - This method is linked to __richcmp__ (in Cython) and __cmp__ or - __eq__/__ne__ (in Python). If you override one, you should (and in - Cython: MUST) override the other! + This method is linked to ``__richcmp__`` (in Cython) and ``__cmp__`` + or ``__eq__``/``__ne__`` (in Python). If you override one, you + should (and, in Cython, \emph{must}) override the other! EXAMPLES:: diff --git a/src/sage/matroids/rank_matroid.py b/src/sage/matroids/rank_matroid.py index 7fa20b131ba..b7ac75209e5 100644 --- a/src/sage/matroids/rank_matroid.py +++ b/src/sage/matroids/rank_matroid.py @@ -142,9 +142,9 @@ def __hash__(self): .. WARNING:: - This method is linked to __richcmp__ (in Cython) and __cmp__ or - __eq__/__ne__ (in Python). If you override one, you should (and in - Cython: MUST) override the other! + This method is linked to ``__richcmp__`` (in Cython) and ``__cmp__`` + or ``__eq__``/``__ne__`` (in Python). If you override one, you + should (and, in Cython, \emph{must}) override the other! EXAMPLES:: diff --git a/src/sage/matroids/transversal_matroid.pxd b/src/sage/matroids/transversal_matroid.pxd new file mode 100644 index 00000000000..b0ade46117b --- /dev/null +++ b/src/sage/matroids/transversal_matroid.pxd @@ -0,0 +1,13 @@ +from sage.matroids.matroid cimport Matroid +from sage.matroids.basis_exchange_matroid cimport BasisExchangeMatroid + +cdef class TransversalMatroid(BasisExchangeMatroid): + cdef dict _matching + cdef object _sets + cdef object _D + cdef list _set_labels, _sets_input, _set_labels_input + + cpdef list sets(self) + cdef dict _translate_matching(self) + cpdef reduce_presentation(self) + cpdef transversal_extension(self, element=*, newset=*, sets=*) diff --git a/src/sage/matroids/transversal_matroid.pyx b/src/sage/matroids/transversal_matroid.pyx new file mode 100644 index 00000000000..7532fac62b0 --- /dev/null +++ b/src/sage/matroids/transversal_matroid.pyx @@ -0,0 +1,889 @@ +r""" +Transversal matroids + +A transversal matroid arises from a groundset `E` and a collection `A` of sets +over the groundset. This can be modeled as a bipartite graph `B`, where the +vertices on the left are groundset elements, the vertices on the right are the +sets, and edges represent containment. Then a set `X` from the groundset is +independent if and only if `X` has a matching in `B`. + +To construct a transversal matroid, first import +:class:`~sage.matroids.transversal_matroid.TransversalMatroid` from +:mod:`sage.matroids.transversal_matroid`. +The input should be a set system, formatted as an iterable of iterables:: + + sage: from sage.matroids.transversal_matroid import TransversalMatroid + sage: sets = [[3, 4, 5, 6, 7, 8]] * 3 + sage: M = TransversalMatroid(sets); M + Transversal matroid of rank 3 on 6 elements, with 3 sets + sage: M.groundset() + frozenset({3, 4, 5, 6, 7, 8}) + sage: M.is_isomorphic(matroids.Uniform(3, 6)) + True + sage: M = TransversalMatroid([[0, 1], [1, 2, 3], [3, 4, 5]], + ....: set_labels=['1', '2', '3']) + sage: M.graph().vertices() + ['1', '2', '3', 0, 1, 2, 3, 4, 5] + +AUTHORS: + +- Zachary Gershkoff (2017-08-07): initial version + +REFERENCES: + +- [Bon2017]_ +""" + +# ***************************************************************************** +# Copyright (C) 2017 Zachary Gershkoff +# +# +# Distributed under the terms of the GNU General Public License (GPL) +# as published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# http://www.gnu.org/licenses/ +# ***************************************************************************** + +from collections import Counter +from copy import copy +from cpython.object cimport Py_EQ, Py_NE +from sage.graphs.graph import Graph +from sage.graphs.digraph import DiGraph +from sage.graphs.bipartite_graph import BipartiteGraph +from sage.matroids.basis_exchange_matroid cimport BasisExchangeMatroid +from sage.matroids.minor_matroid import MinorMatroid +from sage.matroids.utilities import newlabel +import networkx as nx + + +cdef class TransversalMatroid(BasisExchangeMatroid): + r""" + The Transversal Matroid class. + + INPUT: + + - ``sets`` -- iterable of iterables of elements + - ``groundset`` -- (optional) iterable containing names of groundset + elements + - ``set_labels`` -- (optional) list of labels in 1-1 correspondence with + the iterables in ``sets`` + - ``matching`` -- (optional) dictionary specifying a maximal matching + between elements and set labels + + OUTPUT: + + An instance of ``TransversalMatroid``. The sets specified in ``sets`` + define the matroid. If ``matching`` is not specified, the constructor + will determine a matching to use for basis exchange. + + EXAMPLES:: + + sage: from sage.matroids.transversal_matroid import TransversalMatroid + sage: sets = [[0, 1, 2, 3]] * 3 + sage: M = TransversalMatroid(sets) + sage: M.full_rank() + 3 + sage: M.bases_count() + 4 + sage: sum(1 for b in M.bases()) + 4 + + :: + + sage: from sage.matroids.transversal_matroid import TransversalMatroid + sage: M = TransversalMatroid(sets=[['a', 'c']], groundset=['a', 'c', 'd']) + sage: M.loops() + frozenset({'d'}) + sage: M.full_rank() + 1 + """ + + def __init__(self, sets, groundset=None, set_labels=None, matching=None): + """ + See the class definition for full documentation. + + EXAMPLES:: + + sage: from sage.matroids.transversal_matroid import TransversalMatroid + sage: sets = [[0, 1, 2, 3], [1, 2], [1, 3, 4]] + sage: set_labels = [5, 6, 7] + sage: M = TransversalMatroid(sets, set_labels=set_labels) + sage: TestSuite(M).run() + + TESTS:: + + sage: from sage.matroids.transversal_matroid import TransversalMatroid + sage: M = TransversalMatroid([[0, 1], [1, 2], [2, 3], [3, 4]]) + sage: TestSuite(M).run() + + sage: M = TransversalMatroid([[], [], []], groundset=range(3)); M + Transversal matroid of rank 0 on 3 elements, with 3 sets + sage: sets = [[0, 1, 2, 3, 4], [4, 5]] + sage: M = TransversalMatroid(sets, groundset=[0, 1, 2, 3]) + Traceback (most recent call last): + ... + ValueError: groundset and sets do not match + sage: M = TransversalMatroid(sets, set_labels=[1, 2, 3]) + Traceback (most recent call last): + ... + ValueError: set labels do not match sets + sage: M = TransversalMatroid(sets, set_labels=[1, 2]) + Traceback (most recent call last): + ... + ValueError: set labels cannot be element labels + + sage: sets = [['s1', 's2'], ['s1', 's3']] + sage: M = TransversalMatroid(sets); M + Transversal matroid of rank 2 on 3 elements, with 2 sets + sage: M.sets() + [['s1', 's2'], ['s1', 's3']] + sage: M.set_labels() + ['s0', 's4'] + + Testing the matching parameter:: + + sage: M = TransversalMatroid([range(5)] * 4, set_labels='abcd') + sage: M.full_rank() + 4 + sage: M.rank([0, 1, 2]) + 3 + + :: + + sage: sets = [[0, 1, 2, 3], [1, 2], [1, 3, 4]] + sage: set_labels = [5, 6, 7] + sage: m = {0: 5, 1: 6, 3: 7} + sage: M = TransversalMatroid(sets, set_labels=set_labels, matching=m) + sage: len(M.bases()) + 9 + """ + contents = set([e for subset in sets for e in subset]) + if groundset is None: + groundset = contents + elif not contents.issubset(groundset): + raise ValueError("groundset and sets do not match") + groundset = tuple(groundset) + + # keep the original list as input so we don't lose order between minors etc. + self._sets_input = [list(s) for s in sets] + self._sets = Counter([frozenset(s) for s in self._sets_input]) + + # This might be redundant with self._idx from BasisExchangeMatroid + # However, BasisExchangeMatroid has not been called yet + element_int_map = {e: i for i, e in enumerate(groundset)} + int_element_map = {i: e for i, e in enumerate(groundset)} + + # we need a matching and a corresponding graph + if set_labels: + if len(set_labels) != len(sets): + raise ValueError("set labels do not match sets") + if not contents.isdisjoint(set_labels): + raise ValueError("set labels cannot be element labels") + if matching: + matching_temp = matching + self._set_labels_input = list(set_labels) + + else: + if matching: + raise ValueError("set labels must be provided if matching is provided") + self._set_labels_input = [] + increment = 0 + for i in range(len(sets)): # make sure "sn" is not in groundset + label = 's' + str(i + increment) + while label in groundset: + increment += 1 + label = 's' + str(i + increment) + self._set_labels_input.append(label) + # for internal use with integers representing elements + set_labels = ['s' + str(i) for i in range(len(sets))] + + if not matching: + B = BipartiteGraph() + for e in groundset: + B.add_vertex(element_int_map[e], left=True) + for i, s in enumerate(sets): + new_vertex = set_labels[i] + for e in s: + B.add_edge(new_vertex, element_int_map[e]) + matching_temp = {} + for u, v, _ in B.matching(): + if u in range(len(groundset)): + matching_temp[int_element_map[u]] = v + else: + matching_temp[int_element_map[v]] = u + + self._set_labels = list(set_labels) + + # determine the basis from the matching + basis = frozenset(matching_temp) + + # This creates self._groundset attribute, among other things + # It takes the actual groundset labels, not the translated ones + BasisExchangeMatroid.__init__(self, groundset, basis) + + # matching_temp uses actual groundset labels + # self._matching will use the translated ones + if matching: + self._matching = {self._idx[e]: self._set_labels[self._set_labels_input.index(matching_temp[e])] + for e in matching_temp} + else: + self._matching = {self._idx[e]: matching_temp[e] for e in matching_temp} + + # Build a DiGraph for doing basis exchange + self._D = nx.DiGraph() + # Make sure we get isolated vertices, corresponding to loops + self._D.add_nodes_from(self._idx.itervalues()) + # Also get isolated vertices corresponding to empty sets + self._D.add_nodes_from(self._set_labels) + + # For sets in the matching, orient them as starting from the collections + matching_reversed = [(v, k) for k, v in self._matching.iteritems()] + self._D.add_edges_from(matching_reversed) + + other_edges = [] + for i, s in enumerate(sets): + for e in s: + if e not in matching_temp or matching_temp[e] != set_labels[i]: + other_edges.append((self._idx[e], set_labels[i])) + self._D.add_edges_from(other_edges) + + cdef bint _is_exchange_pair(self, long x, long y) except -1: + r""" + Check for `M`-alternating path from `x` to `y`. + """ + return nx.has_path(self._D, y, x) + + cdef int _exchange(self, long x, long y) except -1: + r""" + Replace ``self.basis() with ``self.basis() - x + y``. + + Internal method, does no checks. + """ + # update the internal matching + sh = nx.shortest_path(self._D, y, x) + del self._matching[x] + for i in range(0, len(sh)-1, 2): + self._matching[sh[i]] = sh[i+1] + + # update the graph to reflect this new matching + sh_edges = [(sh[i], sh[i + 1]) for i in xrange(len(sh) - 1)] + sh_edges_r = [(sh[i + 1], sh[i]) for i in xrange(len(sh) - 1)] + self._D.remove_edges_from(sh_edges) + self._D.add_edges_from(sh_edges_r) + + BasisExchangeMatroid._exchange(self, x, y) + + def _repr_(self): + """ + Return a string representation of ``self``. + + EXAMPLES:: + + sage: from sage.matroids.transversal_matroid import TransversalMatroid + sage: sets = [[0, 1, 2, 3]] * 3 + sage: M = TransversalMatroid(sets); M + Transversal matroid of rank 3 on 4 elements, with 3 sets + """ + return "Transversal matroid of rank {} on {} elements, with {} sets".format( + self.rank(), self.size(), len(self._sets_input)) + + cpdef list sets(self): + r""" + Return the sets of ``self``. + + A transversal matroid can be viewed as a groundset with a collection + from its powerset. This is represented as a bipartite graph, where + an edge represents containment. + + OUTPUT: list of lists that correspond to the sets of the transversal matroid + + EXAMPLES:: + + sage: from sage.matroids.transversal_matroid import TransversalMatroid + sage: sets = [[0, 1, 2, 3], [1, 2], [3, 4]] + sage: set_labels = [5, 6, 7] + sage: M = TransversalMatroid(sets, set_labels=set_labels) + sage: sorted(M.sets()) == sorted(sets) + True + """ + return copy(self._sets_input) + + def __richcmp__(left, right, op): + r""" + Compare two matroids. + + We take a very restricted view on equality: the objects need to be of + the exact same type (so no subclassing) and the internal data need to + be the same. For transversal matroids, in particular, the presentation + as a bipartite graph must be the same. + + .. WARNING:: + + This method is linked to ``__hash__``. If you override one, you + MUST override the other! + + EXAMPLES:: + + sage: from sage.matroids.transversal_matroid import TransversalMatroid + sage: sets = [['a', 'b', 'c'], ['c', 'd'], ['a', 'd'], ['e']] + sage: M = TransversalMatroid(sets) + sage: M1 = TransversalMatroid(sets) + sage: sets2 = [['a', 'b', 'c'], ['c', 'd'], ['a', 'd', 'e'], ['e']] + sage: M2 = TransversalMatroid(sets2) + sage: M1 == M2 + False + sage: M1.equals(M2) + True + sage: from sage.matroids.transversal_matroid import TransversalMatroid + sage: sets = [[0, 1, 2, 3], [1, 2], [1, 3, 4]] + sage: M = TransversalMatroid(sets, groundset=range(5), set_labels=[5, 6, 7]) + sage: M2 = TransversalMatroid(sets) + sage: M == M2 + True + + TESTS:: + + sage: M = TransversalMatroid([range(5)] * 4, set_labels='abcd', + ....: matching={0: 'a', 1: 'c'}) + sage: N = TransversalMatroid([range(5)] * 4, set_labels='abcd') + sage: M == N + False + """ + if op not in [Py_EQ, Py_NE]: + return NotImplemented + if not isinstance(left, TransversalMatroid) or not isinstance(right, TransversalMatroid): + return NotImplemented + if left.__class__ != right.__class__: # since we have some subclasses, an extra test + return NotImplemented + if op == Py_EQ: + res = True + if op == Py_NE: + res = False + # res gets inverted if matroids are deemed different. + + cdef TransversalMatroid rhs, lhs + rhs = right + lhs = left + + # If either matroid is not valid, deem them different + if not (lhs.is_valid() and rhs.is_valid()): + return not res + if (lhs._groundset == rhs._groundset and + Counter([frozenset(s) for s in lhs._sets_input]) == Counter([frozenset(s) for s in rhs._sets_input])): + return res + else: + return not res + + def __hash__(self): + r""" + Return the hash of ``self``. + + The hash is based on the groundset and an internal Counter of the + collection of sets. + + This function is called when matroids are added to a set. It is very + desirable to override it so it can distinguish matroids on the same + groundset, which is a very typical use case! + + .. WARNING:: + + This method is linked to ``__richcmp__`` (in Cython) and + ``__eq__`` (in Python). If you override one, you must + override the other! + + EXAMPLES:: + + sage: from sage.matroids.transversal_matroid import TransversalMatroid + sage: sets1 = [[0, 1, 2, 3], [1, 2], [3, 4]] + sage: M1 = TransversalMatroid(sets1) + sage: M2 = TransversalMatroid(sets1, set_labels=[5, 6, 7]) + sage: sets3 = [['a', 'b', 'c'], ['c', 'd'], ['a', 'd', 'e']] + sage: M3 = TransversalMatroid(sets3) + sage: hash(M1) == hash(M2) + True + sage: hash(M1) == hash(M3) + False + """ + return hash((self._groundset, frozenset(self._sets.items()))) + + cdef dict _translate_matching(self): + """ + Return a Python dictionary that can be used as input for ``__init__()``. + """ + cdef dict matching = {} + for x in self._matching: + matching[self._E[x]] = self._set_labels_input[self._set_labels.index(self._matching[x])] + return matching + + def __reduce__(self): + """ + Save the matroid for later reloading. + + OUTPUT: + + A tuple ``(unpickle, (version, data))``, where ``unpickle`` is the + name of a function that, when called with ``(version, data)``, + produces a matroid isomorphic to ``self``. ``version`` is an integer + (currently 0) and ``data`` is a tuple ``(sets, E, name)`` where + ``E`` is the groundset of the matroid, ``sets`` is the subsets of the + transversal, and ``name`` is a custom name. + + EXAMPLES:: + + sage: from sage.matroids.transversal_matroid import * + sage: sets = [range(6)] * 3 + sage: M = TransversalMatroid(sets) + sage: M == loads(dumps(M)) + True + sage: M.rename('U36') + sage: loads(dumps(M)) + U36 + """ + from sage.matroids.unpickling import unpickle_transversal_matroid + data = (self._sets_input, self._E, self._set_labels_input, self._translate_matching(), + self.get_custom_name()) + version = 0 + return unpickle_transversal_matroid, (version, data) + + def graph(self): + """ + Return a bipartite graph representing the transversal matroid. + + A transversal matroid can be represented as a set system, or as a + bipartite graph with one color class corresponding to the groundset + and the other to the sets of the set system. This method returns + that bipartite graph. + + OUTPUT: :class:`Graph` + + EXAMPLES:: + + sage: from sage.matroids.transversal_matroid import TransversalMatroid + sage: edgedict = {5: [0, 1, 2, 3], 6: [1, 2], 7: [1, 3, 4]} + sage: B = BipartiteGraph(edgedict) + sage: M = TransversalMatroid(edgedict.values(), set_labels=edgedict.keys()) + sage: M.graph() == B + True + sage: M2 = TransversalMatroid(edgedict.values()) + sage: B2 = M2.graph() + sage: B2 == B + False + sage: B2.is_isomorphic(B) + True + """ + # cast the internal networkx as a sage DiGraph + D = DiGraph(self._D) + # relabel the vertices, then return as a BipartiteGraph + vertex_map = {i: e for i, e in enumerate(self._E)} + for i, l in enumerate(self._set_labels): + vertex_map[l] = self._set_labels_input[i] + D.relabel(vertex_map) + partition = [list(self._E), self._set_labels_input] + + return BipartiteGraph(D, partition=partition) + + cpdef _minor(self, contractions, deletions): + """ + Return a minor. + + Deletions will yield a new transversal matroid. Contractions will + have to be a :class:`~sage.matroids.minor_matroid.MinorMatroid` + until Gammoids are implemented. + + INPUT: + + - ``contractions`` -- frozenset; an independent subset of the groundset + - ``deletions`` -- frozenset; a coindependent subset of the groundset + + OUTPUT: + + If ``contractions`` is the empty set, or if ``contractions`` + consists of only coloops, an instance of + :class:`~sage.matroids.transversal_matroid.TransversalMatroid`. + Otherwise, an instance of + :class:`~sage.matroids.minor_matroid.MinorMatroid`. + + EXAMPLES:: + + sage: from sage.matroids.transversal_matroid import TransversalMatroid + sage: sets = [[0, 1, 2, 3], [1, 2], [1, 3, 4]] + sage: M1 = TransversalMatroid(sets) + sage: N1 = M1.delete([2,3]) + sage: sets2 = [[0, 1], [1], [4]] + sage: M2 = TransversalMatroid(sets2) + sage: N1.is_isomorphic(M2) + True + sage: M1._minor(deletions=set([3]), contractions=set([4])) + M / {4}, where M is Transversal matroid of rank 3 on 4 elements, with 3 sets + + :: + + sage: from sage.matroids.transversal_matroid import TransversalMatroid + sage: sets = [['a', 'c'], ['e']] + sage: gs = ['a', 'c', 'd', 'e'] + sage: M = TransversalMatroid(sets, groundset=gs) + sage: N = M.delete(['d','e']); N + Transversal matroid of rank 1 on 2 elements, with 1 sets + + TESTS:: + + sage: from sage.matroids.transversal_matroid import TransversalMatroid + sage: sets = [['a', 'c'], ['e']] + sage: gs = ['a', 'c', 'd', 'e'] + sage: M = TransversalMatroid(sets, groundset=gs) + sage: M.contract(['e']) + Transversal matroid of rank 1 on 3 elements, with 1 sets + sage: M.contract(['d', 'e']) + Transversal matroid of rank 1 on 2 elements, with 1 sets + sage: M.contract(['a', 'e']) + M / {'a', 'e'}, where M is Transversal matroid of rank 2 on 4 elements, with 2 sets + """ + cdef TransversalMatroid N + cdef list new_sets, new_set_labels, s, new_s + cdef size_t i + cdef frozenset contract = frozenset(contractions) + cdef frozenset delete = frozenset(deletions) + + # if contractions are just coloops, we can just delete them + if self._corank(contract) == 0: + delete = delete.union(contract) + contract = frozenset() + + if delete: + new_sets = [] + new_set_labels = [] + for i in range(len(self._sets_input)): + s = self._sets_input[i] + new_s = [e for e in s if e not in delete] + if new_s: + # skip over empty buckets, and do bookkeeping with the labels + new_sets.append(new_s) + new_set_labels.append(self._set_labels_input[i]) + groundset = self._groundset.difference(delete) + N = TransversalMatroid(new_sets, groundset, new_set_labels) + # Check if what remains is just coloops + return N._minor(contractions=contract, deletions=frozenset()) + else: + N = self + + if contractions: + # Until gammoids are implemented + return MinorMatroid(N, contractions=contract, deletions=frozenset()) + else: + return N + + def set_labels(self): + """ + Return the labels used for the transversal sets. + + This method will return a list of the labels used of the non-ground + set vertices of the bipartite graph used to represent the transversal + matroid. This method does not set anything. + + OUTPUT: list + + EXAMPLES:: + + sage: from sage.matroids.transversal_matroid import TransversalMatroid + sage: M = TransversalMatroid([[0, 1], [1, 2, 3], [3, 4, 7]]) + sage: M.set_labels() + ['s0', 's1', 's2'] + sage: M.graph().vertices() + ['s0', 's1', 's2', 0, 1, 2, 3, 4, 7] + """ + return copy(self._set_labels_input) + + cpdef reduce_presentation(self): + """ + Return an equal transversal matroid where the number of sets equals the rank. + + Every transversal matroid `M` has a presentation with `r(M)` sets, and if `M` + has no coloops, then every presentation has `r(M)` nonempty sets. This method + discards extra sets if `M` has coloops. + + OUTPUT: :class:`TransversalMatroid` with a reduced presentation + + EXAMPLES:: + + sage: from sage.matroids.transversal_matroid import TransversalMatroid + sage: sets = [[0, 1], [2], [2]] + sage: M = TransversalMatroid(sets); M + Transversal matroid of rank 2 on 3 elements, with 3 sets + sage: N = M.reduce_presentation(); N + Transversal matroid of rank 2 on 3 elements, with 2 sets + sage: N.equals(M) + True + sage: N == M + False + sage: sets = [[0, 1], [], [], [2]] + sage: M1 = TransversalMatroid(sets); M1 + Transversal matroid of rank 2 on 3 elements, with 4 sets + sage: M1.reduce_presentation() + Transversal matroid of rank 2 on 3 elements, with 2 sets + + :: + + sage: from sage.matroids.transversal_matroid import TransversalMatroid + sage: sets = [[0, 1, 2, 3]] * 3 + sage: M = TransversalMatroid(sets) + sage: N = M.reduce_presentation() + sage: M == N + True + + TESTS:: + + sage: from sage.matroids.transversal_matroid import TransversalMatroid + sage: sets = [[4], [1, 3], [4], [0, 1], [2, 3], [1]] + sage: M = TransversalMatroid(sets) + sage: M1 = M.reduce_presentation(); M1 + Transversal matroid of rank 5 on 5 elements, with 5 sets + sage: len(M1.graph().edges()) + 5 + """ + cdef TransversalMatroid N + cdef size_t i + if len(self._sets_input) == self.full_rank(): + return self + + element_int_map = {e: i for i, e in enumerate(self._groundset)} + coloops = self.coloops() + cdef list coloops_to_delete = [e for e in coloops if self._D.degree(element_int_map[e]) > 1] + N = self._minor(contractions=set(), deletions=set(coloops_to_delete)) + cdef list sets = list(N._sets_input) # make a (shallow) copy as we will remove objects + # reuse the old set labels + # this does not respect containment + labels = N.set_labels() + # remove empty sets HERE + if [] in sets: + i = len(sets) + while i > 0: + i -= 1 + if not sets[i]: + del sets[i] + del labels[i] + cdef set free_labels = set(self._set_labels_input).difference(labels) + for c in coloops_to_delete: + l = free_labels.pop() + sets.append([c]) + labels.append(l) + return TransversalMatroid(sets, groundset=self.groundset(), set_labels=labels) + + cpdef transversal_extension(self, element=None, newset=False, sets=[]): + r""" + Return a :class:`TransversalMatroid` extended by an element. + + This will modify the presentation of the transversal matroid by + adding a new element, and placing this element in the specified + sets. It is also possible to use this method to create a new set + that will have the new element as its only member, making it a coloop. + + INPUT: + + - ``element`` -- (optional) the name for the new element + - ``newset`` -- (optional) if specified, the element will be + given its own set + - ``sets`` -- iterable of labels (default: ``None``) representing the + sets in the current presentation that the new element will belong to + + OUTPUT: + + A :class:`~sage.matroids.transversal_matroids.TransversalMatroid` + with a groundset element added to specified sets. Note that the + ``newset`` option will make the new element a coloop. If + ``newset == True``, a name will be generated; otherwise the + value of ``newset`` will be used. + + EXAMPLES:: + + sage: from sage.matroids.transversal_matroid import TransversalMatroid + sage: M = TransversalMatroid([['a', 'c']], groundset=['a', 'c'], set_labels=['b']) + sage: M1 = M.transversal_extension(element='d', newset='e') + sage: M2 = M.transversal_extension(element='d', newset=True) + sage: M1.coloops() + frozenset({'d'}) + sage: True in M2.graph().vertices() + False + sage: M1.is_isomorphic(M2) + True + sage: M3 = M.transversal_extension('d', sets=['b']) + sage: M3.is_isomorphic(matroids.Uniform(1, 3)) + True + sage: M4 = M.transversal_extension('d', sets=['a']) + Traceback (most recent call last): + ... + ValueError: sets do not match presentation + sage: M4 = M.transversal_extension('a', sets=['b']) + Traceback (most recent call last): + ... + ValueError: cannot extend by element already in groundset + sage: M2.transversal_extension(newset='b') + Traceback (most recent call last): + ... + ValueError: newset is already a vertex in the presentation + sage: M5 = M1.transversal_extension() + sage: len(M5.loops()) + 1 + sage: M2.transversal_extension(element='b') + Transversal matroid of rank 2 on 4 elements, with 2 sets + + :: + + sage: from sage.matroids.transversal_matroid import TransversalMatroid + sage: sets = [[0, 1, 2, 3], [1, 2], [1, 3, 4]] + sage: M = TransversalMatroid(sets, groundset=range(5), set_labels=[5, 6, 7]) + sage: N = M.delete(2) + sage: M1 = N.transversal_extension(element=2, sets=[5, 6]) + sage: M1 == M + True + + :: + + sage: from sage.matroids.transversal_matroid import TransversalMatroid + sage: sets = [[0, 1, 2, 3]] * 3 + sage: M = TransversalMatroid(sets, set_labels=[4, 5, 6]) + sage: N = M.transversal_extension(element='a', newset=True, sets=[4]) + sage: N.graph().degree('a') + 2 + + TESTS:: + + sage: N = TransversalMatroid(['abc', 'abd', 'cde']); N + Transversal matroid of rank 3 on 5 elements, with 3 sets + sage: Ne = N.transversal_extension(element='f', sets=['s2']) + """ + cdef set parsed_sets = set(sets) + if element is None: + element = newlabel(self._groundset) + elif element in self._groundset: + raise ValueError("cannot extend by element already in groundset") + cdef list labels = self._set_labels_input + if not parsed_sets.issubset(labels): + raise ValueError("sets do not match presentation") + + # check for conflicts with new labels + labels_map = {l: l for l in labels} + if element in labels: + new_label = newlabel(self._groundset.union(labels).union([newset])) + labels_map[element] = new_label + + # newset should not be a groundset element or existing set + if newset in self._E or newset in self._set_labels_input: + # keywords `True` and `False` give us problems here + if not isinstance(newset, bool): + raise ValueError("newset is already a vertex in the presentation") + + cdef list s, new_sets = [] + cdef size_t i + for i in range(len(self._sets_input)): + s = self._sets_input[i] + if labels[i] in parsed_sets: + new_sets.append(s + [element]) + else: + new_sets.append(s) + + if newset: + if newset is True: + newset = newlabel(self._groundset.union(labels)) + new_sets.append([element]) + labels = list(labels) # Make a shallow copy since we mutate it + labels.append(newset) + + groundset = self._groundset.union([element]) + return TransversalMatroid(new_sets, groundset, labels) + + def transversal_extensions(self, element=None, sets=[]): + r""" + Return an iterator of extensions based on the transversal presentation. + + This method will take an extension by adding an element to every possible + sub-collection of the collection of desired sets. No checking is done + for equal matroids. It is advised to make sure the presentation has as + few sets as possible by using + :meth:`reduce_presentation() ` + + INPUT: + + - ``element`` -- (optional) the name of the new element + - ``sets`` -- (optional) list containing names of sets in the matroid's + presentation + + OUTPUT: iterator over instances of :class:`TransversalMatroid` + + If ``sets`` is not specified, every set will be used. + + EXAMPLES:: + + sage: from sage.matroids.transversal_matroid import TransversalMatroid + sage: sets = [[3, 4, 5, 6]] * 3 + sage: M = TransversalMatroid(sets, set_labels=[0, 1, 2]) + sage: len([N for N in M.transversal_extensions()]) + 8 + sage: len([N for N in M.transversal_extensions(sets=[0, 1])]) + 4 + sage: set(sorted([N.groundset() for N in M.transversal_extensions(element=7)])) + {frozenset({3, 4, 5, 6, 7})} + """ + if element is None: + element = newlabel(self.groundset()) + elif element in self._groundset: + raise ValueError("cannot extend by element already in groundset") + + labels = self._set_labels_input + if not sets: + sets = labels + elif not set(sets).issubset(labels): + raise ValueError("sets do not match presentation") + + # Adapted from the Python documentation + from itertools import chain, combinations + powerset = chain.from_iterable(combinations(sets, r) for r in range(len(sets)+1)) + + for collection in powerset: + yield self.transversal_extension(element=element, sets=collection) + + cpdef is_valid(self, certificate=False): + """ + Test whether the matching in memory is a valid maximal matching. + + The data for a transversal matroid is a set system, which is always valid, + but it is possible for a user to provide invalid input with the ``matching`` + parameter. This checks that the matching provided is indeed a matching, fits in + the set system, and is maximal. + + EXAMPLES:: + + sage: from sage.matroids.transversal_matroid import * + sage: sets = [[0, 1, 2, 3], [1, 2], [1, 3, 4]] + sage: set_labels = [5, 6, 7] + sage: M = TransversalMatroid(sets, set_labels=set_labels) + sage: M.is_valid() + True + sage: m = {0: 5, 1: 5, 3: 7} # not a matching + sage: TransversalMatroid(sets, set_labels=set_labels, matching=m).is_valid() + False + sage: m = {2: 6, 3: 7} # not maximal + sage: TransversalMatroid(sets, set_labels=set_labels, matching=m).is_valid() + False + sage: m = {0: 6, 1: 5, 3: 7} # not in the set system + sage: TransversalMatroid(sets, set_labels=set_labels, matching=m).is_valid() + False + """ + # Check that self._matching is a matching, that is, every entry appears at most once. + # Because of how python dictionaries work, each element appears once, but a set + # can appear more than once. + if len(self._matching) != len(set(self._matching.values())): + return False + + # Check that every element in the matching is actually in the set that the matching + # specifies. + # Note that self._matching uses the internal set and element labels + for e in self._matching: + if e not in self._sets_input[self._set_labels.index(self._matching[e])]: + return False + + # Check that the matching is maximal. + B = self.graph() + if len(B.matching()) != len(self._matching): + return False + + return True diff --git a/src/sage/matroids/union_matroid.pyx b/src/sage/matroids/union_matroid.pyx index 86c78c8463d..f7f26426786 100644 --- a/src/sage/matroids/union_matroid.pyx +++ b/src/sage/matroids/union_matroid.pyx @@ -31,7 +31,7 @@ cdef class MatroidUnion(Matroid): """ def __init__(self, matroids): """ - See class definition for full documentation. + See the class definition for full documentation. EXAMPLES:: @@ -140,7 +140,7 @@ cdef class MatroidSum(Matroid): """ def __init__(self, summands): """ - See class definition for full documentation. + See the class definition for full documentation. EXAMPLES:: @@ -246,7 +246,7 @@ cdef class PartitionMatroid(Matroid): """ def __init__(self, partition): """ - See class definition for full documentation. + See the class definition for full documentation. EXAMPLES:: diff --git a/src/sage/matroids/unpickling.pyx b/src/sage/matroids/unpickling.pyx index 33fa9fe7dc1..8b90dcd69e4 100644 --- a/src/sage/matroids/unpickling.pyx +++ b/src/sage/matroids/unpickling.pyx @@ -33,17 +33,19 @@ from sage.rings.rational cimport Rational from sage.matroids.basis_matroid cimport BasisMatroid from sage.matroids.circuits_matroid cimport CircuitsMatroid from sage.matroids.circuit_closures_matroid cimport CircuitClosuresMatroid -from sage.matroids.flats_matroid cimport FlatsMatroid from sage.matroids.dual_matroid import DualMatroid -from sage.matroids.graphic_matroid import GraphicMatroid +from sage.matroids.flats_matroid cimport FlatsMatroid +from sage.matroids.gammoid import Gammoid +from sage.matroids.graphic_matroid cimport GraphicMatroid from sage.matroids.lean_matrix cimport GenericMatrix, BinaryMatrix, TernaryMatrix, QuaternaryMatrix, PlusMinusOneMatrix, RationalMatrix from sage.matroids.linear_matroid cimport LinearMatroid, RegularMatroid, BinaryMatroid, TernaryMatroid, QuaternaryMatroid from sage.matroids.minor_matroid import MinorMatroid +from sage.matroids.transversal_matroid cimport TransversalMatroid -############################################################################# +# ------------ # BasisMatroid -############################################################################# +# ------------ def unpickle_basis_matroid(version, data): """ @@ -87,9 +89,9 @@ def unpickle_basis_matroid(version, data): return M -############################################################################# +# --------------- # CircuitsMatroid -############################################################################# +# --------------- def unpickle_circuits_matroid(version, data): """ @@ -128,9 +130,9 @@ def unpickle_circuits_matroid(version, data): return M -############################################################################# +# ---------------------- # CircuitClosuresMatroid -############################################################################# +# ---------------------- def unpickle_circuit_closures_matroid(version, data): """ @@ -169,9 +171,9 @@ def unpickle_circuit_closures_matroid(version, data): return M -############################################################################# +# ------------ # FlatsMatroid -############################################################################# +# ------------ def unpickle_flats_matroid(version, data): """ @@ -211,9 +213,9 @@ def unpickle_flats_matroid(version, data): return M -############################################################################# +# ----------- # DualMatroid -############################################################################# +# ----------- def unpickle_dual_matroid(version, data): """ @@ -250,9 +252,50 @@ def unpickle_dual_matroid(version, data): return M -############################################################################# +# ------- +# Gammoid +# ------- + +def unpickle_gammoid(version, data): + """ + Unpickle a :class:`Gammoid`. + + *Pickling* is Python's term for the loading and saving of objects. + Functions like these serve to reconstruct a saved object. This all happens + transparently through the ``load`` and ``save`` commands, and you should + never have to call this function directly. + + INPUT: + + - ``version`` -- integer; expected to be 0 + - ``data`` -- tuple ``(D, roots, E, name)`` in which ``D`` is a loopless + DiGraph representing the gammoid, ``roots`` is a subset of the vertices, + ``E`` is the groundset of the matroid, and ``name`` is a custom name. + + OUTPUT: matroid + + .. WARNING:: + + Users should never call this function directly. + + EXAMPLES:: + + sage: from sage.matroids.gammoid import Gammoid + sage: M = Gammoid(digraphs.TransitiveTournament(5), roots=[3, 4]) + sage: M == loads(dumps(M)) # indirect doctest + True + """ + if version != 0: + raise TypeError("object was created with newer version of Sage. Please upgrade.") + M = Gammoid(D=data[0], roots=data[1], groundset=data[2]) + if data[3] is not None: + M.rename(data[3]) + return M + + +# --------------------- # LeanMatrix subclasses -############################################################################# +# --------------------- def unpickle_generic_matrix(version, data): """ @@ -437,9 +480,9 @@ def unpickle_rational_matrix(version, data): return A -############################################################################# +# ---------------------------- # LinearMatroid and subclasses -############################################################################# +# ---------------------------- def unpickle_linear_matroid(version, data): """ @@ -669,9 +712,9 @@ def unpickle_regular_matroid(version, data): return M -############################################################################# -# Minor matroids -############################################################################# +# ------------ +# MinorMatroid +# ------------ def unpickle_minor_matroid(version, data): """ @@ -710,9 +753,9 @@ def unpickle_minor_matroid(version, data): return M -############################################################################# -# Graphic Matroids -############################################################################# +# -------------- +# GraphicMatroid +# -------------- def unpickle_graphic_matroid(version, data): """ @@ -747,3 +790,50 @@ def unpickle_graphic_matroid(version, data): if name is not None: M.rename(name) return M + + +# ------------------ +# TransversalMatroid +# ------------------ + +def unpickle_transversal_matroid(version, data): + """ + Unpickle a TransversalMatroid. + + *Pickling* is Python's term for the loading and saving of objects. + Functions like these serve to reconstruct a saved object. This all happens + transparently through the ``load`` and ``save`` commands, and you should + never have to call this function directly. + + INPUT: + + - ``version`` -- integer (currently `0`) + - ``data`` -- tuple ``(sets, groundset, name)``, where ``groundset`` is a + ``frozenset`` of elements, and ``sets`` is a ``frozenset`` of tuples + consisting of a name for the set, and a ``frozenset`` of groundset + elements it contains. + + OUTPUT: :class:`TransversalMatroid` + + .. WARNING:: + + Users should never call this function directly. + + EXAMPLES:: + + sage: from sage.matroids.transversal_matroid import * + sage: sets = [range(6)] * 3 + sage: M = TransversalMatroid(sets) + sage: M == loads(dumps(M)) + True + sage: M.rename('U36') + sage: loads(dumps(M)) + U36 + """ + if version != 0: + raise TypeError("object was created with newer version of Sage. Please upgrade.") + sets, groundset, set_labels, matching, name = data + M = TransversalMatroid(sets, groundset, set_labels, matching) + if name is not None: + M.rename(name) + return M diff --git a/src/sage/misc/functional.py b/src/sage/misc/functional.py index 4399007c91d..40fc5630d40 100644 --- a/src/sage/misc/functional.py +++ b/src/sage/misc/functional.py @@ -23,6 +23,7 @@ import math from sage.misc.lazy_import import lazy_import +from sage.misc.superseded import deprecation lazy_import('sage.rings.complex_double', 'CDF') lazy_import('sage.rings.real_double', ['RDF', 'RealDoubleElement']) @@ -918,16 +919,20 @@ def krull_dimension(x): EXAMPLES:: sage: krull_dimension(QQ) + doctest:warning...: + DeprecationWarning: please use the krull_dimension method + See https://github.com/sagemath/sage/issues/39311 for details. 0 - sage: krull_dimension(ZZ) + sage: ZZ.krull_dimension() 1 - sage: krull_dimension(ZZ[sqrt(5)]) # needs sage.rings.number_field sage.symbolic + sage: ZZ[sqrt(5)].krull_dimension() # needs sage.rings.number_field sage.symbolic 1 sage: U. = PolynomialRing(ZZ, 3); U Multivariate Polynomial Ring in x, y, z over Integer Ring sage: U.krull_dimension() 4 """ + deprecation(39311, "please use the krull_dimension method") return x.krull_dimension() diff --git a/src/sage/misc/sage_input.py b/src/sage/misc/sage_input.py index 08bfde6e715..2dbd381e368 100644 --- a/src/sage/misc/sage_input.py +++ b/src/sage/misc/sage_input.py @@ -1405,10 +1405,10 @@ def __call__(self, *args, **kwargs): sage: sie(4) {call: {atomic:3}({atomic:4})} """ - args = [self._sie_builder(_) for _ in args] - for k in kwargs: - kwargs[k] = self._sie_builder(kwargs[k]) - return SIE_call(self._sie_builder, self, args, kwargs) + new_args = [self._sie_builder(arg) for arg in args] + new_kwargs = {key: self._sie_builder(val) + for key, val in kwargs.items()} + return SIE_call(self._sie_builder, self, new_args, new_kwargs) def __getitem__(self, key): r""" diff --git a/src/sage/modular/modform/space.py b/src/sage/modular/modform/space.py index 4405c38f764..9a80d4c97aa 100644 --- a/src/sage/modular/modform/space.py +++ b/src/sage/modular/modform/space.py @@ -1735,8 +1735,8 @@ def embedded_submodule(self): # """ # from sage.modular.modform.all import ModularForms # if self.ambient_module() != right.ambient_module(): -# raise ArithmeticError, "Intersection of %s and %s not defined."%\ -# (self, right) +# raise ArithmeticError("Intersection of %s and %s not defined." % +# (self, right)) # V = self.embedded_submodule().intersection(right.embedded_submodule()) # return ModularForms(self.ambient_module(),V) # return self.span([ self(b) for b in V.basis() ]) diff --git a/src/sage/modular/modsym/relation_matrix.py b/src/sage/modular/modsym/relation_matrix.py index 0562cfdf899..f2733cecf7e 100644 --- a/src/sage/modular/modsym/relation_matrix.py +++ b/src/sage/modular/modsym/relation_matrix.py @@ -243,8 +243,8 @@ def T_relation_matrix_wtk_g0(syms, mod, field, sparse): v[j0] += s0 else: v[j0] = s0 - for j0 in v: - entries[(row, j0)] = v[j0] + for j0, vj0 in v.items(): + entries[(row, j0)] = vj0 row += 1 MAT = MatrixSpace(field, row, len(syms), sparse=True) diff --git a/src/sage/modular/overconvergent/genus0.py b/src/sage/modular/overconvergent/genus0.py index e1df5066186..ef2d143b1af 100644 --- a/src/sage/modular/overconvergent/genus0.py +++ b/src/sage/modular/overconvergent/genus0.py @@ -1187,7 +1187,7 @@ def eigenfunctions(self, n, F=None, exact_arith=True): F = self.base_ring() if F.is_exact(): - # raise TypeError, "cannot calculate eigenfunctions over exact base fields" + # raise TypeError("cannot calculate eigenfunctions over exact base fields") F = pAdicField(self.prime(), 100) # noqa:F821 m = self.hecke_matrix(self.prime(), n, use_recurrence=True, exact_arith=exact_arith) diff --git a/src/sage/modular/pollack_stevens/fund_domain.py b/src/sage/modular/pollack_stevens/fund_domain.py index c9b61b36546..99a8a772743 100644 --- a/src/sage/modular/pollack_stevens/fund_domain.py +++ b/src/sage/modular/pollack_stevens/fund_domain.py @@ -812,7 +812,7 @@ def __init__(self, N): # interior path on either of the last two cusps for s in range(r + 2, len(cusps)): - # s is in the index of the cusp on the right of the path + # s is in the index of the cusp on the right of the path cusp1 = cusps[r] cusp2 = cusps[s] if self.is_unimodular_path(cusp1, cusp2): @@ -1213,10 +1213,10 @@ def form_list_of_cusps(self): if (b1 ** 2 + b2 ** 2 + b1 * b2) % N != 0: - # this congruence is exactly equivalent to - # gam * [0 -1; 1 -1] * gam^(-1) is in Gamma_0(N) - # where gam is the matrix corresponding to the - # unimodular path connecting cusp1 to cusp2 + # this congruence is exactly equivalent to + # gam * [0 -1; 1 -1] * gam^(-1) is in Gamma_0(N) + # where gam is the matrix corresponding to the + # unimodular path connecting cusp1 to cusp2 C[s] = "i" # The '?' is changed to an 'i' # indicating that a new cusp needs to diff --git a/src/sage/modules/free_module_element.pyx b/src/sage/modules/free_module_element.pyx index a9d074007f0..617c53f8781 100644 --- a/src/sage/modules/free_module_element.pyx +++ b/src/sage/modules/free_module_element.pyx @@ -104,13 +104,13 @@ This is a test from :issue:`20211`:: [1] """ -#***************************************************************************** +# **************************************************************************** # 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/ +# **************************************************************************** cimport cython from cpython.slice cimport PySlice_GetIndicesEx @@ -2214,8 +2214,8 @@ cdef class FreeModuleElement(Vector): # abstract base class else: sep=", " entry = S[i] - #if i > 0: - # entry = " "*(width-len(entry)) + entry + # if i > 0: + # entry = " "*(width-len(entry)) + entry s = s + entry + sep s = s + ")" return s @@ -2339,9 +2339,9 @@ cdef class FreeModuleElement(Vector): # abstract base class e[i] = c return e - ############################# + # ############################ # Plotting - ############################# + # ############################ def plot(self, plot_type=None, start=None, **kwds): """ INPUT: @@ -4272,9 +4272,9 @@ cdef class FreeModuleElement(Vector): # abstract base class return vector(coeffs) -############################################# +# ############################################ # Generic dense element -############################################# +# ############################################ @cython.binding(True) def make_FreeModuleElement_generic_dense(parent, entries, degree): @@ -4734,9 +4734,9 @@ cdef class FreeModuleElement_generic_dense(FreeModuleElement): return vector(CallableSymbolicExpressionRing(args), self.list()) -############################################# +# ############################################ # Generic sparse element -############################################# +# ############################################ @cython.binding(True) def make_FreeModuleElement_generic_sparse(parent, entries, degree): diff --git a/src/sage/monoids/string_monoid_element.py b/src/sage/monoids/string_monoid_element.py index d7e06428e0f..d83570f5f0d 100644 --- a/src/sage/monoids/string_monoid_element.py +++ b/src/sage/monoids/string_monoid_element.py @@ -358,12 +358,11 @@ def coincidence_index(self, prec=0): char_dict[i] = 1 nn = 0 ci_num = 0 - for i in char_dict.keys(): - ni = char_dict[i] + for ni in char_dict.values(): nn += ni - ci_num += ni*(ni-1) - ci_den = nn*(nn-1) - return RR(ci_num)/ci_den + ci_num += ni * (ni - 1) + ci_den = nn * (nn - 1) + return RR(ci_num) / ci_den def character_count(self): r""" diff --git a/src/sage/monoids/string_ops.py b/src/sage/monoids/string_ops.py index 304e908c16b..71b3ae8eee7 100644 --- a/src/sage/monoids/string_ops.py +++ b/src/sage/monoids/string_ops.py @@ -7,13 +7,13 @@ # # https://www.gnu.org/licenses/ # **************************************************************************** +from typing import Any from sage.misc.lazy_import import lazy_import +from .string_monoid_element import StringMonoidElement lazy_import('sage.rings.real_mpfr', 'RealField') -from .string_monoid_element import StringMonoidElement - def strip_encoding(S) -> str: """ @@ -27,7 +27,6 @@ def strip_encoding(S) -> str: TESTS:: - sage: S = "The cat in the hat." sage: strip_encoding(44) Traceback (most recent call last): ... @@ -41,7 +40,24 @@ def strip_encoding(S) -> str: def frequency_distribution(S, n=1, field=None): """ The probability space of frequencies of n-character substrings of S. + + EXAMPLES:: + + sage: frequency_distribution('banana not a nana nor ananas', 2) + Discrete probability space defined by {' a': 0.0740740740740741, + ' n': 0.111111111111111, + 'a ': 0.111111111111111, + 'an': 0.185185185185185, + 'as': 0.0370370370370370, + 'ba': 0.0370370370370370, + 'na': 0.222222222222222, + 'no': 0.0740740740740741, + 'or': 0.0370370370370370, + 'ot': 0.0370370370370370, + 'r ': 0.0370370370370370, + 't ': 0.0370370370370370} """ + from sage.probability.random_variable import DiscreteProbabilitySpace if isinstance(S, tuple): S = list(S) elif isinstance(S, (str, StringMonoidElement)): @@ -49,16 +65,15 @@ def frequency_distribution(S, n=1, field=None): if field is None: field = RealField() if isinstance(S, list): - P = {} + P: dict[str, Any] = {} N = len(S) - eps = field(1)/N + eps = field.one() / N for i in range(N): c = S[i] if c in P: P[c] += eps else: P[c] = eps - from sage.probability.random_variable import DiscreteProbabilitySpace return DiscreteProbabilitySpace(S, P, field) raise TypeError("Argument S (= %s) must be a string, list, or tuple.") @@ -80,7 +95,7 @@ def coincidence_index(S, n=1): raise TypeError("Argument S (= %s) must be a string.") S = strip_encoding(S) N = len(S)-n+1 - X = {} + X: dict[str, int] = {} for i in range(N): c = S[i:i+n] if c in X: diff --git a/src/sage/plot/arc.py b/src/sage/plot/arc.py index 77f09c4a485..6c897d12c25 100644 --- a/src/sage/plot/arc.py +++ b/src/sage/plot/arc.py @@ -221,9 +221,9 @@ def get_minmax_data(self): if s < twopi - epsilon: # bb determined by the sector def is_cyclic_ordered(x1, x2, x3): - return ((x1 < x2 and x2 < x3) or - (x2 < x3 and x3 < x1) or - (x3 < x1 and x1 < x2)) + return ((x1 < x2 < x3) or + (x2 < x3 < x1) or + (x3 < x1 < x2)) x1 = cos_angle * r1 * cos(s1) - sin_angle * r2 * sin(s1) x2 = cos_angle * r1 * cos(s2) - sin_angle * r2 * sin(s2) diff --git a/src/sage/plot/colors.py b/src/sage/plot/colors.py index a9792c2e374..bbb192c937b 100644 --- a/src/sage/plot/colors.py +++ b/src/sage/plot/colors.py @@ -1022,8 +1022,8 @@ def __init__(self): 148 """ # Convert the colors_dict defined above to Color instances. - for k in colors_dict: - self[k] = Color(colors_dict[k]) + for k, col in colors_dict.items(): + self[k] = Color(col) def __getattr__(self, name): """ diff --git a/src/sage/plot/plot.py b/src/sage/plot/plot.py index c8f5a0fca96..c5ab3b74aed 100644 --- a/src/sage/plot/plot.py +++ b/src/sage/plot/plot.py @@ -2051,13 +2051,15 @@ def f(x): return (floor(x)+0.5) / (1-(x-0.5)**2) elif n == 1: G = _plot(funcs, *args, **kwds) elif n == 2: - # if there are two extra args, then pull them out and pass them as a tuple + # if there are two extra args, then pull them out + # and pass them as a tuple xmin = args[0] xmax = args[1] args = args[2:] G = _plot(funcs, (xmin, xmax), *args, **kwds) elif n == 3: - # if there are three extra args, then pull them out and pass them as a tuple + # if there are three extra args, then pull them out + # and pass them as a tuple var = args[0] xmin = args[1] xmax = args[2] diff --git a/src/sage/plot/primitive.py b/src/sage/plot/primitive.py index 3c4032085cc..63c8b2acb0c 100644 --- a/src/sage/plot/primitive.py +++ b/src/sage/plot/primitive.py @@ -179,10 +179,10 @@ def options(self): A = self._allowed_options() t = False K = list(A) + ['xmin', 'xmax', 'ymin', 'ymax', 'axes'] - for k in O.keys(): + for k, Ok in O.items(): if k not in K: do_verify = False - verbose(f"WARNING: Ignoring option '{k}'={O[k]}", + verbose(f"WARNING: Ignoring option '{k}'={Ok}", level=0) t = True if t: @@ -195,8 +195,8 @@ def options(self): if 'hue' in O: t = O['hue'] - if not isinstance(t, (tuple,list)): - t = [t,1,1] + if not isinstance(t, (tuple, list)): + t = [t, 1, 1] O['rgbcolor'] = hue(*t) del O['hue'] return O diff --git a/src/sage/quadratic_forms/quadratic_form__mass__Conway_Sloane_masses.py b/src/sage/quadratic_forms/quadratic_form__mass__Conway_Sloane_masses.py index 89460d08713..cd86238e4d9 100644 --- a/src/sage/quadratic_forms/quadratic_form__mass__Conway_Sloane_masses.py +++ b/src/sage/quadratic_forms/quadratic_form__mass__Conway_Sloane_masses.py @@ -656,7 +656,6 @@ def conway_mass(self): # ans *= zeta(RR(j)) # # # Extra L-factor for even dimensional forms -- DO THIS!!! -# raise NotImplementedError, "This routine is not finished yet... =(" +# raise NotImplementedError("This routine is not finished yet") # -# # Return the answer # return ans diff --git a/src/sage/quadratic_forms/ternary.pyx b/src/sage/quadratic_forms/ternary.pyx index 345d6b962b3..a1a5f2a7306 100644 --- a/src/sage/quadratic_forms/ternary.pyx +++ b/src/sage/quadratic_forms/ternary.pyx @@ -305,7 +305,7 @@ def _reduced_ternary_form_eisenstein_with_matrix(a1, a2, a3, a23, a13, a12): [a13, a23] = [a23, a13] return (a1, a2, a3, a23, a13, a12), \ - matrix(ZZ, 3, (m11, m12, m13, m21, m22, m23, m31, m32, m33)) + matrix(ZZ, 3, (m11, m12, m13, m21, m22, m23, m31, m32, m33)) def _reduced_ternary_form_eisenstein_without_matrix(a1, a2, a3, a23, a13, a12): diff --git a/src/sage/quivers/algebra_elements.pyx b/src/sage/quivers/algebra_elements.pyx index a8f7778b202..4703863503a 100644 --- a/src/sage/quivers/algebra_elements.pyx +++ b/src/sage/quivers/algebra_elements.pyx @@ -266,9 +266,10 @@ cdef class PathAlgebraElement(RingElement): sage: X # indirect doctest 5*e_0 + a + 2*b + 3*c + 3*e_2 """ + parent = self._parent return repr_lincomb(self._sorted_items_for_printing(), strip_one=True, - scalar_mult=self.parent()._print_options['scalar_mult'], - repr_monomial=self._parent._repr_monomial) + scalar_mult=parent._print_options['scalar_mult'], + repr_monomial=parent._repr_monomial) def _latex_(self): r""" @@ -283,11 +284,12 @@ cdef class PathAlgebraElement(RingElement): sage: latex(X*X) 10 e_0 + 3 a\cdot c + 5 a + b + 3 c\cdot a + 6 c\cdot b + 9 e_2 """ + parent = self._parent return repr_lincomb(self._sorted_items_for_printing(), - scalar_mult=self.parent()._print_options['scalar_mult'], - latex_scalar_mult=self.parent()._print_options['latex_scalar_mult'], - repr_monomial=self._parent._latex_monomial, - is_latex=True, strip_one=True) + scalar_mult=parent._print_options['scalar_mult'], + latex_scalar_mult=parent._print_options['latex_scalar_mult'], + repr_monomial=parent._latex_monomial, + is_latex=True, strip_one=True) # Basic properties diff --git a/src/sage/rings/finite_rings/element_givaro.pxd b/src/sage/rings/finite_rings/element_givaro.pxd index 4b1e0430a1c..eb9eca7f954 100644 --- a/src/sage/rings/finite_rings/element_givaro.pxd +++ b/src/sage/rings/finite_rings/element_givaro.pxd @@ -21,7 +21,7 @@ cdef extern from "givaro/givrandom.h": cdef extern from "givaro/gfq.h": cdef cppclass GivaroGfq "Givaro::GFqDom": - #attributes + # attributes unsigned int one unsigned int zero @@ -65,7 +65,7 @@ cdef class FiniteField_givaroElement(FinitePolyExtElement): cdef FiniteField_givaroElement _new_c(self, int value) cdef class Cache_givaro(Cache_base): - cdef GivaroGfq *objectptr # C++ object + cdef GivaroGfq *objectptr # C++ object cdef public object _array cdef FiniteField_givaroElement _zero_element cdef FiniteField_givaroElement _one_element diff --git a/src/sage/rings/invariants/invariant_theory.py b/src/sage/rings/invariants/invariant_theory.py index 300e3e9c2f5..1f31834eac0 100644 --- a/src/sage/rings/invariants/invariant_theory.py +++ b/src/sage/rings/invariants/invariant_theory.py @@ -3850,8 +3850,8 @@ def J_covariant(self): sage: p2 = A0*x^2 + A1*y^2 + A2*z^2 + A3*w^2 sage: q = invariant_theory.quaternary_biquadratic(p1, p2, [w, x, y, z]) sage: q.J_covariant().factor() - z * y * x * w * (a3*A2 - a2*A3) * (a3*A1 - a1*A3) * (-a2*A1 + a1*A2) - * (a3*A0 - a0*A3) * (-a2*A0 + a0*A2) * (-a1*A0 + a0*A1) + z * y * x * w * (-a1*A0 + a0*A1) * (-a2*A0 + a0*A2) * (-a2*A1 + a1*A2) + * (a3*A2 - a2*A3) * (a3*A1 - a1*A3) * (a3*A0 - a0*A3) """ F = self._ring.base_ring() return 1/F(16) * self._jacobian_determinant( diff --git a/src/sage/rings/laurent_series_ring.py b/src/sage/rings/laurent_series_ring.py index 1feba6e675b..f40ec694493 100644 --- a/src/sage/rings/laurent_series_ring.py +++ b/src/sage/rings/laurent_series_ring.py @@ -42,7 +42,7 @@ from sage.rings.infinity import infinity from sage.rings.integer_ring import ZZ from sage.rings.laurent_series_ring_element import LaurentSeries -from sage.rings.ring import CommutativeRing +from sage.structure.parent import Parent from sage.structure.unique_representation import UniqueRepresentation try: @@ -84,7 +84,7 @@ def is_LaurentSeriesRing(x): return isinstance(x, (LaurentSeriesRing, LazyLaurentSeriesRing)) -class LaurentSeriesRing(UniqueRepresentation, CommutativeRing): +class LaurentSeriesRing(UniqueRepresentation, Parent): r""" Univariate Laurent Series Ring. @@ -290,9 +290,9 @@ def __init__(self, power_series): self._power_series_ring = power_series self._one_element = self.element_class(self, power_series.one()) - CommutativeRing.__init__(self, base_ring, - names=power_series.variable_names(), - category=category) + Parent.__init__(self, base_ring, + names=power_series.variable_names(), + category=category) def base_extend(self, R): """ @@ -803,6 +803,16 @@ def gen(self, n=0): raise IndexError("generator {} not defined".format(n)) return self.element_class(self, [0, 1]) + def gens(self) -> tuple: + """ + EXAMPLES:: + + sage: R = LaurentSeriesRing(QQ, "x") + sage: R.gens() + (x,) + """ + return (self.gen(),) + def uniformizer(self): """ Return a uniformizer of this Laurent series field if it is diff --git a/src/sage/rings/lazy_series.py b/src/sage/rings/lazy_series.py index 6a4fea857a4..b801c6f1b57 100644 --- a/src/sage/rings/lazy_series.py +++ b/src/sage/rings/lazy_series.py @@ -2435,8 +2435,8 @@ def arctan(self): sage: L. = LazyPowerSeriesRing(QQ) sage: atan(x/(1-y)) - x + x*y + (-1/3*x^3+x*y^2) + (-x^3*y+x*y^3) + (1/5*x^5-2*x^3*y^2+x*y^4) - + (x^5*y-10/3*x^3*y^3+x*y^5) + (-1/7*x^7+3*x^5*y^2-5*x^3*y^4+x*y^6) + O(x,y)^8 + x + x*y - (1/3*x^3-x*y^2) - (x^3*y-x*y^3) + (1/5*x^5-2*x^3*y^2+x*y^4) + + (x^5*y-10/3*x^3*y^3+x*y^5) - (1/7*x^7-3*x^5*y^2+5*x^3*y^4-x*y^6) + O(x,y)^8 TESTS:: @@ -2555,8 +2555,8 @@ def tanh(self): sage: L. = LazyPowerSeriesRing(QQ) sage: tanh(x/(1-y)) # needs sage.libs.flint - x + x*y + (-1/3*x^3+x*y^2) + (-x^3*y+x*y^3) + (2/15*x^5-2*x^3*y^2+x*y^4) - + (2/3*x^5*y-10/3*x^3*y^3+x*y^5) + (-17/315*x^7+2*x^5*y^2-5*x^3*y^4+x*y^6) + O(x,y)^8 + x + x*y - (1/3*x^3-x*y^2) - (x^3*y-x*y^3) + (2/15*x^5-2*x^3*y^2+x*y^4) + + (2/3*x^5*y-10/3*x^3*y^3+x*y^5) - (17/315*x^7-2*x^5*y^2+5*x^3*y^4-x*y^6) + O(x,y)^8 TESTS:: @@ -2618,8 +2618,8 @@ def sech(self): sage: L. = LazyPowerSeriesRing(QQ) sage: sech(x/(1-y)) # needs sage.libs.flint - 1 + (-1/2*x^2) + (-x^2*y) + (5/24*x^4-3/2*x^2*y^2) + (5/6*x^4*y-2*x^2*y^3) - + (-61/720*x^6+25/12*x^4*y^2-5/2*x^2*y^4) + O(x,y)^7 + 1 - 1/2*x^2 - x^2*y + (5/24*x^4-3/2*x^2*y^2) + (5/6*x^4*y-2*x^2*y^3) + - (61/720*x^6-25/12*x^4*y^2+5/2*x^2*y^4) + O(x,y)^7 TESTS:: @@ -2688,8 +2688,8 @@ def arcsinh(self): sage: L. = LazyPowerSeriesRing(QQ) sage: asinh(x/(1-y)) - x + x*y + (-1/6*x^3+x*y^2) + (-1/2*x^3*y+x*y^3) + (3/40*x^5-x^3*y^2+x*y^4) - + (3/8*x^5*y-5/3*x^3*y^3+x*y^5) + (-5/112*x^7+9/8*x^5*y^2-5/2*x^3*y^4+x*y^6) + O(x,y)^8 + x + x*y - (1/6*x^3-x*y^2) - (1/2*x^3*y-x*y^3) + (3/40*x^5-x^3*y^2+x*y^4) + + (3/8*x^5*y-5/3*x^3*y^3+x*y^5) - (5/112*x^7-9/8*x^5*y^2+5/2*x^3*y^4-x*y^6) + O(x,y)^8 TESTS:: @@ -2908,11 +2908,11 @@ def sqrt(self): sage: L. = LazyPowerSeriesRing(QQ) sage: sqrt(1+x/(1-y)) - 1 + 1/2*x + (-1/8*x^2+1/2*x*y) + (1/16*x^3-1/4*x^2*y+1/2*x*y^2) - + (-5/128*x^4+3/16*x^3*y-3/8*x^2*y^2+1/2*x*y^3) - + (7/256*x^5-5/32*x^4*y+3/8*x^3*y^2-1/2*x^2*y^3+1/2*x*y^4) - + (-21/1024*x^6+35/256*x^5*y-25/64*x^4*y^2+5/8*x^3*y^3-5/8*x^2*y^4+1/2*x*y^5) - + O(x,y)^7 + 1 + 1/2*x - (1/8*x^2-1/2*x*y) + (1/16*x^3-1/4*x^2*y+1/2*x*y^2) + - (5/128*x^4-3/16*x^3*y+3/8*x^2*y^2-1/2*x*y^3) + + (7/256*x^5-5/32*x^4*y+3/8*x^3*y^2-1/2*x^2*y^3+1/2*x*y^4) + - (21/1024*x^6-35/256*x^5*y+25/64*x^4*y^2-5/8*x^3*y^3+5/8*x^2*y^4-1/2*x*y^5) + + O(x,y)^7 This also works for Dirichlet series:: @@ -4875,7 +4875,7 @@ class LazyPowerSeries(LazyCauchyProductSeries): sage: L. = LazyPowerSeriesRing(ZZ) sage: f = 1 / (1 - x^2 + y^3); f - 1 + x^2 + (-y^3) + x^4 + (-2*x^2*y^3) + (x^6+y^6) + O(x,y)^7 + 1 + x^2 - y^3 + x^4 - 2*x^2*y^3 + (x^6+y^6) + O(x,y)^7 sage: P. = PowerSeriesRing(ZZ, default_prec=101) sage: g = 1 / (1 - x^2 + y^3); f[100] - g[100] 0 @@ -4884,7 +4884,7 @@ class LazyPowerSeries(LazyCauchyProductSeries): sage: g = loads(dumps(f)) sage: g - 1 + x^2 + (-y^3) + x^4 + (-2*x^2*y^3) + (x^6+y^6) + O(x,y)^7 + 1 + x^2 - y^3 + x^4 - 2*x^2*y^3 + (x^6+y^6) + O(x,y)^7 sage: g == f True """ @@ -5503,14 +5503,14 @@ def derivative(self, *args): sage: f = (1 + x + y^2 + z)^-1 sage: f.derivative(x) - -1 + (2*x+2*z) + (-3*x^2+2*y^2-6*x*z-3*z^2) + ... + O(x,y,z)^6 + -1 + (2*x+2*z) - (3*x^2-2*y^2+6*x*z+3*z^2) + ... + O(x,y,z)^6 sage: f.derivative(y, 2) - -2 + (4*x+4*z) + (-6*x^2+12*y^2-12*x*z-6*z^2) + ... + O(x,y,z)^5 + -2 + (4*x+4*z) - (6*x^2-12*y^2+12*x*z+6*z^2) + ... + O(x,y,z)^5 sage: f.derivative(x, y) - 4*y + (-12*x*y-12*y*z) + (24*x^2*y-12*y^3+48*x*y*z+24*y*z^2) - + (-40*x^3*y+48*x*y^3-120*x^2*y*z+48*y^3*z-120*x*y*z^2-40*y*z^3) + O(x,y,z)^5 + 4*y - (12*x*y+12*y*z) + (24*x^2*y-12*y^3+48*x*y*z+24*y*z^2) + - (40*x^3*y-48*x*y^3+120*x^2*y*z-48*y^3*z+120*x*y*z^2+40*y*z^3) + O(x,y,z)^5 sage: f.derivative(x, y, z) - (-12*y) + (48*x*y+48*y*z) + (-120*x^2*y+48*y^3-240*x*y*z-120*y*z^2) + O(x,y,z)^4 + -12*y + (48*x*y+48*y*z) - (120*x^2*y-48*y^3+240*x*y*z+120*y*z^2) + O(x,y,z)^4 sage: R. = QQ[] sage: L. = LazyPowerSeriesRing(R) @@ -5797,7 +5797,7 @@ def integral(self, variable=None, *, constants=None): sage: L. = LazyPowerSeriesRing(QQ) sage: (x + y - z^2).integral(z) - (x*z+y*z) + (-1/3*z^3) + (x*z+y*z) - 1/3*z^3 TESTS:: @@ -5928,13 +5928,13 @@ def _format_series(self, formatter, format_strings=False): sage: L. = LazyPowerSeriesRing(QQ) sage: f = 1 / (2 - x^2 + y) sage: f._format_series(repr) - '1/2 + (-1/4*y) + (1/4*x^2+1/8*y^2) + (-1/4*x^2*y-1/16*y^3) - + (1/8*x^4+3/16*x^2*y^2+1/32*y^4) + (-3/16*x^4*y-1/8*x^2*y^3-1/64*y^5) + '1/2 - 1/4*y + (1/4*x^2+1/8*y^2) - (1/4*x^2*y+1/16*y^3) + + (1/8*x^4+3/16*x^2*y^2+1/32*y^4) - (3/16*x^4*y+1/8*x^2*y^3+1/64*y^5) + (1/16*x^6+3/16*x^4*y^2+5/64*x^2*y^4+1/128*y^6) + O(x,y)^7' sage: f = (2 - x^2 + y) sage: f._format_series(repr) - '2 + y + (-x^2)' + '2 + y - x^2' """ P = self.parent() cs = self._coeff_stream @@ -6011,7 +6011,7 @@ def polynomial(self, degree=None, names=None): sage: L. = LazyPowerSeriesRing(ZZ) sage: f = x^2 + y*x - x + 2; f - 2 + (-x) + (x^2+x*y) + 2 - x + (x^2+x*y) sage: f.polynomial() x^2 + x*y - x + 2 @@ -6019,7 +6019,7 @@ def polynomial(self, degree=None, names=None): sage: g = 1 / (1 + x + y + x*y) sage: g3 = g.truncate(4); g3 - 1 + (-x-y) + (x^2+x*y+y^2) + (-x^3-x^2*y-x*y^2-y^3) + 1 - (x+y) + (x^2+x*y+y^2) - (x^3+x^2*y+x*y^2+y^3) sage: g.polynomial() Traceback (most recent call last): ... @@ -6628,7 +6628,7 @@ def revert(self): sage: L = LazySymmetricFunctions(p) sage: f = L(a + b*p[1]) sage: f.revert() - (((-a)/b)*p[]) + 1/b*p[1] + (-a/b*p[]) + 1/b*p[1] sage: f = L(2*p[1]) sage: f.revert() 1/2*p[1] diff --git a/src/sage/rings/lazy_series_ring.py b/src/sage/rings/lazy_series_ring.py index 51359391111..17dda1061dd 100644 --- a/src/sage/rings/lazy_series_ring.py +++ b/src/sage/rings/lazy_series_ring.py @@ -2273,9 +2273,9 @@ def _element_constructor_(self, x=None, valuation=None, constant=None, degree=No sage: f.parent() Fraction Field of Multivariate Polynomial Ring in a, b, c over Integer Ring sage: L(f) # needs sage.libs.singular - 1 + (a+b) + (-a*b) + (-a^2*b-a*b^2-c^3) + (a^2*b^2-a*c^3-b*c^3) - + (a^3*b^2+a^2*b^3+2*a*b*c^3) + (-a^3*b^3+2*a^2*b*c^3+2*a*b^2*c^3+c^6) - + O(a,b,c)^7 + 1 + (a+b) - a*b - (a^2*b+a*b^2+c^3) + (a^2*b^2-a*c^3-b*c^3) + + (a^3*b^2+a^2*b^3+2*a*b*c^3) - (a^3*b^3-2*a^2*b*c^3-2*a*b^2*c^3-c^6) + + O(a,b,c)^7 sage: L(f) == (1 + aa + bb) / (1 + aa*bb + cc^3) # needs sage.libs.singular True @@ -2535,11 +2535,9 @@ def some_elements(self): sage: L.some_elements()[:6] [0, 1, q, q + q^2 + q^3, - 1 + q + q^2 + (-q^3) + (-q^4) + (-q^5) + (-q^6) + O(q,t)^7, - 1 + (q+t) + (q^2-q*t+t^2) + (q^3+t^3) - + (q^4+q^3*t+q*t^3+t^4) - + (q^5-q^4*t+q^3*t^2+q^2*t^3-q*t^4+t^5) - + (q^6-q^3*t^3+t^6) + O(q,t)^7] + 1 + q + q^2 - q^3 - q^4 - q^5 - q^6 + O(q,t)^7, + 1 + (q+t) + (q^2-q*t+t^2) + (q^3+t^3) + (q^4+q^3*t+q*t^3+t^4) + + (q^5-q^4*t+q^3*t^2+q^2*t^3-q*t^4+t^5) + (q^6-q^3*t^3+t^6) + O(q,t)^7] """ z = self.gen(0) elts = [self.zero(), self.one(), self.an_element()] @@ -2595,14 +2593,14 @@ def taylor(self, f): sage: L. = LazyPowerSeriesRing(QQ) sage: def f(x, y): return (1 + x) / (1 + y) sage: L.taylor(f) - 1 + (a-b) + (-a*b+b^2) + (a*b^2-b^3) + (-a*b^3+b^4) + (a*b^4-b^5) + (-a*b^5+b^6) + O(a,b)^7 + 1 + (a-b) - (a*b-b^2) + (a*b^2-b^3) - (a*b^3-b^4) + (a*b^4-b^5) - (a*b^5-b^6) + O(a,b)^7 sage: g(w, z) = (1 + w) / (1 + z) sage: L.taylor(g) - 1 + (a-b) + (-a*b+b^2) + (a*b^2-b^3) + (-a*b^3+b^4) + (a*b^4-b^5) + (-a*b^5+b^6) + O(a,b)^7 + 1 + (a-b) - (a*b-b^2) + (a*b^2-b^3) - (a*b^3-b^4) + (a*b^4-b^5) - (a*b^5-b^6) + O(a,b)^7 sage: y = SR.var('y') sage: h = (1 + x) / (1 + y) sage: L.taylor(h) - 1 + (a-b) + (-a*b+b^2) + (a*b^2-b^3) + (-a*b^3+b^4) + (a*b^4-b^5) + (-a*b^5+b^6) + O(a,b)^7 + 1 + (a-b) - (a*b-b^2) + (a*b^2-b^3) - (a*b^3-b^4) + (a*b^4-b^5) - (a*b^5-b^6) + O(a,b)^7 """ try: return f(*self.gens()) diff --git a/src/sage/rings/localization.py b/src/sage/rings/localization.py index 8ac31a6ff67..4692efc0747 100644 --- a/src/sage/rings/localization.py +++ b/src/sage/rings/localization.py @@ -37,8 +37,8 @@ sage: add_units += [q*ui - uj for ui, uj in I if ui != uj] sage: L = R.localization(tuple(add_units)); L # needs sage.libs.pari Multivariate Polynomial Ring in u0, u1, u2, q over Integer Ring localized at - (q, q + 1, u2, u1, u1 - u2, u0, u0 - u2, u0 - u1, u2*q - u1, u2*q - u0, - u1*q - u2, u1*q - u0, u0*q - u2, u0*q - u1) + (q, q + 1, u2, u1 - u2, u1, u0 - u1, u0 - u2, u0, u2*q - u0, u2*q - u1, u1*q - u0, + u1*q - u2, u0*q - u1, u0*q - u2) Define the representation matrices (of one of the three dimensional irreducible representations):: @@ -82,8 +82,8 @@ sage: f = L.hom((3,5,7,11), codomain=Fp); f Ring morphism: From: Multivariate Polynomial Ring in u0, u1, u2, q over Integer Ring localized at - (q, q + 1, u2, u1, u1 - u2, u0, u0 - u2, u0 - u1, u2*q - u1, u2*q - u0, - u1*q - u2, u1*q - u0, u0*q - u2, u0*q - u1) + (q, q + 1, u2, u1 - u2, u1, u0 - u1, u0 - u2, u0, u2*q - u0, u2*q - u1, + u1*q - u0, u1*q - u2, u0*q - u1, u0*q - u2) To: Finite Field of size 17 Defn: u0 |--> 3 u1 |--> 5 @@ -110,8 +110,8 @@ sage: fQ = L.hom((3,5,7,11), codomain=QQ); fQ Ring morphism: From: Multivariate Polynomial Ring in u0, u1, u2, q over Integer Ring - localized at (q, q + 1, u2, u1, u1 - u2, u0, u0 - u2, u0 - u1, - u2*q - u1, u2*q - u0, u1*q - u2, u1*q - u0, u0*q - u2, u0*q - u1) + localized at (q, q + 1, u2, u1 - u2, u1, u0 - u1, u0 - u2, u0, u2*q - u0, + u2*q - u1, u1*q - u0, u1*q - u2, u0*q - u1, u0*q - u2) To: Rational Field Defn: u0 |--> 3 u1 |--> 5 @@ -141,8 +141,8 @@ sage: fF = L.hom((x, y, z, t), codomain=F); fF Ring morphism: From: Multivariate Polynomial Ring in u0, u1, u2, q over Integer Ring - localized at (q, q + 1, u2, u1, u1 - u2, u0, u0 - u2, u0 - u1, - u2*q - u1, u2*q - u0, u1*q - u2, u1*q - u0, u0*q - u2, u0*q - u1) + localized at (q, q + 1, u2, u1 - u2, u1, u0 - u1, u0 - u2, u0, u2*q - u0, + u2*q - u1, u1*q - u0, u1*q - u2, u0*q - u1, u0*q - u2) To: Fraction Field of Quotient of Multivariate Polynomial Ring in x, y, z, t over Rational Field by the ideal (x + y + z) Defn: u0 |--> -ybar - zbar diff --git a/src/sage/rings/number_field/bdd_height.py b/src/sage/rings/number_field/bdd_height.py index 45f08aa4711..9635afa3613 100644 --- a/src/sage/rings/number_field/bdd_height.py +++ b/src/sage/rings/number_field/bdd_height.py @@ -608,8 +608,8 @@ def packet_height(n, pair, u): u_height = sum([max(u_log[k], 0) for k in range(r + 1)]) unit_height_dict[u] = u_height if u_height < inter_bound: - U0.append(u) - if inter_bound <= u_height and u_height < b - (t/12): + U0.append(u) + if inter_bound <= u_height < b - (t/12): U0_tilde.append(u) if u_height > t/12 + d_tilde: U_copy.remove(u) diff --git a/src/sage/rings/number_field/number_field.py b/src/sage/rings/number_field/number_field.py index fa9c452c961..05371850c83 100644 --- a/src/sage/rings/number_field/number_field.py +++ b/src/sage/rings/number_field/number_field.py @@ -8780,40 +8780,10 @@ def subfields(self, degree=0, name=None): polynomials are supported (:issue:`252`):: sage: K. = NumberField(2*x^4 + 6*x^2 + 1/2) - sage: sorted(K.subfields(), key=lambda x: x[0].discriminant()) - [(Number Field in a3 with defining polynomial x^2 + 2, - Ring morphism: - From: Number Field in a3 with defining polynomial x^2 + 2 - To: Number Field in a with defining polynomial 2*x^4 + 6*x^2 + 1/2 - Defn: a3 |--> 2*a^3 + 5*a, - None), - (Number Field in a2 with defining polynomial x^2 + 4, - Ring morphism: - From: Number Field in a2 with defining polynomial x^2 + 4 - To: Number Field in a with defining polynomial 2*x^4 + 6*x^2 + 1/2 - Defn: a2 |--> 2*a^3 + 7*a, - None), - (Number Field in a0 with defining polynomial x, - Ring morphism: - From: Number Field in a0 with defining polynomial x - To: Number Field in a with defining polynomial 2*x^4 + 6*x^2 + 1/2 - Defn: 0 |--> 0, - None), - (Number Field in a1 with defining polynomial x^2 - 2, - Ring morphism: - From: Number Field in a1 with defining polynomial x^2 - 2 - To: Number Field in a with defining polynomial 2*x^4 + 6*x^2 + 1/2 - Defn: a1 |--> a^2 + 3/2, - None), - (Number Field in a4 with defining polynomial x^4 + 1, - Ring morphism: - From: Number Field in a4 with defining polynomial x^4 + 1 - To: Number Field in a with defining polynomial 2*x^4 + 6*x^2 + 1/2 - Defn: a4 |--> a^3 + 1/2*a^2 + 5/2*a + 3/4, - Ring morphism: - From: Number Field in a with defining polynomial 2*x^4 + 6*x^2 + 1/2 - To: Number Field in a4 with defining polynomial x^4 + 1 - Defn: a |--> -1/2*a4^3 + a4^2 - 1/2*a4)] + sage: K + Number Field in a with defining polynomial 2*x^4 + 6*x^2 + 1/2 + sage: sorted([F.discriminant() for F, _, _ in K.subfields()]) + [-8, -4, 1, 8, 256] """ return self._subfields_helper(degree=degree, name=name, both_maps=True, optimize=False) diff --git a/src/sage/rings/number_field/number_field_rel.py b/src/sage/rings/number_field/number_field_rel.py index ea81834f56c..970707f2457 100644 --- a/src/sage/rings/number_field/number_field_rel.py +++ b/src/sage/rings/number_field/number_field_rel.py @@ -302,7 +302,7 @@ def __init__(self, base, polynomial, name, raise ValueError("base field and extension cannot have the same name %r" % name) if polynomial.parent().base_ring() != base: polynomial = polynomial.change_ring(base) - #raise ValueError, "The polynomial must be defined over the base field" + # raise ValueError("The polynomial must be defined over the base field") # Generate the nf and bnf corresponding to the base field # defined as polynomials in y, e.g. for rnfisfree diff --git a/src/sage/rings/padics/common_conversion.pyx b/src/sage/rings/padics/common_conversion.pyx index 6831fbde141..b6f0dc17e4d 100644 --- a/src/sage/rings/padics/common_conversion.pyx +++ b/src/sage/rings/padics/common_conversion.pyx @@ -1,4 +1,6 @@ r""" +Tools for creation of `p`-adic elements + The functions in this file are used in creating new `p`-adic elements. When creating a `p`-adic element, the user can specify that the absolute @@ -49,7 +51,7 @@ cdef Rational rat_temp = PY_NEW(Rational) cdef long get_ordp(x, PowComputer_class prime_pow) except? -10000: """ - This function determines the valuation of the `p`-adic element + Determine the valuation of the `p`-adic element that will result from the given data ``x``. Note that the valuation can differ depending on the ring: if the @@ -160,7 +162,7 @@ cdef long get_ordp(x, PowComputer_class prime_pow) except? -10000: cdef long get_preccap(x, PowComputer_class prime_pow) except? -10000: """ - This function determines the maximum absolute precision possible + Determine the maximum absolute precision possible for an element created from the given data ``x``. Note that the valuation can differ depending on the ring: if the @@ -231,7 +233,7 @@ cdef long get_preccap(x, PowComputer_class prime_pow) except? -10000: cdef long comb_prec(iprec, long prec) except? -10000: """ - This function returns the minimum of iprec and prec. + Return the minimum of ``iprec`` and ``prec``. INPUT: @@ -255,7 +257,7 @@ cdef long comb_prec(iprec, long prec) except? -10000: cdef int _process_args_and_kwds(long *aprec, long *rprec, args, kwds, bint absolute, PowComputer_class prime_pow) except -1: """ - This function obtains values for absprec and relprec from a + Obtain values for ``absprec`` and ``relprec`` from a combination of positional and keyword arguments. When creating a `p`-adic element, the user can pass in two arguments: ``absprec`` and ``relprec``. @@ -332,7 +334,7 @@ cdef inline long cconv_mpq_t_shared(mpz_t out, mpq_t x, long prec, bint absolute OUTPUT: - - If ``absolute`` is False then returns the valuation that was + - If ``absolute`` is ``False`` then returns the valuation that was extracted (``maxordp`` when `x = 0`). """ cdef long numval, denval @@ -364,6 +366,8 @@ cdef inline int cconv_mpq_t_out_shared(mpq_t out, mpz_t x, long valshift, long p """ Convert the underlying `p`-adic element into a rational. + INPUT: + - ``out`` -- gives a rational approximating the input. Currently uses rational reconstruction but may change in the future to use a more naive method @@ -447,11 +451,11 @@ cdef inline int cconv_shared(mpz_t out, x, long prec, long valshift, PowComputer else: raise NotImplementedError else: - raise NotImplementedError("No conversion defined for %s which is a %s in %s"%(x,type(x),x.parent() if hasattr(x,"parent") else "no parent")) + raise NotImplementedError("No conversion defined for %s which is a %s in %s" % (x, type(x), x.parent() if hasattr(x, "parent") else "no parent")) cdef inline long cconv_mpz_t_shared(mpz_t out, mpz_t x, long prec, bint absolute, PowComputer_class prime_pow) except -2: """ - A fast pathway for conversion of integers that doesn't require + A fast pathway for conversion of integers that does not require precomputation of the valuation. INPUT: @@ -485,6 +489,8 @@ cdef inline int cconv_mpz_t_out_shared(mpz_t out, mpz_t x, long valshift, long p """ Convert the underlying `p`-adic element into an integer if possible. + INPUT: + - ``out`` -- stores the resulting integer as an integer between 0 and `p^{prec + valshift}` - ``x`` -- an ``mpz_t`` giving the underlying `p`-adic element diff --git a/src/sage/rings/padics/factory.py b/src/sage/rings/padics/factory.py index de5e112343f..9dce85e130f 100644 --- a/src/sage/rings/padics/factory.py +++ b/src/sage/rings/padics/factory.py @@ -2608,7 +2608,7 @@ def Zq(q, prec=None, type='capped-rel', modulus=None, names=None, raise TypeError("modulus must be a polynomial") if names is not None and not isinstance(names, str): names = str(names) - #raise TypeError, "names must be a string" + # raise TypeError("names must be a string") q = Integer(q) F = q.factor() if len(F) != 1: diff --git a/src/sage/rings/padics/misc.py b/src/sage/rings/padics/misc.py index d7ce570a732..3ce3f4f39f9 100644 --- a/src/sage/rings/padics/misc.py +++ b/src/sage/rings/padics/misc.py @@ -14,7 +14,7 @@ - Ander Steele - Kiran Kedlaya (modified gauss_sum 2017/09) """ -#***************************************************************************** +# **************************************************************************** # Copyright (C) 2007-2013 David Roe # William Stein # @@ -22,8 +22,8 @@ # 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.rings.infinity import infinity @@ -214,7 +214,7 @@ def precprint(prec_type, prec_cap, p): def trim_zeros(L): r""" - Strips trailing zeros/empty lists from a list. + Strip trailing zeros/empty lists from a list. EXAMPLES:: @@ -228,7 +228,7 @@ def trim_zeros(L): sage: trim_zeros([]) [] - Zeros are also trimmed from nested lists (one deep): + Zeros are also trimmed from nested lists (one deep):: sage: trim_zeros([[1,0]]) [[1]] diff --git a/src/sage/rings/padics/padic_generic.py b/src/sage/rings/padics/padic_generic.py index be3f3de2e7d..479b5a18457 100644 --- a/src/sage/rings/padics/padic_generic.py +++ b/src/sage/rings/padics/padic_generic.py @@ -195,7 +195,7 @@ def __richcmp__(self, other, op): return self._printer.richcmp_modes(other._printer, op) - def print_mode(self): + def print_mode(self) -> str: r""" Return the current print mode as a string. diff --git a/src/sage/rings/padics/pow_computer_ext.pxd b/src/sage/rings/padics/pow_computer_ext.pxd index 5d31790e02e..75132381330 100644 --- a/src/sage/rings/padics/pow_computer_ext.pxd +++ b/src/sage/rings/padics/pow_computer_ext.pxd @@ -48,7 +48,7 @@ cdef class PowComputer_ZZ_pX_FM_Eis(PowComputer_ZZ_pX_FM): cdef void cleanup_ZZ_pX_FM_Eis(self) noexcept cdef class PowComputer_ZZ_pX_small(PowComputer_ZZ_pX): - cdef object c # using a python list so that we can store ntl_ZZ_pContext_class objects + cdef object c # using a python list so that we can store ntl_ZZ_pContext_class objects cdef ZZ_pX_Modulus_c *mod cdef void cleanup_ZZ_pX_small(self) noexcept @@ -62,14 +62,14 @@ cdef class PowComputer_ZZ_pX_small_Eis(PowComputer_ZZ_pX_small): cdef void cleanup_ZZ_pX_small_Eis(self) noexcept cdef class PowComputer_ZZ_pX_big(PowComputer_ZZ_pX): - cdef object context_list # using a python list so that we can store ntl_ZZ_pContext_class objects + cdef object context_list # using a python list so that we can store ntl_ZZ_pContext_class objects cdef ZZ_pX_Modulus_c *modulus_list cdef ntl_ZZ_pContext_class top_context cdef ZZ_pX_Modulus_c top_mod - cdef object context_dict #currently using a dict, optimize for speed later - cdef object modulus_dict #currently using a dict, optimize for speed later + cdef object context_dict # currently using a dict, optimize for speed later + cdef object modulus_dict # currently using a dict, optimize for speed later cdef void cleanup_ZZ_pX_big(self) noexcept @@ -81,7 +81,7 @@ cdef class PowComputer_ZZ_pX_big_Eis(PowComputer_ZZ_pX_big): cdef void cleanup_ZZ_pX_big_Eis(self) noexcept -#cdef class PowComputer_ZZ_pEX(PowComputer_ext): +# cdef class PowComputer_ZZ_pEX(PowComputer_ext): # cdef ntl_ZZ_pEContext get_context(self, long n) # cdef ntl_ZZ_pEContext get_top_context(self) # cdef void restore_context(self, long n) @@ -89,19 +89,18 @@ cdef class PowComputer_ZZ_pX_big_Eis(PowComputer_ZZ_pX_big): # cdef ZZ_pEX_Modulus_c get_modulus(self, long n) # cdef ZZ_pEX_Modulus_c get_top_modulus(self) # -#cdef class PowComputer_ZZ_pEX_FM(PowComputer_ZZ_pEX): +# cdef class PowComputer_ZZ_pEX_FM(PowComputer_ZZ_pEX): # cdef ZZ_pEX_c poly # cdef ntl_ZZ_pEContext c # cdef ZZ_pEX_Modulus_c mod # # -#cdef class PowComputer_ZZ_pEX_small(PowComputer_ZZ_pEX): +# cdef class PowComputer_ZZ_pEX_small(PowComputer_ZZ_pEX): # cdef ZZ_pEX_c *poly # cdef ntl_ZZ_pEContext *c # cdef ZZ_pEX_Modulus_c *mod # -#cdef class PowComputer_ZZ_pEX_big(PowComputer_ZZ_pEX): +# cdef class PowComputer_ZZ_pEX_big(PowComputer_ZZ_pEX): # cdef ZZ_pEX_c poly -# cdef context_dict #currently using a dict, optimize for speed later -# cdef modulus_dict #currently using a dict, optimize for speed later -# +# cdef context_dict # currently using a dict, optimize for speed later +# cdef modulus_dict # currently using a dict, optimize for speed later diff --git a/src/sage/rings/polynomial/multi_polynomial_ideal.py b/src/sage/rings/polynomial/multi_polynomial_ideal.py index 24239660dec..d8546e31b33 100644 --- a/src/sage/rings/polynomial/multi_polynomial_ideal.py +++ b/src/sage/rings/polynomial/multi_polynomial_ideal.py @@ -1067,31 +1067,28 @@ def triangular_decomposition(self, algorithm=None, singular=None): [Ideal (a - 1, b - 1, c - 1, d^2 + 3*d + 1, e + d + 3) of Multivariate Polynomial Ring in e, d, c, b, a over Rational Field, Ideal (a - 1, b - 1, c^2 + 3*c + 1, d + c + 3, e - 1) of Multivariate Polynomial Ring in e, d, c, b, a over Rational Field, Ideal (a - 1, b^2 + 3*b + 1, c + b + 3, d - 1, e - 1) of Multivariate Polynomial Ring in e, d, c, b, a over Rational Field, - Ideal (a - 1, b^4 + b^3 + b^2 + b + 1, -c + b^2, -d + b^3, - e + b^3 + b^2 + b + 1) of Multivariate Polynomial Ring in e, d, c, b, a over Rational Field, + Ideal (a - 1, b^4 + b^3 + b^2 + b + 1, -c + b^2, -d + b^3, e + b^3 + b^2 + b + 1) of Multivariate + Polynomial Ring in e, d, c, b, a over Rational Field, Ideal (a^2 + 3*a + 1, b - 1, c - 1, d - 1, e + a + 3) of Multivariate Polynomial Ring in e, d, c, b, a over Rational Field, Ideal (a^2 + 3*a + 1, b + a + 3, c - 1, d - 1, e - 1) of Multivariate Polynomial Ring in e, d, c, b, a over Rational Field, Ideal (a^4 - 4*a^3 + 6*a^2 + a + 1, -11*b^2 + 6*b*a^3 - 26*b*a^2 + 41*b*a - 4*b - 8*a^3 + 31*a^2 - 40*a - 24, 11*c + 3*a^3 - 13*a^2 + 26*a - 2, 11*d + 3*a^3 - 13*a^2 + 26*a - 2, -11*e - 11*b + 6*a^3 - 26*a^2 + 41*a - 4) of Multivariate Polynomial Ring in e, d, c, b, a over Rational Field, - Ideal (a^4 + a^3 + a^2 + a + 1, - b - 1, c + a^3 + a^2 + a + 1, -d + a^3, -e + a^2) of Multivariate Polynomial Ring in e, d, c, b, a over Rational Field, - Ideal (a^4 + a^3 + a^2 + a + 1, - b - a, c - a, d^2 + 3*d*a + a^2, e + d + 3*a) of Multivariate Polynomial Ring in e, d, c, b, a over Rational Field, - Ideal (a^4 + a^3 + a^2 + a + 1, - b - a, c^2 + 3*c*a + a^2, d + c + 3*a, e - a) of Multivariate Polynomial Ring in e, d, c, b, a over Rational Field, - Ideal (a^4 + a^3 + a^2 + a + 1, - b^2 + 3*b*a + a^2, c + b + 3*a, d - a, e - a) of Multivariate Polynomial Ring in e, d, c, b, a over Rational Field, - Ideal (a^4 + a^3 + a^2 + a + 1, - b^3 + b^2*a + b^2 + b*a^2 + b*a + b + a^3 + a^2 + a + 1, - c + b^2*a^3 + b^2*a^2 + b^2*a + b^2, - -d + b^2*a^2 + b^2*a + b^2 + b*a^2 + b*a + a^2, + Ideal (a^4 + a^3 + a^2 + a + 1, b - a, c - a, d^2 + 3*d*a + a^2, + e + d + 3*a) of Multivariate Polynomial Ring in e, d, c, b, a over Rational Field, + Ideal (a^4 + a^3 + a^2 + a + 1, b - a, c^2 + 3*c*a + a^2, d + c + 3*a, + e - a) of Multivariate Polynomial Ring in e, d, c, b, a over Rational Field, + Ideal (a^4 + a^3 + a^2 + a + 1, b - 1, c + a^3 + a^2 + a + 1, -d + a^3, + -e + a^2) of Multivariate Polynomial Ring in e, d, c, b, a over Rational Field, + Ideal (a^4 + a^3 + a^2 + a + 1, b^2 + 3*b*a + a^2, c + b + 3*a, d - a, + e - a) of Multivariate Polynomial Ring in e, d, c, b, a over Rational Field, + Ideal (a^4 + a^3 + a^2 + a + 1, b^3 + b^2*a + b^2 + b*a^2 + b*a + b + a^3 + a^2 + a + 1, + c + b^2*a^3 + b^2*a^2 + b^2*a + b^2, -d + b^2*a^2 + b^2*a + b^2 + b*a^2 + b*a + a^2, -e + b^2*a^3 - b*a^2 - b*a - b - a^2 - a) of Multivariate Polynomial Ring in e, d, c, b, a over Rational Field, - Ideal (a^4 + a^3 + 6*a^2 - 4*a + 1, - -11*b^2 + 6*b*a^3 + 10*b*a^2 + 39*b*a + 2*b + 16*a^3 + 23*a^2 + 104*a - 24, - 11*c + 3*a^3 + 5*a^2 + 25*a + 1, 11*d + 3*a^3 + 5*a^2 + 25*a + 1, - -11*e - 11*b + 6*a^3 + 10*a^2 + 39*a + 2) of Multivariate Polynomial Ring in e, d, c, b, a over Rational Field] + Ideal (a^4 + a^3 + 6*a^2 - 4*a + 1, -11*b^2 + 6*b*a^3 + 10*b*a^2 + 39*b*a + 2*b + 16*a^3 + 23*a^2 + 104*a - 24, + 11*c + 3*a^3 + 5*a^2 + 25*a + 1, 11*d + 3*a^3 + 5*a^2 + 25*a + 1, -11*e - 11*b + 6*a^3 + 10*a^2 + 39*a + 2) + of Multivariate Polynomial Ring in e, d, c, b, a over Rational Field] sage: R. = PolynomialRing(QQ, 2, order='lex') sage: f1 = 1/2*((x1^2 + 2*x1 - 4)*x2^2 + 2*(x1^2 + x1)*x2 + x1^2) @@ -2333,7 +2330,7 @@ def elimination_ideal(self, variables, algorithm=None, *args, **kwds): Check that this method works over QQbar (:issue:`25351`):: - sage: # needs sage.rings.number_field sage.libs.giac + sage: # needs sage.libs.giac sage.rings.number_field sage: R. = QQbar[] sage: I = R * [x - t, y - t^2, z - t^3, s - x + y^3] sage: J = I.elimination_ideal([t, s]); J @@ -4635,7 +4632,7 @@ def groebner_basis(self, algorithm='', deg_bound=None, mult_bound=None, prot=Fal sage: I.groebner_basis('libsingular:slimgb') [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] - sage: # needs sage.rings.number_field sage.libs.giac + sage: # needs sage.libs.giac sage.rings.number_field sage: I = sage.rings.ideal.Katsura(P,3) # regenerate to prevent caching sage: J = I.change_ring(P.change_ring(order='degrevlex')) sage: gb = J.groebner_basis('giac') # random diff --git a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx index adf3df1cf95..ddbd4bdbca2 100644 --- a/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx +++ b/src/sage/rings/polynomial/multi_polynomial_libsingular.pyx @@ -619,8 +619,8 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: P._singular_() polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 3 + // coefficients: QQ... + // number of vars : 3 // block 1 : ordering dp // : names x y z // block 2 : ordering C @@ -1182,8 +1182,8 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: P. = QQ[] sage: P._singular_() polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 3 + // coefficients: QQ... + // number of vars : 3 // block 1 : ordering dp // : names x y z // block 2 : ordering C @@ -1198,8 +1198,8 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: P. = PolynomialRing(k, 3) # needs sage.rings.finite_rings sage: P._singular_() # needs sage.rings.finite_rings polynomial ring, over a field, global ordering - // coefficients: ZZ/3[a]/(a^3-a+1) - // number of vars : 3 + // coefficients: ZZ/3[a]/(a^3-a+1)... + // number of vars : 3 // block 1 : ordering dp // : names x y z // block 2 : ordering C @@ -1215,8 +1215,8 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: P. = QQ[] sage: P._singular_() polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 1 + // coefficients: QQ... + // number of vars : 1 // block 1 : ordering lp // : names x // block 2 : ordering C @@ -1257,8 +1257,8 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: P. = QQ[] sage: P._singular_init_() polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 3 + // coefficients: QQ... + // number of vars : 3 // block 1 : ordering dp // : names x y z // block 2 : ordering C @@ -1272,8 +1272,8 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: R. = PolynomialRing(NumberField(w^2 + 1,'s')) # needs sage.rings.number_field sage: singular(R) # needs sage.rings.number_field polynomial ring, over a field, global ordering - // coefficients: QQ[s]/(s^2+1) - // number of vars : 2 + // coefficients: QQ[s]/(s^2+1)... + // number of vars : 2 // block 1 : ordering dp // : names x y // block 2 : ordering C @@ -1281,8 +1281,8 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: R = PolynomialRing(GF(2**8,'a'),10,'x', order='invlex') # needs sage.rings.finite_rings sage: singular(R) # needs sage.rings.finite_rings polynomial ring, over a field, global ordering - // coefficients: ZZ/2[a]/(a^8+a^4+a^3+a^2+1) - // number of vars : 10 + // coefficients: ZZ/2[a]/(a^8+a^4+a^3+a^2+1)... + // number of vars : 10 // block 1 : ordering ip // : names x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 // block 2 : ordering C @@ -1290,8 +1290,8 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: R = PolynomialRing(GF(127),2,'x', order='invlex') sage: singular(R) # needs sage.rings.finite_rings polynomial ring, over a field, global ordering - // coefficients: ZZ/127 - // number of vars : 2 + // coefficients: ZZ/127... + // number of vars : 2 // block 1 : ordering ip // : names x0 x1 // block 2 : ordering C @@ -1299,8 +1299,8 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: R = PolynomialRing(QQ,2,'x', order='invlex') sage: singular(R) # needs sage.rings.function_field polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 2 + // coefficients: QQ... + // number of vars : 2 // block 1 : ordering ip // : names x0 x1 // block 2 : ordering C @@ -1308,8 +1308,8 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: R = PolynomialRing(QQ,2,'x', order='degneglex') sage: singular(R) # needs sage.rings.function_field polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 2 + // coefficients: QQ... + // number of vars : 2 // block 1 : ordering a // : names x0 x1 // : weights 1 1 @@ -1320,8 +1320,8 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: R = PolynomialRing(QQ,'x') sage: singular(R) # needs sage.rings.function_field polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 1 + // coefficients: QQ... + // number of vars : 1 // block 1 : ordering lp // : names x // block 2 : ordering C @@ -1329,8 +1329,8 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: R = PolynomialRing(GF(127),'x') sage: singular(R) # needs sage.rings.finite_rings polynomial ring, over a field, global ordering - // coefficients: ZZ/127 - // number of vars : 1 + // coefficients: ZZ/127... + // number of vars : 1 // block 1 : ordering lp // : names x // block 2 : ordering C @@ -1338,8 +1338,8 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: R = ZZ['x,y'] sage: singular(R) # needs sage.rings.function_field polynomial ring, over a domain, global ordering - // coefficients: ZZ - // number of vars : 2 + // coefficients: ZZ... + // number of vars : 2 // block 1 : ordering dp // : names x y // block 2 : ordering C @@ -1347,8 +1347,8 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: R = IntegerModRing(1024)['x,y'] sage: singular(R) # needs sage.rings.function_field polynomial ring, over a ring (with zero-divisors), global ordering - // coefficients: ZZ/(2^10) - // number of vars : 2 + // coefficients: ZZ/(2^10)... + // number of vars : 2 // block 1 : ordering dp // : names x y // block 2 : ordering C @@ -1356,8 +1356,8 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: R = IntegerModRing(15)['x,y'] sage: singular(R) # needs sage.rings.function_field polynomial ring, over a ring (with zero-divisors), global ordering - // coefficients: ZZ/...(15) - // number of vars : 2 + // coefficients: ZZ/(15)... + // number of vars : 2 // block 1 : ordering dp // : names x y // block 2 : ordering C @@ -1367,8 +1367,8 @@ cdef class MPolynomialRing_libsingular(MPolynomialRing_base): sage: P. = QQ[] sage: P._singular_init_() polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 1 + // coefficients: QQ... + // number of vars : 1 // block 1 : ordering lp // : names x // block 2 : ordering C @@ -4312,9 +4312,9 @@ cdef class MPolynomial_libsingular(MPolynomial_libsingular_base): sage: R. = QQ[] sage: f = (-2) * (a - d) * (-a + b) * (b - d) * (a - c) * (b - c) * (c - d) sage: F = f.factor(); F - (-2) * (c - d) * (-b + c) * (b - d) * (-a + c) * (-a + b) * (a - d) + (-2) * (-a + c) * (-a + b) * (-b + c) * (c - d) * (b - d) * (a - d) sage: F[0][0] - c - d + -a + c sage: F.unit() -2 diff --git a/src/sage/rings/polynomial/pbori/pbori.pyx b/src/sage/rings/polynomial/pbori/pbori.pyx index 14a929c3238..404771a2c85 100644 --- a/src/sage/rings/polynomial/pbori/pbori.pyx +++ b/src/sage/rings/polynomial/pbori/pbori.pyx @@ -1425,8 +1425,8 @@ cdef class BooleanPolynomialRing(BooleanPolynomialRing_base): sage: B. = BooleanPolynomialRing(2) sage: B._singular_() # indirect doctest polynomial ring, over a field, global ordering - // coefficients: ZZ/2 - // number of vars : 2 + // coefficients: ZZ/2... + // number of vars : 2 // block 1 : ordering lp // : names x y // block 2 : ordering C diff --git a/src/sage/rings/polynomial/polynomial_element.pyx b/src/sage/rings/polynomial/polynomial_element.pyx index b8445edeb20..4d2e607b37d 100644 --- a/src/sage/rings/polynomial/polynomial_element.pyx +++ b/src/sage/rings/polynomial/polynomial_element.pyx @@ -7177,9 +7177,9 @@ cdef class Polynomial(CommutativePolynomial): sage: f = R('e*i') * x + x^2 sage: f._giac_init_() '((1)*1)*sageVARx^2+((1)*sageVARe*sageVARi)*sageVARx' - sage: giac(f) # needs giac + sage: giac(f) # needs giac sageVARx^2+sageVARe*sageVARi*sageVARx - sage: giac(R.zero()) # needs giac + sage: giac(R.zero()) # needs giac 0 """ g = 'sageVAR' + self.variable_name() @@ -7646,7 +7646,7 @@ cdef class Polynomial(CommutativePolynomial): sage: x = polygen(R) sage: f = (x - a) * (x - b) * (x - c) sage: f.compose_power(2).factor() # needs sage.libs.singular sage.modules - (x - c^2) * (x - b^2) * (x - a^2) * (x - b*c)^2 * (x - a*c)^2 * (x - a*b)^2 + (x - a^2) * (x - b^2) * (x - c^2) * (x - a*b)^2 * (x - a*c)^2 * (x - b*c)^2 sage: # needs sage.libs.singular sage.modules sage: x = polygen(QQ) @@ -7715,7 +7715,7 @@ cdef class Polynomial(CommutativePolynomial): sage: x = polygen(QQ) sage: f = x^2 - 2*x + 2 - sage: f.adams_operator_on_roots(10) # needs sage.libs.singular + sage: f.adams_operator_on_roots(10) # needs sage.libs.singular x^2 + 1024 When ``self`` is monic, the output will have leading coefficient @@ -7725,10 +7725,10 @@ cdef class Polynomial(CommutativePolynomial): sage: R. = ZZ[] sage: x = polygen(R) sage: f = (x - a) * (x - b) * (x - c) - sage: f.adams_operator_on_roots(3).factor() # needs sage.libs.singular - (-1) * (x - c^3) * (x - b^3) * (x - a^3) - sage: f.adams_operator_on_roots(3, monic=True).factor() # needs sage.libs.singular - (x - c^3) * (x - b^3) * (x - a^3) + sage: f.adams_operator_on_roots(3).factor() # needs sage.libs.singular + (-1) * (x - a^3) * (x - b^3) * (x - c^3) + sage: f.adams_operator_on_roots(3, monic=True).factor() # needs sage.libs.singular + (x - a^3) * (x - b^3) * (x - c^3) """ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing @@ -7768,8 +7768,8 @@ cdef class Polynomial(CommutativePolynomial): sage: [f.symmetric_power(k).factor() for k in range(5)] # needs sage.libs.singular [x - 1, (-x + d) * (-x + c) * (-x + b) * (-x + a), - (x - c*d) * (x - b*d) * (x - a*d) * (x - b*c) * (x - a*c) * (x - a*b), - (x - b*c*d) * (x - a*c*d) * (x - a*b*d) * (x - a*b*c), + (x - a*b) * (x - a*c) * (x - b*c) * (x - a*d) * (x - b*d) * (x - c*d), + (x - a*b*c) * (x - a*b*d) * (x - a*c*d) * (x - b*c*d), x - a*b*c*d] """ try: diff --git a/src/sage/rings/polynomial/polynomial_quotient_ring.py b/src/sage/rings/polynomial/polynomial_quotient_ring.py index 115647adadf..627765cf8f0 100644 --- a/src/sage/rings/polynomial/polynomial_quotient_ring.py +++ b/src/sage/rings/polynomial/polynomial_quotient_ring.py @@ -749,8 +749,8 @@ def _singular_init_(self, S=None): sage: Q = P.quo([(x^2 + 1)]) sage: singular(Q) # indirect doctest # needs sage.libs.singular polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 1 + // coefficients: QQ... + // number of vars : 1 // block 1 : ordering lp // : names xbar // block 2 : ordering C diff --git a/src/sage/rings/polynomial/polynomial_singular_interface.py b/src/sage/rings/polynomial/polynomial_singular_interface.py index 60d2dd74b52..10bbc6d6ec0 100644 --- a/src/sage/rings/polynomial/polynomial_singular_interface.py +++ b/src/sage/rings/polynomial/polynomial_singular_interface.py @@ -62,7 +62,7 @@ def _do_singular_init_(singular, base_ring, char, _vars, order): sage: from sage.rings.polynomial.polynomial_singular_interface import _do_singular_init_ sage: _do_singular_init_(singular, ZZ, 0, 'X', 'dp') # needs sage.libs.singular (polynomial ring, over a domain, global ordering - // coefficients: ZZ + // coefficients: ZZ... // number of vars : 1 // block 1 : ordering dp // : names X @@ -196,7 +196,7 @@ def _singular_(self, singular=None): sage: R. = PolynomialRing(CC) # needs sage.rings.real_mpfr sage: singular(R) # needs sage.libs.singular sage.rings.real_mpfr polynomial ring, over a field, global ordering - // coefficients: real[I](complex:15 digits, additional 0 digits)/(I^2+1) + // coefficients: real[I](complex:15 digits, additional 0 digits)/(I^2+1)... // number of vars : 2 // block 1 : ordering dp // : names x y @@ -205,7 +205,7 @@ def _singular_(self, singular=None): sage: R. = PolynomialRing(RealField(100)) # needs sage.rings.real_mpfr sage: singular(R) # needs sage.libs.singular sage.rings.real_mpfr polynomial ring, over a field, global ordering - // coefficients: Float() + // coefficients: Float()... // number of vars : 2 // block 1 : ordering dp // : names x y @@ -215,8 +215,8 @@ def _singular_(self, singular=None): sage: R. = PolynomialRing(NumberField(w^2 + 1, 's')) # needs sage.rings.number_field sage: singular(R) # needs sage.libs.singular sage.rings.number_field polynomial ring, over a field, global ordering - // coefficients: QQ[s]/(s^2+1) - // number of vars : 1 + // coefficients: QQ[s]/(s^2+1)... + // number of vars : 1 // block 1 : ordering lp // : names x // block 2 : ordering C @@ -224,8 +224,8 @@ def _singular_(self, singular=None): sage: R = PolynomialRing(GF(127), 'x', implementation='singular') # needs sage.libs.singular sage: singular(R) # needs sage.libs.singular polynomial ring, over a field, global ordering - // coefficients: ZZ/127 - // number of vars : 1 + // coefficients: ZZ/127... + // number of vars : 1 // block 1 : ordering dp // : names x // block 2 : ordering C @@ -233,8 +233,8 @@ def _singular_(self, singular=None): sage: R = PolynomialRing(QQ, 'x', implementation='singular') # needs sage.libs.singular sage: singular(R) # needs sage.libs.singular polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 1 + // coefficients: QQ... + // number of vars : 1 // block 1 : ordering dp // : names x // block 2 : ordering C @@ -242,8 +242,8 @@ def _singular_(self, singular=None): sage: R = PolynomialRing(QQ,'x') sage: singular(R) # needs sage.libs.singular polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 1 + // coefficients: QQ... + // number of vars : 1 // block 1 : ordering lp // : names x // block 2 : ordering C @@ -251,8 +251,8 @@ def _singular_(self, singular=None): sage: R = PolynomialRing(GF(127), 'x') sage: singular(R) # needs sage.libs.singular polynomial ring, over a field, global ordering - // coefficients: ZZ/127 - // number of vars : 1 + // coefficients: ZZ/127... + // number of vars : 1 // block 1 : ordering lp // : names x // block 2 : ordering C @@ -260,8 +260,8 @@ def _singular_(self, singular=None): sage: R = Frac(ZZ['a,b'])['x,y'] sage: singular(R) # needs sage.libs.singular polynomial ring, over a field, global ordering - // coefficients: QQ(a, b) - // number of vars : 2 + // coefficients: QQ(a, b)... + // number of vars : 2 // block 1 : ordering dp // : names x y // block 2 : ordering C @@ -270,8 +270,8 @@ def _singular_(self, singular=None): sage: R = IntegerModRing(1024)['x,y'] sage: singular(R) # needs sage.libs.singular polynomial ring, over a ring (with zero-divisors), global ordering - // coefficients: ZZ/(2^10) - // number of vars : 2 + // coefficients: ZZ/(2^10)... + // number of vars : 2 // block 1 : ordering dp // : names x y // block 2 : ordering C @@ -279,8 +279,8 @@ def _singular_(self, singular=None): sage: R = IntegerModRing(15)['x,y'] sage: singular(R) # needs sage.libs.singular polynomial ring, over a ring (with zero-divisors), global ordering - // coefficients: ZZ/...(15) - // number of vars : 2 + // coefficients: ZZ/(15)... + // number of vars : 2 // block 1 : ordering dp // : names x y // block 2 : ordering C @@ -288,8 +288,8 @@ def _singular_(self, singular=None): sage: R = ZZ['x,y'] sage: singular(R) # needs sage.libs.singular polynomial ring, over a domain, global ordering - // coefficients: ZZ - // number of vars : 2 + // coefficients: ZZ... + // number of vars : 2 // block 1 : ordering dp // : names x y // block 2 : ordering C @@ -297,7 +297,7 @@ def _singular_(self, singular=None): sage: R = ZZ['x'] sage: singular(R) # needs sage.libs.singular polynomial ring, over a domain, global ordering - // coefficients: ZZ + // coefficients: ZZ... // number of vars : 1 // block 1 : ordering lp // : names x @@ -310,8 +310,8 @@ def _singular_(self, singular=None): sage: S = K['y'] sage: singular(S) # needs sage.libs.singular polynomial ring, over a field, global ordering - // coefficients: ZZ/5(x) - // number of vars : 2 + // coefficients: ZZ/5(x)... + // number of vars : 2 // block 1 : ordering lp // : names a y // block 2 : ordering C @@ -353,8 +353,8 @@ def _singular_init_(self, singular=None): sage: PolynomialRing(QQ,'u_ba')._singular_init_() # needs sage.libs.singular polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 1 + // coefficients: QQ... + // number of vars : 1 // block 1 : ordering lp // : names u_ba // block 2 : ordering C diff --git a/src/sage/rings/polynomial/symmetric_ideal.py b/src/sage/rings/polynomial/symmetric_ideal.py index 869af07d904..b271846b59c 100644 --- a/src/sage/rings/polynomial/symmetric_ideal.py +++ b/src/sage/rings/polynomial/symmetric_ideal.py @@ -27,8 +27,8 @@ sage: # needs sage.combinat sage: G = R * I.groebner_basis() sage: G - Symmetric Ideal (x_1^2 + x_1, x_2 - x_1) of - Infinite polynomial ring in x over Rational Field + Symmetric Ideal (x_2 - x_1, x_1^2 + x_1) of Infinite polynomial ring in x + over Rational Field sage: Q = R.quotient(G) sage: p = x[3]*x[1] + x[2]^2 + 3 sage: Q(p) @@ -123,8 +123,8 @@ class SymmetricIdeal(Ideal_generic): The default ordering is lexicographic. We now compute a Groebner basis:: sage: J = I.groebner_basis(); J # about 3 seconds # needs sage.combinat - [x_1*y_2*y_1 + 2*x_1*y_2, x_2*y_2*y_1 + 2*x_2*y_1, - x_2*x_1*y_1^2 + 2*x_2*x_1*y_1, x_2*x_1*y_2 - x_2*x_1*y_1] + [x_2*x_1*y_2 - x_2*x_1*y_1, x_1*y_2*y_1 + 2*x_1*y_2, + x_2*y_2*y_1 + 2*x_2*y_1, x_2*x_1*y_1^2 + 2*x_2*x_1*y_1] Note that even though the symmetric ideal can be generated by a single polynomial, its reduced symmetric Groebner basis comprises @@ -139,11 +139,11 @@ class SymmetricIdeal(Ideal_generic): sage: # needs sage.combinat sage: P = Permutation([2, 1]) sage: J[2] - x_2*x_1*y_1^2 + 2*x_2*x_1*y_1 + x_2*y_2*y_1 + 2*x_2*y_1 sage: J[2]^P - x_2*x_1*y_2^2 + 2*x_2*x_1*y_2 + x_1*y_2*y_1 + 2*x_1*y_2 sage: J[2]^P in J - False + True However, any element of ``J`` has symmetric reduction zero even after applying a permutation. This even holds when the @@ -157,7 +157,7 @@ class SymmetricIdeal(Ideal_generic): ideal membership:: sage: [p.reduce(I) for p in J] # needs sage.combinat - [0, x_2*y_2*y_1 + 2*x_2*y_1, x_2*x_1*y_1^2 + 2*x_2*x_1*y_1, x_2*x_1*y_2 - x_2*x_1*y_1] + [x_2*x_1*y_2 - x_2*x_1*y_1, 0, x_2*y_2*y_1 + 2*x_2*y_1, x_2*x_1*y_1^2 + 2*x_2*x_1*y_1] Note that we give no guarantee that the computation of a symmetric Groebner basis will terminate in any order different from @@ -239,8 +239,8 @@ def _contains_(self, p): sage: I = R.ideal([x[1]*x[2] + x[3]]) sage: I = R * I.groebner_basis() # needs sage.combinat sage: I # needs sage.combinat - Symmetric Ideal (x_1^2 + x_1, x_2 - x_1) of - Infinite polynomial ring in x over Rational Field + Symmetric Ideal (x_2 - x_1, x_1^2 + x_1) of + Infinite polynomial ring in x over Rational Field sage: x[2]^2 + x[3] in I # indirect doctest # needs sage.combinat True """ @@ -617,12 +617,14 @@ def symmetrisation(self, N=None, tailreduce=False, report=None, use_full_group=F sage: X. = InfinitePolynomialRing(QQ) sage: I = X * (x[1] + x[2], x[1]*x[2]) sage: I.symmetrisation() # needs sage.combinat - Symmetric Ideal (-x_1^2, x_2 + x_1) of - Infinite polynomial ring in x over Rational Field + Symmetric Ideal (-x_2^2, -x_1^2, x_2 + x_1) of Infinite polynomial ring in x + over Rational Field sage: I.symmetrisation(N=3) # needs sage.combinat - Symmetric Ideal (-2*x_1) of Infinite polynomial ring in x over Rational Field + Symmetric Ideal (-x_2^2, -x_1^2, -2*x_1) of Infinite polynomial ring in x + over Rational Field sage: I.symmetrisation(N=3, use_full_group=True) # needs sage.combinat - Symmetric Ideal (-2*x_1) of Infinite polynomial ring in x over Rational Field + Symmetric Ideal (-x_1^2, -2*x_1) of Infinite polynomial ring in x + over Rational Field """ newOUT = self.interreduction(tailreduce=tailreduce, report=report).squeezed() R = self.ring() @@ -678,7 +680,7 @@ def symmetric_basis(self): sage: X. = InfinitePolynomialRing(QQ) sage: I = X * (x[1] + x[2], x[1]*x[2]) sage: I.symmetric_basis() # needs sage.combinat - [x_1^2, x_2 + x_1] + [x_2^2, x_1^2, x_2 + x_1] """ return Sequence(self.symmetrisation(tailreduce=True).normalisation().gens(), self.ring(), check=False) @@ -822,27 +824,32 @@ def groebner_basis(self, tailreduce=False, reduced=True, algorithm=None, report= sage: I1.groebner_basis(report=True, reduced=True) # needs sage.combinat Symmetric interreduction - [1/2] > + [1/2] > [2/2] :> - [1/2] > - [2/2] > + [1/2] > + [2/2] > Symmetrise 2 polynomials at level 2 Apply permutations > > Symmetric interreduction - [1/3] > - [2/3] > - [3/3] :> - -> 0 - [1/2] > - [2/2] > + [1/3] > + [2/3] > + [3/3] > + Apply permutations + > + :> + :> + Symmetric interreduction + [1/3] > + [2/3] > + [3/3] > Symmetrisation done Classical Groebner basis -> 2 generators Symmetric interreduction - [1/2] > - [2/2] > + [1/2] > + [2/2] > Symmetrise 2 polynomials at level 3 Apply permutations > @@ -852,24 +859,24 @@ def groebner_basis(self, tailreduce=False, reduced=True, algorithm=None, report= :> ::> Symmetric interreduction - [1/4] > + [1/4] > [2/4] :> -> 0 [3/4] ::> -> 0 [4/4] :> -> 0 - [1/1] > + [1/1] > Apply permutations :> :> :> Symmetric interreduction - [1/1] > + [1/1] > Classical Groebner basis -> 1 generators Symmetric interreduction - [1/1] > + [1/1] > Symmetrise 1 polynomials at level 4 Apply permutations > @@ -879,12 +886,12 @@ def groebner_basis(self, tailreduce=False, reduced=True, algorithm=None, report= :> :> Symmetric interreduction - [1/2] > + [1/2] > [2/2] :> -> 0 - [1/1] > + [1/1] > Symmetric interreduction - [1/1] > + [1/1] > [x_1] The Aschenbrenner-Hillar algorithm is only guaranteed to work diff --git a/src/sage/rings/polynomial/term_order.py b/src/sage/rings/polynomial/term_order.py index a88568248ce..f8ddd0a9652 100644 --- a/src/sage/rings/polynomial/term_order.py +++ b/src/sage/rings/polynomial/term_order.py @@ -660,7 +660,7 @@ def __init__(self, name='lex', n=0, force=False): sage: R. = PolynomialRing(QQ, order=T) sage: R._singular_() # needs sage.libs.singular polynomial ring, over a field, global ordering - // coefficients: QQ + // coefficients: QQ... // number of vars : 3 // block 1 : ordering dp // : names x y z @@ -676,7 +676,7 @@ def __init__(self, name='lex', n=0, force=False): False sage: S._singular_() # needs sage.libs.singular polynomial ring, over a field, global ordering - // coefficients: QQ + // coefficients: QQ... // number of vars : 3 // block 1 : ordering C // block 2 : ordering dp @@ -1661,8 +1661,8 @@ def singular_str(self): '(lp(3),Dp(5),lp(2))' sage: P._singular_() # needs sage.libs.singular polynomial ring, over a field, global ordering - // coefficients: ZZ/127 - // number of vars : 10 + // coefficients: ZZ/127... + // number of vars : 10 // block 1 : ordering lp // : names x0 x1 x2 // block 2 : ordering Dp @@ -1687,8 +1687,8 @@ def singular_str(self): '(a(1:2),ls(2),a(1:2),ls(2))' sage: P._singular_() # needs sage.libs.singular polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 4 + // coefficients: QQ... + // number of vars : 4 // block 1 : ordering a // : names x0 x1 // : weights 1 1 @@ -1709,7 +1709,7 @@ def singular_str(self): sage: P = PolynomialRing(QQ, 4, names='x', order=T) sage: P._singular_() # needs sage.libs.singular polynomial ring, over a field, global ordering - // coefficients: QQ + // coefficients: QQ... // number of vars : 4 // block 1 : ordering C // block 2 : ordering a @@ -1727,7 +1727,7 @@ def singular_str(self): sage: P = PolynomialRing(QQ, 4, names='y', order=T) sage: P._singular_() # needs sage.libs.singular polynomial ring, over a field, global ordering - // coefficients: QQ + // coefficients: QQ... // number of vars : 4 // block 1 : ordering c // block 2 : ordering a @@ -1745,7 +1745,7 @@ def singular_str(self): sage: P = PolynomialRing(QQ, 4, names='z', order=T) sage: P._singular_() # needs sage.libs.singular polynomial ring, over a field, global ordering - // coefficients: QQ + // coefficients: QQ... // number of vars : 4 // block 1 : ordering a // : names z0 z1 @@ -2183,7 +2183,7 @@ def termorder_from_singular(S): sage: # needs sage.libs.singular sage: singular.ring(0, '(x,y,z,w)', '(C,dp(2),lp(2))') polynomial ring, over a field, global ordering - // coefficients: QQ + // coefficients: QQ... // number of vars : 4 // block 1 : ordering C // block 2 : ordering dp @@ -2201,7 +2201,7 @@ def termorder_from_singular(S): sage: # needs sage.libs.singular sage: singular.ring(0, '(x,y,z,w)', '(c,dp(2),lp(2))') polynomial ring, over a field, global ordering - // coefficients: QQ + // coefficients: QQ... // number of vars : 4 // block 1 : ordering c // block 2 : ordering dp diff --git a/src/sage/rings/polynomial/toy_variety.py b/src/sage/rings/polynomial/toy_variety.py index ba67a1ece2e..3543c92474b 100644 --- a/src/sage/rings/polynomial/toy_variety.py +++ b/src/sage/rings/polynomial/toy_variety.py @@ -255,10 +255,10 @@ def triangular_factorization(B, n=-1): sage: p3 = (x-2)^2*(y-1)^3 sage: I = R.ideal(p1,p2,p3) sage: triangular_factorization(I.groebner_basis()) # needs sage.libs.singular - [[x^2 - 4*x + 4, y, z], - [x^5 - 3*x^4 + 3*x^3 - x^2, y - 1, z], - [x^2 - 4*x + 4, y, z - 1], - [x^5 - 3*x^4 + 3*x^3 - x^2, y - 1, z - 1]] + [[x^2 - 4*x + 4, y, z - 1], + [x^5 - 3*x^4 + 3*x^3 - x^2, y - 1, z - 1], + [x^2 - 4*x + 4, y, z], + [x^5 - 3*x^4 + 3*x^3 - x^2, y - 1, z]] """ # type checking in a probably vain attempt to avoid stupid errors if isinstance(B, (tuple, list)): diff --git a/src/sage/rings/quotient_ring.py b/src/sage/rings/quotient_ring.py index 1043333a63e..45f8147cde9 100644 --- a/src/sage/rings/quotient_ring.py +++ b/src/sage/rings/quotient_ring.py @@ -1268,8 +1268,8 @@ def _singular_(self, singular=None): sage: S = R.quotient_ring(x^2 + y^2) sage: S._singular_() # needs sage.libs.singular polynomial ring, over a field, global ordering - // coefficients: QQ - // number of vars : 2 + // coefficients: QQ... + // number of vars : 2 // block 1 : ordering dp // : names x y // block 2 : ordering C diff --git a/src/sage/rings/quotient_ring_element.py b/src/sage/rings/quotient_ring_element.py index 6699ae9f74b..9f05c54f21c 100644 --- a/src/sage/rings/quotient_ring_element.py +++ b/src/sage/rings/quotient_ring_element.py @@ -813,8 +813,8 @@ def _singular_(self, singular=None): sage: Q = P.quo(I) sage: Q._singular_() polynomial ring, over a field, global ordering - // coefficients: ZZ/2 - // number of vars : 2 + // coefficients: ZZ/2... + // number of vars : 2 // block 1 : ordering dp // : names x y // block 2 : ordering C diff --git a/src/sage/rings/ring.pyx b/src/sage/rings/ring.pyx index 04ed386e799..db62e4844e2 100644 --- a/src/sage/rings/ring.pyx +++ b/src/sage/rings/ring.pyx @@ -826,54 +826,6 @@ cdef class CommutativeRing(Ring): except (NotImplementedError,TypeError): return coercion_model.division_parent(self) - def krull_dimension(self): - """ - Return the Krull dimension of this commutative ring. - - The Krull dimension is the length of the longest ascending chain - of prime ideals. - - TESTS: - - ``krull_dimension`` is not implemented for generic commutative - rings. Fields and PIDs, with Krull dimension equal to 0 and 1, - respectively, have naive implementations of ``krull_dimension``. - Orders in number fields also have Krull dimension 1:: - - sage: R = CommutativeRing(ZZ) - sage: R.krull_dimension() - Traceback (most recent call last): - ... - NotImplementedError - sage: QQ.krull_dimension() - 0 - 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:: - - sage: # needs sage.rings.number_field - sage: K. = QuadraticField(-1) - sage: R = K.maximal_order(); R - Gaussian Integers generated by i in Number Field in i - with defining polynomial x^2 + 1 with i = 1*I - sage: R.krull_dimension() - 1 - sage: R = K.order(2*i); R - Order of conductor 2 generated by 2*i in Number Field in i - with defining polynomial x^2 + 1 with i = 1*I - sage: R.is_maximal() - False - sage: R.krull_dimension() - 1 - """ - raise NotImplementedError - def extension(self, poly, name=None, names=None, **kwds): """ Algebraically extend ``self`` by taking the quotient @@ -1095,19 +1047,6 @@ cdef class Field(CommutativeRing): """ return True - def krull_dimension(self): - """ - Return the Krull dimension of this field, which is 0. - - EXAMPLES:: - - sage: QQ.krull_dimension() - 0 - sage: Frac(QQ['x,y']).krull_dimension() - 0 - """ - return 0 - def prime_subfield(self): """ Return the prime subfield of ``self``. diff --git a/src/sage/schemes/affine/affine_morphism.py b/src/sage/schemes/affine/affine_morphism.py index 0eba4c662ec..baa58aeb639 100644 --- a/src/sage/schemes/affine/affine_morphism.py +++ b/src/sage/schemes/affine/affine_morphism.py @@ -541,7 +541,7 @@ def homogenize(self, n): Scheme endomorphism of Projective Space of dimension 1 over Algebraic Field Defn: Defined on coordinates by sending (x0 : x1) to - (x0*x1 : 1/2*x0^2 + x0*x1 + 3/2*x1^2) + (2*x0*x1 : x0^2 + 2*x0*x1 + 3*x1^2) :: diff --git a/src/sage/schemes/curves/point.py b/src/sage/schemes/curves/point.py index e74e009b1ce..782fc4abe14 100644 --- a/src/sage/schemes/curves/point.py +++ b/src/sage/schemes/curves/point.py @@ -307,7 +307,7 @@ def tangents(self): ....: 5*x - y + 1]) sage: Q = C([-1,0]) sage: Q.tangents() - [y, x + 1, x - y + 1, x + y + 1] + [y, x - y + 1, x + 1, x + y + 1] """ return self.codomain().tangents(self) diff --git a/src/sage/schemes/elliptic_curves/ell_field.py b/src/sage/schemes/elliptic_curves/ell_field.py index 920fd99dfed..376568cc90b 100644 --- a/src/sage/schemes/elliptic_curves/ell_field.py +++ b/src/sage/schemes/elliptic_curves/ell_field.py @@ -2579,9 +2579,9 @@ class of curves. If the j-invariant is not unique in the isogeny A = [] # adjacency matrix labels = [] # list of vertex labels for (i, E) in enumerate(Es): - if 0 < curve_max and curve_max < len(Es): + if 0 < curve_max < len(Es): warn('Isogeny graph contains more than ' - + str(curve_max) + ' curves.') + + str(curve_max) + ' curves.') curve_max = 0 r = [0] * len(Es) # adjacency matrix row diff --git a/src/sage/schemes/elliptic_curves/heegner.py b/src/sage/schemes/elliptic_curves/heegner.py index f0a7087d7ea..52820d8166b 100644 --- a/src/sage/schemes/elliptic_curves/heegner.py +++ b/src/sage/schemes/elliptic_curves/heegner.py @@ -449,7 +449,7 @@ def degree_over_H(self): """ c = self.__c if c == 1: - return ZZ(1) + return ZZ.one() # Let K_c be the ring class field. We have by class field theory that # Gal(K_c / H) = (O_K / c O_K)^* / ((Z/cZ)^* M), @@ -1388,17 +1388,17 @@ def _repr_(self): """ return "Complex conjugation automorphism of %s" % self.domain() -## def __mul__(self, right): -## """ -## Return the composition of two automorphisms. +# def __mul__(self, right): +# """ +# Return the composition of two automorphisms. -## EXAMPLES:: +# EXAMPLES:: -## sage: ? -## """ -## if self.parent() != right.__parent(): -## raise TypeError, "automorphisms must be of the same class field" -## raise NotImplementedError +# sage: ? +# """ +# if self.parent() != right.__parent(): +# raise TypeError("automorphisms must be of the same class field") +# raise NotImplementedError def __invert__(self): """ @@ -1679,7 +1679,7 @@ def ideal(self): f = self.quadratic_form() c = M.conductor() sqrtD = K.gen() - (A,B,C) = f + A, B, C = f if A % c == 0: A, C = C, A return K.fractional_ideal([A, (-B+c*sqrtD)/2]) @@ -1706,7 +1706,7 @@ def ideal(self): ## """ ## if isinstance(z, HeegnerPointOnX0N): ## if z.ring_class_field() != self.domain(): -## raise NotImplementedError, "class fields must be the same" +## raise NotImplementedError("class fields must be the same") ## # TODO -- check more compatibilities? ## # TODO -- this is surely backwards -- something must be inverted? ## f = z.quadratic_form() * self.quadratic_form() diff --git a/src/sage/schemes/elliptic_curves/hom.py b/src/sage/schemes/elliptic_curves/hom.py index 01112bc8bb2..96700fa254d 100644 --- a/src/sage/schemes/elliptic_curves/hom.py +++ b/src/sage/schemes/elliptic_curves/hom.py @@ -1197,7 +1197,7 @@ def compare_via_evaluation(left, right): for _ in range(100): P = E.lift_x(F.random_element(), extend=True) if P._has_order_at_least(4*d + 1, attempts=50): - # if P.height(precision=250) == 0: # slow sometimes + # if P.height(precision=250) == 0: # slow sometimes return left._eval(P) == right._eval(P) else: assert False, "couldn't find a point of large enough order" diff --git a/src/sage/schemes/elliptic_curves/mod_sym_num.pyx b/src/sage/schemes/elliptic_curves/mod_sym_num.pyx index e55500f0d0f..3ff26e6791c 100644 --- a/src/sage/schemes/elliptic_curves/mod_sym_num.pyx +++ b/src/sage/schemes/elliptic_curves/mod_sym_num.pyx @@ -1,6 +1,6 @@ -#cdivision=False -#cython: cdivision_warnings=False -#cython: profile=False +# cdivision=False +# cython: cdivision_warnings=False +# cython: profile=False r""" Modular symbols by numerical integration @@ -1254,8 +1254,8 @@ cdef class ModularSymbolNumerical: if err > 0.1: # the following did not work (compilation failed) - #from warnings import warn - #warn(Rounded an error of %s, looks like a bug." % err, + # from warnings import warn + # warn(Rounded an error of %s, looks like a bug." % err, # RuntimeWarning, stacklevel=5) print ("Warning: Rounded an error of ", err, ", looks like a bug " + "in mod_sym_num.pyx.") @@ -1411,8 +1411,8 @@ cdef class ModularSymbolNumerical: cdef ComplexNumber q, s cdef int n - #self.nc_sums += 1 - #self.nc_terms += Integer(number_of_terms) + # self.nc_sums += 1 + # self.nc_terms += Integer(number_of_terms) if number_of_terms > 10000000: print("Warning: more than 10^7 terms to sum") @@ -1467,12 +1467,12 @@ cdef class ModularSymbolNumerical: # " T=%s" % (tau,number_of_terms), level=5) cdef complex q, s cdef int n - #self.nc_sums += 1 - #self.nc_terms += Integer(number_of_terms) + # self.nc_sums += 1 + # self.nc_terms += Integer(number_of_terms) if number_of_terms > 10000000: print("Warning: more than 10^7 terms to sum") - #raise Warning("more than 10^7 terms to sum") + # raise Warning("more than 10^7 terms to sum") if number_of_terms > self._lans: self._add_an_coefficients(number_of_terms) @@ -1525,8 +1525,8 @@ cdef class ModularSymbolNumerical: # " T=%s" % (y,m,number_of_terms), level=5) cdef double q, qq cdef int n, i - #self.nc_sums += 1 - #self.nc_terms += Integer(number_of_terms) + # self.nc_sums += 1 + # self.nc_terms += Integer(number_of_terms) if number_of_terms > 10000000: print(" Warning: more than 10^7 terms to sum") @@ -1605,8 +1605,8 @@ cdef class ModularSymbolNumerical: # " T=%s" % (y,m,number_of_terms), level=5) cdef RealNumber q, qq cdef int n, i - #self.nc_sums += 1 - #self.nc_terms += Integer(number_of_terms) + # self.nc_sums += 1 + # self.nc_terms += Integer(number_of_terms) if number_of_terms > 10000000: print(" Warning: more than 10^7 terms to sum") @@ -2293,7 +2293,7 @@ cdef class ModularSymbolNumerical: if method == "direct" or method == "both": verbose(" using the direct integration from %s to %s with " "%s terms to sum" % (r, rr, T), level=2) - #self.nc_direct += 1 + # self.nc_direct += 1 ans = self._from_r_to_rr_approx_direct(r, rr, epsQ, epsQQ, wQ, wQQ, T, prec, eps, use_partials) @@ -2303,7 +2303,7 @@ cdef class ModularSymbolNumerical: if method == "indirect" or method == "both": verbose(" using the indirect integration from %s to %s " "with %s terms to sum" % (r, rr, T1+T2), level=2) - #self.nc_indirect += 1 + # self.nc_indirect += 1 ans2 = (self._from_ioo_to_r_approx(r, eps/2, use_partials=use_partials) - self._from_ioo_to_r_approx(rr, eps/2, diff --git a/src/sage/schemes/elliptic_curves/period_lattice_region.pyx b/src/sage/schemes/elliptic_curves/period_lattice_region.pyx index 40b92ab23eb..e436e0f756d 100644 --- a/src/sage/schemes/elliptic_curves/period_lattice_region.pyx +++ b/src/sage/schemes/elliptic_curves/period_lattice_region.pyx @@ -16,15 +16,15 @@ AUTHORS: - John Cremona (2014): added some docstrings and doctests """ -#***************************************************************************** +# *************************************************************************** # Copyright (C) 2010 Robert Bradshaw # # 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 numpy as np cimport numpy as np diff --git a/src/sage/schemes/generic/homset.py b/src/sage/schemes/generic/homset.py index 370049d2238..b6c59d7090a 100644 --- a/src/sage/schemes/generic/homset.py +++ b/src/sage/schemes/generic/homset.py @@ -584,10 +584,10 @@ def _coerce_map_from_(self, other): except AttributeError: # no .ambient_space return False elif isinstance(other, SchemeHomset_points): - #we are converting between scheme points + # we are converting between scheme points source = other.codomain() if isinstance(target, AlgebraicScheme_subscheme): - #subscheme coerce when there is containment + # subscheme coerce when there is containment if not isinstance(source, AlgebraicScheme_subscheme): return False if target.ambient_space() == source.ambient_space(): @@ -595,9 +595,9 @@ def _coerce_map_from_(self, other): for g in target.defining_polynomials()): return self.domain().coordinate_ring().has_coerce_map_from(other.domain().coordinate_ring()) else: - #if the target is an ambient space, we can coerce if the base rings coerce - #and they are the same type: affine, projective, etc and have the same - #variable names + # if the target is an ambient space, we can coerce if the base rings coerce + # and they are the same type: affine, projective, etc and have the same + # variable names try: ta = target.ambient_space() sa = source.ambient_space() diff --git a/src/sage/schemes/generic/morphism.py b/src/sage/schemes/generic/morphism.py index 51906d804eb..c3ee035d907 100644 --- a/src/sage/schemes/generic/morphism.py +++ b/src/sage/schemes/generic/morphism.py @@ -248,12 +248,14 @@ def __call__(self, x, *args, **kwds): try: return self.pushforward(x, *args, **kwds) except (AttributeError, TypeError, NotImplementedError): - pass # raise TypeError, "%s must be coercible into %s"%(x, self.domain()) + # raise TypeError("%s must be coercible into %s" % (x, self.domain())) + pass + # Here, we would like to do ##try: ## x = D(x). ##except (TypeError, NotImplementedError): - ## raise TypeError, "%s fails to convert into the map's domain %s, but a `pushforward` method is not properly implemented"%(x, self.domain()) + ## raise TypeError("%s fails to convert into the map's domain %s, but a `pushforward` method is not properly implemented" % (x, self.domain())) # However, this would involve a test whether x.codomain() == # self. This would trigger a Groebner basis computation, that # (1) could be slow and (2) could involve an even slower toy diff --git a/src/sage/schemes/hyperelliptic_curves/monsky_washnitzer.py b/src/sage/schemes/hyperelliptic_curves/monsky_washnitzer.py index a533b7d4e92..36d629888b5 100644 --- a/src/sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +++ b/src/sage/schemes/hyperelliptic_curves/monsky_washnitzer.py @@ -2596,7 +2596,7 @@ def monomial(self, i, j, b=None): i = int(i) j = int(j) - if 0 < i and i < self._n: + if 0 < i < self._n: if b is None: by_to_j = self._series_ring_y << (j - 1) else: diff --git a/src/sage/schemes/toric/divisor_class.pyx b/src/sage/schemes/toric/divisor_class.pyx index 98ed1b377b3..048cc2992d7 100644 --- a/src/sage/schemes/toric/divisor_class.pyx +++ b/src/sage/schemes/toric/divisor_class.pyx @@ -46,7 +46,7 @@ divisor representing a divisor class:: """ -#***************************************************************************** +# *************************************************************************** # Copyright (C) 2010 Volker Braun # Copyright (C) 2010 Andrey Novoseltsev # Copyright (C) 2010 William Stein @@ -54,7 +54,7 @@ divisor representing a divisor class:: # Distributed under the terms of the GNU General Public License (GPL) # # https://www.gnu.org/licenses/ -#***************************************************************************** +# *************************************************************************** from sage.libs.gmp.mpq cimport * diff --git a/src/sage/sets/integer_range.py b/src/sage/sets/integer_range.py index 3b95506f591..f005f972624 100644 --- a/src/sage/sets/integer_range.py +++ b/src/sage/sets/integer_range.py @@ -748,8 +748,8 @@ def __contains__(self, elt): except (TypeError, ValueError): return False if abs(self._step).divides(Integer(elt)-self._middle_point): - return (self._begin <= elt and elt < self._end) or \ - (self._begin >= elt and elt > self._end) + return (self._begin <= elt < self._end) or \ + (self._begin >= elt > self._end) return False def next(self, elt): diff --git a/src/sage/structure/category_object.pyx b/src/sage/structure/category_object.pyx index e0c217a0e3b..8571811dd97 100644 --- a/src/sage/structure/category_object.pyx +++ b/src/sage/structure/category_object.pyx @@ -756,7 +756,7 @@ cdef class CategoryObject(SageObject): pass except (AttributeError, KeyError): raise - #raise RuntimeError, "If you change the pickling code in parent or category_object, you need to update the _pickle_version field" + # raise RuntimeError("If you change the pickling code in parent or category_object, you need to update the _pickle_version field") def __hash__(self): """ diff --git a/src/sage/structure/list_clone_demo.pyx b/src/sage/structure/list_clone_demo.pyx index dbd199fa317..fde51727af6 100644 --- a/src/sage/structure/list_clone_demo.pyx +++ b/src/sage/structure/list_clone_demo.pyx @@ -6,19 +6,20 @@ This module demonstrate the usage of the various classes defined in :mod:`~sage.structure.list_clone` """ -#***************************************************************************** +# *************************************************************************** # Copyright (C) 2011 Florent Hivert # # Distributed under the terms of the GNU General Public License (GPL) -# http://www.gnu.org/licenses/ -#***************************************************************************** +# https://www.gnu.org/licenses/ +# *************************************************************************** from sage.categories.sets_cat import Sets from sage.structure.unique_representation import UniqueRepresentation from sage.structure.list_clone cimport ( - ClonableArray, ClonableList, NormalizedClonableList, ClonableIntArray ) + ClonableArray, ClonableList, NormalizedClonableList, ClonableIntArray) from sage.structure.parent import Parent + cdef class IncreasingArray(ClonableArray): """ A small extension class for testing diff --git a/src/sage/symbolic/ginac/infinity.cpp b/src/sage/symbolic/ginac/infinity.cpp index 3a2a7b8469e..187ff7ac67d 100644 --- a/src/sage/symbolic/ginac/infinity.cpp +++ b/src/sage/symbolic/ginac/infinity.cpp @@ -371,8 +371,8 @@ const infinity & infinity::operator += (const ex & rhs) const infinity Infinity = infinity::from_sign(+1); -/** Infinity, i.e., positive infinity. - * Calls python function py_eval_infinity for evalf(). */ +/** NegInfinity, i.e., negative infinity. + * Calls python function py_eval_neg_infinity for evalf(). */ const infinity NegInfinity = infinity::from_sign(-1); diff --git a/src/sage/symbolic/pynac_function_impl.pxi b/src/sage/symbolic/pynac_function_impl.pxi index a9faf2e7de7..ca2b459e095 100644 --- a/src/sage/symbolic/pynac_function_impl.pxi +++ b/src/sage/symbolic/pynac_function_impl.pxi @@ -47,14 +47,16 @@ cpdef call_registered_function(unsigned serial, res = g_function_evalv(serial, vec, hold) elif nargs == 1: res = g_function_eval1(serial, - (args[0])._gobj, hold) + (args[0])._gobj, hold) elif nargs == 2: - res = g_function_eval2(serial, (args[0])._gobj, - (args[1])._gobj, hold) + res = g_function_eval2(serial, + (args[0])._gobj, + (args[1])._gobj, hold) elif nargs == 3: res = g_function_eval3(serial, - (args[0])._gobj, (args[1])._gobj, - (args[2])._gobj, hold) + (args[0])._gobj, + (args[1])._gobj, + (args[2])._gobj, hold) if allow_numeric_result and is_a_numeric(res): return py_object_from_numeric(res) diff --git a/src/sage/tensor/modules/format_utilities.py b/src/sage/tensor/modules/format_utilities.py index d00e00f8071..293ab146942 100644 --- a/src/sage/tensor/modules/format_utilities.py +++ b/src/sage/tensor/modules/format_utilities.py @@ -247,7 +247,7 @@ def format_unop_txt(operator, name): if name is None: return None if not is_atomic(name) or not is_atomic_wedge_txt(name): - #!# is_atomic_otimes_txt should be added + # ! is_atomic_otimes_txt should be added name = '(' + name + ')' return operator + name @@ -270,7 +270,7 @@ def format_unop_latex(operator, name): if name is None: return None if not is_atomic(name) or not is_atomic_wedge_latex(name): - #!# is_atomic_otimes_latex should be added + # ! is_atomic_otimes_latex should be added name = r'\left(' + name + r'\right)' return operator + name diff --git a/src/sage/tests/books/computational-mathematics-with-sagemath/mpoly_doctest.py b/src/sage/tests/books/computational-mathematics-with-sagemath/mpoly_doctest.py index 24d438dca07..63bdb6fca43 100644 --- a/src/sage/tests/books/computational-mathematics-with-sagemath/mpoly_doctest.py +++ b/src/sage/tests/books/computational-mathematics-with-sagemath/mpoly_doctest.py @@ -1,4 +1,4 @@ -""" +r""" This file (./mpoly_doctest.sage) was *autogenerated* from ./mpoly.tex, with sagetex.sty version 2011/05/27 v2.3.1. It contains the contents of all the sageexample environments from this file. @@ -73,14 +73,14 @@ Sage example in ./mpoly.tex, line 381:: - sage: print("total={d} (in x)={dx} partial={ds}"\ + sage: print("total={d} (in x)={dx} partial={ds}" ....: .format(d=p.degree(), dx=p.degree(x), ds=p.degrees())) total=4 (in x)=3 partial=(3, 2, 1) Sage example in ./mpoly.tex, line 441:: sage: R. = QQ[]; p = x^2 + y^2; q = x + y - sage: print("({quo})*({q}) + ({rem}) == {p}".format( \ + sage: print("({quo})*({q}) + ({rem}) == {p}".format( ....: quo=p//q, q=q, rem=p%q, p=p//q*q+p%q)) (-x + y)*(x + y) + (2*x^2) == x^2 + y^2 sage: p.mod(q) # is NOT equivalent to p%q @@ -92,7 +92,7 @@ sage: (x^10 + y^5).gcd(x^4 - y^2) x^2 + y sage: (x^10 + y^5).factor() - (x^2 + y) * (x^2 + (a^3)*y) * (x^2 + (a^2)*y) * (x^2 + a*y) * (x^2 + (-a^3 - a^2 - a - 1)*y) + (x^2 + y) * (x^2 + a*y) * (x^2 + (a^2)*y) * (x^2 + (-a^3 - a^2 - a - 1)*y) * (x^2 + (a^3)*y) Sage example in ./mpoly.tex, line 564:: @@ -170,7 +170,7 @@ [Ideal (z^17 - 1, y - 2*z^10, x - 3*z^3) of Multivariate Polynomial Ring in x, y, z over Rational Field] sage: J.transformed_basis() - [z^17 - 1, -2*z^10 + y, -3/4*y^2 + x] + [z^17 - 1, -3/4*y^2 + x, -2*z^10 + y] Sage example in ./mpoly.tex, line 909:: diff --git a/src/sage/topology/cubical_complex.py b/src/sage/topology/cubical_complex.py index 055a597776e..5d95c8f7522 100644 --- a/src/sage/topology/cubical_complex.py +++ b/src/sage/topology/cubical_complex.py @@ -1472,13 +1472,13 @@ def suspension(self, n=1): ... NotImplementedError: suspensions are not implemented for cubical complexes """ -# if n<0: -# raise ValueError, "n must be nonnegative." -# if n==0: -# return self -# if n==1: -# return self.join(cubical_complexes.Sphere(0)) -# return self.suspension().suspension(int(n-1)) + # if n < 0: + # raise ValueError("n must be nonnegative") + # if n == 0: + # return self + # if n == 1: + # return self.join(cubical_complexes.Sphere(0)) + # return self.suspension().suspension(int(n-1)) raise NotImplementedError("suspensions are not implemented for cubical complexes") def product(self, other): diff --git a/src/sage/version.py b/src/sage/version.py index 16c67de2983..a8b68889f48 100644 --- a/src/sage/version.py +++ b/src/sage/version.py @@ -1,5 +1,5 @@ # Sage version information for Python scripts # This file is auto-generated by the sage-update-version script, do not edit! -version = '10.6.beta4' -date = '2025-01-18' -banner = 'SageMath version 10.6.beta4, Release Date: 2025-01-18' +version = '10.6.beta5' +date = '2025-01-26' +banner = 'SageMath version 10.6.beta5, Release Date: 2025-01-26' diff --git a/src/sage_docbuild/conf.py b/src/sage_docbuild/conf.py index dab2531bac3..2b1cbd138ae 100644 --- a/src/sage_docbuild/conf.py +++ b/src/sage_docbuild/conf.py @@ -712,8 +712,8 @@ def add_page_context(app, pagename, templatename, context, doctree): # source files are generated. suffix = '.py' if importlib.import_module(pagename.replace('/','.')).__file__.endswith('.py') else '.pyx' context['page_source_suffix'] = suffix - context['theme_source_view_link'] = os.path.join(source_repository, f'blob/develop/src', '{filename}') - context['theme_source_edit_link'] = os.path.join(source_repository, f'edit/develop/src', '{filename}') + context['theme_source_view_link'] = os.path.join(source_repository, 'blob/develop/src', '{filename}') + context['theme_source_edit_link'] = os.path.join(source_repository, 'edit/develop/src', '{filename}') dangling_debug = False diff --git a/src/sage_setup/autogen/giacpy-mkkeywords.py b/src/sage_setup/autogen/giacpy-mkkeywords.py index c1a277b119c..48e9c033736 100644 --- a/src/sage_setup/autogen/giacpy-mkkeywords.py +++ b/src/sage_setup/autogen/giacpy-mkkeywords.py @@ -45,7 +45,6 @@ mostkeywords = f.read().split() mostkeywordorig = ['Airy_Ai', 'Airy_Bi', 'Archive', 'BesselJ', 'BesselY', 'Beta', 'BlockDiagonal', 'Ci', 'Circle', 'Col', 'CopyVar', 'Dirac', 'Ei', 'Factor', 'GF', 'Gamma', 'Heaviside', 'JordanBlock', 'LU', 'LambertW', 'Li', 'Line', 'LineHorz', 'LineTan', 'LineVert', 'Phi', 'Pi', 'Psi', 'QR', 'RandSeed', 'Row', 'SortA', 'SortD', 'UTPC', 'UTPF', 'UTPN', 'UTPT', 'VARS', 'VAS', 'VAS_positive', 'Zeta', '_qe_', 'a2q', 'abcuv', 'about', 'abs', 'abscissa', 'accumulate_head_tail', 'acos', 'acos2asin', 'acos2atan', 'acosh', 'acot', 'acsc', 'acyclic', 'add', 'add_arc', 'add_edge', 'add_vertex', 'additionally', 'adjacency_matrix', 'adjoint_matrix', 'affix', 'algsubs', 'algvar', 'all_trig_solutions', 'allpairs_distance', 'alog10', 'altitude', 'angle', 'angle_radian', 'angleat', 'angleatraw', 'ans', 'antiprism_graph', 'apply', 'approx', 'arc', 'arcLen', 'arccos', 'arccosh', 'arclen', 'arcsin', 'arcsinh', 'arctan', 'arctanh', 'area', 'areaat', 'areaatraw', 'areaplot', 'arg', 'array', 'arrivals', 'articulation_points', 'asin', 'asin2acos', 'asin2atan', 'asinh', 'assign_edge_weights', 'assume', 'at', 'atan', 'atan2acos', 'atan2asin', 'atanh', 'atrig2ln', 'augment', 'auto_correlation', 'autosimplify', 'avance', 'avgRC', 'axes', 'back', 'backward', 'baisse_crayon', 'bandwidth', 'bar_plot', 'bartlett_hann_window', 'barycenter', 'base', 'basis', 'batons', 'bellman_ford', 'bernoulli', 'besselJ', 'besselY', 'betad', 'betad_cdf', 'betad_icdf', 'betavariate', 'bezier', 'bezout_entiers', 'biconnected_components', 'binomial', 'binomial_cdf', 'binomial_icdf', 'bins', 'bipartite', 'bipartite_matching', 'bisection_solver', 'bisector', 'bit_depth', 'bitand', 'bitor', 'bitxor', 'blackman_harris_window', 'blackman_window', 'blockmatrix', 'bohman_window', 'border', 'boxwhisker', 'brent_solver', 'bvpsolve', 'cFactor', 'cSolve', 'cZeros', 'camembert', 'canonical_form', 'canonical_labeling', 'cartesian_product', 'cauchy', 'cauchy_cdf', 'cauchy_icdf', 'cauchyd', 'cauchyd_cdf', 'cauchyd_icdf', 'cdf', 'ceil', 'ceiling', 'center', 'center2interval', 'centered_cube', 'centered_tetrahedron', 'cfactor', 'cfsolve', 'changebase', 'channel_data', 'channels', 'char', 'charpoly', 'chinrem', 'chisquare', 'chisquare_cdf', 'chisquare_icdf', 'chisquared', 'chisquared_cdf', 'chisquared_icdf', 'chisquaret', 'choice', 'cholesky', 'chr', 'chrem', 'chromatic_index', 'chromatic_number', 'chromatic_polynomial', 'circle', 'circumcircle', 'classes', 'clear', 'clique_cover', 'clique_cover_number', 'clique_number', 'clique_stats', 'clustering_coefficient', 'coeff', 'coeffs', 'col', 'colDim', 'colNorm', 'colSwap', 'coldim', 'collect', 'colnorm', 'color', 'colspace', 'colswap', 'comDenom', 'comb', 'combine', 'comment', 'common_perpendicular', 'companion', 'compare', 'complete_binary_tree', 'complete_graph', 'complete_kary_tree', 'complex', 'complex_variables', 'complexroot', 'concat', 'cond', 'condensation', 'cone', 'confrac', 'conic', 'conj', 'conjugate_equation', 'conjugate_gradient', 'connected', 'connected_components', 'cont', 'contains', 'content', 'contourplot', 'contract_edge', 'convert', 'convertir', 'convex', 'convexhull', 'convolution', 'coordinates', 'copy', 'correlation', 'cos', 'cos2sintan', 'cosh', 'cosine_window', 'cot', 'cote', 'count', 'count_eq', 'count_inf', 'count_sup', 'courbe_parametrique', 'courbe_polaire', 'covariance', 'covariance_correlation', 'cpartfrac', 'crationalroot', 'crayon', 'createwav', 'cross', 'crossP', 'cross_correlation', 'cross_point', 'cross_ratio', 'crossproduct', 'csc', 'csolve', 'csv2gen', 'cube', 'cumSum', 'cumsum', 'cumulated_frequencies', 'curl', 'current_sheet', 'curvature', 'curve', 'cyan', 'cycle2perm', 'cycle_graph', 'cycleinv', 'cycles2permu', 'cyclotomic', 'cylinder', 'dash_line', 'dashdot_line', 'dashdotdot_line', 'dayofweek', 'deSolve', 'debut_enregistrement', 'degree', 'degree_sequence', 'delcols', 'delete_arc', 'delete_edge', 'delete_vertex', 'delrows', 'deltalist', 'denom', 'densityplot', 'departures', 'derive', 'deriver', 'desolve', 'dessine_tortue', 'det', 'det_minor', 'developper', 'developper_transcendant', 'dfc', 'dfc2f', 'diag', 'diff', 'digraph', 'dijkstra', 'dim', 'directed', 'discard_edge_attribute', 'discard_graph_attribute', 'discard_vertex_attribute', 'disjoint_union', 'display', 'disque', 'disque_centre', 'distance', 'distance2', 'distanceat', 'distanceatraw', 'divergence', 'divide', 'divis', 'division_point', 'divisors', 'divmod', 'divpc', 'dnewton_solver', 'dodecahedron', 'domain', 'dot', 'dotP', 'dot_paper', 'dotprod', 'draw_arc', 'draw_circle', 'draw_graph', 'draw_line', 'draw_pixel', 'draw_polygon', 'draw_rectangle', 'droit', 'droite_tangente', 'dsolve', 'duration', 'e', 'e2r', 'ecart_type', 'ecart_type_population', 'ecm_factor', 'edge_connectivity', 'edges', 'egcd', 'egv', 'egvl', 'eigVc', 'eigVl', 'eigenvals', 'eigenvalues', 'eigenvectors', 'eigenvects', 'element', 'eliminate', 'ellipse', 'entry', 'envelope', 'epsilon', 'epsilon2zero', 'equal', 'equal2diff', 'equal2list', 'equation', 'equilateral_triangle', 'erf', 'erfc', 'error', 'est_permu', 'euler', 'euler_gamma', 'euler_lagrange', 'eval_level', 'evala', 'evalb', 'evalc', 'evalf', 'evalm', 'even', 'evolute', 'exact', 'exbisector', 'excircle', 'execute', 'exp', 'exp2list', 'exp2pow', 'exp2trig', 'expand', 'expexpand', 'expln', 'exponential', 'exponential_cdf', 'exponential_icdf', 'exponential_regression', 'exponential_regression_plot', 'exponentiald', 'exponentiald_cdf', 'exponentiald_icdf', 'export_graph', 'expovariate', 'expr', 'extend', 'extract_measure', 'extrema', 'ezgcd', 'f2nd', 'fMax', 'fMin', 'fPart', 'faces', 'facteurs_premiers', 'factor', 'factor_xn', 'factorial', 'factoriser', 'factoriser_entier', 'factoriser_sur_C', 'factors', 'fadeev', 'false', 'falsepos_solver', 'fclose', 'fcoeff', 'fdistrib', 'fft', 'fieldplot', 'find', 'find_cycles', 'findhelp', 'fisher', 'fisher_cdf', 'fisher_icdf', 'fisherd', 'fisherd_cdf', 'fisherd_icdf', 'fitdistr', 'flatten', 'float2rational', 'floor', 'flow_polynomial', 'fmod', 'foldl', 'foldr', 'fonction_derivee', 'forward', 'fourier_an', 'fourier_bn', 'fourier_cn', 'fprint', 'frac', 'fracmod', 'frame_2d', 'frequencies', 'frobenius_norm', 'froot', 'fsolve', 'fullparfrac', 'funcplot', 'function_diff', 'fxnd', 'gammad', 'gammad_cdf', 'gammad_icdf', 'gammavariate', 'gauss', 'gauss15', 'gauss_seidel_linsolve', 'gaussian_window', 'gaussjord', 'gaussquad', 'gbasis', 'gbasis_max_pairs', 'gbasis_reinject', 'gbasis_simult_primes', 'gcd', 'gcdex', 'genpoly', 'geometric', 'geometric_cdf', 'geometric_icdf', 'getDenom', 'getKey', 'getNum', 'getType', 'get_edge_attribute', 'get_edge_weight', 'get_graph_attribute', 'get_vertex_attribute', 'girth', 'gl_showaxes', 'grad', 'gramschmidt', 'graph', 'graph_automorphisms', 'graph_charpoly', 'graph_complement', 'graph_diameter', 'graph_equal', 'graph_join', 'graph_power', 'graph_rank', 'graph_spectrum', 'graph_union', 'graph_vertices', 'greduce', 'greedy_color', 'grid_graph', 'groupermu', 'hadamard', 'half_cone', 'half_line', 'halftan', 'halftan_hyp2exp', 'halt', 'hamdist', 'hamming_window', 'hann_poisson_window', 'hann_window', 'harmonic_conjugate', 'harmonic_division', 'has', 'has_arc', 'has_edge', 'hasard', 'head', 'heading', 'heapify', 'heappop', 'heappush', 'hermite', 'hessenberg', 'hessian', 'heugcd', 'hexagon', 'highlight_edges', 'highlight_subgraph', 'highlight_trail', 'highlight_vertex', 'highpass', 'hilbert', 'histogram', 'hold', 'homothety', 'horner', 'hybrid_solver', 'hybridj_solver', 'hybrids_solver', 'hybridsj_solver', 'hyp2exp', 'hyperbola', 'hypercube_graph', 'iPart', 'iabcuv', 'ibasis', 'ibpdv', 'ibpu', 'icdf', 'ichinrem', 'ichrem', 'icomp', 'icontent', 'icosahedron', 'id', 'identity', 'idivis', 'idn', 'iegcd', 'ifactor', 'ifactors', 'igamma', 'igcd', 'igcdex', 'ihermite', 'ilaplace', 'im', 'imag', 'image', 'implicitdiff', 'implicitplot', 'import_graph', 'inString', 'in_ideal', 'incidence_matrix', 'incident_edges', 'incircle', 'increasing_power', 'independence_number', 'indets', 'index', 'induced_subgraph', 'inequationplot', 'inf', 'infinity', 'insert', 'insmod', 'int', 'intDiv', 'integer', 'integrate', 'integrer', 'inter', 'interactive_odeplot', 'interactive_plotode', 'interp', 'interval', 'interval2center', 'interval_graph', 'inv', 'inverse', 'inversion', 'invisible_point', 'invlaplace', 'invztrans', 'iquo', 'iquorem', 'iratrecon', 'irem', 'isPrime', 'is_acyclic', 'is_arborescence', 'is_biconnected', 'is_bipartite', 'is_clique', 'is_collinear', 'is_concyclic', 'is_conjugate', 'is_connected', 'is_coplanar', 'is_cospherical', 'is_cut_set', 'is_cycle', 'is_directed', 'is_element', 'is_equilateral', 'is_eulerian', 'is_forest', 'is_graphic_sequence', 'is_hamiltonian', 'is_harmonic', 'is_harmonic_circle_bundle', 'is_harmonic_line_bundle', 'is_inside', 'is_integer_graph', 'is_isomorphic', 'is_isosceles', 'is_network', 'is_orthogonal', 'is_parallel', 'is_parallelogram', 'is_permu', 'is_perpendicular', 'is_planar', 'is_prime', 'is_pseudoprime', 'is_rectangle', 'is_regular', 'is_rhombus', 'is_square', 'is_strongly_connected', 'is_strongly_regular', 'is_tournament', 'is_tree', 'is_triconnected', 'is_two_edge_connected', 'is_vertex_colorable', 'is_weighted', 'ismith', 'isobarycenter', 'isom', 'isomorphic_copy', 'isopolygon', 'isosceles_triangle', 'isprime', 'ithprime', 'jacobi_equation', 'jacobi_linsolve', 'jacobi_symbol', 'jordan', 'kde', 'keep_pivot', 'ker', 'kernel', 'kernel_density', 'kneser_graph', 'kolmogorovd', 'kolmogorovt', 'kovacicsols', 'kspaths', 'l1norm', 'l2norm', 'lagrange', 'laguerre', 'laplace', 'laplacian', 'laplacian_matrix', 'latex', 'lcf_graph', 'lcm', 'lcoeff', 'ldegree', 'left', 'left_rectangle', 'legend', 'legendre', 'legendre_symbol', 'length', 'lgcd', 'lhs', 'ligne_chapeau_carre', 'ligne_chapeau_plat', 'ligne_chapeau_rond', 'ligne_polygonale', 'ligne_polygonale_pointee', 'ligne_tiret', 'ligne_tiret_point', 'ligne_tiret_pointpoint', 'ligne_trait_plein', 'limit', 'limite', 'lin', 'line', 'line_graph', 'line_inter', 'line_paper', 'line_segments', 'linear_interpolate', 'linear_regression', 'linear_regression_plot', 'lineariser', 'lineariser_trigo', 'linfnorm', 'linsolve', 'linspace', 'lis_phrase', 'list2exp', 'list2mat', 'list_edge_attributes', 'list_graph_attributes', 'list_vertex_attributes', 'listplot', 'lll', 'ln', 'lname', 'lncollect', 'lnexpand', 'locus', 'log', 'log10', 'logarithmic_regression', 'logarithmic_regression_plot', 'logb', 'logistic_regression', 'logistic_regression_plot', 'lower', 'lowest_common_ancestor', 'lowpass', 'lp_assume', 'lp_bestprojection', 'lp_binary', 'lp_binaryvariables', 'lp_breadthfirst', 'lp_depthfirst', 'lp_depthlimit', 'lp_firstfractional', 'lp_gaptolerance', 'lp_hybrid', 'lp_initialpoint', 'lp_integer', 'lp_integertolerance', 'lp_integervariables', 'lp_interiorpoint', 'lp_iterationlimit', 'lp_lastfractional', 'lp_maxcuts', 'lp_maximize', 'lp_method', 'lp_mostfractional', 'lp_nodelimit', 'lp_nodeselect', 'lp_nonnegative', 'lp_nonnegint', 'lp_pseudocost', 'lp_simplex', 'lp_timelimit', 'lp_variables', 'lp_varselect', 'lp_verbose', 'lpsolve', 'lsmod', 'lsq', 'lu', 'lvar', 'mRow', 'mRowAdd', 'magenta', 'make_directed', 'make_weighted', 'makelist', 'makemat', 'makesuite', 'makevector', 'map', 'maple2mupad', 'maple2xcas', 'maple_ifactors', 'maple_mode', 'markov', 'mat2list', 'mathml', 'matpow', 'matrix', 'matrix_norm', 'max', 'maxflow', 'maximal_independent_set', 'maximize', 'maximum_clique', 'maximum_degree', 'maximum_independent_set', 'maximum_matching', 'maxnorm', 'mean', 'median', 'median_line', 'member', 'mgf', 'mid', 'middle_point', 'midpoint', 'min', 'minimal_edge_coloring', 'minimal_spanning_tree', 'minimal_vertex_coloring', 'minimax', 'minimize', 'minimum_cut', 'minimum_degree', 'mkisom', 'mksa', 'modgcd', 'mods', 'monotonic', 'montre_tortue', 'moustache', 'moving_average', 'moyal', 'moyenne', 'mul', 'mult_c_conjugate', 'mult_conjugate', 'multinomial', 'multiplier_conjugue', 'multiplier_conjugue_complexe', 'multiply', 'mupad2maple', 'mupad2xcas', 'mycielski', 'nCr', 'nDeriv', 'nInt', 'nPr', 'nSolve', 'ncols', 'negbinomial', 'negbinomial_cdf', 'negbinomial_icdf', 'neighbors', 'network_transitivity', 'newList', 'newMat', 'newton', 'newton_solver', 'newtonj_solver', 'nextperm', 'nextprime', 'nlpsolve', 'nodisp', 'non_recursive_normal', 'nop', 'nops', 'norm', 'normal', 'normal_cdf', 'normal_icdf', 'normald', 'normald_cdf', 'normald_icdf', 'normalize', 'normalt', 'normalvariate', 'nprimes', 'nrows', 'nuage_points', 'nullspace', 'number_of_edges', 'number_of_spanning_trees', 'number_of_triangles', 'number_of_vertices', 'numer', 'octahedron', 'odd', 'odd_girth', 'odd_graph', 'odeplot', 'odesolve', 'op', 'open_polygon', 'ord', 'order', 'order_size', 'ordinate', 'orthocenter', 'orthogonal', 'osculating_circle', 'p1oc2', 'p1op2', 'pa2b2', 'pade', 'parabola', 'parallel', 'parallelepiped', 'parallelogram', 'parameq', 'parameter', 'paramplot', 'parfrac', 'pari', 'part', 'partfrac', 'parzen_window', 'pas_de_cote', 'path_graph', 'pcar', 'pcar_hessenberg', 'pcoef', 'pcoeff', 'pencolor', 'pendown', 'penup', 'perimeter', 'perimeterat', 'perimeteratraw', 'periodic', 'perm', 'perminv', 'permu2cycles', 'permu2mat', 'permuorder', 'permute_vertices', 'perpen_bisector', 'perpendicular', 'petersen_graph', 'peval', 'pi', 'piecewise', 'pivot', 'pixoff', 'pixon', 'planar', 'plane', 'plane_dual', 'playsnd', 'plex', 'plot', 'plot3d', 'plotarea', 'plotcdf', 'plotcontour', 'plotdensity', 'plotfield', 'plotfunc', 'plotimplicit', 'plotinequation', 'plotlist', 'plotode', 'plotparam', 'plotpolar', 'plotproba', 'plotseq', 'plotspectrum', 'plotwav', 'plus_point', 'pmin', 'point', 'point2d', 'point3d', 'poisson', 'poisson_cdf', 'poisson_icdf', 'poisson_window', 'polar', 'polar_coordinates', 'polar_point', 'polarplot', 'pole', 'poly2symb', 'polyEval', 'polygon', 'polygone_rempli', 'polygonplot', 'polygonscatterplot', 'polyhedron', 'polynom', 'polynomial_regression', 'polynomial_regression_plot', 'position', 'poslbdLMQ', 'posubLMQ', 'potential', 'pow2exp', 'power_regression', 'power_regression_plot', 'powermod', 'powerpc', 'powexpand', 'powmod', 'prepend', 'preval', 'prevperm', 'prevprime', 'primpart', 'printf', 'prism', 'prism_graph', 'product', 'projection', 'proot', 'propFrac', 'propfrac', 'psrgcd', 'ptayl', 'purge', 'pwd', 'pyramid', 'python_compat', 'q2a', 'qr', 'quadric', 'quadrilateral', 'quantile', 'quartile1', 'quartile3', 'quartiles', 'quest', 'quo', 'quorem', 'quote', 'r2e', 'radical_axis', 'radius', 'ramene', 'rand', 'randMat', 'randNorm', 'randPoly', 'randbetad', 'randbinomial', 'randchisquare', 'randexp', 'randfisher', 'randgammad', 'randgeometric', 'randint', 'randmarkov', 'randmatrix', 'randmultinomial', 'randnorm', 'random', 'random_bipartite_graph', 'random_digraph', 'random_graph', 'random_network', 'random_planar_graph', 'random_regular_graph', 'random_sequence_graph', 'random_tournament', 'random_tree', 'random_variable', 'randperm', 'randpoisson', 'randpoly', 'randseed', 'randstudent', 'randvar', 'randvector', 'randweibulld', 'rank', 'ranm', 'ranv', 'rassembler_trigo', 'rat_jordan', 'rational', 'rationalroot', 'ratnormal', 'rcl', 'rdiv', 're', 'read', 'readrgb', 'readwav', 'real', 'realroot', 'reciprocation', 'rectangle', 'rectangle_droit', 'rectangle_gauche', 'rectangle_plein', 'rectangular_coordinates', 'recule', 'red', 'reduced_conic', 'reduced_quadric', 'ref', 'reflection', 'regroup', 'relabel_vertices', 'reliability_polynomial', 'rem', 'remain', 'remove', 'reorder', 'resample', 'residue', 'resoudre', 'resoudre_dans_C', 'resoudre_systeme_lineaire', 'resultant', 'reverse', 'reverse_graph', 'reverse_rsolve', 'revert', 'revlex', 'revlist', 'rgb', 'rhombus', 'rhombus_point', 'rhs', 'riemann_window', 'right', 'right_rectangle', 'right_triangle', 'risch', 'rm_a_z', 'rm_all_vars', 'rmbreakpoint', 'rmmod', 'rmwatch', 'romberg', 'rombergm', 'rombergt', 'rond', 'root', 'rootof', 'roots', 'rotate', 'rotation', 'round', 'row', 'rowAdd', 'rowDim', 'rowNorm', 'rowSwap', 'rowdim', 'rownorm', 'rowspace', 'rowswap', 'rref', 'rsolve', 'same', 'sample', 'samplerate', 'sans_factoriser', 'saute', 'scalarProduct', 'scalar_product', 'scatterplot', 'schur', 'sec', 'secant_solver', 'segment', 'seidel_spectrum', 'seidel_switch', 'select', 'semi_augment', 'seq', 'seqplot', 'seqsolve', 'sequence_graph', 'series', 'set_edge_attribute', 'set_edge_weight', 'set_graph_attribute', 'set_pixel', 'set_vertex_attribute', 'set_vertex_positions', 'shift', 'shift_phase', 'shortest_path', 'show_pixels', 'shuffle', 'sierpinski_graph', 'sign', 'signature', 'signe', 'similarity', 'simp2', 'simplex_reduce', 'simplifier', 'simplify', 'simpson', 'simult', 'sin', 'sin2costan', 'sincos', 'single_inter', 'sinh', 'sizes', 'slope', 'slopeat', 'slopeatraw', 'smith', 'smod', 'snedecor', 'snedecor_cdf', 'snedecor_icdf', 'snedecord', 'snedecord_cdf', 'snedecord_icdf', 'solid_line', 'solve', 'somme', 'sommet', 'sort', 'sorta', 'sortd', 'sorted', 'soundsec', 'spanning_tree', 'sphere', 'spline', 'split', 'spring', 'sq', 'sqrfree', 'sqrt', 'square', 'square_point', 'srand', 'sst', 'sst_in', 'st_ordering', 'star_graph', 'star_point', 'start', 'stdDev', 'stddev', 'stddevp', 'steffenson_solver', 'stereo2mono', 'str', 'strongly_connected_components', 'student', 'student_cdf', 'student_icdf', 'studentd', 'studentt', 'sturm', 'sturmab', 'sturmseq', 'style', 'subMat', 'subdivide_edges', 'subgraph', 'subs', 'subsop', 'subst', 'substituer', 'subtype', 'sum', 'sum_riemann', 'suppress', 'surd', 'svd', 'swapcol', 'swaprow', 'switch_axes', 'sylvester', 'symb2poly', 'symbol', 'syst2mat', 'tCollect', 'tExpand', 'table', 'tablefunc', 'tableseq', 'tabvar', 'tail', 'tan', 'tan2cossin2', 'tan2sincos', 'tan2sincos2', 'tangent', 'tangente', 'tanh', 'taux_accroissement', 'taylor', 'tchebyshev1', 'tchebyshev2', 'tcoeff', 'tcollect', 'tdeg', 'tensor_product', 'tetrahedron', 'texpand', 'thickness', 'threshold', 'throw', 'title', 'titre', 'tlin', 'tonnetz', 'topologic_sort', 'topological_sort', 'torus_grid_graph', 'total_degree', 'tourne_droite', 'tourne_gauche', 'tpsolve', 'trace', 'trail', 'trail2edges', 'trames', 'tran', 'transitive_closure', 'translation', 'transpose', 'trapeze', 'trapezoid', 'traveling_salesman', 'tree', 'tree_height', 'triangle', 'triangle_paper', 'triangle_plein', 'triangle_point', 'triangle_window', 'trig2exp', 'trigcos', 'trigexpand', 'triginterp', 'trigsimplify', 'trigsin', 'trigtan', 'trn', 'true', 'trunc', 'truncate', 'truncate_graph', 'tsimplify', 'tuer', 'tukey_window', 'tutte_polynomial', 'two_edge_connected_components', 'ufactor', 'ugamma', 'unapply', 'unarchive', 'underlying_graph', 'unfactored', 'uniform', 'uniform_cdf', 'uniform_icdf', 'uniformd', 'uniformd_cdf', 'uniformd_icdf', 'unitV', 'unquote', 'upper', 'user_operator', 'usimplify', 'valuation', 'vandermonde', 'variables_are_files', 'variance', 'version', 'vertex_connectivity', 'vertex_degree', 'vertex_distance', 'vertex_in_degree', 'vertex_out_degree', 'vertices', 'vertices_abc', 'vertices_abca', 'vpotential', 'web_graph', 'weibull', 'weibull_cdf', 'weibull_icdf', 'weibulld', 'weibulld_cdf', 'weibulld_icdf', 'weibullvariate', 'weight_matrix', 'weighted', 'weights', 'welch_window', 'wheel_graph', 'widget_size', 'wilcoxonp', 'wilcoxons', 'wilcoxont', 'with_sqrt', 'writergb', 'writewav', 'xcas_mode', 'xyztrange', 'zeros', 'ztrans'] -# missing = set(mostkeywordorig).difference(mostkeywords) print("Missing",missing) diff --git a/src/setup.py b/src/setup.py index dfa2e59b2e1..19853e8a228 100755 --- a/src/setup.py +++ b/src/setup.py @@ -87,7 +87,7 @@ python_packages = find_namespace_packages(where=SAGE_SRC, include=['sage', 'sage.*']) log.debug(f"python_packages = {python_packages}") - log.info(f"Discovering Python/Cython source code... done") + log.info("Discovering Python/Cython source code... done") # from sage_build_cython: import Cython.Compiler.Options diff --git a/src/tox.ini b/src/tox.ini index 29dd3fcaa15..81822de97cf 100644 --- a/src/tox.ini +++ b/src/tox.ini @@ -180,7 +180,7 @@ description = # W605: invalid escape sequence ‘x’ # See https://pycodestyle.pycqa.org/en/latest/intro.html#error-codes deps = pycodestyle -commands = pycodestyle --select E111,E21,E221,E222,E225,E227,E228,E25,E271,E275,E302,E303,E305,E306,E401,E502,E701,E702,E703,E71,E72,W291,W293,W391,W605 {posargs:{toxinidir}/sage/} +commands = pycodestyle --select E111,E115,E21,E221,E222,E225,E227,E228,E25,E271,E275,E302,E303,E305,E306,E401,E502,E701,E702,E703,E71,E72,W291,W293,W391,W605 {posargs:{toxinidir}/sage/} pycodestyle --select E111,E271,E301,E302,E303,E305,E306,E401,E502,E703,E712,E713,E714,E72,W29,W391,W605, --filename *.pyx {posargs:{toxinidir}/sage/} [pycodestyle] @@ -311,7 +311,7 @@ passenv = RUFF_OUTPUT_FORMAT # 1 F402 [ ] Import `factor` from line 259 shadowed by loop variable # 1 PLC0208 [*] Use a sequence type instead of a `set` when iterating over values # -commands = ruff check --ignore E402,E721,E731,E741,E742,E743,F401,F402,F403,F405,F821,F841,I001,PLC0206,PLC0208,PLC2401,PLC3002,PLE0302,PLR0124,PLR0402,PLR0911,PLR0912,PLR0913,PLR0915,PLR1704,PLR1711,PLR1714,PLR1736,PLR2004,PLR5501,PLW0120,PLW0127,PLW0211,PLW0602,PLW0603,PLW0642,PLW1508,PLW1510,PLW2901,PLW3301 {posargs:{toxinidir}/sage/} +commands = ruff check --ignore E402,E721,E731,E741,E742,E743,F401,F402,F403,F405,F821,F841,I001,PLC0206,PLC0208,PLC2401,PLC3002,PLE0302,PLR0124,PLR0402,PLR0911,PLR0912,PLR0913,PLR0915,PLR1704,PLR1711,PLR1714,PLR1716,PLR1736,PLR2004,PLR5501,PLW0120,PLW0127,PLW0211,PLW0602,PLW0603,PLW0642,PLW1508,PLW1510,PLW2901,PLW3301 {posargs:{toxinidir}/sage/} [flake8] rst-roles =